blob: be9489d645bf82ca9d65fdd45426b375b89f27ef [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"
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +000013#include "libGLESv2/renderer/formatutils11.h"
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000014#include "libGLESv2/renderer/Renderer11.h"
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +000015#include "libGLESv2/renderer/shaders/compiled/passthrough2d11vs.h"
16#include "libGLESv2/renderer/shaders/compiled/passthroughrgba2d11ps.h"
daniel@transgaming.come0970472012-11-28 21:05:07 +000017
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000018namespace rx
19{
20
21SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
22 GLenum backBufferFormat, GLenum depthBufferFormat)
23 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
24{
25 mSwapChain = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000026 mBackBufferTexture = NULL;
27 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000028 mOffscreenTexture = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000029 mOffscreenRTView = NULL;
daniel@transgaming.come0970472012-11-28 21:05:07 +000030 mOffscreenSRView = NULL;
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000031 mDepthStencilTexture = NULL;
32 mDepthStencilDSView = NULL;
daniel@transgaming.comf06e5392013-01-11 21:15:50 +000033 mQuadVB = NULL;
34 mPassThroughSampler = NULL;
35 mPassThroughIL = NULL;
36 mPassThroughVS = NULL;
37 mPassThroughPS = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000038 mWidth = -1;
39 mHeight = -1;
shannon.woods@transgaming.comad74a4b2013-02-28 23:04:09 +000040 mSwapInterval = 0;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000041 mAppCreatedShareHandle = mShareHandle != NULL;
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +000042 mPassThroughResourcesInit = false;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000043}
44
45SwapChain11::~SwapChain11()
46{
47 release();
48}
49
50void SwapChain11::release()
51{
52 if (mSwapChain)
53 {
54 mSwapChain->Release();
55 mSwapChain = NULL;
56 }
57
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000058 if (mBackBufferTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000059 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000060 mBackBufferTexture->Release();
61 mBackBufferTexture = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000062 }
63
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000064 if (mBackBufferRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000065 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000066 mBackBufferRTView->Release();
67 mBackBufferRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000068 }
69
70 if (mOffscreenTexture)
71 {
72 mOffscreenTexture->Release();
73 mOffscreenTexture = NULL;
74 }
75
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000076 if (mOffscreenRTView)
77 {
78 mOffscreenRTView->Release();
79 mOffscreenRTView = NULL;
80 }
81
daniel@transgaming.come0970472012-11-28 21:05:07 +000082 if (mOffscreenSRView)
83 {
84 mOffscreenSRView->Release();
85 mOffscreenSRView = NULL;
86 }
87
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +000088 if (mDepthStencilTexture)
89 {
90 mDepthStencilTexture->Release();
91 mDepthStencilTexture = NULL;
92 }
93
94 if (mDepthStencilDSView)
95 {
96 mDepthStencilDSView->Release();
97 mDepthStencilDSView = NULL;
98 }
99
daniel@transgaming.come0970472012-11-28 21:05:07 +0000100 if (mQuadVB)
101 {
102 mQuadVB->Release();
103 mQuadVB = NULL;
104 }
105
106 if (mPassThroughSampler)
107 {
108 mPassThroughSampler->Release();
109 mPassThroughSampler = NULL;
110 }
111
112 if (mPassThroughIL)
113 {
114 mPassThroughIL->Release();
115 mPassThroughIL = NULL;
116 }
117
118 if (mPassThroughVS)
119 {
120 mPassThroughVS->Release();
121 mPassThroughVS = NULL;
122 }
123
124 if (mPassThroughPS)
125 {
126 mPassThroughPS->Release();
127 mPassThroughPS = NULL;
128 }
129
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000130 if (!mAppCreatedShareHandle)
131 {
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000132 mShareHandle = NULL;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000133 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000134}
135
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000136void SwapChain11::releaseOffscreenTexture()
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000137{
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000138 if (mOffscreenTexture)
139 {
140 mOffscreenTexture->Release();
141 mOffscreenTexture = NULL;
142 }
143
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000144 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000145 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000146 mOffscreenRTView->Release();
147 mOffscreenRTView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000148 }
149
daniel@transgaming.come0970472012-11-28 21:05:07 +0000150 if (mOffscreenSRView)
151 {
152 mOffscreenSRView->Release();
153 mOffscreenSRView = NULL;
154 }
155
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000156 if (mDepthStencilTexture)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000157 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000158 mDepthStencilTexture->Release();
159 mDepthStencilTexture = NULL;
160 }
161
162 if (mDepthStencilDSView)
163 {
164 mDepthStencilDSView->Release();
165 mDepthStencilDSView = NULL;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000166 }
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000167}
168
169EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
170{
171 ID3D11Device *device = mRenderer->getDevice();
172
173 ASSERT(device != NULL);
174
175 // D3D11 does not allow zero size textures
176 ASSERT(backbufferWidth >= 1);
177 ASSERT(backbufferHeight >= 1);
178
179 // Preserve the render target content
180 ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
181 if (previousOffscreenTexture)
182 {
183 previousOffscreenTexture->AddRef();
184 }
185 const int previousWidth = mWidth;
186 const int previousHeight = mHeight;
187
188 releaseOffscreenTexture();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000189
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000190 // If the app passed in a share handle, open the resource
191 // See EGL_ANGLE_d3d_share_handle_client_buffer
192 if (mAppCreatedShareHandle)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000193 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000194 ID3D11Resource *tempResource11;
195 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000196
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000197 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000198 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000199 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
200 release();
201 return EGL_BAD_PARAMETER;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000202 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000203
204 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
205 tempResource11->Release();
206
207 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000208 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000209 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
210 release();
211 return EGL_BAD_PARAMETER;
212 }
213
214 // Validate offscreen texture parameters
215 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
216 mOffscreenTexture->GetDesc(&offscreenTextureDesc);
217
218 if (offscreenTextureDesc.Width != (UINT)backbufferWidth
219 || offscreenTextureDesc.Height != (UINT)backbufferHeight
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000220 || offscreenTextureDesc.Format != gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion())
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000221 || offscreenTextureDesc.MipLevels != 1
222 || offscreenTextureDesc.ArraySize != 1)
223 {
224 ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
225 release();
226 return EGL_BAD_PARAMETER;
227 }
228 }
229 else
230 {
231 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
232
233 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
234 offscreenTextureDesc.Width = backbufferWidth;
235 offscreenTextureDesc.Height = backbufferHeight;
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000236 offscreenTextureDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000237 offscreenTextureDesc.MipLevels = 1;
238 offscreenTextureDesc.ArraySize = 1;
239 offscreenTextureDesc.SampleDesc.Count = 1;
240 offscreenTextureDesc.SampleDesc.Quality = 0;
241 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
242 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
243 offscreenTextureDesc.CPUAccessFlags = 0;
244 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
245
246 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
247
248 if (FAILED(result))
249 {
250 ERR("Could not create offscreen texture: %08lX", result);
251 release();
252
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000253 if (d3d11::isDeviceLostError(result))
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000254 {
255 return EGL_CONTEXT_LOST;
256 }
257 else
258 {
259 return EGL_BAD_ALLOC;
260 }
261 }
262
263 d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
264
265 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
266 if (useSharedResource)
267 {
268 IDXGIResource *offscreenTextureResource = NULL;
269 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
270
271 // Fall back to no share handle on failure
272 if (FAILED(result))
273 {
274 ERR("Could not query offscreen texture resource: %08lX", result);
275 }
276 else
277 {
278 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
279
280 if (FAILED(result))
281 {
282 mShareHandle = NULL;
283 ERR("Could not get offscreen texture shared handle: %08lX", result);
284 }
285 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000286 }
287 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000288
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000289
290 D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
291 offscreenRTVDesc.Format = gl_d3d11::GetRTVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
292 offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
293 offscreenRTVDesc.Texture2D.MipSlice = 0;
294
295 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000296 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000297 d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000298
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000299 D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
300 offscreenSRVDesc.Format = gl_d3d11::GetSRVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
301 offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
302 offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
303 offscreenSRVDesc.Texture2D.MipLevels = -1;
304
305 result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000306 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000307 d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000308
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000309 if (mDepthBufferFormat != GL_NONE)
310 {
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000311 D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
312 depthStencilTextureDesc.Width = backbufferWidth;
313 depthStencilTextureDesc.Height = backbufferHeight;
314 depthStencilTextureDesc.Format = gl_d3d11::GetTexFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion());
315 depthStencilTextureDesc.MipLevels = 1;
316 depthStencilTextureDesc.ArraySize = 1;
317 depthStencilTextureDesc.SampleDesc.Count = 1;
318 depthStencilTextureDesc.SampleDesc.Quality = 0;
319 depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
320 depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
321 depthStencilTextureDesc.CPUAccessFlags = 0;
322 depthStencilTextureDesc.MiscFlags = 0;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000323
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000324 result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000325 if (FAILED(result))
326 {
327 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
328 release();
329
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000330 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000331 {
332 return EGL_CONTEXT_LOST;
333 }
334 else
335 {
336 return EGL_BAD_ALLOC;
337 }
338 }
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000339 d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000340
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000341 D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc;
342 depthStencilDesc.Format = gl_d3d11::GetDSVFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion());
343 depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
344 depthStencilDesc.Flags = 0;
345 depthStencilDesc.Texture2D.MipSlice = 0;
346
347 result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000348 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000349 d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000350 }
351
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000352 mWidth = backbufferWidth;
353 mHeight = backbufferHeight;
354
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000355 if (previousOffscreenTexture != NULL)
356 {
357 D3D11_BOX sourceBox = {0};
358 sourceBox.left = 0;
359 sourceBox.right = std::min(previousWidth, mWidth);
360 sourceBox.top = std::max(previousHeight - mHeight, 0);
361 sourceBox.bottom = previousHeight;
362 sourceBox.front = 0;
363 sourceBox.back = 1;
364
365 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
366 const int yoffset = std::max(mHeight - previousHeight, 0);
367 deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
368
369 previousOffscreenTexture->Release();
370
371 if (mSwapChain)
372 {
373 swapRect(0, 0, mWidth, mHeight);
374 }
375 }
376
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000377 return EGL_SUCCESS;
378}
379
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000380EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
381{
382 ID3D11Device *device = mRenderer->getDevice();
383
384 if (device == NULL)
385 {
386 return EGL_BAD_ACCESS;
387 }
388
389 // Can only call resize if we have already created our swap buffer and resources
390 ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
391
392 if (mBackBufferTexture)
393 {
394 mBackBufferTexture->Release();
395 mBackBufferTexture = NULL;
396 }
397
398 if (mBackBufferRTView)
399 {
400 mBackBufferRTView->Release();
401 mBackBufferRTView = NULL;
402 }
403
404 // Resize swap chain
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000405 DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000406 HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
407
408 if (FAILED(result))
409 {
410 ERR("Error resizing swap chain buffers: 0x%08X", result);
411 release();
412
413 if (d3d11::isDeviceLostError(result))
414 {
415 return EGL_CONTEXT_LOST;
416 }
417 else
418 {
419 return EGL_BAD_ALLOC;
420 }
421 }
422
423 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
424 ASSERT(SUCCEEDED(result));
425 if (SUCCEEDED(result))
426 {
427 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
428 }
429
430 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
431 ASSERT(SUCCEEDED(result));
432 if (SUCCEEDED(result))
433 {
434 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
435 }
436
437 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
438}
439
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000440EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
441{
442 ID3D11Device *device = mRenderer->getDevice();
443
444 if (device == NULL)
445 {
446 return EGL_BAD_ACCESS;
447 }
448
449 // Release specific resources to free up memory for the new render target, while the
450 // old render target still exists for the purpose of preserving its contents.
451 if (mSwapChain)
452 {
453 mSwapChain->Release();
454 mSwapChain = NULL;
455 }
456
457 if (mBackBufferTexture)
458 {
459 mBackBufferTexture->Release();
460 mBackBufferTexture = NULL;
461 }
462
463 if (mBackBufferRTView)
464 {
465 mBackBufferRTView->Release();
466 mBackBufferRTView = NULL;
467 }
468
469 mSwapInterval = static_cast<unsigned int>(swapInterval);
470 if (mSwapInterval > 4)
471 {
472 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
473 return EGL_BAD_PARAMETER;
474 }
475
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +0000476 // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
477 if (backbufferWidth < 1 || backbufferHeight < 1)
478 {
479 releaseOffscreenTexture();
480 return EGL_SUCCESS;
481 }
482
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000483 if (mWindow)
484 {
485 // We cannot create a swap chain for an HWND that is owned by a different process
486 DWORD currentProcessId = GetCurrentProcessId();
487 DWORD wndProcessId;
488 GetWindowThreadProcessId(mWindow, &wndProcessId);
489
490 if (currentProcessId != wndProcessId)
491 {
492 ERR("Could not create swap chain, window owned by different process");
493 release();
494 return EGL_BAD_NATIVE_WINDOW;
495 }
496
497 IDXGIFactory *factory = mRenderer->getDxgiFactory();
498
499 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
500 swapChainDesc.BufferCount = 2;
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000501 swapChainDesc.BufferDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000502 swapChainDesc.BufferDesc.Width = backbufferWidth;
503 swapChainDesc.BufferDesc.Height = backbufferHeight;
504 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
505 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
506 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
507 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
508 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
509 swapChainDesc.Flags = 0;
510 swapChainDesc.OutputWindow = mWindow;
511 swapChainDesc.SampleDesc.Count = 1;
512 swapChainDesc.SampleDesc.Quality = 0;
513 swapChainDesc.Windowed = TRUE;
514
515 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
516
517 if (FAILED(result))
518 {
519 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
520 release();
521
522 if (d3d11::isDeviceLostError(result))
523 {
524 return EGL_CONTEXT_LOST;
525 }
526 else
527 {
528 return EGL_BAD_ALLOC;
529 }
530 }
531
532 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
533 ASSERT(SUCCEEDED(result));
534 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
535
536 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
537 ASSERT(SUCCEEDED(result));
538 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
539 }
540
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000541 // If we are resizing the swap chain, we don't wish to recreate all the static resources
542 if (!mPassThroughResourcesInit)
543 {
544 mPassThroughResourcesInit = true;
545 initPassThroughResources();
546 }
547
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000548 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000549}
550
551void SwapChain11::initPassThroughResources()
552{
553 ID3D11Device *device = mRenderer->getDevice();
554
555 ASSERT(device != NULL);
556
557 // Make sure our resources are all not allocated, when we create
558 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
559 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
560
daniel@transgaming.come0970472012-11-28 21:05:07 +0000561 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000562 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000563 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
564 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
565 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
566 vbDesc.MiscFlags = 0;
567 vbDesc.StructureByteStride = 0;
568
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000569 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000570 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000571 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000572
573 D3D11_SAMPLER_DESC samplerDesc;
574 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
575 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
576 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
577 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
578 samplerDesc.MipLODBias = 0.0f;
579 samplerDesc.MaxAnisotropy = 0;
580 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
581 samplerDesc.BorderColor[0] = 0.0f;
582 samplerDesc.BorderColor[1] = 0.0f;
583 samplerDesc.BorderColor[2] = 0.0f;
584 samplerDesc.BorderColor[3] = 0.0f;
585 samplerDesc.MinLOD = 0;
586 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
587
588 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
589 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000590 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000591
592 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
593 {
594 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
595 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
596 };
597
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000598 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000599 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000600 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000601
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000602 result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000603 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000604 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000605
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000606 result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000607 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000608 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000609}
610
611// parameters should be validated/clamped by caller
612EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
613{
614 if (!mSwapChain)
615 {
616 return EGL_SUCCESS;
617 }
618
619 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000620 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000621
daniel@transgaming.come0970472012-11-28 21:05:07 +0000622 // Set vertices
623 D3D11_MAPPED_SUBRESOURCE mappedResource;
624 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
625 if (FAILED(result))
626 {
627 return EGL_BAD_ACCESS;
628 }
629
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000630 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000631
632 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000633 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000634 float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000635 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000636 float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000637
638 float u1 = x / float(mWidth);
639 float v1 = y / float(mHeight);
640 float u2 = (x + width) / float(mWidth);
641 float v2 = (y + height) / float(mHeight);
642
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000643 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
644 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
645 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
646 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000647
648 deviceContext->Unmap(mQuadVB, 0);
649
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000650 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000651 static UINT startIdx = 0;
652 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
653
654 // Apply state
655 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
656
657 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
658 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
659
660 deviceContext->RSSetState(NULL);
661
662 // Apply shaders
663 deviceContext->IASetInputLayout(mPassThroughIL);
664 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
665 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
666 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000667 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000668
669 // Apply render targets
shannon.woods%transgaming.com@gtempaccount.comba2744f2013-04-13 03:33:38 +0000670 mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000671
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000672 // Set the viewport
673 D3D11_VIEWPORT viewport;
674 viewport.TopLeftX = 0;
675 viewport.TopLeftY = 0;
676 viewport.Width = mWidth;
677 viewport.Height = mHeight;
678 viewport.MinDepth = 0.0f;
679 viewport.MaxDepth = 1.0f;
680 deviceContext->RSSetViewports(1, &viewport);
681
daniel@transgaming.come0970472012-11-28 21:05:07 +0000682 // Apply textures
683 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
684 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
685
686 // Draw
687 deviceContext->Draw(4, 0);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000688 result = mSwapChain->Present(mSwapInterval, 0);
689
690 if (result == DXGI_ERROR_DEVICE_REMOVED)
691 {
692 HRESULT removedReason = device->GetDeviceRemovedReason();
693 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
694 return EGL_CONTEXT_LOST;
695 }
696 else if (result == DXGI_ERROR_DEVICE_RESET)
697 {
698 ERR("Present failed: the D3D11 device was reset from a bad command.");
699 return EGL_CONTEXT_LOST;
700 }
701 else if (FAILED(result))
702 {
703 ERR("Present failed with error code 0x%08X", result);
704 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000705
706 // Unbind
707 static ID3D11ShaderResourceView *const nullSRV = NULL;
708 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
709
shannon.woods%transgaming.com@gtempaccount.comba2744f2013-04-13 03:33:38 +0000710 mRenderer->unapplyRenderTargets();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000711 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000712
713 return EGL_SUCCESS;
714}
715
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000716// Increments refcount on texture.
717// caller must Release() the returned texture
718ID3D11Texture2D *SwapChain11::getOffscreenTexture()
719{
720 if (mOffscreenTexture)
721 {
722 mOffscreenTexture->AddRef();
723 }
724
725 return mOffscreenTexture;
726}
727
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000728// Increments refcount on view.
729// caller must Release() the returned view
730ID3D11RenderTargetView *SwapChain11::getRenderTarget()
731{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000732 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000733 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000734 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000735 }
736
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000737 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000738}
739
740// Increments refcount on view.
741// caller must Release() the returned view
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000742ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
743{
744 if (mOffscreenSRView)
745 {
746 mOffscreenSRView->AddRef();
747 }
748
749 return mOffscreenSRView;
750}
751
752// Increments refcount on view.
753// caller must Release() the returned view
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000754ID3D11DepthStencilView *SwapChain11::getDepthStencil()
755{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000756 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000757 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000758 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000759 }
760
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000761 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000762}
763
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000764ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
765{
766 if (mDepthStencilTexture)
767 {
768 mDepthStencilTexture->AddRef();
769 }
770
771 return mDepthStencilTexture;
772}
773
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000774SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
775{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000776 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000777 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000778}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000779
shannon.woods%transgaming.com@gtempaccount.com8bce3f52013-04-13 03:35:32 +0000780void SwapChain11::recreate()
781{
782 // possibly should use this method instead of reset
783}
784
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000785}