blob: 846e53ae64fc62a6ccf2d380cf70efdcea0ca1b0 [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//
daniel@transgaming.comed36abd2013-01-11 21:15:58 +00003// Copyright (c) 2012-2013 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
10#include "libGLESv2/renderer/SwapChain11.h"
11
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000012#include "libGLESv2/renderer/renderer11_utils.h"
13#include "libGLESv2/renderer/Renderer11.h"
daniel@transgaming.com8dc8e272013-01-11 04:10:45 +000014#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +000015#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
daniel@transgaming.come0970472012-11-28 21:05:07 +000016
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000017namespace rx
18{
19
20SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
21 GLenum backBufferFormat, GLenum depthBufferFormat)
22 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
23{
24 mSwapChain = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000025 mBackBufferTexture = NULL;
26 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000027 mOffscreenTexture = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000028 mOffscreenRTView = NULL;
daniel@transgaming.come0970472012-11-28 21:05:07 +000029 mOffscreenSRView = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000030 mDepthStencilTexture = NULL;
31 mDepthStencilDSView = NULL;
daniel@transgaming.comf06e5392013-01-11 21:15:50 +000032 mQuadVB = NULL;
33 mPassThroughSampler = NULL;
34 mPassThroughIL = NULL;
35 mPassThroughVS = NULL;
36 mPassThroughPS = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000037 mWidth = -1;
38 mHeight = -1;
shannon.woods@transgaming.comad74a4b2013-02-28 23:04:09 +000039 mSwapInterval = 0;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000040 mAppCreatedShareHandle = mShareHandle != NULL;
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +000041 mPassThroughResourcesInit = false;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000042}
43
44SwapChain11::~SwapChain11()
45{
46 release();
47}
48
49void SwapChain11::release()
50{
51 if (mSwapChain)
52 {
53 mSwapChain->Release();
54 mSwapChain = NULL;
55 }
56
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000057 if (mBackBufferTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000058 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000059 mBackBufferTexture->Release();
60 mBackBufferTexture = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000061 }
62
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000063 if (mBackBufferRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000064 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000065 mBackBufferRTView->Release();
66 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000067 }
68
69 if (mOffscreenTexture)
70 {
71 mOffscreenTexture->Release();
72 mOffscreenTexture = NULL;
73 }
74
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000075 if (mOffscreenRTView)
76 {
77 mOffscreenRTView->Release();
78 mOffscreenRTView = NULL;
79 }
80
daniel@transgaming.come0970472012-11-28 21:05:07 +000081 if (mOffscreenSRView)
82 {
83 mOffscreenSRView->Release();
84 mOffscreenSRView = NULL;
85 }
86
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000087 if (mDepthStencilTexture)
88 {
89 mDepthStencilTexture->Release();
90 mDepthStencilTexture = NULL;
91 }
92
93 if (mDepthStencilDSView)
94 {
95 mDepthStencilDSView->Release();
96 mDepthStencilDSView = NULL;
97 }
98
daniel@transgaming.come0970472012-11-28 21:05:07 +000099 if (mQuadVB)
100 {
101 mQuadVB->Release();
102 mQuadVB = NULL;
103 }
104
105 if (mPassThroughSampler)
106 {
107 mPassThroughSampler->Release();
108 mPassThroughSampler = NULL;
109 }
110
111 if (mPassThroughIL)
112 {
113 mPassThroughIL->Release();
114 mPassThroughIL = NULL;
115 }
116
117 if (mPassThroughVS)
118 {
119 mPassThroughVS->Release();
120 mPassThroughVS = NULL;
121 }
122
123 if (mPassThroughPS)
124 {
125 mPassThroughPS->Release();
126 mPassThroughPS = NULL;
127 }
128
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000129 if (!mAppCreatedShareHandle)
130 {
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000131 mShareHandle = NULL;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000132 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000133}
134
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000135void SwapChain11::releaseOffscreenTexture()
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000136{
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000137 if (mOffscreenTexture)
138 {
139 mOffscreenTexture->Release();
140 mOffscreenTexture = NULL;
141 }
142
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000143 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000144 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000145 mOffscreenRTView->Release();
146 mOffscreenRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000147 }
148
daniel@transgaming.come0970472012-11-28 21:05:07 +0000149 if (mOffscreenSRView)
150 {
151 mOffscreenSRView->Release();
152 mOffscreenSRView = NULL;
153 }
154
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000155 if (mDepthStencilTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000156 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000157 mDepthStencilTexture->Release();
158 mDepthStencilTexture = NULL;
159 }
160
161 if (mDepthStencilDSView)
162 {
163 mDepthStencilDSView->Release();
164 mDepthStencilDSView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000165 }
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000166}
167
168EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
169{
170 ID3D11Device *device = mRenderer->getDevice();
171
172 ASSERT(device != NULL);
173
174 // D3D11 does not allow zero size textures
175 ASSERT(backbufferWidth >= 1);
176 ASSERT(backbufferHeight >= 1);
177
178 // Preserve the render target content
179 ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
180 if (previousOffscreenTexture)
181 {
182 previousOffscreenTexture->AddRef();
183 }
184 const int previousWidth = mWidth;
185 const int previousHeight = mHeight;
186
187 releaseOffscreenTexture();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000188
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000189 // If the app passed in a share handle, open the resource
190 // See EGL_ANGLE_d3d_share_handle_client_buffer
191 if (mAppCreatedShareHandle)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000192 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000193 ID3D11Resource *tempResource11;
194 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000195
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000196 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000197 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000198 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
199 release();
200 return EGL_BAD_PARAMETER;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000201 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000202
203 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
204 tempResource11->Release();
205
206 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000207 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000208 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
209 release();
210 return EGL_BAD_PARAMETER;
211 }
212
213 // Validate offscreen texture parameters
214 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
215 mOffscreenTexture->GetDesc(&offscreenTextureDesc);
216
217 if (offscreenTextureDesc.Width != (UINT)backbufferWidth
218 || offscreenTextureDesc.Height != (UINT)backbufferHeight
219 || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
220 || offscreenTextureDesc.MipLevels != 1
221 || offscreenTextureDesc.ArraySize != 1)
222 {
223 ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
224 release();
225 return EGL_BAD_PARAMETER;
226 }
227 }
228 else
229 {
230 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
231
232 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
233 offscreenTextureDesc.Width = backbufferWidth;
234 offscreenTextureDesc.Height = backbufferHeight;
235 offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
236 offscreenTextureDesc.MipLevels = 1;
237 offscreenTextureDesc.ArraySize = 1;
238 offscreenTextureDesc.SampleDesc.Count = 1;
239 offscreenTextureDesc.SampleDesc.Quality = 0;
240 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
241 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
242 offscreenTextureDesc.CPUAccessFlags = 0;
243 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
244
245 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
246
247 if (FAILED(result))
248 {
249 ERR("Could not create offscreen texture: %08lX", result);
250 release();
251
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000252 if (d3d11::isDeviceLostError(result))
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000253 {
254 return EGL_CONTEXT_LOST;
255 }
256 else
257 {
258 return EGL_BAD_ALLOC;
259 }
260 }
261
262 d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
263
264 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
265 if (useSharedResource)
266 {
267 IDXGIResource *offscreenTextureResource = NULL;
268 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
269
270 // Fall back to no share handle on failure
271 if (FAILED(result))
272 {
273 ERR("Could not query offscreen texture resource: %08lX", result);
274 }
275 else
276 {
277 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
278
279 if (FAILED(result))
280 {
281 mShareHandle = NULL;
282 ERR("Could not get offscreen texture shared handle: %08lX", result);
283 }
284 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000285 }
286 }
287
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000288 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
289
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000290 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000291 d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000292
daniel@transgaming.come0970472012-11-28 21:05:07 +0000293 result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
294 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000295 d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000296
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000297 if (mDepthBufferFormat != GL_NONE)
298 {
299 D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
300 depthStencilDesc.Width = backbufferWidth;
301 depthStencilDesc.Height = backbufferHeight;
302 depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
303 depthStencilDesc.MipLevels = 1;
304 depthStencilDesc.ArraySize = 1;
305 depthStencilDesc.SampleDesc.Count = 1;
306 depthStencilDesc.SampleDesc.Quality = 0;
307 depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
308 depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
309 depthStencilDesc.CPUAccessFlags = 0;
310 depthStencilDesc.MiscFlags = 0;
311
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000312 result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000313 if (FAILED(result))
314 {
315 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
316 release();
317
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000318 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000319 {
320 return EGL_CONTEXT_LOST;
321 }
322 else
323 {
324 return EGL_BAD_ALLOC;
325 }
326 }
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000327 d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000328
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000329 result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000330 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000331 d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000332 }
333
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000334 mWidth = backbufferWidth;
335 mHeight = backbufferHeight;
336
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000337 if (previousOffscreenTexture != NULL)
338 {
339 D3D11_BOX sourceBox = {0};
340 sourceBox.left = 0;
341 sourceBox.right = std::min(previousWidth, mWidth);
342 sourceBox.top = std::max(previousHeight - mHeight, 0);
343 sourceBox.bottom = previousHeight;
344 sourceBox.front = 0;
345 sourceBox.back = 1;
346
347 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
348 const int yoffset = std::max(mHeight - previousHeight, 0);
349 deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
350
351 previousOffscreenTexture->Release();
352
353 if (mSwapChain)
354 {
355 swapRect(0, 0, mWidth, mHeight);
356 }
357 }
358
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000359 return EGL_SUCCESS;
360}
361
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000362EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
363{
364 ID3D11Device *device = mRenderer->getDevice();
365
366 if (device == NULL)
367 {
368 return EGL_BAD_ACCESS;
369 }
370
371 // Can only call resize if we have already created our swap buffer and resources
372 ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
373
374 if (mBackBufferTexture)
375 {
376 mBackBufferTexture->Release();
377 mBackBufferTexture = NULL;
378 }
379
380 if (mBackBufferRTView)
381 {
382 mBackBufferRTView->Release();
383 mBackBufferRTView = NULL;
384 }
385
386 // Resize swap chain
387 DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
388 HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
389
390 if (FAILED(result))
391 {
392 ERR("Error resizing swap chain buffers: 0x%08X", result);
393 release();
394
395 if (d3d11::isDeviceLostError(result))
396 {
397 return EGL_CONTEXT_LOST;
398 }
399 else
400 {
401 return EGL_BAD_ALLOC;
402 }
403 }
404
405 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
406 ASSERT(SUCCEEDED(result));
407 if (SUCCEEDED(result))
408 {
409 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
410 }
411
412 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
413 ASSERT(SUCCEEDED(result));
414 if (SUCCEEDED(result))
415 {
416 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
417 }
418
419 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
420}
421
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000422EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
423{
424 ID3D11Device *device = mRenderer->getDevice();
425
426 if (device == NULL)
427 {
428 return EGL_BAD_ACCESS;
429 }
430
431 // Release specific resources to free up memory for the new render target, while the
432 // old render target still exists for the purpose of preserving its contents.
433 if (mSwapChain)
434 {
435 mSwapChain->Release();
436 mSwapChain = NULL;
437 }
438
439 if (mBackBufferTexture)
440 {
441 mBackBufferTexture->Release();
442 mBackBufferTexture = NULL;
443 }
444
445 if (mBackBufferRTView)
446 {
447 mBackBufferRTView->Release();
448 mBackBufferRTView = NULL;
449 }
450
451 mSwapInterval = static_cast<unsigned int>(swapInterval);
452 if (mSwapInterval > 4)
453 {
454 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
455 return EGL_BAD_PARAMETER;
456 }
457
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +0000458 // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
459 if (backbufferWidth < 1 || backbufferHeight < 1)
460 {
461 releaseOffscreenTexture();
462 return EGL_SUCCESS;
463 }
464
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000465 if (mWindow)
466 {
467 // We cannot create a swap chain for an HWND that is owned by a different process
468 DWORD currentProcessId = GetCurrentProcessId();
469 DWORD wndProcessId;
470 GetWindowThreadProcessId(mWindow, &wndProcessId);
471
472 if (currentProcessId != wndProcessId)
473 {
474 ERR("Could not create swap chain, window owned by different process");
475 release();
476 return EGL_BAD_NATIVE_WINDOW;
477 }
478
479 IDXGIFactory *factory = mRenderer->getDxgiFactory();
480
481 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
482 swapChainDesc.BufferCount = 2;
483 swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
484 swapChainDesc.BufferDesc.Width = backbufferWidth;
485 swapChainDesc.BufferDesc.Height = backbufferHeight;
486 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
487 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
488 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
489 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
490 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
491 swapChainDesc.Flags = 0;
492 swapChainDesc.OutputWindow = mWindow;
493 swapChainDesc.SampleDesc.Count = 1;
494 swapChainDesc.SampleDesc.Quality = 0;
495 swapChainDesc.Windowed = TRUE;
496
497 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
498
499 if (FAILED(result))
500 {
501 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
502 release();
503
504 if (d3d11::isDeviceLostError(result))
505 {
506 return EGL_CONTEXT_LOST;
507 }
508 else
509 {
510 return EGL_BAD_ALLOC;
511 }
512 }
513
514 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
515 ASSERT(SUCCEEDED(result));
516 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
517
518 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
519 ASSERT(SUCCEEDED(result));
520 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
521 }
522
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000523 // If we are resizing the swap chain, we don't wish to recreate all the static resources
524 if (!mPassThroughResourcesInit)
525 {
526 mPassThroughResourcesInit = true;
527 initPassThroughResources();
528 }
529
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000530 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000531}
532
533void SwapChain11::initPassThroughResources()
534{
535 ID3D11Device *device = mRenderer->getDevice();
536
537 ASSERT(device != NULL);
538
539 // Make sure our resources are all not allocated, when we create
540 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
541 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
542
daniel@transgaming.come0970472012-11-28 21:05:07 +0000543 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000544 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000545 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
546 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
547 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
548 vbDesc.MiscFlags = 0;
549 vbDesc.StructureByteStride = 0;
550
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000551 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000552 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000553 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000554
555 D3D11_SAMPLER_DESC samplerDesc;
556 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
557 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
558 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
559 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
560 samplerDesc.MipLODBias = 0.0f;
561 samplerDesc.MaxAnisotropy = 0;
562 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
563 samplerDesc.BorderColor[0] = 0.0f;
564 samplerDesc.BorderColor[1] = 0.0f;
565 samplerDesc.BorderColor[2] = 0.0f;
566 samplerDesc.BorderColor[3] = 0.0f;
567 samplerDesc.MinLOD = 0;
568 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
569
570 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
571 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000572 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000573
574 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
575 {
576 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
577 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
578 };
579
580 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
581 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000582 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000583
584 result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
585 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000586 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000587
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +0000588 result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000589 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000590 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000591}
592
593// parameters should be validated/clamped by caller
594EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
595{
596 if (!mSwapChain)
597 {
598 return EGL_SUCCESS;
599 }
600
601 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000602 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000603
daniel@transgaming.come0970472012-11-28 21:05:07 +0000604 // Set vertices
605 D3D11_MAPPED_SUBRESOURCE mappedResource;
606 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
607 if (FAILED(result))
608 {
609 return EGL_BAD_ACCESS;
610 }
611
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000612 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000613
614 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000615 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000616 float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000617 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000618 float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000619
620 float u1 = x / float(mWidth);
621 float v1 = y / float(mHeight);
622 float u2 = (x + width) / float(mWidth);
623 float v2 = (y + height) / float(mHeight);
624
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000625 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
626 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
627 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
628 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000629
630 deviceContext->Unmap(mQuadVB, 0);
631
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000632 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000633 static UINT startIdx = 0;
634 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
635
636 // Apply state
637 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
638
639 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
640 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
641
642 deviceContext->RSSetState(NULL);
643
644 // Apply shaders
645 deviceContext->IASetInputLayout(mPassThroughIL);
646 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
647 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
648 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000649 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000650
651 // Apply render targets
652 deviceContext->OMSetRenderTargets(1, &mBackBufferRTView, NULL);
653
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000654 // Set the viewport
655 D3D11_VIEWPORT viewport;
656 viewport.TopLeftX = 0;
657 viewport.TopLeftY = 0;
658 viewport.Width = mWidth;
659 viewport.Height = mHeight;
660 viewport.MinDepth = 0.0f;
661 viewport.MaxDepth = 1.0f;
662 deviceContext->RSSetViewports(1, &viewport);
663
daniel@transgaming.come0970472012-11-28 21:05:07 +0000664 // Apply textures
665 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
666 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
667
668 // Draw
669 deviceContext->Draw(4, 0);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000670 result = mSwapChain->Present(mSwapInterval, 0);
671
672 if (result == DXGI_ERROR_DEVICE_REMOVED)
673 {
674 HRESULT removedReason = device->GetDeviceRemovedReason();
675 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
676 return EGL_CONTEXT_LOST;
677 }
678 else if (result == DXGI_ERROR_DEVICE_RESET)
679 {
680 ERR("Present failed: the D3D11 device was reset from a bad command.");
681 return EGL_CONTEXT_LOST;
682 }
683 else if (FAILED(result))
684 {
685 ERR("Present failed with error code 0x%08X", result);
686 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000687
688 // Unbind
689 static ID3D11ShaderResourceView *const nullSRV = NULL;
690 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
691
692 static ID3D11RenderTargetView *const nullRTV = NULL;
693 deviceContext->OMSetRenderTargets(1, &nullRTV, NULL);
694
daniel@transgaming.come0970472012-11-28 21:05:07 +0000695 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000696
697 return EGL_SUCCESS;
698}
699
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000700// Increments refcount on texture.
701// caller must Release() the returned texture
702ID3D11Texture2D *SwapChain11::getOffscreenTexture()
703{
704 if (mOffscreenTexture)
705 {
706 mOffscreenTexture->AddRef();
707 }
708
709 return mOffscreenTexture;
710}
711
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000712// Increments refcount on view.
713// caller must Release() the returned view
714ID3D11RenderTargetView *SwapChain11::getRenderTarget()
715{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000716 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000717 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000718 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000719 }
720
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000721 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000722}
723
724// Increments refcount on view.
725// caller must Release() the returned view
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000726ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
727{
728 if (mOffscreenSRView)
729 {
730 mOffscreenSRView->AddRef();
731 }
732
733 return mOffscreenSRView;
734}
735
736// Increments refcount on view.
737// caller must Release() the returned view
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000738ID3D11DepthStencilView *SwapChain11::getDepthStencil()
739{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000740 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000741 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000742 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000743 }
744
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000745 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000746}
747
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000748ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
749{
750 if (mDepthStencilTexture)
751 {
752 mDepthStencilTexture->AddRef();
753 }
754
755 return mDepthStencilTexture;
756}
757
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000758SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
759{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000760 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000761 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000762}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000763
764}