|
1 #include "precompiled.h" |
|
2 // |
|
3 // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. |
|
4 // 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 |
|
12 #include "libGLESv2/renderer/renderer11_utils.h" |
|
13 #include "libGLESv2/renderer/Renderer11.h" |
|
14 #include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" |
|
15 #include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" |
|
16 |
|
17 namespace rx |
|
18 { |
|
19 |
|
20 SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, |
|
21 GLenum backBufferFormat, GLenum depthBufferFormat) |
|
22 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) |
|
23 { |
|
24 mSwapChain = NULL; |
|
25 mBackBufferTexture = NULL; |
|
26 mBackBufferRTView = NULL; |
|
27 mOffscreenTexture = NULL; |
|
28 mOffscreenRTView = NULL; |
|
29 mOffscreenSRView = NULL; |
|
30 mDepthStencilTexture = NULL; |
|
31 mDepthStencilDSView = NULL; |
|
32 mQuadVB = NULL; |
|
33 mPassThroughSampler = NULL; |
|
34 mPassThroughIL = NULL; |
|
35 mPassThroughVS = NULL; |
|
36 mPassThroughPS = NULL; |
|
37 mWidth = -1; |
|
38 mHeight = -1; |
|
39 mSwapInterval = 0; |
|
40 mAppCreatedShareHandle = mShareHandle != NULL; |
|
41 mPassThroughResourcesInit = false; |
|
42 } |
|
43 |
|
44 SwapChain11::~SwapChain11() |
|
45 { |
|
46 release(); |
|
47 } |
|
48 |
|
49 void SwapChain11::release() |
|
50 { |
|
51 if (mSwapChain) |
|
52 { |
|
53 mSwapChain->Release(); |
|
54 mSwapChain = NULL; |
|
55 } |
|
56 |
|
57 if (mBackBufferTexture) |
|
58 { |
|
59 mBackBufferTexture->Release(); |
|
60 mBackBufferTexture = NULL; |
|
61 } |
|
62 |
|
63 if (mBackBufferRTView) |
|
64 { |
|
65 mBackBufferRTView->Release(); |
|
66 mBackBufferRTView = NULL; |
|
67 } |
|
68 |
|
69 if (mOffscreenTexture) |
|
70 { |
|
71 mOffscreenTexture->Release(); |
|
72 mOffscreenTexture = NULL; |
|
73 } |
|
74 |
|
75 if (mOffscreenRTView) |
|
76 { |
|
77 mOffscreenRTView->Release(); |
|
78 mOffscreenRTView = NULL; |
|
79 } |
|
80 |
|
81 if (mOffscreenSRView) |
|
82 { |
|
83 mOffscreenSRView->Release(); |
|
84 mOffscreenSRView = NULL; |
|
85 } |
|
86 |
|
87 if (mDepthStencilTexture) |
|
88 { |
|
89 mDepthStencilTexture->Release(); |
|
90 mDepthStencilTexture = NULL; |
|
91 } |
|
92 |
|
93 if (mDepthStencilDSView) |
|
94 { |
|
95 mDepthStencilDSView->Release(); |
|
96 mDepthStencilDSView = NULL; |
|
97 } |
|
98 |
|
99 if (mQuadVB) |
|
100 { |
|
101 mQuadVB->Release(); |
|
102 mQuadVB = NULL; |
|
103 } |
|
104 |
|
105 if (mPassThroughSampler) |
|
106 { |
|
107 mPassThroughSampler->Release(); |
|
108 mPassThroughSampler = NULL; |
|
109 } |
|
110 |
|
111 if (mPassThroughIL) |
|
112 { |
|
113 mPassThroughIL->Release(); |
|
114 mPassThroughIL = NULL; |
|
115 } |
|
116 |
|
117 if (mPassThroughVS) |
|
118 { |
|
119 mPassThroughVS->Release(); |
|
120 mPassThroughVS = NULL; |
|
121 } |
|
122 |
|
123 if (mPassThroughPS) |
|
124 { |
|
125 mPassThroughPS->Release(); |
|
126 mPassThroughPS = NULL; |
|
127 } |
|
128 |
|
129 if (!mAppCreatedShareHandle) |
|
130 { |
|
131 mShareHandle = NULL; |
|
132 } |
|
133 } |
|
134 |
|
135 void SwapChain11::releaseOffscreenTexture() |
|
136 { |
|
137 if (mOffscreenTexture) |
|
138 { |
|
139 mOffscreenTexture->Release(); |
|
140 mOffscreenTexture = NULL; |
|
141 } |
|
142 |
|
143 if (mOffscreenRTView) |
|
144 { |
|
145 mOffscreenRTView->Release(); |
|
146 mOffscreenRTView = NULL; |
|
147 } |
|
148 |
|
149 if (mOffscreenSRView) |
|
150 { |
|
151 mOffscreenSRView->Release(); |
|
152 mOffscreenSRView = NULL; |
|
153 } |
|
154 |
|
155 if (mDepthStencilTexture) |
|
156 { |
|
157 mDepthStencilTexture->Release(); |
|
158 mDepthStencilTexture = NULL; |
|
159 } |
|
160 |
|
161 if (mDepthStencilDSView) |
|
162 { |
|
163 mDepthStencilDSView->Release(); |
|
164 mDepthStencilDSView = NULL; |
|
165 } |
|
166 } |
|
167 |
|
168 EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) |
|
169 { |
|
170 ID3D11Device *device = mRenderer->getDevice(); |
|
171 |
|
172 ASSERT(device != NULL); |
|
173 |
|
174 // D3D11 does not allow zero size textures |
|
175 ASSERT(backbufferWidth >= 1); |
|
176 ASSERT(backbufferHeight >= 1); |
|
177 |
|
178 // Preserve the render target content |
|
179 ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; |
|
180 if (previousOffscreenTexture) |
|
181 { |
|
182 previousOffscreenTexture->AddRef(); |
|
183 } |
|
184 const int previousWidth = mWidth; |
|
185 const int previousHeight = mHeight; |
|
186 |
|
187 releaseOffscreenTexture(); |
|
188 |
|
189 // If the app passed in a share handle, open the resource |
|
190 // See EGL_ANGLE_d3d_share_handle_client_buffer |
|
191 if (mAppCreatedShareHandle) |
|
192 { |
|
193 ID3D11Resource *tempResource11; |
|
194 HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); |
|
195 |
|
196 if (FAILED(result)) |
|
197 { |
|
198 ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); |
|
199 release(); |
|
200 return EGL_BAD_PARAMETER; |
|
201 } |
|
202 |
|
203 result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); |
|
204 tempResource11->Release(); |
|
205 |
|
206 if (FAILED(result)) |
|
207 { |
|
208 ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); |
|
209 release(); |
|
210 return EGL_BAD_PARAMETER; |
|
211 } |
|
212 |
|
213 // Validate offscreen texture parameters |
|
214 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; |
|
215 mOffscreenTexture->GetDesc(&offscreenTextureDesc); |
|
216 |
|
217 if (offscreenTextureDesc.Width != (UINT)backbufferWidth |
|
218 || offscreenTextureDesc.Height != (UINT)backbufferHeight |
|
219 || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) |
|
220 || offscreenTextureDesc.MipLevels != 1 |
|
221 || offscreenTextureDesc.ArraySize != 1) |
|
222 { |
|
223 ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); |
|
224 release(); |
|
225 return EGL_BAD_PARAMETER; |
|
226 } |
|
227 } |
|
228 else |
|
229 { |
|
230 const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); |
|
231 |
|
232 D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; |
|
233 offscreenTextureDesc.Width = backbufferWidth; |
|
234 offscreenTextureDesc.Height = backbufferHeight; |
|
235 offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); |
|
236 offscreenTextureDesc.MipLevels = 1; |
|
237 offscreenTextureDesc.ArraySize = 1; |
|
238 offscreenTextureDesc.SampleDesc.Count = 1; |
|
239 offscreenTextureDesc.SampleDesc.Quality = 0; |
|
240 offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; |
|
241 offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; |
|
242 offscreenTextureDesc.CPUAccessFlags = 0; |
|
243 offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; |
|
244 |
|
245 HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); |
|
246 |
|
247 if (FAILED(result)) |
|
248 { |
|
249 ERR("Could not create offscreen texture: %08lX", result); |
|
250 release(); |
|
251 |
|
252 if (d3d11::isDeviceLostError(result)) |
|
253 { |
|
254 return EGL_CONTEXT_LOST; |
|
255 } |
|
256 else |
|
257 { |
|
258 return EGL_BAD_ALLOC; |
|
259 } |
|
260 } |
|
261 |
|
262 d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); |
|
263 |
|
264 // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client |
|
265 if (useSharedResource) |
|
266 { |
|
267 IDXGIResource *offscreenTextureResource = NULL; |
|
268 result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); |
|
269 |
|
270 // Fall back to no share handle on failure |
|
271 if (FAILED(result)) |
|
272 { |
|
273 ERR("Could not query offscreen texture resource: %08lX", result); |
|
274 } |
|
275 else |
|
276 { |
|
277 result = offscreenTextureResource->GetSharedHandle(&mShareHandle); |
|
278 |
|
279 if (FAILED(result)) |
|
280 { |
|
281 mShareHandle = NULL; |
|
282 ERR("Could not get offscreen texture shared handle: %08lX", result); |
|
283 } |
|
284 } |
|
285 } |
|
286 } |
|
287 |
|
288 HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); |
|
289 |
|
290 ASSERT(SUCCEEDED(result)); |
|
291 d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); |
|
292 |
|
293 result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); |
|
294 ASSERT(SUCCEEDED(result)); |
|
295 d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); |
|
296 |
|
297 if (mDepthBufferFormat != GL_NONE) |
|
298 { |
|
299 D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; |
|
300 depthStencilDesc.Width = backbufferWidth; |
|
301 depthStencilDesc.Height = backbufferHeight; |
|
302 depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); |
|
303 depthStencilDesc.MipLevels = 1; |
|
304 depthStencilDesc.ArraySize = 1; |
|
305 depthStencilDesc.SampleDesc.Count = 1; |
|
306 depthStencilDesc.SampleDesc.Quality = 0; |
|
307 depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; |
|
308 depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; |
|
309 depthStencilDesc.CPUAccessFlags = 0; |
|
310 depthStencilDesc.MiscFlags = 0; |
|
311 |
|
312 result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); |
|
313 if (FAILED(result)) |
|
314 { |
|
315 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); |
|
316 release(); |
|
317 |
|
318 if (d3d11::isDeviceLostError(result)) |
|
319 { |
|
320 return EGL_CONTEXT_LOST; |
|
321 } |
|
322 else |
|
323 { |
|
324 return EGL_BAD_ALLOC; |
|
325 } |
|
326 } |
|
327 d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); |
|
328 |
|
329 result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); |
|
330 ASSERT(SUCCEEDED(result)); |
|
331 d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); |
|
332 } |
|
333 |
|
334 mWidth = backbufferWidth; |
|
335 mHeight = backbufferHeight; |
|
336 |
|
337 if (previousOffscreenTexture != NULL) |
|
338 { |
|
339 D3D11_BOX sourceBox = {0}; |
|
340 sourceBox.left = 0; |
|
341 sourceBox.right = std::min(previousWidth, mWidth); |
|
342 sourceBox.top = std::max(previousHeight - mHeight, 0); |
|
343 sourceBox.bottom = previousHeight; |
|
344 sourceBox.front = 0; |
|
345 sourceBox.back = 1; |
|
346 |
|
347 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); |
|
348 const int yoffset = std::max(mHeight - previousHeight, 0); |
|
349 deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); |
|
350 |
|
351 previousOffscreenTexture->Release(); |
|
352 |
|
353 if (mSwapChain) |
|
354 { |
|
355 swapRect(0, 0, mWidth, mHeight); |
|
356 } |
|
357 } |
|
358 |
|
359 return EGL_SUCCESS; |
|
360 } |
|
361 |
|
362 EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) |
|
363 { |
|
364 ID3D11Device *device = mRenderer->getDevice(); |
|
365 |
|
366 if (device == NULL) |
|
367 { |
|
368 return EGL_BAD_ACCESS; |
|
369 } |
|
370 |
|
371 // Can only call resize if we have already created our swap buffer and resources |
|
372 ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); |
|
373 |
|
374 if (mBackBufferTexture) |
|
375 { |
|
376 mBackBufferTexture->Release(); |
|
377 mBackBufferTexture = NULL; |
|
378 } |
|
379 |
|
380 if (mBackBufferRTView) |
|
381 { |
|
382 mBackBufferRTView->Release(); |
|
383 mBackBufferRTView = NULL; |
|
384 } |
|
385 |
|
386 // Resize swap chain |
|
387 DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); |
|
388 HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); |
|
389 |
|
390 if (FAILED(result)) |
|
391 { |
|
392 ERR("Error resizing swap chain buffers: 0x%08X", result); |
|
393 release(); |
|
394 |
|
395 if (d3d11::isDeviceLostError(result)) |
|
396 { |
|
397 return EGL_CONTEXT_LOST; |
|
398 } |
|
399 else |
|
400 { |
|
401 return EGL_BAD_ALLOC; |
|
402 } |
|
403 } |
|
404 |
|
405 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); |
|
406 ASSERT(SUCCEEDED(result)); |
|
407 if (SUCCEEDED(result)) |
|
408 { |
|
409 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); |
|
410 } |
|
411 |
|
412 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); |
|
413 ASSERT(SUCCEEDED(result)); |
|
414 if (SUCCEEDED(result)) |
|
415 { |
|
416 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); |
|
417 } |
|
418 |
|
419 return resetOffscreenTexture(backbufferWidth, backbufferHeight); |
|
420 } |
|
421 |
|
422 EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) |
|
423 { |
|
424 ID3D11Device *device = mRenderer->getDevice(); |
|
425 |
|
426 if (device == NULL) |
|
427 { |
|
428 return EGL_BAD_ACCESS; |
|
429 } |
|
430 |
|
431 // Release specific resources to free up memory for the new render target, while the |
|
432 // old render target still exists for the purpose of preserving its contents. |
|
433 if (mSwapChain) |
|
434 { |
|
435 mSwapChain->Release(); |
|
436 mSwapChain = NULL; |
|
437 } |
|
438 |
|
439 if (mBackBufferTexture) |
|
440 { |
|
441 mBackBufferTexture->Release(); |
|
442 mBackBufferTexture = NULL; |
|
443 } |
|
444 |
|
445 if (mBackBufferRTView) |
|
446 { |
|
447 mBackBufferRTView->Release(); |
|
448 mBackBufferRTView = NULL; |
|
449 } |
|
450 |
|
451 mSwapInterval = static_cast<unsigned int>(swapInterval); |
|
452 if (mSwapInterval > 4) |
|
453 { |
|
454 // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range |
|
455 return EGL_BAD_PARAMETER; |
|
456 } |
|
457 |
|
458 // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains |
|
459 if (backbufferWidth < 1 || backbufferHeight < 1) |
|
460 { |
|
461 releaseOffscreenTexture(); |
|
462 return EGL_SUCCESS; |
|
463 } |
|
464 |
|
465 if (mWindow) |
|
466 { |
|
467 // We cannot create a swap chain for an HWND that is owned by a different process |
|
468 DWORD currentProcessId = GetCurrentProcessId(); |
|
469 DWORD wndProcessId; |
|
470 GetWindowThreadProcessId(mWindow, &wndProcessId); |
|
471 |
|
472 if (currentProcessId != wndProcessId) |
|
473 { |
|
474 ERR("Could not create swap chain, window owned by different process"); |
|
475 release(); |
|
476 return EGL_BAD_NATIVE_WINDOW; |
|
477 } |
|
478 |
|
479 IDXGIFactory *factory = mRenderer->getDxgiFactory(); |
|
480 |
|
481 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; |
|
482 swapChainDesc.BufferCount = 2; |
|
483 swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); |
|
484 swapChainDesc.BufferDesc.Width = backbufferWidth; |
|
485 swapChainDesc.BufferDesc.Height = backbufferHeight; |
|
486 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; |
|
487 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; |
|
488 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; |
|
489 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; |
|
490 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; |
|
491 swapChainDesc.Flags = 0; |
|
492 swapChainDesc.OutputWindow = mWindow; |
|
493 swapChainDesc.SampleDesc.Count = 1; |
|
494 swapChainDesc.SampleDesc.Quality = 0; |
|
495 swapChainDesc.Windowed = TRUE; |
|
496 |
|
497 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); |
|
498 |
|
499 if (FAILED(result)) |
|
500 { |
|
501 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); |
|
502 release(); |
|
503 |
|
504 if (d3d11::isDeviceLostError(result)) |
|
505 { |
|
506 return EGL_CONTEXT_LOST; |
|
507 } |
|
508 else |
|
509 { |
|
510 return EGL_BAD_ALLOC; |
|
511 } |
|
512 } |
|
513 |
|
514 result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); |
|
515 ASSERT(SUCCEEDED(result)); |
|
516 d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); |
|
517 |
|
518 result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); |
|
519 ASSERT(SUCCEEDED(result)); |
|
520 d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); |
|
521 } |
|
522 |
|
523 // If we are resizing the swap chain, we don't wish to recreate all the static resources |
|
524 if (!mPassThroughResourcesInit) |
|
525 { |
|
526 mPassThroughResourcesInit = true; |
|
527 initPassThroughResources(); |
|
528 } |
|
529 |
|
530 return resetOffscreenTexture(backbufferWidth, backbufferHeight); |
|
531 } |
|
532 |
|
533 void SwapChain11::initPassThroughResources() |
|
534 { |
|
535 ID3D11Device *device = mRenderer->getDevice(); |
|
536 |
|
537 ASSERT(device != NULL); |
|
538 |
|
539 // Make sure our resources are all not allocated, when we create |
|
540 ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); |
|
541 ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); |
|
542 |
|
543 D3D11_BUFFER_DESC vbDesc; |
|
544 vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; |
|
545 vbDesc.Usage = D3D11_USAGE_DYNAMIC; |
|
546 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; |
|
547 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; |
|
548 vbDesc.MiscFlags = 0; |
|
549 vbDesc.StructureByteStride = 0; |
|
550 |
|
551 HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); |
|
552 ASSERT(SUCCEEDED(result)); |
|
553 d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); |
|
554 |
|
555 D3D11_SAMPLER_DESC samplerDesc; |
|
556 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; |
|
557 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; |
|
558 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; |
|
559 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; |
|
560 samplerDesc.MipLODBias = 0.0f; |
|
561 samplerDesc.MaxAnisotropy = 0; |
|
562 samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; |
|
563 samplerDesc.BorderColor[0] = 0.0f; |
|
564 samplerDesc.BorderColor[1] = 0.0f; |
|
565 samplerDesc.BorderColor[2] = 0.0f; |
|
566 samplerDesc.BorderColor[3] = 0.0f; |
|
567 samplerDesc.MinLOD = 0; |
|
568 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; |
|
569 |
|
570 result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); |
|
571 ASSERT(SUCCEEDED(result)); |
|
572 d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); |
|
573 |
|
574 D3D11_INPUT_ELEMENT_DESC quadLayout[] = |
|
575 { |
|
576 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, |
|
577 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, |
|
578 }; |
|
579 |
|
580 result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL); |
|
581 ASSERT(SUCCEEDED(result)); |
|
582 d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); |
|
583 |
|
584 result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS); |
|
585 ASSERT(SUCCEEDED(result)); |
|
586 d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); |
|
587 |
|
588 result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS); |
|
589 ASSERT(SUCCEEDED(result)); |
|
590 d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); |
|
591 } |
|
592 |
|
593 // parameters should be validated/clamped by caller |
|
594 EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) |
|
595 { |
|
596 if (!mSwapChain) |
|
597 { |
|
598 return EGL_SUCCESS; |
|
599 } |
|
600 |
|
601 ID3D11Device *device = mRenderer->getDevice(); |
|
602 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); |
|
603 |
|
604 // Set vertices |
|
605 D3D11_MAPPED_SUBRESOURCE mappedResource; |
|
606 HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); |
|
607 if (FAILED(result)) |
|
608 { |
|
609 return EGL_BAD_ACCESS; |
|
610 } |
|
611 |
|
612 d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); |
|
613 |
|
614 // Create a quad in homogeneous coordinates |
|
615 float x1 = (x / float(mWidth)) * 2.0f - 1.0f; |
|
616 float y1 = (y / float(mHeight)) * 2.0f - 1.0f; |
|
617 float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; |
|
618 float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; |
|
619 |
|
620 float u1 = x / float(mWidth); |
|
621 float v1 = y / float(mHeight); |
|
622 float u2 = (x + width) / float(mWidth); |
|
623 float v2 = (y + height) / float(mHeight); |
|
624 |
|
625 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); |
|
626 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); |
|
627 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); |
|
628 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); |
|
629 |
|
630 deviceContext->Unmap(mQuadVB, 0); |
|
631 |
|
632 static UINT stride = sizeof(d3d11::PositionTexCoordVertex); |
|
633 static UINT startIdx = 0; |
|
634 deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); |
|
635 |
|
636 // Apply state |
|
637 deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); |
|
638 |
|
639 static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; |
|
640 deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); |
|
641 |
|
642 deviceContext->RSSetState(NULL); |
|
643 |
|
644 // Apply shaders |
|
645 deviceContext->IASetInputLayout(mPassThroughIL); |
|
646 deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); |
|
647 deviceContext->VSSetShader(mPassThroughVS, NULL, 0); |
|
648 deviceContext->PSSetShader(mPassThroughPS, NULL, 0); |
|
649 deviceContext->GSSetShader(NULL, NULL, 0); |
|
650 |
|
651 // Apply render targets |
|
652 mRenderer->setOneTimeRenderTarget(mBackBufferRTView); |
|
653 |
|
654 // Set the viewport |
|
655 D3D11_VIEWPORT viewport; |
|
656 viewport.TopLeftX = 0; |
|
657 viewport.TopLeftY = 0; |
|
658 viewport.Width = mWidth; |
|
659 viewport.Height = mHeight; |
|
660 viewport.MinDepth = 0.0f; |
|
661 viewport.MaxDepth = 1.0f; |
|
662 deviceContext->RSSetViewports(1, &viewport); |
|
663 |
|
664 // Apply textures |
|
665 deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); |
|
666 deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); |
|
667 |
|
668 // Draw |
|
669 deviceContext->Draw(4, 0); |
|
670 result = mSwapChain->Present(mSwapInterval, 0); |
|
671 |
|
672 if (result == DXGI_ERROR_DEVICE_REMOVED) |
|
673 { |
|
674 HRESULT removedReason = device->GetDeviceRemovedReason(); |
|
675 ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); |
|
676 return EGL_CONTEXT_LOST; |
|
677 } |
|
678 else if (result == DXGI_ERROR_DEVICE_RESET) |
|
679 { |
|
680 ERR("Present failed: the D3D11 device was reset from a bad command."); |
|
681 return EGL_CONTEXT_LOST; |
|
682 } |
|
683 else if (FAILED(result)) |
|
684 { |
|
685 ERR("Present failed with error code 0x%08X", result); |
|
686 } |
|
687 |
|
688 // Unbind |
|
689 static ID3D11ShaderResourceView *const nullSRV = NULL; |
|
690 deviceContext->PSSetShaderResources(0, 1, &nullSRV); |
|
691 |
|
692 mRenderer->unapplyRenderTargets(); |
|
693 mRenderer->markAllStateDirty(); |
|
694 |
|
695 return EGL_SUCCESS; |
|
696 } |
|
697 |
|
698 // Increments refcount on texture. |
|
699 // caller must Release() the returned texture |
|
700 ID3D11Texture2D *SwapChain11::getOffscreenTexture() |
|
701 { |
|
702 if (mOffscreenTexture) |
|
703 { |
|
704 mOffscreenTexture->AddRef(); |
|
705 } |
|
706 |
|
707 return mOffscreenTexture; |
|
708 } |
|
709 |
|
710 // Increments refcount on view. |
|
711 // caller must Release() the returned view |
|
712 ID3D11RenderTargetView *SwapChain11::getRenderTarget() |
|
713 { |
|
714 if (mOffscreenRTView) |
|
715 { |
|
716 mOffscreenRTView->AddRef(); |
|
717 } |
|
718 |
|
719 return mOffscreenRTView; |
|
720 } |
|
721 |
|
722 // Increments refcount on view. |
|
723 // caller must Release() the returned view |
|
724 ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() |
|
725 { |
|
726 if (mOffscreenSRView) |
|
727 { |
|
728 mOffscreenSRView->AddRef(); |
|
729 } |
|
730 |
|
731 return mOffscreenSRView; |
|
732 } |
|
733 |
|
734 // Increments refcount on view. |
|
735 // caller must Release() the returned view |
|
736 ID3D11DepthStencilView *SwapChain11::getDepthStencil() |
|
737 { |
|
738 if (mDepthStencilDSView) |
|
739 { |
|
740 mDepthStencilDSView->AddRef(); |
|
741 } |
|
742 |
|
743 return mDepthStencilDSView; |
|
744 } |
|
745 |
|
746 ID3D11Texture2D *SwapChain11::getDepthStencilTexture() |
|
747 { |
|
748 if (mDepthStencilTexture) |
|
749 { |
|
750 mDepthStencilTexture->AddRef(); |
|
751 } |
|
752 |
|
753 return mDepthStencilTexture; |
|
754 } |
|
755 |
|
756 SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) |
|
757 { |
|
758 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); |
|
759 return static_cast<rx::SwapChain11*>(swapChain); |
|
760 } |
|
761 |
|
762 void SwapChain11::recreate() |
|
763 { |
|
764 // possibly should use this method instead of reset |
|
765 } |
|
766 |
|
767 } |