blob: f8c38aba96b10414f05d5856ee18a99303d090cb [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{
Geoff Langea228632013-07-30 15:17:12 -040052 SafeRelease(mSwapChain);
53 SafeRelease(mBackBufferTexture);
54 SafeRelease(mBackBufferRTView);
55 SafeRelease(mOffscreenTexture);
56 SafeRelease(mOffscreenRTView);
57 SafeRelease(mOffscreenSRView);
58 SafeRelease(mDepthStencilTexture);
59 SafeRelease(mDepthStencilDSView);
60 SafeRelease(mQuadVB);
61 SafeRelease(mPassThroughSampler);
62 SafeRelease(mPassThroughIL);
63 SafeRelease(mPassThroughVS);
64 SafeRelease(mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +000065
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000066 if (!mAppCreatedShareHandle)
67 {
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000068 mShareHandle = NULL;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000069 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000070}
71
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +000072void SwapChain11::releaseOffscreenTexture()
daniel@transgaming.com32fdf822012-11-28 20:53:30 +000073{
Geoff Langea228632013-07-30 15:17:12 -040074 SafeRelease(mOffscreenTexture);
75 SafeRelease(mOffscreenRTView);
76 SafeRelease(mOffscreenSRView);
77 SafeRelease(mDepthStencilTexture);
78 SafeRelease(mDepthStencilDSView);
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +000079}
80
81EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
82{
83 ID3D11Device *device = mRenderer->getDevice();
84
85 ASSERT(device != NULL);
86
87 // D3D11 does not allow zero size textures
88 ASSERT(backbufferWidth >= 1);
89 ASSERT(backbufferHeight >= 1);
90
91 // Preserve the render target content
92 ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
93 if (previousOffscreenTexture)
94 {
95 previousOffscreenTexture->AddRef();
96 }
97 const int previousWidth = mWidth;
98 const int previousHeight = mHeight;
99
100 releaseOffscreenTexture();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000101
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000102 // If the app passed in a share handle, open the resource
103 // See EGL_ANGLE_d3d_share_handle_client_buffer
104 if (mAppCreatedShareHandle)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000105 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000106 ID3D11Resource *tempResource11;
107 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000108
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000109 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000110 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000111 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
112 release();
113 return EGL_BAD_PARAMETER;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000114 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000115
116 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
Geoff Langea228632013-07-30 15:17:12 -0400117 SafeRelease(tempResource11);
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000118
119 if (FAILED(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000120 {
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000121 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
122 release();
123 return EGL_BAD_PARAMETER;
124 }
125
126 // Validate offscreen texture parameters
127 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
128 mOffscreenTexture->GetDesc(&offscreenTextureDesc);
129
130 if (offscreenTextureDesc.Width != (UINT)backbufferWidth
131 || offscreenTextureDesc.Height != (UINT)backbufferHeight
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000132 || offscreenTextureDesc.Format != gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion())
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000133 || offscreenTextureDesc.MipLevels != 1
134 || offscreenTextureDesc.ArraySize != 1)
135 {
136 ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
137 release();
138 return EGL_BAD_PARAMETER;
139 }
140 }
141 else
142 {
143 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
144
145 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
146 offscreenTextureDesc.Width = backbufferWidth;
147 offscreenTextureDesc.Height = backbufferHeight;
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000148 offscreenTextureDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000149 offscreenTextureDesc.MipLevels = 1;
150 offscreenTextureDesc.ArraySize = 1;
151 offscreenTextureDesc.SampleDesc.Count = 1;
152 offscreenTextureDesc.SampleDesc.Quality = 0;
153 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
154 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
155 offscreenTextureDesc.CPUAccessFlags = 0;
156 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
157
158 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
159
160 if (FAILED(result))
161 {
162 ERR("Could not create offscreen texture: %08lX", result);
163 release();
164
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000165 if (d3d11::isDeviceLostError(result))
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000166 {
167 return EGL_CONTEXT_LOST;
168 }
169 else
170 {
171 return EGL_BAD_ALLOC;
172 }
173 }
174
175 d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
176
177 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
178 if (useSharedResource)
179 {
180 IDXGIResource *offscreenTextureResource = NULL;
181 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
182
183 // Fall back to no share handle on failure
184 if (FAILED(result))
185 {
186 ERR("Could not query offscreen texture resource: %08lX", result);
187 }
188 else
189 {
190 result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
191
192 if (FAILED(result))
193 {
194 mShareHandle = NULL;
195 ERR("Could not get offscreen texture shared handle: %08lX", result);
196 }
197 }
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000198 }
199 }
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +0000200
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000201
202 D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
203 offscreenRTVDesc.Format = gl_d3d11::GetRTVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
204 offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
205 offscreenRTVDesc.Texture2D.MipSlice = 0;
206
207 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000208 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000209 d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000210
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000211 D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
212 offscreenSRVDesc.Format = gl_d3d11::GetSRVFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
213 offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
214 offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
215 offscreenSRVDesc.Texture2D.MipLevels = -1;
216
217 result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000218 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000219 d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000220
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000221 if (mDepthBufferFormat != GL_NONE)
222 {
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000223 D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
224 depthStencilTextureDesc.Width = backbufferWidth;
225 depthStencilTextureDesc.Height = backbufferHeight;
226 depthStencilTextureDesc.Format = gl_d3d11::GetTexFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion());
227 depthStencilTextureDesc.MipLevels = 1;
228 depthStencilTextureDesc.ArraySize = 1;
229 depthStencilTextureDesc.SampleDesc.Count = 1;
230 depthStencilTextureDesc.SampleDesc.Quality = 0;
231 depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
232 depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
233 depthStencilTextureDesc.CPUAccessFlags = 0;
234 depthStencilTextureDesc.MiscFlags = 0;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000235
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000236 result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000237 if (FAILED(result))
238 {
239 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
240 release();
241
shannon.woods@transgaming.comf5f59492013-02-28 23:04:40 +0000242 if (d3d11::isDeviceLostError(result))
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000243 {
244 return EGL_CONTEXT_LOST;
245 }
246 else
247 {
248 return EGL_BAD_ALLOC;
249 }
250 }
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000251 d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000252
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000253 D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc;
254 depthStencilDesc.Format = gl_d3d11::GetDSVFormat(mDepthBufferFormat, mRenderer->getCurrentClientVersion());
255 depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
256 depthStencilDesc.Flags = 0;
257 depthStencilDesc.Texture2D.MipSlice = 0;
258
259 result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000260 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000261 d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000262 }
263
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000264 mWidth = backbufferWidth;
265 mHeight = backbufferHeight;
266
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000267 if (previousOffscreenTexture != NULL)
268 {
269 D3D11_BOX sourceBox = {0};
270 sourceBox.left = 0;
271 sourceBox.right = std::min(previousWidth, mWidth);
272 sourceBox.top = std::max(previousHeight - mHeight, 0);
273 sourceBox.bottom = previousHeight;
274 sourceBox.front = 0;
275 sourceBox.back = 1;
276
277 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
278 const int yoffset = std::max(mHeight - previousHeight, 0);
279 deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
280
Geoff Langea228632013-07-30 15:17:12 -0400281 SafeRelease(previousOffscreenTexture);
shannon.woods@transgaming.com30f52c62013-02-28 23:05:34 +0000282
283 if (mSwapChain)
284 {
285 swapRect(0, 0, mWidth, mHeight);
286 }
287 }
288
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000289 return EGL_SUCCESS;
290}
291
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000292EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
293{
294 ID3D11Device *device = mRenderer->getDevice();
295
296 if (device == NULL)
297 {
298 return EGL_BAD_ACCESS;
299 }
300
301 // Can only call resize if we have already created our swap buffer and resources
302 ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
303
Geoff Langea228632013-07-30 15:17:12 -0400304 SafeRelease(mBackBufferTexture);
305 SafeRelease(mBackBufferRTView);
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000306
307 // Resize swap chain
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000308 DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
shannon.woods@transgaming.comc71ca752013-02-28 23:06:50 +0000309 HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
310
311 if (FAILED(result))
312 {
313 ERR("Error resizing swap chain buffers: 0x%08X", result);
314 release();
315
316 if (d3d11::isDeviceLostError(result))
317 {
318 return EGL_CONTEXT_LOST;
319 }
320 else
321 {
322 return EGL_BAD_ALLOC;
323 }
324 }
325
326 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
327 ASSERT(SUCCEEDED(result));
328 if (SUCCEEDED(result))
329 {
330 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
331 }
332
333 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
334 ASSERT(SUCCEEDED(result));
335 if (SUCCEEDED(result))
336 {
337 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
338 }
339
340 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
341}
342
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000343EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
344{
345 ID3D11Device *device = mRenderer->getDevice();
346
347 if (device == NULL)
348 {
349 return EGL_BAD_ACCESS;
350 }
351
352 // Release specific resources to free up memory for the new render target, while the
353 // old render target still exists for the purpose of preserving its contents.
Geoff Langea228632013-07-30 15:17:12 -0400354 SafeRelease(mSwapChain);
355 SafeRelease(mBackBufferTexture);
356 SafeRelease(mBackBufferRTView);
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000357
358 mSwapInterval = static_cast<unsigned int>(swapInterval);
359 if (mSwapInterval > 4)
360 {
361 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
362 return EGL_BAD_PARAMETER;
363 }
364
shannon.woods@transgaming.com8c6d9df2013-02-28 23:08:57 +0000365 // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
366 if (backbufferWidth < 1 || backbufferHeight < 1)
367 {
368 releaseOffscreenTexture();
369 return EGL_SUCCESS;
370 }
371
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000372 if (mWindow)
373 {
374 // We cannot create a swap chain for an HWND that is owned by a different process
375 DWORD currentProcessId = GetCurrentProcessId();
376 DWORD wndProcessId;
377 GetWindowThreadProcessId(mWindow, &wndProcessId);
378
379 if (currentProcessId != wndProcessId)
380 {
381 ERR("Could not create swap chain, window owned by different process");
382 release();
383 return EGL_BAD_NATIVE_WINDOW;
384 }
385
386 IDXGIFactory *factory = mRenderer->getDxgiFactory();
387
388 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
389 swapChainDesc.BufferCount = 2;
shannonwoods@chromium.org755012f2013-05-30 00:09:32 +0000390 swapChainDesc.BufferDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat, mRenderer->getCurrentClientVersion());
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000391 swapChainDesc.BufferDesc.Width = backbufferWidth;
392 swapChainDesc.BufferDesc.Height = backbufferHeight;
393 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
394 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
395 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
396 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
397 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
398 swapChainDesc.Flags = 0;
399 swapChainDesc.OutputWindow = mWindow;
400 swapChainDesc.SampleDesc.Count = 1;
401 swapChainDesc.SampleDesc.Quality = 0;
402 swapChainDesc.Windowed = TRUE;
403
404 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
405
406 if (FAILED(result))
407 {
408 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
409 release();
410
411 if (d3d11::isDeviceLostError(result))
412 {
413 return EGL_CONTEXT_LOST;
414 }
415 else
416 {
417 return EGL_BAD_ALLOC;
418 }
419 }
420
421 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
422 ASSERT(SUCCEEDED(result));
423 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
424
425 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
426 ASSERT(SUCCEEDED(result));
427 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
428 }
429
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000430 // If we are resizing the swap chain, we don't wish to recreate all the static resources
431 if (!mPassThroughResourcesInit)
432 {
433 mPassThroughResourcesInit = true;
434 initPassThroughResources();
435 }
436
shannon.woods@transgaming.comae813832013-02-28 23:05:28 +0000437 return resetOffscreenTexture(backbufferWidth, backbufferHeight);
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000438}
439
440void SwapChain11::initPassThroughResources()
441{
442 ID3D11Device *device = mRenderer->getDevice();
443
444 ASSERT(device != NULL);
445
446 // Make sure our resources are all not allocated, when we create
447 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
448 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
449
daniel@transgaming.come0970472012-11-28 21:05:07 +0000450 D3D11_BUFFER_DESC vbDesc;
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000451 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000452 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
453 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
454 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
455 vbDesc.MiscFlags = 0;
456 vbDesc.StructureByteStride = 0;
457
shannon.woods@transgaming.com211fa2e2013-02-28 23:05:23 +0000458 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000459 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000460 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000461
462 D3D11_SAMPLER_DESC samplerDesc;
463 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
464 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
465 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
466 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
467 samplerDesc.MipLODBias = 0.0f;
468 samplerDesc.MaxAnisotropy = 0;
469 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
470 samplerDesc.BorderColor[0] = 0.0f;
471 samplerDesc.BorderColor[1] = 0.0f;
472 samplerDesc.BorderColor[2] = 0.0f;
473 samplerDesc.BorderColor[3] = 0.0f;
474 samplerDesc.MinLOD = 0;
475 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
476
477 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
478 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000479 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000480
481 D3D11_INPUT_ELEMENT_DESC quadLayout[] =
482 {
483 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
484 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
485 };
486
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000487 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000488 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000489 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000490
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000491 result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000492 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000493 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
daniel@transgaming.come0970472012-11-28 21:05:07 +0000494
shannonwoods@chromium.orgad8a0d32013-05-30 00:03:28 +0000495 result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000496 ASSERT(SUCCEEDED(result));
daniel@transgaming.comad3d8272013-01-11 04:11:14 +0000497 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000498}
499
500// parameters should be validated/clamped by caller
501EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
502{
503 if (!mSwapChain)
504 {
505 return EGL_SUCCESS;
506 }
507
508 ID3D11Device *device = mRenderer->getDevice();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000509 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000510
daniel@transgaming.come0970472012-11-28 21:05:07 +0000511 // Set vertices
512 D3D11_MAPPED_SUBRESOURCE mappedResource;
513 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
514 if (FAILED(result))
515 {
516 return EGL_BAD_ACCESS;
517 }
518
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000519 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000520
521 // Create a quad in homogeneous coordinates
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000522 float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000523 float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
shannon.woods@transgaming.com2ac02d52013-01-25 21:56:54 +0000524 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
shannon.woods@transgaming.com0bbb08d2013-02-28 23:09:11 +0000525 float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
daniel@transgaming.come0970472012-11-28 21:05:07 +0000526
527 float u1 = x / float(mWidth);
528 float v1 = y / float(mHeight);
529 float u2 = (x + width) / float(mWidth);
530 float v2 = (y + height) / float(mHeight);
531
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000532 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
533 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
534 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
535 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000536
537 deviceContext->Unmap(mQuadVB, 0);
538
shannon.woods@transgaming.comf3d82072013-01-25 21:50:43 +0000539 static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000540 static UINT startIdx = 0;
541 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
542
543 // Apply state
544 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
545
546 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
547 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
548
549 deviceContext->RSSetState(NULL);
550
551 // Apply shaders
552 deviceContext->IASetInputLayout(mPassThroughIL);
553 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
554 deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
555 deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000556 deviceContext->GSSetShader(NULL, NULL, 0);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000557
558 // Apply render targets
shannon.woods%transgaming.com@gtempaccount.comba2744f2013-04-13 03:33:38 +0000559 mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
daniel@transgaming.come0970472012-11-28 21:05:07 +0000560
daniel@transgaming.com9799a2f2013-01-11 04:09:27 +0000561 // Set the viewport
562 D3D11_VIEWPORT viewport;
563 viewport.TopLeftX = 0;
564 viewport.TopLeftY = 0;
565 viewport.Width = mWidth;
566 viewport.Height = mHeight;
567 viewport.MinDepth = 0.0f;
568 viewport.MaxDepth = 1.0f;
569 deviceContext->RSSetViewports(1, &viewport);
570
daniel@transgaming.come0970472012-11-28 21:05:07 +0000571 // Apply textures
572 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
573 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
574
575 // Draw
576 deviceContext->Draw(4, 0);
shannon.woods@transgaming.comddd6c802013-02-28 23:05:14 +0000577 result = mSwapChain->Present(mSwapInterval, 0);
578
579 if (result == DXGI_ERROR_DEVICE_REMOVED)
580 {
581 HRESULT removedReason = device->GetDeviceRemovedReason();
582 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
583 return EGL_CONTEXT_LOST;
584 }
585 else if (result == DXGI_ERROR_DEVICE_RESET)
586 {
587 ERR("Present failed: the D3D11 device was reset from a bad command.");
588 return EGL_CONTEXT_LOST;
589 }
590 else if (FAILED(result))
591 {
592 ERR("Present failed with error code 0x%08X", result);
593 }
daniel@transgaming.come0970472012-11-28 21:05:07 +0000594
595 // Unbind
596 static ID3D11ShaderResourceView *const nullSRV = NULL;
597 deviceContext->PSSetShaderResources(0, 1, &nullSRV);
598
shannon.woods%transgaming.com@gtempaccount.comba2744f2013-04-13 03:33:38 +0000599 mRenderer->unapplyRenderTargets();
daniel@transgaming.come0970472012-11-28 21:05:07 +0000600 mRenderer->markAllStateDirty();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000601
602 return EGL_SUCCESS;
603}
604
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000605// Increments refcount on texture.
606// caller must Release() the returned texture
607ID3D11Texture2D *SwapChain11::getOffscreenTexture()
608{
609 if (mOffscreenTexture)
610 {
611 mOffscreenTexture->AddRef();
612 }
613
614 return mOffscreenTexture;
615}
616
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000617// Increments refcount on view.
618// caller must Release() the returned view
619ID3D11RenderTargetView *SwapChain11::getRenderTarget()
620{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000621 if (mOffscreenRTView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000622 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000623 mOffscreenRTView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000624 }
625
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000626 return mOffscreenRTView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000627}
628
629// Increments refcount on view.
630// caller must Release() the returned view
shannon.woods@transgaming.com5c25ed22013-01-25 21:49:51 +0000631ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
632{
633 if (mOffscreenSRView)
634 {
635 mOffscreenSRView->AddRef();
636 }
637
638 return mOffscreenSRView;
639}
640
641// Increments refcount on view.
642// caller must Release() the returned view
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000643ID3D11DepthStencilView *SwapChain11::getDepthStencil()
644{
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000645 if (mDepthStencilDSView)
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000646 {
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000647 mDepthStencilDSView->AddRef();
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000648 }
649
daniel@transgaming.comc8c70ad2012-11-28 21:04:37 +0000650 return mDepthStencilDSView;
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000651}
652
shannon.woods@transgaming.com7e232852013-02-28 23:06:15 +0000653ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
654{
655 if (mDepthStencilTexture)
656 {
657 mDepthStencilTexture->AddRef();
658 }
659
660 return mDepthStencilTexture;
661}
662
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000663SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
664{
apatrick@chromium.org8b400b12013-01-30 21:53:40 +0000665 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000666 return static_cast<rx::SwapChain11*>(swapChain);
daniel@transgaming.com32fdf822012-11-28 20:53:30 +0000667}
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000668
shannon.woods%transgaming.com@gtempaccount.com8bce3f52013-04-13 03:35:32 +0000669void SwapChain11::recreate()
670{
671 // possibly should use this method instead of reset
672}
673
daniel@transgaming.comd733bb82012-11-28 20:53:40 +0000674}