1 /**************************************************************************
3 * Copyright 2011 Jose Fonseca
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 **************************************************************************/
33 #include "d3d11imports.hpp"
34 #include "d3d10state.hpp"
40 stageResource(ID3D11DeviceContext *pDeviceContext,
41 ID3D11Resource *pResource,
42 ID3D11Resource **ppStagingResource,
43 UINT *pWidth, UINT *pHeight, UINT *pDepth) {
44 D3D11_USAGE Usage = D3D11_USAGE_STAGING;
46 UINT CPUAccessFlags = D3D11_CPU_ACCESS_READ;
49 ID3D11Resource *pStagingResource;
50 ID3D11Buffer *pStagingBuffer;
51 ID3D11Texture1D *pStagingTexture1D;
52 ID3D11Texture2D *pStagingTexture2D;
53 ID3D11Texture3D *pStagingTexture3D;
57 ID3D11Device *pDevice = NULL;
58 pDeviceContext->GetDevice(&pDevice);
60 D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
61 pResource->GetType(&Type);
63 case D3D11_RESOURCE_DIMENSION_BUFFER:
65 D3D11_BUFFER_DESC Desc;
66 static_cast<ID3D11Buffer *>(pResource)->GetDesc(&Desc);
68 Desc.BindFlags = BindFlags;
69 Desc.CPUAccessFlags = CPUAccessFlags;
70 Desc.MiscFlags = MiscFlags;
72 *pWidth = Desc.ByteWidth;
76 hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
79 case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
81 D3D11_TEXTURE1D_DESC Desc;
82 static_cast<ID3D11Texture1D *>(pResource)->GetDesc(&Desc);
84 Desc.BindFlags = BindFlags;
85 Desc.CPUAccessFlags = CPUAccessFlags;
86 Desc.MiscFlags = MiscFlags;
92 hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
95 case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
97 D3D11_TEXTURE2D_DESC Desc;
98 static_cast<ID3D11Texture2D *>(pResource)->GetDesc(&Desc);
100 Desc.BindFlags = BindFlags;
101 Desc.CPUAccessFlags = CPUAccessFlags;
102 Desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
104 *pWidth = Desc.Width;
105 *pHeight = Desc.Height;
108 hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
111 case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
113 D3D11_TEXTURE3D_DESC Desc;
114 static_cast<ID3D11Texture3D *>(pResource)->GetDesc(&Desc);
116 Desc.BindFlags = BindFlags;
117 Desc.CPUAccessFlags = CPUAccessFlags;
118 Desc.MiscFlags = MiscFlags;
120 *pWidth = Desc.Width;
121 *pHeight = Desc.Height;
122 *pDepth = Desc.Depth;
124 hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
134 *ppStagingResource = pStagingResource;
135 pDeviceContext->CopyResource(pStagingResource, pResource);
144 getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
145 ID3D11RenderTargetView *pRenderTargetView) {
146 image::Image *image = NULL;
148 D3D11_RENDER_TARGET_VIEW_DESC Desc;
149 ID3D11Resource *pResource = NULL;
150 ID3D11Resource *pStagingResource = NULL;
151 UINT Width, Height, Depth;
154 D3D11_MAPPED_SUBRESOURCE MappedSubresource;
156 const unsigned char *src;
159 if (!pRenderTargetView) {
163 pRenderTargetView->GetResource(&pResource);
166 pRenderTargetView->GetDesc(&Desc);
167 if (Desc.Format != DXGI_FORMAT_R8G8B8A8_UNORM &&
168 Desc.Format != DXGI_FORMAT_R32G32B32A32_FLOAT &&
169 Desc.Format != DXGI_FORMAT_B8G8R8A8_UNORM) {
170 std::cerr << "warning: unsupported DXGI format " << Desc.Format << "\n";
174 hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth);
179 // TODO: Take the slice in consideration
180 switch (Desc.ViewDimension) {
181 case D3D11_RTV_DIMENSION_BUFFER:
184 case D3D11_RTV_DIMENSION_TEXTURE1D:
185 MipSlice = Desc.Texture1D.MipSlice;
187 case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
188 MipSlice = Desc.Texture1DArray.MipSlice;
190 case D3D11_RTV_DIMENSION_TEXTURE2D:
191 MipSlice = Desc.Texture2D.MipSlice;
194 case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
195 MipSlice = Desc.Texture2DArray.MipSlice;
197 case D3D11_RTV_DIMENSION_TEXTURE2DMS:
200 case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
203 case D3D11_RTV_DIMENSION_TEXTURE3D:
204 MipSlice = Desc.Texture3D.MipSlice;
206 case D3D11_SRV_DIMENSION_UNKNOWN:
211 Subresource = MipSlice;
213 Width = std::max(Width >> MipSlice, 1U);
214 Height = std::max(Height >> MipSlice, 1U);
215 Depth = std::max(Depth >> MipSlice, 1U);
217 hr = pDevice->Map(pStagingResource, Subresource, D3D11_MAP_READ, 0, &MappedSubresource);
222 image = new image::Image(Width, Height, 4, true);
227 dst = image->start();
228 src = (const unsigned char *)MappedSubresource.pData;
229 for (unsigned y = 0; y < Height; ++y) {
230 if (Desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM) {
231 memcpy(dst, src, Width * 4);
232 } else if (Desc.Format == DXGI_FORMAT_R32G32B32A32_FLOAT) {
233 float scale = 1.0f/255.0f;
234 for (unsigned x = 0; x < Width; ++x) {
235 dst[4*x + 0] = ((float *)src)[4*x + 0] * scale;
236 dst[4*x + 1] = ((float *)src)[4*x + 1] * scale;
237 dst[4*x + 2] = ((float *)src)[4*x + 2] * scale;
238 dst[4*x + 3] = ((float *)src)[4*x + 3] * scale;
240 } else if (Desc.Format == DXGI_FORMAT_B8G8R8A8_UNORM) {
241 for (unsigned x = 0; x < Width; ++x) {
242 dst[4*x + 0] = src[4*x + 2];
243 dst[4*x + 1] = src[4*x + 1];
244 dst[4*x + 2] = src[4*x + 0];
245 dst[4*x + 3] = src[4*x + 3];
250 src += MappedSubresource.RowPitch;
251 dst += image->stride();
255 pDevice->Unmap(pStagingResource, Subresource);
257 if (pStagingResource) {
258 pStagingResource->Release();
262 pResource->Release();
271 getRenderTargetImage(ID3D11DeviceContext *pDevice) {
272 ID3D11RenderTargetView *pRenderTargetView = NULL;
273 pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
275 image::Image *image = NULL;
276 if (pRenderTargetView) {
277 image = getRenderTargetViewImage(pDevice, pRenderTargetView);
278 pRenderTargetView->Release();
286 dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
288 json.beginMember("framebuffer");
291 ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
292 pDevice->OMGetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, pRenderTargetViews, NULL);
294 for (UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
295 if (!pRenderTargetViews[i]) {
300 image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
303 _snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
304 json.beginMember(label);
305 json.writeImage(image, "UNKNOWN");
306 json.endMember(); // RENDER_TARGET_*
309 pRenderTargetViews[i]->Release();
313 json.endMember(); // framebuffer
317 } /* namespace d3dstate */