]> git.cworth.org Git - apitrace/blob - retrace/d3d11state_images.cpp
Merge branch 'master' into trim-auto
[apitrace] / retrace / d3d11state_images.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include <assert.h>
28
29 #include <iostream>
30 #include <algorithm>
31
32 #include "image.hpp"
33 #include "d3d11imports.hpp"
34
35
36 namespace d3dstate {
37
38 static HRESULT
39 stageResource(ID3D11DeviceContext *pDeviceContext,
40               ID3D11Resource *pResource,
41               ID3D11Resource **ppStagingResource,
42               UINT *pWidth, UINT *pHeight, UINT *pDepth) {
43     D3D11_USAGE Usage = D3D11_USAGE_STAGING;
44     UINT BindFlags = 0;
45     UINT CPUAccessFlags = D3D11_CPU_ACCESS_READ;
46     UINT MiscFlags = 0;
47     union {
48          ID3D11Resource *pStagingResource;
49          ID3D11Buffer *pStagingBuffer;
50          ID3D11Texture1D *pStagingTexture1D;
51          ID3D11Texture2D *pStagingTexture2D;
52          ID3D11Texture3D *pStagingTexture3D;
53     };
54     HRESULT hr;
55
56     ID3D11Device *pDevice = NULL;
57     pDeviceContext->GetDevice(&pDevice);
58
59     D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
60     pResource->GetType(&Type);
61     switch (Type) {
62     case D3D11_RESOURCE_DIMENSION_BUFFER:
63         {
64             D3D11_BUFFER_DESC Desc;
65             static_cast<ID3D11Buffer *>(pResource)->GetDesc(&Desc);
66             Desc.Usage = Usage;
67             Desc.BindFlags = BindFlags;
68             Desc.CPUAccessFlags = CPUAccessFlags;
69             Desc.MiscFlags = MiscFlags;
70
71             *pWidth = Desc.ByteWidth;
72             *pHeight = 1;
73             *pDepth = 1;
74
75             hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
76         }
77         break;
78     case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
79         {
80             D3D11_TEXTURE1D_DESC Desc;
81             static_cast<ID3D11Texture1D *>(pResource)->GetDesc(&Desc);
82             Desc.Usage = Usage;
83             Desc.BindFlags = BindFlags;
84             Desc.CPUAccessFlags = CPUAccessFlags;
85             Desc.MiscFlags = MiscFlags;
86
87             *pWidth = Desc.Width;
88             *pHeight = 1;
89             *pDepth = 1;
90
91             hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
92         }
93         break;
94     case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
95         {
96             D3D11_TEXTURE2D_DESC Desc;
97             static_cast<ID3D11Texture2D *>(pResource)->GetDesc(&Desc);
98             Desc.Usage = Usage;
99             Desc.BindFlags = BindFlags;
100             Desc.CPUAccessFlags = CPUAccessFlags;
101             Desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
102
103             *pWidth = Desc.Width;
104             *pHeight = Desc.Height;
105             *pDepth = 1;
106
107             hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
108         }
109         break;
110     case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
111         {
112             D3D11_TEXTURE3D_DESC Desc;
113             static_cast<ID3D11Texture3D *>(pResource)->GetDesc(&Desc);
114             Desc.Usage = Usage;
115             Desc.BindFlags = BindFlags;
116             Desc.CPUAccessFlags = CPUAccessFlags;
117             Desc.MiscFlags = MiscFlags;
118
119             *pWidth = Desc.Width;
120             *pHeight = Desc.Height;
121             *pDepth = Desc.Depth;
122
123             hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
124         }
125         break;
126     default:
127         assert(0);
128         hr = E_NOTIMPL;
129         break;
130     }
131
132     if (SUCCEEDED(hr)) {
133         *ppStagingResource = pStagingResource;
134         pDeviceContext->CopyResource(pStagingResource, pResource);
135     }
136     
137     pDevice->Release();
138
139     return hr;
140 }
141
142 image::Image *
143 getRenderTargetImage(ID3D11DeviceContext *pDevice) {
144     image::Image *image = NULL;
145     ID3D11RenderTargetView *pRenderTargetView = NULL;
146     D3D11_RENDER_TARGET_VIEW_DESC Desc;
147     ID3D11Resource *pResource = NULL;
148     ID3D11Resource *pStagingResource = NULL;
149     UINT Width, Height, Depth;
150     UINT MipSlice;
151     UINT Subresource;
152     D3D11_MAPPED_SUBRESOURCE MappedSubresource;
153     HRESULT hr;
154     const unsigned char *src;
155     unsigned char *dst;
156
157     pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
158     if (!pRenderTargetView) {
159         goto no_rendertarget;
160     }
161
162     pRenderTargetView->GetResource(&pResource);
163     assert(pResource);
164
165     pRenderTargetView->GetDesc(&Desc);
166     if (Desc.Format != DXGI_FORMAT_R8G8B8A8_UNORM &&
167         Desc.Format != DXGI_FORMAT_R32G32B32A32_FLOAT) {
168         std::cerr << "warning: unsupported DXGI format " << Desc.Format << "\n";
169         goto no_staging;
170     }
171
172     hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth);
173     if (FAILED(hr)) {
174         goto no_staging;
175     }
176
177     // TODO: Take the slice in consideration
178     switch (Desc.ViewDimension) {
179     case D3D11_RTV_DIMENSION_BUFFER:
180         MipSlice = 0;
181         break;
182     case D3D11_RTV_DIMENSION_TEXTURE1D:
183         MipSlice = Desc.Texture1D.MipSlice;
184         break;
185     case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
186         MipSlice = Desc.Texture1DArray.MipSlice;
187         break;
188     case D3D11_RTV_DIMENSION_TEXTURE2D:
189         MipSlice = Desc.Texture2D.MipSlice;
190         MipSlice = 0;
191         break;
192     case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
193         MipSlice = Desc.Texture2DArray.MipSlice;
194         break;
195     case D3D11_RTV_DIMENSION_TEXTURE2DMS:
196         MipSlice = 0;
197         break;
198     case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
199         MipSlice = 0;
200         break;
201     case D3D11_RTV_DIMENSION_TEXTURE3D:
202         MipSlice = Desc.Texture3D.MipSlice;
203         break;
204     case D3D11_SRV_DIMENSION_UNKNOWN:
205     default:
206         assert(0);
207         goto no_map;
208     }
209     Subresource = MipSlice;
210
211     Width  = std::max(Width  >> MipSlice, 1U);
212     Height = std::max(Height >> MipSlice, 1U);
213     Depth  = std::max(Depth  >> MipSlice, 1U);
214
215     hr = pDevice->Map(pStagingResource, Subresource, D3D11_MAP_READ, 0, &MappedSubresource);
216     if (FAILED(hr)) {
217         goto no_map;
218     }
219
220     image = new image::Image(Width, Height, 4, true);
221     if (!image) {
222         goto no_image;
223     }
224
225     dst = image->start();
226     src = (const unsigned char *)MappedSubresource.pData;
227     for (unsigned y = 0; y < Height; ++y) {
228         if (Desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM) {
229             memcpy(dst, src, Width * 4);
230         } else if (Desc.Format == DXGI_FORMAT_R32G32B32A32_FLOAT) {
231             float scale = 1.0f/255.0f;
232             for (unsigned x = 0; x < Width; ++x) {
233                 dst[4*x + 0] = ((float *)src)[4*x + 0] * scale;
234                 dst[4*x + 1] = ((float *)src)[4*x + 1] * scale;
235                 dst[4*x + 2] = ((float *)src)[4*x + 2] * scale;
236                 dst[4*x + 3] = ((float *)src)[4*x + 3] * scale;
237             }
238         } else {
239             assert(0);
240         }
241         src += MappedSubresource.RowPitch;
242         dst += image->stride();
243     }
244
245 no_image:
246     pDevice->Unmap(pStagingResource, Subresource);
247 no_map:
248     if (pStagingResource) {
249         pStagingResource->Release();
250     }
251 no_staging:
252     if (pResource) {
253         pResource->Release();
254     }
255     if (pRenderTargetView) {
256         pRenderTargetView->Release();
257     }
258 no_rendertarget:
259     return image;
260 }
261
262
263 } /* namespace d3dstate */