blob: a15d061feaf477a351cfd3513233a8eba17e3c3e [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com32fdf822012-11-28 20:53:30 +00002//
Nicolas Capens673e6802014-05-28 10:28:33 -04003// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com32fdf822012-11-28 20:53:30 +00004// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
9
Geoff Langd47e0fc2013-08-29 11:40:43 -040010#include "libGLESv2/renderer/d3d11/SwapChain11.h"
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000011
Geoff Langd47e0fc2013-08-29 11:40:43 -040012#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
13#include "libGLESv2/renderer/d3d11/formatutils11.h"
14#include "libGLESv2/renderer/d3d11/Renderer11.h"
15#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough2d11vs.h"
16#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
daniel@transgaming.come0970472012-11-28 21:05:07 +000017
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000018namespace rx
19{
20
21SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
22 GLenum backBufferFormat, GLenum depthBufferFormat)
23 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
24{
25 mSwapChain = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000026 mBackBufferTexture = NULL;
27 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000028 mOffscreenTexture = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000029 mOffscreenRTView = NULL;
daniel@transgaming.come0970472012-11-28 21:05:07 +000030 mOffscreenSRView = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000031 mDepthStencilTexture = NULL;
32 mDepthStencilDSView = NULL;
Geoff Lang88f9cbf2013-10-18 14:33:37 -040033 mDepthStencilSRView = NULL;
daniel@transgaming.comf06e5392013-01-11 21:15:50 +000034 mQuadVB = NULL;
35 mPassThroughSampler = NULL;
36 mPassThroughIL = NULL;
37 mPassThroughVS = NULL;
38 mPassThroughPS = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000039 mWidth = -1;
40 mHeight = -1;
shannon.woods@transgaming.comad74a4b2013-02-28 23:04:09 +000041 mSwapInterval = 0;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000042 mAppCreatedShareHandle = mShareHandle != NULL;
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +000043 mPassThroughResourcesInit = false;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000044}
45
46SwapChain11::~SwapChain11()
47{
48 release();
49}
50
51void SwapChain11::release()
52{
Geoff Langea228632013-07-30 15:17:12 -040053 SafeRelease(mSwapChain);
54 SafeRelease(mBackBufferTexture);
55 SafeRelease(mBackBufferRTView);
56 SafeRelease(mOffscreenTexture);
57 SafeRelease(mOffscreenRTView);
58 SafeRelease(mOffscreenSRView);
59 SafeRelease(mDepthStencilTexture);
60 SafeRelease(mDepthStencilDSView);
Geoff Lang88f9cbf2013-10-18 14:33:37 -040061 SafeRelease(mDepthStencilSRView);
Geoff Langea228632013-07-30 15:17:12 -040062 SafeRelease(mQuadVB);
63 SafeRelease(mPassThroughSampler);
64 SafeRelease(mPassThroughIL);
65 SafeRelease(mPassThroughVS);
66 SafeRelease(mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +000067
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000068 if (!mAppCreatedShareHandle)
69 {
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000070 mShareHandle = NULL;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000071 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000072}
73
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +000074void SwapChain11::releaseOffscreenTexture()
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000075{
Geoff Langea228632013-07-30 15:17:12 -040076 SafeRelease(mOffscreenTexture);
77 SafeRelease(mOffscreenRTView);
78 SafeRelease(mOffscreenSRView);
79 SafeRelease(mDepthStencilTexture);
80 SafeRelease(mDepthStencilDSView);
Jamie Madill8b4f8f82014-03-26 14:01:58 -040081 SafeRelease(mDepthStencilSRView);
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +000082}
83
84EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
85{
86 ID3D11Device *device = mRenderer->getDevice();
87
88 ASSERT(device != NULL);
89
90 // D3D11 does not allow zero size textures
91 ASSERT(backbufferWidth >= 1);
92 ASSERT(backbufferHeight >= 1);
93
94 // Preserve the render target content
95 ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
96 if (previousOffscreenTexture)
97 {
98 previousOffscreenTexture->AddRef();
99 }
100 const int previousWidth = mWidth;
101 const int previousHeight = mHeight;
102
103 releaseOffscreenTexture();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000104
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000105 // If the app passed in a share handle, open the resource
106 // See EGL_ANGLE_d3d_share_handle_client_buffer
107 if (mAppCreatedShareHandle)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000108 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000109 ID3D11Resource *tempResource11;
110 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000111
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000112 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000113 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000114 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
115 release();
116 return EGL_BAD_PARAMETER;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000117 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000118
119 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
Geoff Langea228632013-07-30 15:17:12 -0400120 SafeRelease(tempResource11);
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000121
122 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000123 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000124 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
125 release();
126 return EGL_BAD_PARAMETER;
127 }
128
129 // Validate offscreen texture parameters
130 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
131 mOffscreenTexture->GetDesc(&offscreenTextureDesc);
132
133 if (offscreenTextureDesc.Width != (UINT)backbufferWidth
134 || offscreenTextureDesc.Height != (UINT)backbufferHeight
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000135 || offscreenTextureDesc.Format != gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion())
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000136 || offscreenTextureDesc.MipLevels != 1
137 || offscreenTextureDesc.ArraySize != 1)
138 {
139 ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
140 release();
141 return EGL_BAD_PARAMETER;
142 }
143 }
144 else
145 {
146 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
147
148 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
149 offscreenTextureDesc.Width = backbufferWidth;
150 offscreenTextureDesc.Height = backbufferHeight;
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000151 offscreenTextureDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000152 offscreenTextureDesc.MipLevels = 1;
153 offscreenTextureDesc.ArraySize = 1;
154 offscreenTextureDesc.SampleDesc.Count = 1;
155 offscreenTextureDesc.SampleDesc.Quality = 0;
156 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
157 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
158 offscreenTextureDesc.CPUAccessFlags = 0;
159 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
160
161 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
162
163 if (FAILED(result))
164 {
165 ERR("Could not create offscreen texture: %08lX", result);
166 release();
167
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000168 if (d3d11::isDeviceLostError(result))
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000169 {
170 return EGL_CONTEXT_LOST;
171 }
172 else
173 {
174 return EGL_BAD_ALLOC;
175 }
176 }
177
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400178 d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture");
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000179
180 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
181 if (useSharedResource)
182 {
183 IDXGIResource *offscreenTextureResource = NULL;
184 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
185
186 // Fall back to no share handle on failure
187 if (FAILED(result))
188 {
189 ERR("Could not query offscreen texture resource: %08lX", result);
190 }
191 else
192 {
193 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
Shannon Woods78568ba2013-08-08 14:15:08 -0400194 SafeRelease(offscreenTextureResource);
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000195
196 if (FAILED(result))
197 {
198 mShareHandle = NULL;
199 ERR("Could not get offscreen texture shared handle: %08lX", result);
200 }
201 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000202 }
203 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000204
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000205
206 D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
207 offscreenRTVDesc.Format = gl_d3d11::GetRTVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
208 offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
209 offscreenRTVDesc.Texture2D.MipSlice = 0;
210
211 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000212 ASSERT(SUCCEEDED(result));
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400213 d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000214
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000215 D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
216 offscreenSRVDesc.Format = gl_d3d11::GetSRVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
217 offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
218 offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
219 offscreenSRVDesc.Texture2D.MipLevels = -1;
220
221 result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000222 ASSERT(SUCCEEDED(result));
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400223 d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000224
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000225 if (mDepthBufferFormat != GL_NONE)
226 {
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000227 D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
228 depthStencilTextureDesc.Width = backbufferWidth;
229 depthStencilTextureDesc.Height = backbufferHeight;
230 depthStencilTextureDesc.Format = gl_d3d11::GetTexFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion());
231 depthStencilTextureDesc.MipLevels = 1;
232 depthStencilTextureDesc.ArraySize = 1;
233 depthStencilTextureDesc.SampleDesc.Count = 1;
234 depthStencilTextureDesc.SampleDesc.Quality = 0;
235 depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400236 depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000237 depthStencilTextureDesc.CPUAccessFlags = 0;
238 depthStencilTextureDesc.MiscFlags = 0;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000239
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000240 result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000241 if (FAILED(result))
242 {
243 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
244 release();
245
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000246 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000247 {
248 return EGL_CONTEXT_LOST;
249 }
250 else
251 {
252 return EGL_BAD_ALLOC;
253 }
254 }
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400255 d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000256
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000257 D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc;
258 depthStencilDesc.Format = gl_d3d11::GetDSVFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion());
259 depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
260 depthStencilDesc.Flags = 0;
261 depthStencilDesc.Texture2D.MipSlice = 0;
262
263 result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000264 ASSERT(SUCCEEDED(result));
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400265 d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view");
266
267 D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
268 depthStencilSRVDesc.Format = gl_d3d11::GetSRVFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion());
269 depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
270 depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
271 depthStencilSRVDesc.Texture2D.MipLevels = -1;
272
273 result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView);
274 ASSERT(SUCCEEDED(result));
275 d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000276 }
277
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000278 mWidth = backbufferWidth;
279 mHeight = backbufferHeight;
280
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000281 if (previousOffscreenTexture != NULL)
282 {
283 D3D11_BOX sourceBox = {0};
284 sourceBox.left = 0;
285 sourceBox.right = std::min(previousWidth, mWidth);
286 sourceBox.top = std::max(previousHeight - mHeight, 0);
287 sourceBox.bottom = previousHeight;
288 sourceBox.front = 0;
289 sourceBox.back = 1;
290
291 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
292 const int yoffset = std::max(mHeight - previousHeight, 0);
293 deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
294
Geoff Langea228632013-07-30 15:17:12 -0400295 SafeRelease(previousOffscreenTexture);
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000296
297 if (mSwapChain)
298 {
299 swapRect(0, 0, mWidth, mHeight);
300 }
301 }
302
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000303 return EGL_SUCCESS;
304}
305
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000306EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
307{
308 ID3D11Device *device = mRenderer->getDevice();
309
310 if (device == NULL)
311 {
312 return EGL_BAD_ACCESS;
313 }
314
Jamie Madillfa3d9f32013-12-03 16:58:17 -0500315 // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
316 if (backbufferWidth < 1 || backbufferHeight < 1)
317 {
318 return EGL_SUCCESS;
319 }
320
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000321 // Can only call resize if we have already created our swap buffer and resources
322 ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
323
Geoff Langea228632013-07-30 15:17:12 -0400324 SafeRelease(mBackBufferTexture);
325 SafeRelease(mBackBufferRTView);
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000326
327 // Resize swap chain
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000328 DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
Nicolas Capens673e6802014-05-28 10:28:33 -0400329 HRESULT result = mSwapChain->ResizeBuffers(1, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000330
331 if (FAILED(result))
332 {
333 ERR("Error resizing swap chain buffers: 0x%08X", result);
334 release();
335
336 if (d3d11::isDeviceLostError(result))
337 {
338 return EGL_CONTEXT_LOST;
339 }
340 else
341 {
342 return EGL_BAD_ALLOC;
343 }
344 }
345
346 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
347 ASSERT(SUCCEEDED(result));
348 if (SUCCEEDED(result))
349 {
350 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
351 }
352
353 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
354 ASSERT(SUCCEEDED(result));
355 if (SUCCEEDED(result))
356 {
357 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
358 }
359
360 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
361}
362
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000363EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
364{
365 ID3D11Device *device = mRenderer->getDevice();
366
367 if (device == NULL)
368 {
369 return EGL_BAD_ACCESS;
370 }
371
372 // Release specific resources to free up memory for the new render target, while the
373 // old render target still exists for the purpose of preserving its contents.
Geoff Langea228632013-07-30 15:17:12 -0400374 SafeRelease(mSwapChain);
375 SafeRelease(mBackBufferTexture);
376 SafeRelease(mBackBufferRTView);
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000377
378 mSwapInterval = static_cast<unsigned int>(swapInterval);
379 if (mSwapInterval > 4)
380 {
381 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
382 return EGL_BAD_PARAMETER;
383 }
384
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +0000385 // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
386 if (backbufferWidth < 1 || backbufferHeight < 1)
387 {
388 releaseOffscreenTexture();
389 return EGL_SUCCESS;
390 }
391
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000392 if (mWindow)
393 {
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000394 IDXGIFactory *factory = mRenderer->getDxgiFactory();
395
396 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000397 swapChainDesc.BufferDesc.Width = backbufferWidth;
398 swapChainDesc.BufferDesc.Height = backbufferHeight;
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000399 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
400 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
Nicolas Capens0e3efa52014-05-16 16:54:23 -0400401 swapChainDesc.BufferDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
402 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
403 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000404 swapChainDesc.SampleDesc.Count = 1;
405 swapChainDesc.SampleDesc.Quality = 0;
Nicolas Capens0e3efa52014-05-16 16:54:23 -0400406 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
Nicolas Capens673e6802014-05-28 10:28:33 -0400407 swapChainDesc.BufferCount = 1;
Nicolas Capens0e3efa52014-05-16 16:54:23 -0400408 swapChainDesc.OutputWindow = mWindow;
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000409 swapChainDesc.Windowed = TRUE;
Nicolas Capens0e3efa52014-05-16 16:54:23 -0400410 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
411 swapChainDesc.Flags = 0;
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000412
413 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
414
415 if (FAILED(result))
416 {
417 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
418 release();
419
420 if (d3d11::isDeviceLostError(result))
421 {
422 return EGL_CONTEXT_LOST;
423 }
424 else
425 {
Geoff Lang94a90892014-02-18 17:14:19 -0500426 return EGL_BAD_ALLOC;
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000427 }
428 }
429
430 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
431 ASSERT(SUCCEEDED(result));
432 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
433
434 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
435 ASSERT(SUCCEEDED(result));
436 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
437 }
438
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000439 // If we are resizing the swap chain, we don't wish to recreate all the static resources
440 if (!mPassThroughResourcesInit)
441 {
442 mPassThroughResourcesInit = true;
443 initPassThroughResources();
444 }
445
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000446 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000447}
448
449void SwapChain11::initPassThroughResources()
450{
451 ID3D11Device *device = mRenderer->getDevice();
452
453 ASSERT(device != NULL);
454
455 // Make sure our resources are all not allocated, when we create
456 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
457 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
458
daniel@transgaming.come0970472012-11-28 21:05:07 +0000459 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000460 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000461 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
462 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
463 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
464 vbDesc.MiscFlags = 0;
465 vbDesc.StructureByteStride = 0;
466
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000467 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000468 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000469 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000470
471 D3D11_SAMPLER_DESC samplerDesc;
472 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
473 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
474 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
475 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
476 samplerDesc.MipLODBias = 0.0f;
477 samplerDesc.MaxAnisotropy = 0;
478 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
479 samplerDesc.BorderColor[0] = 0.0f;
480 samplerDesc.BorderColor[1] = 0.0f;
481 samplerDesc.BorderColor[2] = 0.0f;
482 samplerDesc.BorderColor[3] = 0.0f;
483 samplerDesc.MinLOD = 0;
484 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
485
486 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
487 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000488 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000489
490 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
491 {
492 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
493 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
494 };
495
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000496 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000497 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000498 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000499
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000500 result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000501 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000502 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000503
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000504 result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000505 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000506 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000507}
508
509// parameters should be validated/clamped by caller
510EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
511{
512 if (!mSwapChain)
513 {
514 return EGL_SUCCESS;
515 }
516
517 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000518 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000519
daniel@transgaming.come0970472012-11-28 21:05:07 +0000520 // Set vertices
521 D3D11_MAPPED_SUBRESOURCE mappedResource;
522 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
523 if (FAILED(result))
524 {
525 return EGL_BAD_ACCESS;
526 }
527
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000528 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000529
530 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000531 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000532 float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000533 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000534 float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000535
536 float u1 = x / float(mWidth);
537 float v1 = y / float(mHeight);
538 float u2 = (x + width) / float(mWidth);
539 float v2 = (y + height) / float(mHeight);
540
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000541 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
542 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
543 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
544 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000545
546 deviceContext->Unmap(mQuadVB, 0);
547
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000548 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000549 static UINT startIdx = 0;
550 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
551
552 // Apply state
553 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
554
555 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
556 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
557
558 deviceContext->RSSetState(NULL);
559
560 // Apply shaders
561 deviceContext->IASetInputLayout(mPassThroughIL);
562 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
563 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
564 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000565 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000566
567 // Apply render targets
shannon.woods%transgaming.com@gtempaccount.comba2744f2013-04-13 03:33:38 +0000568 mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000569
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000570 // Set the viewport
571 D3D11_VIEWPORT viewport;
572 viewport.TopLeftX = 0;
573 viewport.TopLeftY = 0;
574 viewport.Width = mWidth;
575 viewport.Height = mHeight;
576 viewport.MinDepth = 0.0f;
577 viewport.MaxDepth = 1.0f;
578 deviceContext->RSSetViewports(1, &viewport);
579
daniel@transgaming.come0970472012-11-28 21:05:07 +0000580 // Apply textures
581 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
582 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
583
584 // Draw
585 deviceContext->Draw(4, 0);
Geoff Langf5ef21c2013-10-03 11:20:48 -0400586
587#if ANGLE_FORCE_VSYNC_OFF
588 result = mSwapChain->Present(0, 0);
589#else
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000590 result = mSwapChain->Present(mSwapInterval, 0);
Geoff Langf5ef21c2013-10-03 11:20:48 -0400591#endif
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000592
593 if (result == DXGI_ERROR_DEVICE_REMOVED)
594 {
595 HRESULT removedReason = device->GetDeviceRemovedReason();
Geoff Lang9cd19152014-05-28 15:54:34 -0400596 UNUSED_ASSERTION_VARIABLE(removedReason);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000597 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
598 return EGL_CONTEXT_LOST;
599 }
600 else if (result == DXGI_ERROR_DEVICE_RESET)
601 {
602 ERR("Present failed: the D3D11 device was reset from a bad command.");
603 return EGL_CONTEXT_LOST;
604 }
605 else if (FAILED(result))
606 {
607 ERR("Present failed with error code 0x%08X", result);
608 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000609
610 // Unbind
611 static ID3D11ShaderResourceView *const nullSRV = NULL;
612 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
613
shannon.woods%transgaming.com@gtempaccount.comba2744f2013-04-13 03:33:38 +0000614 mRenderer->unapplyRenderTargets();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000615 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000616
617 return EGL_SUCCESS;
618}
619
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000620ID3D11Texture2D *SwapChain11::getOffscreenTexture()
621{
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000622 return mOffscreenTexture;
623}
624
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000625ID3D11RenderTargetView *SwapChain11::getRenderTarget()
626{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000627 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000628}
629
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000630ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
631{
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000632 return mOffscreenSRView;
633}
634
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000635ID3D11DepthStencilView *SwapChain11::getDepthStencil()
636{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000637 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000638}
639
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400640ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource()
641{
Geoff Lang88f9cbf2013-10-18 14:33:37 -0400642 return mDepthStencilSRView;
643}
644
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000645ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
646{
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000647 return mDepthStencilTexture;
648}
649
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000650SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
651{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000652 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000653 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000654}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000655
shannon.woods%transgaming.com@gtempaccount.com8bce3f52013-04-13 03:35:32 +0000656void SwapChain11::recreate()
657{
658 // possibly should use this method instead of reset
659}
660
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000661}