blob: f0f1f28f9ef271269967fa480e5720a6087348f6 [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
366EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
367{
368 ID3D11Device *device = mRenderer->getDevice();
369
370 if (device == NULL)
371 {
372 return EGL_BAD_ACCESS;
373 }
374
375 // Release specific resources to free up memory for the new render target, while the
376 // old render target still exists for the purpose of preserving its contents.
377 if (mSwapChain)
378 {
379 mSwapChain->Release();
380 mSwapChain = NULL;
381 }
382
383 if (mBackBufferTexture)
384 {
385 mBackBufferTexture->Release();
386 mBackBufferTexture = NULL;
387 }
388
389 if (mBackBufferRTView)
390 {
391 mBackBufferRTView->Release();
392 mBackBufferRTView = NULL;
393 }
394
395 mSwapInterval = static_cast<unsigned int>(swapInterval);
396 if (mSwapInterval > 4)
397 {
398 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
399 return EGL_BAD_PARAMETER;
400 }
401
402 if (mWindow)
403 {
404 // We cannot create a swap chain for an HWND that is owned by a different process
405 DWORD currentProcessId = GetCurrentProcessId();
406 DWORD wndProcessId;
407 GetWindowThreadProcessId(mWindow, &wndProcessId);
408
409 if (currentProcessId != wndProcessId)
410 {
411 ERR("Could not create swap chain, window owned by different process");
412 release();
413 return EGL_BAD_NATIVE_WINDOW;
414 }
415
416 IDXGIFactory *factory = mRenderer->getDxgiFactory();
417
418 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
419 swapChainDesc.BufferCount = 2;
420 swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
421 swapChainDesc.BufferDesc.Width = backbufferWidth;
422 swapChainDesc.BufferDesc.Height = backbufferHeight;
423 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
424 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
425 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
426 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
427 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
428 swapChainDesc.Flags = 0;
429 swapChainDesc.OutputWindow = mWindow;
430 swapChainDesc.SampleDesc.Count = 1;
431 swapChainDesc.SampleDesc.Quality = 0;
432 swapChainDesc.Windowed = TRUE;
433
434 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
435
436 if (FAILED(result))
437 {
438 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
439 release();
440
441 if (d3d11::isDeviceLostError(result))
442 {
443 return EGL_CONTEXT_LOST;
444 }
445 else
446 {
447 return EGL_BAD_ALLOC;
448 }
449 }
450
451 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
452 ASSERT(SUCCEEDED(result));
453 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
454
455 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
456 ASSERT(SUCCEEDED(result));
457 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
458 }
459
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000460 // If we are resizing the swap chain, we don't wish to recreate all the static resources
461 if (!mPassThroughResourcesInit)
462 {
463 mPassThroughResourcesInit = true;
464 initPassThroughResources();
465 }
466
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000467 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000468}
469
470void SwapChain11::initPassThroughResources()
471{
472 ID3D11Device *device = mRenderer->getDevice();
473
474 ASSERT(device != NULL);
475
476 // Make sure our resources are all not allocated, when we create
477 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
478 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
479
daniel@transgaming.come0970472012-11-28 21:05:07 +0000480 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000481 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000482 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
483 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
484 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
485 vbDesc.MiscFlags = 0;
486 vbDesc.StructureByteStride = 0;
487
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000488 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000489 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000490 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000491
492 D3D11_SAMPLER_DESC samplerDesc;
493 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
494 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
495 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
496 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
497 samplerDesc.MipLODBias = 0.0f;
498 samplerDesc.MaxAnisotropy = 0;
499 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
500 samplerDesc.BorderColor[0] = 0.0f;
501 samplerDesc.BorderColor[1] = 0.0f;
502 samplerDesc.BorderColor[2] = 0.0f;
503 samplerDesc.BorderColor[3] = 0.0f;
504 samplerDesc.MinLOD = 0;
505 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
506
507 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
508 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000509 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000510
511 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
512 {
513 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
514 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
515 };
516
517 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
518 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000519 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000520
521 result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
522 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000523 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000524
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +0000525 result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000526 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000527 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000528}
529
530// parameters should be validated/clamped by caller
531EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
532{
533 if (!mSwapChain)
534 {
535 return EGL_SUCCESS;
536 }
537
538 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000539 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000540
daniel@transgaming.come0970472012-11-28 21:05:07 +0000541 // Set vertices
542 D3D11_MAPPED_SUBRESOURCE mappedResource;
543 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
544 if (FAILED(result))
545 {
546 return EGL_BAD_ACCESS;
547 }
548
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000549 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000550
551 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000552 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
553 float y1 = ((mHeight - y - height) / float(mHeight)) * 2.0f - 1.0f;
554 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
555 float y2 = ((mHeight - y) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000556
557 float u1 = x / float(mWidth);
558 float v1 = y / float(mHeight);
559 float u2 = (x + width) / float(mWidth);
560 float v2 = (y + height) / float(mHeight);
561
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000562 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
563 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
564 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
565 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000566
567 deviceContext->Unmap(mQuadVB, 0);
568
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000569 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000570 static UINT startIdx = 0;
571 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
572
573 // Apply state
574 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
575
576 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
577 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
578
579 deviceContext->RSSetState(NULL);
580
581 // Apply shaders
582 deviceContext->IASetInputLayout(mPassThroughIL);
583 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
584 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
585 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000586 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000587
588 // Apply render targets
589 deviceContext->OMSetRenderTargets(1, &mBackBufferRTView, NULL);
590
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000591 // Set the viewport
592 D3D11_VIEWPORT viewport;
593 viewport.TopLeftX = 0;
594 viewport.TopLeftY = 0;
595 viewport.Width = mWidth;
596 viewport.Height = mHeight;
597 viewport.MinDepth = 0.0f;
598 viewport.MaxDepth = 1.0f;
599 deviceContext->RSSetViewports(1, &viewport);
600
daniel@transgaming.come0970472012-11-28 21:05:07 +0000601 // Apply textures
602 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
603 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
604
605 // Draw
606 deviceContext->Draw(4, 0);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000607 result = mSwapChain->Present(mSwapInterval, 0);
608
609 if (result == DXGI_ERROR_DEVICE_REMOVED)
610 {
611 HRESULT removedReason = device->GetDeviceRemovedReason();
612 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
613 return EGL_CONTEXT_LOST;
614 }
615 else if (result == DXGI_ERROR_DEVICE_RESET)
616 {
617 ERR("Present failed: the D3D11 device was reset from a bad command.");
618 return EGL_CONTEXT_LOST;
619 }
620 else if (FAILED(result))
621 {
622 ERR("Present failed with error code 0x%08X", result);
623 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000624
625 // Unbind
626 static ID3D11ShaderResourceView *const nullSRV = NULL;
627 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
628
629 static ID3D11RenderTargetView *const nullRTV = NULL;
630 deviceContext->OMSetRenderTargets(1, &nullRTV, NULL);
631
daniel@transgaming.come0970472012-11-28 21:05:07 +0000632 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000633
634 return EGL_SUCCESS;
635}
636
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000637// Increments refcount on texture.
638// caller must Release() the returned texture
639ID3D11Texture2D *SwapChain11::getOffscreenTexture()
640{
641 if (mOffscreenTexture)
642 {
643 mOffscreenTexture->AddRef();
644 }
645
646 return mOffscreenTexture;
647}
648
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000649// Increments refcount on view.
650// caller must Release() the returned view
651ID3D11RenderTargetView *SwapChain11::getRenderTarget()
652{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000653 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000654 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000655 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000656 }
657
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000658 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000659}
660
661// Increments refcount on view.
662// caller must Release() the returned view
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000663ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
664{
665 if (mOffscreenSRView)
666 {
667 mOffscreenSRView->AddRef();
668 }
669
670 return mOffscreenSRView;
671}
672
673// Increments refcount on view.
674// caller must Release() the returned view
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000675ID3D11DepthStencilView *SwapChain11::getDepthStencil()
676{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000677 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000678 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000679 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000680 }
681
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000682 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000683}
684
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000685SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
686{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000687 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000688 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000689}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000690
691}