]> git.cworth.org Git - apitrace/blob - retrace/d3d11state_images.cpp
glstate: Fallback to GLX when there is no current EGL context (issue #124).
[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 "os.hpp"
33 #include "json.hpp"
34 #include "d3d11imports.hpp"
35 #include "d3d10state.hpp"
36 #include "dxgistate.hpp"
37
38
39 namespace d3dstate {
40
41 static HRESULT
42 stageResource(ID3D11DeviceContext *pDeviceContext,
43               ID3D11Resource *pResource,
44               ID3D11Resource **ppStagingResource,
45               UINT *pWidth, UINT *pHeight, UINT *pDepth) {
46     D3D11_USAGE Usage = D3D11_USAGE_STAGING;
47     UINT BindFlags = 0;
48     UINT CPUAccessFlags = D3D11_CPU_ACCESS_READ;
49     UINT MiscFlags = 0;
50     union {
51          ID3D11Resource *pStagingResource;
52          ID3D11Buffer *pStagingBuffer;
53          ID3D11Texture1D *pStagingTexture1D;
54          ID3D11Texture2D *pStagingTexture2D;
55          ID3D11Texture3D *pStagingTexture3D;
56     };
57     HRESULT hr;
58
59     ID3D11Device *pDevice = NULL;
60     pDeviceContext->GetDevice(&pDevice);
61
62     D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
63     pResource->GetType(&Type);
64     switch (Type) {
65     case D3D11_RESOURCE_DIMENSION_BUFFER:
66         {
67             D3D11_BUFFER_DESC Desc;
68             static_cast<ID3D11Buffer *>(pResource)->GetDesc(&Desc);
69             Desc.Usage = Usage;
70             Desc.BindFlags = BindFlags;
71             Desc.CPUAccessFlags = CPUAccessFlags;
72             Desc.MiscFlags = MiscFlags;
73
74             *pWidth = Desc.ByteWidth;
75             *pHeight = 1;
76             *pDepth = 1;
77
78             hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
79         }
80         break;
81     case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
82         {
83             D3D11_TEXTURE1D_DESC Desc;
84             static_cast<ID3D11Texture1D *>(pResource)->GetDesc(&Desc);
85             Desc.Usage = Usage;
86             Desc.BindFlags = BindFlags;
87             Desc.CPUAccessFlags = CPUAccessFlags;
88             Desc.MiscFlags = MiscFlags;
89
90             *pWidth = Desc.Width;
91             *pHeight = 1;
92             *pDepth = 1;
93
94             hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
95         }
96         break;
97     case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
98         {
99             D3D11_TEXTURE2D_DESC Desc;
100             static_cast<ID3D11Texture2D *>(pResource)->GetDesc(&Desc);
101             Desc.Usage = Usage;
102             Desc.BindFlags = BindFlags;
103             Desc.CPUAccessFlags = CPUAccessFlags;
104             Desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
105
106             *pWidth = Desc.Width;
107             *pHeight = Desc.Height;
108             *pDepth = 1;
109
110             hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
111         }
112         break;
113     case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
114         {
115             D3D11_TEXTURE3D_DESC Desc;
116             static_cast<ID3D11Texture3D *>(pResource)->GetDesc(&Desc);
117             Desc.Usage = Usage;
118             Desc.BindFlags = BindFlags;
119             Desc.CPUAccessFlags = CPUAccessFlags;
120             Desc.MiscFlags = MiscFlags;
121
122             *pWidth = Desc.Width;
123             *pHeight = Desc.Height;
124             *pDepth = Desc.Depth;
125
126             hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
127         }
128         break;
129     default:
130         assert(0);
131         hr = E_NOTIMPL;
132         break;
133     }
134
135     if (SUCCEEDED(hr)) {
136         *ppStagingResource = pStagingResource;
137         pDeviceContext->CopyResource(pStagingResource, pResource);
138     }
139     
140     pDevice->Release();
141
142     return hr;
143 }
144
145 image::Image *
146 getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
147                          ID3D11RenderTargetView *pRenderTargetView) {
148     image::Image *image = NULL;
149     D3D11_RENDER_TARGET_VIEW_DESC Desc;
150     ID3D11Resource *pResource = NULL;
151     ID3D11Resource *pStagingResource = NULL;
152     UINT Width, Height, Depth;
153     UINT MipSlice;
154     UINT Subresource;
155     D3D11_MAPPED_SUBRESOURCE MappedSubresource;
156     HRESULT hr;
157
158     if (!pRenderTargetView) {
159         return NULL;
160     }
161
162     pRenderTargetView->GetResource(&pResource);
163     assert(pResource);
164
165     pRenderTargetView->GetDesc(&Desc);
166
167     hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth);
168     if (FAILED(hr)) {
169         goto no_staging;
170     }
171
172     // TODO: Take the slice in consideration
173     switch (Desc.ViewDimension) {
174     case D3D11_RTV_DIMENSION_BUFFER:
175         MipSlice = 0;
176         break;
177     case D3D11_RTV_DIMENSION_TEXTURE1D:
178         MipSlice = Desc.Texture1D.MipSlice;
179         break;
180     case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
181         MipSlice = Desc.Texture1DArray.MipSlice;
182         break;
183     case D3D11_RTV_DIMENSION_TEXTURE2D:
184         MipSlice = Desc.Texture2D.MipSlice;
185         MipSlice = 0;
186         break;
187     case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
188         MipSlice = Desc.Texture2DArray.MipSlice;
189         break;
190     case D3D11_RTV_DIMENSION_TEXTURE2DMS:
191         MipSlice = 0;
192         break;
193     case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
194         MipSlice = 0;
195         break;
196     case D3D11_RTV_DIMENSION_TEXTURE3D:
197         MipSlice = Desc.Texture3D.MipSlice;
198         break;
199     case D3D11_SRV_DIMENSION_UNKNOWN:
200     default:
201         assert(0);
202         goto no_map;
203     }
204     Subresource = MipSlice;
205
206     Width  = std::max(Width  >> MipSlice, 1U);
207     Height = std::max(Height >> MipSlice, 1U);
208     Depth  = std::max(Depth  >> MipSlice, 1U);
209
210     hr = pDevice->Map(pStagingResource, Subresource, D3D11_MAP_READ, 0, &MappedSubresource);
211     if (FAILED(hr)) {
212         goto no_map;
213     }
214
215     image = ConvertImage(Desc.Format,
216                          MappedSubresource.pData,
217                          MappedSubresource.RowPitch,
218                          Width, Height);
219
220     pDevice->Unmap(pStagingResource, Subresource);
221 no_map:
222     if (pStagingResource) {
223         pStagingResource->Release();
224     }
225 no_staging:
226     if (pResource) {
227         pResource->Release();
228     }
229     return image;
230 }
231
232
233 image::Image *
234 getRenderTargetImage(ID3D11DeviceContext *pDevice) {
235     ID3D11RenderTargetView *pRenderTargetView = NULL;
236     pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
237
238     image::Image *image = NULL;
239     if (pRenderTargetView) {
240         image = getRenderTargetViewImage(pDevice, pRenderTargetView);
241         pRenderTargetView->Release();
242     }
243
244     return image;
245 }
246
247
248 void
249 dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
250 {
251     json.beginMember("framebuffer");
252     json.beginObject();
253
254     ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
255     pDevice->OMGetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, pRenderTargetViews, NULL);
256
257     for (UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
258         if (!pRenderTargetViews[i]) {
259             continue;
260         }
261
262         image::Image *image;
263         image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
264         if (image) {
265             char label[64];
266             _snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
267             json.beginMember(label);
268             json.writeImage(image, "UNKNOWN");
269             json.endMember(); // RENDER_TARGET_*
270         }
271
272         pRenderTargetViews[i]->Release();
273     }
274
275     json.endObject();
276     json.endMember(); // framebuffer
277 }
278
279
280 } /* namespace d3dstate */