blob: 275bf7ab472b6ee84f5121de735d733fda2cb43d [file] [log] [blame]
daniel@transgaming.com32fdf822012-11-28 20:53:30 +00001//
daniel@transgaming.comed36abd2013-01-11 21:15:58 +00002// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com32fdf822012-11-28 20:53:30 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
8
9#include "libGLESv2/renderer/SwapChain11.h"
10
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000011#include "libGLESv2/renderer/renderer11_utils.h"
12#include "libGLESv2/renderer/Renderer11.h"
daniel@transgaming.com8dc8e272013-01-11 04:10:45 +000013#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +000014#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
daniel@transgaming.come0970472012-11-28 21:05:07 +000015
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000016namespace rx
17{
18
19SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
20 GLenum backBufferFormat, GLenum depthBufferFormat)
21 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
22{
23 mSwapChain = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000024 mBackBufferTexture = NULL;
25 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000026 mOffscreenTexture = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000027 mOffscreenRTView = NULL;
daniel@transgaming.come0970472012-11-28 21:05:07 +000028 mOffscreenSRView = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000029 mDepthStencilTexture = NULL;
30 mDepthStencilDSView = NULL;
daniel@transgaming.comf06e5392013-01-11 21:15:50 +000031 mQuadVB = NULL;
32 mPassThroughSampler = NULL;
33 mPassThroughIL = NULL;
34 mPassThroughVS = NULL;
35 mPassThroughPS = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000036 mWidth = -1;
37 mHeight = -1;
shannon.woods@transgaming.comad74a4b2013-02-28 23:04:09 +000038 mSwapInterval = 0;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000039 mAppCreatedShareHandle = mShareHandle != NULL;
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +000040 mPassThroughResourcesInit = false;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000041}
42
43SwapChain11::~SwapChain11()
44{
45 release();
46}
47
48void SwapChain11::release()
49{
50 if (mSwapChain)
51 {
52 mSwapChain->Release();
53 mSwapChain = NULL;
54 }
55
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000056 if (mBackBufferTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000057 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000058 mBackBufferTexture->Release();
59 mBackBufferTexture = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000060 }
61
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000062 if (mBackBufferRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000063 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000064 mBackBufferRTView->Release();
65 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000066 }
67
68 if (mOffscreenTexture)
69 {
70 mOffscreenTexture->Release();
71 mOffscreenTexture = NULL;
72 }
73
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000074 if (mOffscreenRTView)
75 {
76 mOffscreenRTView->Release();
77 mOffscreenRTView = NULL;
78 }
79
daniel@transgaming.come0970472012-11-28 21:05:07 +000080 if (mOffscreenSRView)
81 {
82 mOffscreenSRView->Release();
83 mOffscreenSRView = NULL;
84 }
85
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000086 if (mDepthStencilTexture)
87 {
88 mDepthStencilTexture->Release();
89 mDepthStencilTexture = NULL;
90 }
91
92 if (mDepthStencilDSView)
93 {
94 mDepthStencilDSView->Release();
95 mDepthStencilDSView = NULL;
96 }
97
daniel@transgaming.come0970472012-11-28 21:05:07 +000098 if (mQuadVB)
99 {
100 mQuadVB->Release();
101 mQuadVB = NULL;
102 }
103
104 if (mPassThroughSampler)
105 {
106 mPassThroughSampler->Release();
107 mPassThroughSampler = NULL;
108 }
109
110 if (mPassThroughIL)
111 {
112 mPassThroughIL->Release();
113 mPassThroughIL = NULL;
114 }
115
116 if (mPassThroughVS)
117 {
118 mPassThroughVS->Release();
119 mPassThroughVS = NULL;
120 }
121
122 if (mPassThroughPS)
123 {
124 mPassThroughPS->Release();
125 mPassThroughPS = NULL;
126 }
127
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000128 if (!mAppCreatedShareHandle)
129 {
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000130 mShareHandle = NULL;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000131 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000132}
133
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000134void SwapChain11::releaseOffscreenTexture()
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000135{
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000136 if (mOffscreenTexture)
137 {
138 mOffscreenTexture->Release();
139 mOffscreenTexture = NULL;
140 }
141
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000142 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000143 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000144 mOffscreenRTView->Release();
145 mOffscreenRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000146 }
147
daniel@transgaming.come0970472012-11-28 21:05:07 +0000148 if (mOffscreenSRView)
149 {
150 mOffscreenSRView->Release();
151 mOffscreenSRView = NULL;
152 }
153
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000154 if (mDepthStencilTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000155 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000156 mDepthStencilTexture->Release();
157 mDepthStencilTexture = NULL;
158 }
159
160 if (mDepthStencilDSView)
161 {
162 mDepthStencilDSView->Release();
163 mDepthStencilDSView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000164 }
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000165}
166
167EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
168{
169 ID3D11Device *device = mRenderer->getDevice();
170
171 ASSERT(device != NULL);
172
173 // D3D11 does not allow zero size textures
174 ASSERT(backbufferWidth >= 1);
175 ASSERT(backbufferHeight >= 1);
176
177 // Preserve the render target content
178 ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
179 if (previousOffscreenTexture)
180 {
181 previousOffscreenTexture->AddRef();
182 }
183 const int previousWidth = mWidth;
184 const int previousHeight = mHeight;
185
186 releaseOffscreenTexture();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000187
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000188 // If the app passed in a share handle, open the resource
189 // See EGL_ANGLE_d3d_share_handle_client_buffer
190 if (mAppCreatedShareHandle)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000191 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000192 ID3D11Resource *tempResource11;
193 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000194
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000195 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000196 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000197 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
198 release();
199 return EGL_BAD_PARAMETER;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000200 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000201
202 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
203 tempResource11->Release();
204
205 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000206 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000207 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
208 release();
209 return EGL_BAD_PARAMETER;
210 }
211
212 // Validate offscreen texture parameters
213 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
214 mOffscreenTexture->GetDesc(&offscreenTextureDesc);
215
216 if (offscreenTextureDesc.Width != (UINT)backbufferWidth
217 || offscreenTextureDesc.Height != (UINT)backbufferHeight
218 || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
219 || offscreenTextureDesc.MipLevels != 1
220 || offscreenTextureDesc.ArraySize != 1)
221 {
222 ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
223 release();
224 return EGL_BAD_PARAMETER;
225 }
226 }
227 else
228 {
229 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
230
231 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
232 offscreenTextureDesc.Width = backbufferWidth;
233 offscreenTextureDesc.Height = backbufferHeight;
234 offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
235 offscreenTextureDesc.MipLevels = 1;
236 offscreenTextureDesc.ArraySize = 1;
237 offscreenTextureDesc.SampleDesc.Count = 1;
238 offscreenTextureDesc.SampleDesc.Quality = 0;
239 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
240 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
241 offscreenTextureDesc.CPUAccessFlags = 0;
242 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
243
244 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
245
246 if (FAILED(result))
247 {
248 ERR("Could not create offscreen texture: %08lX", result);
249 release();
250
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000251 if (d3d11::isDeviceLostError(result))
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000252 {
253 return EGL_CONTEXT_LOST;
254 }
255 else
256 {
257 return EGL_BAD_ALLOC;
258 }
259 }
260
261 d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
262
263 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
264 if (useSharedResource)
265 {
266 IDXGIResource *offscreenTextureResource = NULL;
267 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
268
269 // Fall back to no share handle on failure
270 if (FAILED(result))
271 {
272 ERR("Could not query offscreen texture resource: %08lX", result);
273 }
274 else
275 {
276 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
277
278 if (FAILED(result))
279 {
280 mShareHandle = NULL;
281 ERR("Could not get offscreen texture shared handle: %08lX", result);
282 }
283 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000284 }
285 }
286
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000287 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
288
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000289 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000290 d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000291
daniel@transgaming.come0970472012-11-28 21:05:07 +0000292 result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
293 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000294 d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000295
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000296 if (mDepthBufferFormat != GL_NONE)
297 {
298 D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
299 depthStencilDesc.Width = backbufferWidth;
300 depthStencilDesc.Height = backbufferHeight;
301 depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
302 depthStencilDesc.MipLevels = 1;
303 depthStencilDesc.ArraySize = 1;
304 depthStencilDesc.SampleDesc.Count = 1;
305 depthStencilDesc.SampleDesc.Quality = 0;
306 depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
307 depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
308 depthStencilDesc.CPUAccessFlags = 0;
309 depthStencilDesc.MiscFlags = 0;
310
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000311 result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000312 if (FAILED(result))
313 {
314 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
315 release();
316
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000317 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000318 {
319 return EGL_CONTEXT_LOST;
320 }
321 else
322 {
323 return EGL_BAD_ALLOC;
324 }
325 }
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000326 d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000327
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000328 result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000329 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000330 d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000331 }
332
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000333 mWidth = backbufferWidth;
334 mHeight = backbufferHeight;
335
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000336 if (previousOffscreenTexture != NULL)
337 {
338 D3D11_BOX sourceBox = {0};
339 sourceBox.left = 0;
340 sourceBox.right = std::min(previousWidth, mWidth);
341 sourceBox.top = std::max(previousHeight - mHeight, 0);
342 sourceBox.bottom = previousHeight;
343 sourceBox.front = 0;
344 sourceBox.back = 1;
345
346 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
347 const int yoffset = std::max(mHeight - previousHeight, 0);
348 deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
349
350 previousOffscreenTexture->Release();
351
352 if (mSwapChain)
353 {
354 swapRect(0, 0, mWidth, mHeight);
355 }
356 }
357
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000358 return EGL_SUCCESS;
359}
360
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000361EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
362{
363 ID3D11Device *device = mRenderer->getDevice();
364
365 if (device == NULL)
366 {
367 return EGL_BAD_ACCESS;
368 }
369
370 // Can only call resize if we have already created our swap buffer and resources
371 ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
372
373 if (mBackBufferTexture)
374 {
375 mBackBufferTexture->Release();
376 mBackBufferTexture = NULL;
377 }
378
379 if (mBackBufferRTView)
380 {
381 mBackBufferRTView->Release();
382 mBackBufferRTView = NULL;
383 }
384
385 // Resize swap chain
386 DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
387 HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
388
389 if (FAILED(result))
390 {
391 ERR("Error resizing swap chain buffers: 0x%08X", result);
392 release();
393
394 if (d3d11::isDeviceLostError(result))
395 {
396 return EGL_CONTEXT_LOST;
397 }
398 else
399 {
400 return EGL_BAD_ALLOC;
401 }
402 }
403
404 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
405 ASSERT(SUCCEEDED(result));
406 if (SUCCEEDED(result))
407 {
408 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
409 }
410
411 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
412 ASSERT(SUCCEEDED(result));
413 if (SUCCEEDED(result))
414 {
415 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
416 }
417
418 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
419}
420
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000421EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
422{
423 ID3D11Device *device = mRenderer->getDevice();
424
425 if (device == NULL)
426 {
427 return EGL_BAD_ACCESS;
428 }
429
430 // Release specific resources to free up memory for the new render target, while the
431 // old render target still exists for the purpose of preserving its contents.
432 if (mSwapChain)
433 {
434 mSwapChain->Release();
435 mSwapChain = NULL;
436 }
437
438 if (mBackBufferTexture)
439 {
440 mBackBufferTexture->Release();
441 mBackBufferTexture = NULL;
442 }
443
444 if (mBackBufferRTView)
445 {
446 mBackBufferRTView->Release();
447 mBackBufferRTView = NULL;
448 }
449
450 mSwapInterval = static_cast<unsigned int>(swapInterval);
451 if (mSwapInterval > 4)
452 {
453 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
454 return EGL_BAD_PARAMETER;
455 }
456
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +0000457 // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
458 if (backbufferWidth < 1 || backbufferHeight < 1)
459 {
460 releaseOffscreenTexture();
461 return EGL_SUCCESS;
462 }
463
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000464 if (mWindow)
465 {
466 // We cannot create a swap chain for an HWND that is owned by a different process
467 DWORD currentProcessId = GetCurrentProcessId();
468 DWORD wndProcessId;
469 GetWindowThreadProcessId(mWindow, &wndProcessId);
470
471 if (currentProcessId != wndProcessId)
472 {
473 ERR("Could not create swap chain, window owned by different process");
474 release();
475 return EGL_BAD_NATIVE_WINDOW;
476 }
477
478 IDXGIFactory *factory = mRenderer->getDxgiFactory();
479
480 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
481 swapChainDesc.BufferCount = 2;
482 swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
483 swapChainDesc.BufferDesc.Width = backbufferWidth;
484 swapChainDesc.BufferDesc.Height = backbufferHeight;
485 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
486 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
487 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
488 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
489 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
490 swapChainDesc.Flags = 0;
491 swapChainDesc.OutputWindow = mWindow;
492 swapChainDesc.SampleDesc.Count = 1;
493 swapChainDesc.SampleDesc.Quality = 0;
494 swapChainDesc.Windowed = TRUE;
495
496 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
497
498 if (FAILED(result))
499 {
500 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
501 release();
502
503 if (d3d11::isDeviceLostError(result))
504 {
505 return EGL_CONTEXT_LOST;
506 }
507 else
508 {
509 return EGL_BAD_ALLOC;
510 }
511 }
512
513 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
514 ASSERT(SUCCEEDED(result));
515 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
516
517 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
518 ASSERT(SUCCEEDED(result));
519 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
520 }
521
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000522 // If we are resizing the swap chain, we don't wish to recreate all the static resources
523 if (!mPassThroughResourcesInit)
524 {
525 mPassThroughResourcesInit = true;
526 initPassThroughResources();
527 }
528
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000529 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000530}
531
532void SwapChain11::initPassThroughResources()
533{
534 ID3D11Device *device = mRenderer->getDevice();
535
536 ASSERT(device != NULL);
537
538 // Make sure our resources are all not allocated, when we create
539 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
540 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
541
daniel@transgaming.come0970472012-11-28 21:05:07 +0000542 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000543 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000544 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
545 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
546 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
547 vbDesc.MiscFlags = 0;
548 vbDesc.StructureByteStride = 0;
549
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000550 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000551 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000552 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000553
554 D3D11_SAMPLER_DESC samplerDesc;
555 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
556 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
557 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
558 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
559 samplerDesc.MipLODBias = 0.0f;
560 samplerDesc.MaxAnisotropy = 0;
561 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
562 samplerDesc.BorderColor[0] = 0.0f;
563 samplerDesc.BorderColor[1] = 0.0f;
564 samplerDesc.BorderColor[2] = 0.0f;
565 samplerDesc.BorderColor[3] = 0.0f;
566 samplerDesc.MinLOD = 0;
567 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
568
569 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
570 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000571 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000572
573 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
574 {
575 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
576 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
577 };
578
579 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
580 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000581 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000582
583 result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
584 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000585 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000586
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +0000587 result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000588 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000589 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000590}
591
592// parameters should be validated/clamped by caller
593EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
594{
595 if (!mSwapChain)
596 {
597 return EGL_SUCCESS;
598 }
599
600 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000601 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000602
daniel@transgaming.come0970472012-11-28 21:05:07 +0000603 // Set vertices
604 D3D11_MAPPED_SUBRESOURCE mappedResource;
605 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
606 if (FAILED(result))
607 {
608 return EGL_BAD_ACCESS;
609 }
610
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000611 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000612
613 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000614 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000615 float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000616 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000617 float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000618
619 float u1 = x / float(mWidth);
620 float v1 = y / float(mHeight);
621 float u2 = (x + width) / float(mWidth);
622 float v2 = (y + height) / float(mHeight);
623
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000624 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
625 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
626 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
627 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000628
629 deviceContext->Unmap(mQuadVB, 0);
630
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000631 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000632 static UINT startIdx = 0;
633 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
634
635 // Apply state
636 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
637
638 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
639 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
640
641 deviceContext->RSSetState(NULL);
642
643 // Apply shaders
644 deviceContext->IASetInputLayout(mPassThroughIL);
645 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
646 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
647 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000648 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000649
650 // Apply render targets
651 deviceContext->OMSetRenderTargets(1, &mBackBufferRTView, NULL);
652
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000653 // Set the viewport
654 D3D11_VIEWPORT viewport;
655 viewport.TopLeftX = 0;
656 viewport.TopLeftY = 0;
657 viewport.Width = mWidth;
658 viewport.Height = mHeight;
659 viewport.MinDepth = 0.0f;
660 viewport.MaxDepth = 1.0f;
661 deviceContext->RSSetViewports(1, &viewport);
662
daniel@transgaming.come0970472012-11-28 21:05:07 +0000663 // Apply textures
664 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
665 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
666
667 // Draw
668 deviceContext->Draw(4, 0);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000669 result = mSwapChain->Present(mSwapInterval, 0);
670
671 if (result == DXGI_ERROR_DEVICE_REMOVED)
672 {
673 HRESULT removedReason = device->GetDeviceRemovedReason();
674 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
675 return EGL_CONTEXT_LOST;
676 }
677 else if (result == DXGI_ERROR_DEVICE_RESET)
678 {
679 ERR("Present failed: the D3D11 device was reset from a bad command.");
680 return EGL_CONTEXT_LOST;
681 }
682 else if (FAILED(result))
683 {
684 ERR("Present failed with error code 0x%08X", result);
685 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000686
687 // Unbind
688 static ID3D11ShaderResourceView *const nullSRV = NULL;
689 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
690
691 static ID3D11RenderTargetView *const nullRTV = NULL;
692 deviceContext->OMSetRenderTargets(1, &nullRTV, NULL);
693
daniel@transgaming.come0970472012-11-28 21:05:07 +0000694 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000695
696 return EGL_SUCCESS;
697}
698
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000699// Increments refcount on texture.
700// caller must Release() the returned texture
701ID3D11Texture2D *SwapChain11::getOffscreenTexture()
702{
703 if (mOffscreenTexture)
704 {
705 mOffscreenTexture->AddRef();
706 }
707
708 return mOffscreenTexture;
709}
710
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000711// Increments refcount on view.
712// caller must Release() the returned view
713ID3D11RenderTargetView *SwapChain11::getRenderTarget()
714{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000715 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000716 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000717 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000718 }
719
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000720 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000721}
722
723// Increments refcount on view.
724// caller must Release() the returned view
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000725ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
726{
727 if (mOffscreenSRView)
728 {
729 mOffscreenSRView->AddRef();
730 }
731
732 return mOffscreenSRView;
733}
734
735// Increments refcount on view.
736// caller must Release() the returned view
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000737ID3D11DepthStencilView *SwapChain11::getDepthStencil()
738{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000739 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000740 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000741 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000742 }
743
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000744 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000745}
746
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000747ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
748{
749 if (mDepthStencilTexture)
750 {
751 mDepthStencilTexture->AddRef();
752 }
753
754 return mDepthStencilTexture;
755}
756
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000757SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
758{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000759 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000760 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000761}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000762
763}