blob: d469da72ee78e20ec3e83552e0887dc47a5a8893 [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
11#include "common/debug.h"
12#include "libGLESv2/utilities.h"
13#include "libGLESv2/renderer/renderer11_utils.h"
14#include "libGLESv2/renderer/Renderer11.h"
15#include "libGLESv2/Context.h"
16#include "libGLESv2/main.h"
17
daniel@transgaming.com8dc8e272013-01-11 04:10:45 +000018#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +000019#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
daniel@transgaming.come0970472012-11-28 21:05:07 +000020
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000021namespace rx
22{
23
24SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
25 GLenum backBufferFormat, GLenum depthBufferFormat)
26 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
27{
28 mSwapChain = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000029 mBackBufferTexture = NULL;
30 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000031 mOffscreenTexture = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000032 mOffscreenRTView = NULL;
daniel@transgaming.come0970472012-11-28 21:05:07 +000033 mOffscreenSRView = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000034 mDepthStencilTexture = NULL;
35 mDepthStencilDSView = NULL;
daniel@transgaming.comf06e5392013-01-11 21:15:50 +000036 mQuadVB = NULL;
37 mPassThroughSampler = NULL;
38 mPassThroughIL = NULL;
39 mPassThroughVS = NULL;
40 mPassThroughPS = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000041 mWidth = -1;
42 mHeight = -1;
shannon.woods@transgaming.comad74a4b2013-02-28 23:04:09 +000043 mSwapInterval = 0;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000044 mAppCreatedShareHandle = mShareHandle != NULL;
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +000045 mPassThroughResourcesInit = false;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000046}
47
48SwapChain11::~SwapChain11()
49{
50 release();
51}
52
53void SwapChain11::release()
54{
55 if (mSwapChain)
56 {
57 mSwapChain->Release();
58 mSwapChain = NULL;
59 }
60
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000061 if (mBackBufferTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000062 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000063 mBackBufferTexture->Release();
64 mBackBufferTexture = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000065 }
66
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000067 if (mBackBufferRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000068 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000069 mBackBufferRTView->Release();
70 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000071 }
72
73 if (mOffscreenTexture)
74 {
75 mOffscreenTexture->Release();
76 mOffscreenTexture = NULL;
77 }
78
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000079 if (mOffscreenRTView)
80 {
81 mOffscreenRTView->Release();
82 mOffscreenRTView = NULL;
83 }
84
daniel@transgaming.come0970472012-11-28 21:05:07 +000085 if (mOffscreenSRView)
86 {
87 mOffscreenSRView->Release();
88 mOffscreenSRView = NULL;
89 }
90
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000091 if (mDepthStencilTexture)
92 {
93 mDepthStencilTexture->Release();
94 mDepthStencilTexture = NULL;
95 }
96
97 if (mDepthStencilDSView)
98 {
99 mDepthStencilDSView->Release();
100 mDepthStencilDSView = NULL;
101 }
102
daniel@transgaming.come0970472012-11-28 21:05:07 +0000103 if (mQuadVB)
104 {
105 mQuadVB->Release();
106 mQuadVB = NULL;
107 }
108
109 if (mPassThroughSampler)
110 {
111 mPassThroughSampler->Release();
112 mPassThroughSampler = NULL;
113 }
114
115 if (mPassThroughIL)
116 {
117 mPassThroughIL->Release();
118 mPassThroughIL = NULL;
119 }
120
121 if (mPassThroughVS)
122 {
123 mPassThroughVS->Release();
124 mPassThroughVS = NULL;
125 }
126
127 if (mPassThroughPS)
128 {
129 mPassThroughPS->Release();
130 mPassThroughPS = NULL;
131 }
132
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000133 if (!mAppCreatedShareHandle)
134 {
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000135 mShareHandle = NULL;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000136 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000137}
138
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000139void SwapChain11::releaseOffscreenTexture()
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000140{
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000141 if (mOffscreenTexture)
142 {
143 mOffscreenTexture->Release();
144 mOffscreenTexture = NULL;
145 }
146
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000147 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000148 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000149 mOffscreenRTView->Release();
150 mOffscreenRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000151 }
152
daniel@transgaming.come0970472012-11-28 21:05:07 +0000153 if (mOffscreenSRView)
154 {
155 mOffscreenSRView->Release();
156 mOffscreenSRView = NULL;
157 }
158
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000159 if (mDepthStencilTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000160 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000161 mDepthStencilTexture->Release();
162 mDepthStencilTexture = NULL;
163 }
164
165 if (mDepthStencilDSView)
166 {
167 mDepthStencilDSView->Release();
168 mDepthStencilDSView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000169 }
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000170}
171
172EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
173{
174 ID3D11Device *device = mRenderer->getDevice();
175
176 ASSERT(device != NULL);
177
178 // D3D11 does not allow zero size textures
179 ASSERT(backbufferWidth >= 1);
180 ASSERT(backbufferHeight >= 1);
181
182 // Preserve the render target content
183 ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
184 if (previousOffscreenTexture)
185 {
186 previousOffscreenTexture->AddRef();
187 }
188 const int previousWidth = mWidth;
189 const int previousHeight = mHeight;
190
191 releaseOffscreenTexture();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000192
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000193 // If the app passed in a share handle, open the resource
194 // See EGL_ANGLE_d3d_share_handle_client_buffer
195 if (mAppCreatedShareHandle)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000196 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000197 ID3D11Resource *tempResource11;
198 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000199
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000200 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000201 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000202 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
203 release();
204 return EGL_BAD_PARAMETER;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000205 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000206
207 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
208 tempResource11->Release();
209
210 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000211 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000212 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
213 release();
214 return EGL_BAD_PARAMETER;
215 }
216
217 // Validate offscreen texture parameters
218 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
219 mOffscreenTexture->GetDesc(&offscreenTextureDesc);
220
221 if (offscreenTextureDesc.Width != (UINT)backbufferWidth
222 || offscreenTextureDesc.Height != (UINT)backbufferHeight
223 || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
224 || offscreenTextureDesc.MipLevels != 1
225 || offscreenTextureDesc.ArraySize != 1)
226 {
227 ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
228 release();
229 return EGL_BAD_PARAMETER;
230 }
231 }
232 else
233 {
234 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
235
236 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
237 offscreenTextureDesc.Width = backbufferWidth;
238 offscreenTextureDesc.Height = backbufferHeight;
239 offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
240 offscreenTextureDesc.MipLevels = 1;
241 offscreenTextureDesc.ArraySize = 1;
242 offscreenTextureDesc.SampleDesc.Count = 1;
243 offscreenTextureDesc.SampleDesc.Quality = 0;
244 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
245 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
246 offscreenTextureDesc.CPUAccessFlags = 0;
247 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
248
249 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
250
251 if (FAILED(result))
252 {
253 ERR("Could not create offscreen texture: %08lX", result);
254 release();
255
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000256 if (d3d11::isDeviceLostError(result))
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000257 {
258 return EGL_CONTEXT_LOST;
259 }
260 else
261 {
262 return EGL_BAD_ALLOC;
263 }
264 }
265
266 d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
267
268 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
269 if (useSharedResource)
270 {
271 IDXGIResource *offscreenTextureResource = NULL;
272 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
273
274 // Fall back to no share handle on failure
275 if (FAILED(result))
276 {
277 ERR("Could not query offscreen texture resource: %08lX", result);
278 }
279 else
280 {
281 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
282
283 if (FAILED(result))
284 {
285 mShareHandle = NULL;
286 ERR("Could not get offscreen texture shared handle: %08lX", result);
287 }
288 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000289 }
290 }
291
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000292 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
293
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000294 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000295 d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000296
daniel@transgaming.come0970472012-11-28 21:05:07 +0000297 result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
298 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000299 d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000300
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000301 if (mDepthBufferFormat != GL_NONE)
302 {
303 D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
304 depthStencilDesc.Width = backbufferWidth;
305 depthStencilDesc.Height = backbufferHeight;
306 depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
307 depthStencilDesc.MipLevels = 1;
308 depthStencilDesc.ArraySize = 1;
309 depthStencilDesc.SampleDesc.Count = 1;
310 depthStencilDesc.SampleDesc.Quality = 0;
311 depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
312 depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
313 depthStencilDesc.CPUAccessFlags = 0;
314 depthStencilDesc.MiscFlags = 0;
315
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000316 result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000317 if (FAILED(result))
318 {
319 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
320 release();
321
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000322 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000323 {
324 return EGL_CONTEXT_LOST;
325 }
326 else
327 {
328 return EGL_BAD_ALLOC;
329 }
330 }
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000331 d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000332
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000333 result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000334 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000335 d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000336 }
337
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000338 mWidth = backbufferWidth;
339 mHeight = backbufferHeight;
340
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000341 if (previousOffscreenTexture != NULL)
342 {
343 D3D11_BOX sourceBox = {0};
344 sourceBox.left = 0;
345 sourceBox.right = std::min(previousWidth, mWidth);
346 sourceBox.top = std::max(previousHeight - mHeight, 0);
347 sourceBox.bottom = previousHeight;
348 sourceBox.front = 0;
349 sourceBox.back = 1;
350
351 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
352 const int yoffset = std::max(mHeight - previousHeight, 0);
353 deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
354
355 previousOffscreenTexture->Release();
356
357 if (mSwapChain)
358 {
359 swapRect(0, 0, mWidth, mHeight);
360 }
361 }
362
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000363 return EGL_SUCCESS;
364}
365
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000366EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
367{
368 ID3D11Device *device = mRenderer->getDevice();
369
370 if (device == NULL)
371 {
372 return EGL_BAD_ACCESS;
373 }
374
375 // Can only call resize if we have already created our swap buffer and resources
376 ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
377
378 if (mBackBufferTexture)
379 {
380 mBackBufferTexture->Release();
381 mBackBufferTexture = NULL;
382 }
383
384 if (mBackBufferRTView)
385 {
386 mBackBufferRTView->Release();
387 mBackBufferRTView = NULL;
388 }
389
390 // Resize swap chain
391 DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
392 HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
393
394 if (FAILED(result))
395 {
396 ERR("Error resizing swap chain buffers: 0x%08X", result);
397 release();
398
399 if (d3d11::isDeviceLostError(result))
400 {
401 return EGL_CONTEXT_LOST;
402 }
403 else
404 {
405 return EGL_BAD_ALLOC;
406 }
407 }
408
409 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
410 ASSERT(SUCCEEDED(result));
411 if (SUCCEEDED(result))
412 {
413 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
414 }
415
416 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
417 ASSERT(SUCCEEDED(result));
418 if (SUCCEEDED(result))
419 {
420 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
421 }
422
423 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
424}
425
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000426EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
427{
428 ID3D11Device *device = mRenderer->getDevice();
429
430 if (device == NULL)
431 {
432 return EGL_BAD_ACCESS;
433 }
434
435 // Release specific resources to free up memory for the new render target, while the
436 // old render target still exists for the purpose of preserving its contents.
437 if (mSwapChain)
438 {
439 mSwapChain->Release();
440 mSwapChain = NULL;
441 }
442
443 if (mBackBufferTexture)
444 {
445 mBackBufferTexture->Release();
446 mBackBufferTexture = NULL;
447 }
448
449 if (mBackBufferRTView)
450 {
451 mBackBufferRTView->Release();
452 mBackBufferRTView = NULL;
453 }
454
455 mSwapInterval = static_cast<unsigned int>(swapInterval);
456 if (mSwapInterval > 4)
457 {
458 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
459 return EGL_BAD_PARAMETER;
460 }
461
462 if (mWindow)
463 {
464 // We cannot create a swap chain for an HWND that is owned by a different process
465 DWORD currentProcessId = GetCurrentProcessId();
466 DWORD wndProcessId;
467 GetWindowThreadProcessId(mWindow, &wndProcessId);
468
469 if (currentProcessId != wndProcessId)
470 {
471 ERR("Could not create swap chain, window owned by different process");
472 release();
473 return EGL_BAD_NATIVE_WINDOW;
474 }
475
476 IDXGIFactory *factory = mRenderer->getDxgiFactory();
477
478 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
479 swapChainDesc.BufferCount = 2;
480 swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
481 swapChainDesc.BufferDesc.Width = backbufferWidth;
482 swapChainDesc.BufferDesc.Height = backbufferHeight;
483 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
484 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
485 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
486 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
487 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
488 swapChainDesc.Flags = 0;
489 swapChainDesc.OutputWindow = mWindow;
490 swapChainDesc.SampleDesc.Count = 1;
491 swapChainDesc.SampleDesc.Quality = 0;
492 swapChainDesc.Windowed = TRUE;
493
494 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
495
496 if (FAILED(result))
497 {
498 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
499 release();
500
501 if (d3d11::isDeviceLostError(result))
502 {
503 return EGL_CONTEXT_LOST;
504 }
505 else
506 {
507 return EGL_BAD_ALLOC;
508 }
509 }
510
511 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
512 ASSERT(SUCCEEDED(result));
513 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
514
515 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
516 ASSERT(SUCCEEDED(result));
517 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
518 }
519
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000520 // If we are resizing the swap chain, we don't wish to recreate all the static resources
521 if (!mPassThroughResourcesInit)
522 {
523 mPassThroughResourcesInit = true;
524 initPassThroughResources();
525 }
526
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000527 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000528}
529
530void SwapChain11::initPassThroughResources()
531{
532 ID3D11Device *device = mRenderer->getDevice();
533
534 ASSERT(device != NULL);
535
536 // Make sure our resources are all not allocated, when we create
537 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
538 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
539
daniel@transgaming.come0970472012-11-28 21:05:07 +0000540 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000541 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000542 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
543 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
544 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
545 vbDesc.MiscFlags = 0;
546 vbDesc.StructureByteStride = 0;
547
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000548 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000549 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000550 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000551
552 D3D11_SAMPLER_DESC samplerDesc;
553 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
554 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
555 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
556 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
557 samplerDesc.MipLODBias = 0.0f;
558 samplerDesc.MaxAnisotropy = 0;
559 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
560 samplerDesc.BorderColor[0] = 0.0f;
561 samplerDesc.BorderColor[1] = 0.0f;
562 samplerDesc.BorderColor[2] = 0.0f;
563 samplerDesc.BorderColor[3] = 0.0f;
564 samplerDesc.MinLOD = 0;
565 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
566
567 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
568 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000569 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000570
571 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
572 {
573 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
574 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
575 };
576
577 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
578 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000579 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000580
581 result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
582 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000583 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000584
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +0000585 result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000586 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000587 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000588}
589
590// parameters should be validated/clamped by caller
591EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
592{
593 if (!mSwapChain)
594 {
595 return EGL_SUCCESS;
596 }
597
598 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000599 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000600
daniel@transgaming.come0970472012-11-28 21:05:07 +0000601 // Set vertices
602 D3D11_MAPPED_SUBRESOURCE mappedResource;
603 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
604 if (FAILED(result))
605 {
606 return EGL_BAD_ACCESS;
607 }
608
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000609 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000610
611 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000612 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
613 float y1 = ((mHeight - y - height) / float(mHeight)) * 2.0f - 1.0f;
614 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
615 float y2 = ((mHeight - y) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000616
617 float u1 = x / float(mWidth);
618 float v1 = y / float(mHeight);
619 float u2 = (x + width) / float(mWidth);
620 float v2 = (y + height) / float(mHeight);
621
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000622 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
623 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
624 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
625 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000626
627 deviceContext->Unmap(mQuadVB, 0);
628
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000629 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000630 static UINT startIdx = 0;
631 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
632
633 // Apply state
634 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
635
636 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
637 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
638
639 deviceContext->RSSetState(NULL);
640
641 // Apply shaders
642 deviceContext->IASetInputLayout(mPassThroughIL);
643 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
644 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
645 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000646 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000647
648 // Apply render targets
649 deviceContext->OMSetRenderTargets(1, &mBackBufferRTView, NULL);
650
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000651 // Set the viewport
652 D3D11_VIEWPORT viewport;
653 viewport.TopLeftX = 0;
654 viewport.TopLeftY = 0;
655 viewport.Width = mWidth;
656 viewport.Height = mHeight;
657 viewport.MinDepth = 0.0f;
658 viewport.MaxDepth = 1.0f;
659 deviceContext->RSSetViewports(1, &viewport);
660
daniel@transgaming.come0970472012-11-28 21:05:07 +0000661 // Apply textures
662 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
663 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
664
665 // Draw
666 deviceContext->Draw(4, 0);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000667 result = mSwapChain->Present(mSwapInterval, 0);
668
669 if (result == DXGI_ERROR_DEVICE_REMOVED)
670 {
671 HRESULT removedReason = device->GetDeviceRemovedReason();
672 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
673 return EGL_CONTEXT_LOST;
674 }
675 else if (result == DXGI_ERROR_DEVICE_RESET)
676 {
677 ERR("Present failed: the D3D11 device was reset from a bad command.");
678 return EGL_CONTEXT_LOST;
679 }
680 else if (FAILED(result))
681 {
682 ERR("Present failed with error code 0x%08X", result);
683 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000684
685 // Unbind
686 static ID3D11ShaderResourceView *const nullSRV = NULL;
687 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
688
689 static ID3D11RenderTargetView *const nullRTV = NULL;
690 deviceContext->OMSetRenderTargets(1, &nullRTV, NULL);
691
daniel@transgaming.come0970472012-11-28 21:05:07 +0000692 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000693
694 return EGL_SUCCESS;
695}
696
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000697// Increments refcount on texture.
698// caller must Release() the returned texture
699ID3D11Texture2D *SwapChain11::getOffscreenTexture()
700{
701 if (mOffscreenTexture)
702 {
703 mOffscreenTexture->AddRef();
704 }
705
706 return mOffscreenTexture;
707}
708
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000709// Increments refcount on view.
710// caller must Release() the returned view
711ID3D11RenderTargetView *SwapChain11::getRenderTarget()
712{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000713 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000714 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000715 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000716 }
717
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000718 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000719}
720
721// Increments refcount on view.
722// caller must Release() the returned view
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000723ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
724{
725 if (mOffscreenSRView)
726 {
727 mOffscreenSRView->AddRef();
728 }
729
730 return mOffscreenSRView;
731}
732
733// Increments refcount on view.
734// caller must Release() the returned view
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000735ID3D11DepthStencilView *SwapChain11::getDepthStencil()
736{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000737 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000738 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000739 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000740 }
741
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000742 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000743}
744
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000745ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
746{
747 if (mDepthStencilTexture)
748 {
749 mDepthStencilTexture->AddRef();
750 }
751
752 return mDepthStencilTexture;
753}
754
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000755SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
756{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000757 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000758 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000759}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000760
761}