blob: 39711ba72cdefba2aa4c80f1dd5871fb57766b7a [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
139EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
140{
141 ID3D11Device *device = mRenderer->getDevice();
142
143 if (device == NULL)
144 {
145 return EGL_BAD_ACCESS;
146 }
147
148 // Release specific resources to free up memory for the new render target, while the
149 // old render target still exists for the purpose of preserving its contents.
150 if (mSwapChain)
151 {
152 mSwapChain->Release();
153 mSwapChain = NULL;
154 }
155
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000156 if (mBackBufferTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000157 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000158 mBackBufferTexture->Release();
159 mBackBufferTexture = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000160 }
161
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000162 if (mBackBufferRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000163 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000164 mBackBufferRTView->Release();
165 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000166 }
167
168 if (mOffscreenTexture)
169 {
170 mOffscreenTexture->Release();
171 mOffscreenTexture = NULL;
172 }
173
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000174 if (mOffscreenRTView) // TODO: Preserve the render target content
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000175 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000176 mOffscreenRTView->Release();
177 mOffscreenRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000178 }
179
daniel@transgaming.come0970472012-11-28 21:05:07 +0000180 if (mOffscreenSRView)
181 {
182 mOffscreenSRView->Release();
183 mOffscreenSRView = NULL;
184 }
185
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000186 if (mDepthStencilTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000187 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000188 mDepthStencilTexture->Release();
189 mDepthStencilTexture = NULL;
190 }
191
192 if (mDepthStencilDSView)
193 {
194 mDepthStencilDSView->Release();
195 mDepthStencilDSView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000196 }
197
shannon.woods@transgaming.comad74a4b2013-02-28 23:04:09 +0000198 mSwapInterval = static_cast<unsigned int>(swapInterval);
199 if (mSwapInterval > 4)
200 {
201 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
202 return EGL_BAD_PARAMETER;
203 }
204
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000205 // If the app passed in a share handle, open the resource
206 // See EGL_ANGLE_d3d_share_handle_client_buffer
207 if (mAppCreatedShareHandle)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000208 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000209 ID3D11Resource *tempResource11;
210 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000211
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000212 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000213 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000214 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
215 release();
216 return EGL_BAD_PARAMETER;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000217 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000218
219 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
220 tempResource11->Release();
221
222 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000223 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000224 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
225 release();
226 return EGL_BAD_PARAMETER;
227 }
228
229 // Validate offscreen texture parameters
230 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
231 mOffscreenTexture->GetDesc(&offscreenTextureDesc);
232
233 if (offscreenTextureDesc.Width != (UINT)backbufferWidth
234 || offscreenTextureDesc.Height != (UINT)backbufferHeight
235 || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
236 || offscreenTextureDesc.MipLevels != 1
237 || offscreenTextureDesc.ArraySize != 1)
238 {
239 ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
240 release();
241 return EGL_BAD_PARAMETER;
242 }
243 }
244 else
245 {
246 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
247
248 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
249 offscreenTextureDesc.Width = backbufferWidth;
250 offscreenTextureDesc.Height = backbufferHeight;
251 offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
252 offscreenTextureDesc.MipLevels = 1;
253 offscreenTextureDesc.ArraySize = 1;
254 offscreenTextureDesc.SampleDesc.Count = 1;
255 offscreenTextureDesc.SampleDesc.Quality = 0;
256 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
257 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
258 offscreenTextureDesc.CPUAccessFlags = 0;
259 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
260
261 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
262
263 if (FAILED(result))
264 {
265 ERR("Could not create offscreen texture: %08lX", result);
266 release();
267
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000268 if (d3d11::isDeviceLostError(result))
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000269 {
270 return EGL_CONTEXT_LOST;
271 }
272 else
273 {
274 return EGL_BAD_ALLOC;
275 }
276 }
277
278 d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
279
280 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
281 if (useSharedResource)
282 {
283 IDXGIResource *offscreenTextureResource = NULL;
284 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
285
286 // Fall back to no share handle on failure
287 if (FAILED(result))
288 {
289 ERR("Could not query offscreen texture resource: %08lX", result);
290 }
291 else
292 {
293 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
294
295 if (FAILED(result))
296 {
297 mShareHandle = NULL;
298 ERR("Could not get offscreen texture shared handle: %08lX", result);
299 }
300 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000301 }
302 }
303
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000304 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
305
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000306 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000307 d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000308
daniel@transgaming.come0970472012-11-28 21:05:07 +0000309 result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
310 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000311 d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000312
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000313 if (mWindow)
314 {
shannon.woods@transgaming.com7d4b4822013-01-25 21:52:27 +0000315 // We cannot create a swap chain for an HWND that is owned by a different process
316 DWORD currentProcessId = GetCurrentProcessId();
317 DWORD wndProcessId;
318 GetWindowThreadProcessId(mWindow, &wndProcessId);
319
320 if (currentProcessId != wndProcessId)
321 {
322 ERR("Could not create swap chain, window owned by different process");
323 release();
324 return EGL_BAD_NATIVE_WINDOW;
325 }
326
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000327 IDXGIFactory *factory = mRenderer->getDxgiFactory();
328
329 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
330 swapChainDesc.BufferCount = 2;
331 swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
daniel@transgaming.com567b9cf2012-11-28 21:04:46 +0000332 swapChainDesc.BufferDesc.Width = backbufferWidth;
333 swapChainDesc.BufferDesc.Height = backbufferHeight;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000334 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
335 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
336 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
337 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
338 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
339 swapChainDesc.Flags = 0;
340 swapChainDesc.OutputWindow = mWindow;
341 swapChainDesc.SampleDesc.Count = 1;
342 swapChainDesc.SampleDesc.Quality = 0;
343 swapChainDesc.Windowed = TRUE;
344
345 result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
346
347 if (FAILED(result))
348 {
349 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
350 release();
351
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000352 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000353 {
354 return EGL_CONTEXT_LOST;
355 }
356 else
357 {
358 return EGL_BAD_ALLOC;
359 }
360 }
361
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000362 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000363 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000364 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000365
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000366 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000367 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000368 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000369 }
370
371 if (mDepthBufferFormat != GL_NONE)
372 {
373 D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
374 depthStencilDesc.Width = backbufferWidth;
375 depthStencilDesc.Height = backbufferHeight;
376 depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
377 depthStencilDesc.MipLevels = 1;
378 depthStencilDesc.ArraySize = 1;
379 depthStencilDesc.SampleDesc.Count = 1;
380 depthStencilDesc.SampleDesc.Quality = 0;
381 depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
382 depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
383 depthStencilDesc.CPUAccessFlags = 0;
384 depthStencilDesc.MiscFlags = 0;
385
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000386 result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000387 if (FAILED(result))
388 {
389 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
390 release();
391
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000392 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000393 {
394 return EGL_CONTEXT_LOST;
395 }
396 else
397 {
398 return EGL_BAD_ALLOC;
399 }
400 }
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000401 d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000402
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000403 result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000404 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000405 d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000406 }
407
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000408 // If we are resizing the swap chain, we don't wish to recreate all the static resources
409 if (!mPassThroughResourcesInit)
410 {
411 mPassThroughResourcesInit = true;
412 initPassThroughResources();
413 }
414
415 mWidth = backbufferWidth;
416 mHeight = backbufferHeight;
417
418 return EGL_SUCCESS;
419}
420
421void SwapChain11::initPassThroughResources()
422{
423 ID3D11Device *device = mRenderer->getDevice();
424
425 ASSERT(device != NULL);
426
427 // Make sure our resources are all not allocated, when we create
428 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
429 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
430
daniel@transgaming.come0970472012-11-28 21:05:07 +0000431 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000432 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000433 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
434 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
435 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
436 vbDesc.MiscFlags = 0;
437 vbDesc.StructureByteStride = 0;
438
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000439 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000440 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000441 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000442
443 D3D11_SAMPLER_DESC samplerDesc;
444 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
445 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
446 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
447 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
448 samplerDesc.MipLODBias = 0.0f;
449 samplerDesc.MaxAnisotropy = 0;
450 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
451 samplerDesc.BorderColor[0] = 0.0f;
452 samplerDesc.BorderColor[1] = 0.0f;
453 samplerDesc.BorderColor[2] = 0.0f;
454 samplerDesc.BorderColor[3] = 0.0f;
455 samplerDesc.MinLOD = 0;
456 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
457
458 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
459 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000460 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000461
462 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
463 {
464 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
465 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
466 };
467
468 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
469 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000470 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000471
472 result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
473 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000474 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000475
shannon.woods@transgaming.com2570c342013-01-25 21:50:22 +0000476 result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000477 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000478 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000479}
480
481// parameters should be validated/clamped by caller
482EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
483{
484 if (!mSwapChain)
485 {
486 return EGL_SUCCESS;
487 }
488
489 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000490 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000491
daniel@transgaming.come0970472012-11-28 21:05:07 +0000492 // Set vertices
493 D3D11_MAPPED_SUBRESOURCE mappedResource;
494 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
495 if (FAILED(result))
496 {
497 return EGL_BAD_ACCESS;
498 }
499
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000500 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000501
502 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000503 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
504 float y1 = ((mHeight - y - height) / float(mHeight)) * 2.0f - 1.0f;
505 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
506 float y2 = ((mHeight - y) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000507
508 float u1 = x / float(mWidth);
509 float v1 = y / float(mHeight);
510 float u2 = (x + width) / float(mWidth);
511 float v2 = (y + height) / float(mHeight);
512
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000513 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
514 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
515 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
516 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000517
518 deviceContext->Unmap(mQuadVB, 0);
519
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000520 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000521 static UINT startIdx = 0;
522 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
523
524 // Apply state
525 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
526
527 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
528 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
529
530 deviceContext->RSSetState(NULL);
531
532 // Apply shaders
533 deviceContext->IASetInputLayout(mPassThroughIL);
534 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
535 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
536 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000537 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000538
539 // Apply render targets
540 deviceContext->OMSetRenderTargets(1, &mBackBufferRTView, NULL);
541
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000542 // Set the viewport
543 D3D11_VIEWPORT viewport;
544 viewport.TopLeftX = 0;
545 viewport.TopLeftY = 0;
546 viewport.Width = mWidth;
547 viewport.Height = mHeight;
548 viewport.MinDepth = 0.0f;
549 viewport.MaxDepth = 1.0f;
550 deviceContext->RSSetViewports(1, &viewport);
551
daniel@transgaming.come0970472012-11-28 21:05:07 +0000552 // Apply textures
553 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
554 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
555
556 // Draw
557 deviceContext->Draw(4, 0);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000558 result = mSwapChain->Present(mSwapInterval, 0);
559
560 if (result == DXGI_ERROR_DEVICE_REMOVED)
561 {
562 HRESULT removedReason = device->GetDeviceRemovedReason();
563 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
564 return EGL_CONTEXT_LOST;
565 }
566 else if (result == DXGI_ERROR_DEVICE_RESET)
567 {
568 ERR("Present failed: the D3D11 device was reset from a bad command.");
569 return EGL_CONTEXT_LOST;
570 }
571 else if (FAILED(result))
572 {
573 ERR("Present failed with error code 0x%08X", result);
574 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000575
576 // Unbind
577 static ID3D11ShaderResourceView *const nullSRV = NULL;
578 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
579
580 static ID3D11RenderTargetView *const nullRTV = NULL;
581 deviceContext->OMSetRenderTargets(1, &nullRTV, NULL);
582
daniel@transgaming.come0970472012-11-28 21:05:07 +0000583 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000584
585 return EGL_SUCCESS;
586}
587
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000588// Increments refcount on texture.
589// caller must Release() the returned texture
590ID3D11Texture2D *SwapChain11::getOffscreenTexture()
591{
592 if (mOffscreenTexture)
593 {
594 mOffscreenTexture->AddRef();
595 }
596
597 return mOffscreenTexture;
598}
599
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000600// Increments refcount on view.
601// caller must Release() the returned view
602ID3D11RenderTargetView *SwapChain11::getRenderTarget()
603{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000604 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000605 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000606 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000607 }
608
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000609 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000610}
611
612// Increments refcount on view.
613// caller must Release() the returned view
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000614ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
615{
616 if (mOffscreenSRView)
617 {
618 mOffscreenSRView->AddRef();
619 }
620
621 return mOffscreenSRView;
622}
623
624// Increments refcount on view.
625// caller must Release() the returned view
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000626ID3D11DepthStencilView *SwapChain11::getDepthStencil()
627{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000628 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000629 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000630 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000631 }
632
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000633 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000634}
635
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000636SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
637{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000638 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000639 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000640}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000641
642}