1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libGLESv2/renderer/SwapChain11.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,767 @@ 1.4 +#include "precompiled.h" 1.5 +// 1.6 +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. 1.7 +// Use of this source code is governed by a BSD-style license that can be 1.8 +// found in the LICENSE file. 1.9 +// 1.10 + 1.11 +// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. 1.12 + 1.13 +#include "libGLESv2/renderer/SwapChain11.h" 1.14 + 1.15 +#include "libGLESv2/renderer/renderer11_utils.h" 1.16 +#include "libGLESv2/renderer/Renderer11.h" 1.17 +#include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h" 1.18 +#include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h" 1.19 + 1.20 +namespace rx 1.21 +{ 1.22 + 1.23 +SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle, 1.24 + GLenum backBufferFormat, GLenum depthBufferFormat) 1.25 + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) 1.26 +{ 1.27 + mSwapChain = NULL; 1.28 + mBackBufferTexture = NULL; 1.29 + mBackBufferRTView = NULL; 1.30 + mOffscreenTexture = NULL; 1.31 + mOffscreenRTView = NULL; 1.32 + mOffscreenSRView = NULL; 1.33 + mDepthStencilTexture = NULL; 1.34 + mDepthStencilDSView = NULL; 1.35 + mQuadVB = NULL; 1.36 + mPassThroughSampler = NULL; 1.37 + mPassThroughIL = NULL; 1.38 + mPassThroughVS = NULL; 1.39 + mPassThroughPS = NULL; 1.40 + mWidth = -1; 1.41 + mHeight = -1; 1.42 + mSwapInterval = 0; 1.43 + mAppCreatedShareHandle = mShareHandle != NULL; 1.44 + mPassThroughResourcesInit = false; 1.45 +} 1.46 + 1.47 +SwapChain11::~SwapChain11() 1.48 +{ 1.49 + release(); 1.50 +} 1.51 + 1.52 +void SwapChain11::release() 1.53 +{ 1.54 + if (mSwapChain) 1.55 + { 1.56 + mSwapChain->Release(); 1.57 + mSwapChain = NULL; 1.58 + } 1.59 + 1.60 + if (mBackBufferTexture) 1.61 + { 1.62 + mBackBufferTexture->Release(); 1.63 + mBackBufferTexture = NULL; 1.64 + } 1.65 + 1.66 + if (mBackBufferRTView) 1.67 + { 1.68 + mBackBufferRTView->Release(); 1.69 + mBackBufferRTView = NULL; 1.70 + } 1.71 + 1.72 + if (mOffscreenTexture) 1.73 + { 1.74 + mOffscreenTexture->Release(); 1.75 + mOffscreenTexture = NULL; 1.76 + } 1.77 + 1.78 + if (mOffscreenRTView) 1.79 + { 1.80 + mOffscreenRTView->Release(); 1.81 + mOffscreenRTView = NULL; 1.82 + } 1.83 + 1.84 + if (mOffscreenSRView) 1.85 + { 1.86 + mOffscreenSRView->Release(); 1.87 + mOffscreenSRView = NULL; 1.88 + } 1.89 + 1.90 + if (mDepthStencilTexture) 1.91 + { 1.92 + mDepthStencilTexture->Release(); 1.93 + mDepthStencilTexture = NULL; 1.94 + } 1.95 + 1.96 + if (mDepthStencilDSView) 1.97 + { 1.98 + mDepthStencilDSView->Release(); 1.99 + mDepthStencilDSView = NULL; 1.100 + } 1.101 + 1.102 + if (mQuadVB) 1.103 + { 1.104 + mQuadVB->Release(); 1.105 + mQuadVB = NULL; 1.106 + } 1.107 + 1.108 + if (mPassThroughSampler) 1.109 + { 1.110 + mPassThroughSampler->Release(); 1.111 + mPassThroughSampler = NULL; 1.112 + } 1.113 + 1.114 + if (mPassThroughIL) 1.115 + { 1.116 + mPassThroughIL->Release(); 1.117 + mPassThroughIL = NULL; 1.118 + } 1.119 + 1.120 + if (mPassThroughVS) 1.121 + { 1.122 + mPassThroughVS->Release(); 1.123 + mPassThroughVS = NULL; 1.124 + } 1.125 + 1.126 + if (mPassThroughPS) 1.127 + { 1.128 + mPassThroughPS->Release(); 1.129 + mPassThroughPS = NULL; 1.130 + } 1.131 + 1.132 + if (!mAppCreatedShareHandle) 1.133 + { 1.134 + mShareHandle = NULL; 1.135 + } 1.136 +} 1.137 + 1.138 +void SwapChain11::releaseOffscreenTexture() 1.139 +{ 1.140 + if (mOffscreenTexture) 1.141 + { 1.142 + mOffscreenTexture->Release(); 1.143 + mOffscreenTexture = NULL; 1.144 + } 1.145 + 1.146 + if (mOffscreenRTView) 1.147 + { 1.148 + mOffscreenRTView->Release(); 1.149 + mOffscreenRTView = NULL; 1.150 + } 1.151 + 1.152 + if (mOffscreenSRView) 1.153 + { 1.154 + mOffscreenSRView->Release(); 1.155 + mOffscreenSRView = NULL; 1.156 + } 1.157 + 1.158 + if (mDepthStencilTexture) 1.159 + { 1.160 + mDepthStencilTexture->Release(); 1.161 + mDepthStencilTexture = NULL; 1.162 + } 1.163 + 1.164 + if (mDepthStencilDSView) 1.165 + { 1.166 + mDepthStencilDSView->Release(); 1.167 + mDepthStencilDSView = NULL; 1.168 + } 1.169 +} 1.170 + 1.171 +EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) 1.172 +{ 1.173 + ID3D11Device *device = mRenderer->getDevice(); 1.174 + 1.175 + ASSERT(device != NULL); 1.176 + 1.177 + // D3D11 does not allow zero size textures 1.178 + ASSERT(backbufferWidth >= 1); 1.179 + ASSERT(backbufferHeight >= 1); 1.180 + 1.181 + // Preserve the render target content 1.182 + ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; 1.183 + if (previousOffscreenTexture) 1.184 + { 1.185 + previousOffscreenTexture->AddRef(); 1.186 + } 1.187 + const int previousWidth = mWidth; 1.188 + const int previousHeight = mHeight; 1.189 + 1.190 + releaseOffscreenTexture(); 1.191 + 1.192 + // If the app passed in a share handle, open the resource 1.193 + // See EGL_ANGLE_d3d_share_handle_client_buffer 1.194 + if (mAppCreatedShareHandle) 1.195 + { 1.196 + ID3D11Resource *tempResource11; 1.197 + HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); 1.198 + 1.199 + if (FAILED(result)) 1.200 + { 1.201 + ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); 1.202 + release(); 1.203 + return EGL_BAD_PARAMETER; 1.204 + } 1.205 + 1.206 + result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); 1.207 + tempResource11->Release(); 1.208 + 1.209 + if (FAILED(result)) 1.210 + { 1.211 + ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); 1.212 + release(); 1.213 + return EGL_BAD_PARAMETER; 1.214 + } 1.215 + 1.216 + // Validate offscreen texture parameters 1.217 + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; 1.218 + mOffscreenTexture->GetDesc(&offscreenTextureDesc); 1.219 + 1.220 + if (offscreenTextureDesc.Width != (UINT)backbufferWidth 1.221 + || offscreenTextureDesc.Height != (UINT)backbufferHeight 1.222 + || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) 1.223 + || offscreenTextureDesc.MipLevels != 1 1.224 + || offscreenTextureDesc.ArraySize != 1) 1.225 + { 1.226 + ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); 1.227 + release(); 1.228 + return EGL_BAD_PARAMETER; 1.229 + } 1.230 + } 1.231 + else 1.232 + { 1.233 + const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); 1.234 + 1.235 + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; 1.236 + offscreenTextureDesc.Width = backbufferWidth; 1.237 + offscreenTextureDesc.Height = backbufferHeight; 1.238 + offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); 1.239 + offscreenTextureDesc.MipLevels = 1; 1.240 + offscreenTextureDesc.ArraySize = 1; 1.241 + offscreenTextureDesc.SampleDesc.Count = 1; 1.242 + offscreenTextureDesc.SampleDesc.Quality = 0; 1.243 + offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; 1.244 + offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; 1.245 + offscreenTextureDesc.CPUAccessFlags = 0; 1.246 + offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; 1.247 + 1.248 + HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); 1.249 + 1.250 + if (FAILED(result)) 1.251 + { 1.252 + ERR("Could not create offscreen texture: %08lX", result); 1.253 + release(); 1.254 + 1.255 + if (d3d11::isDeviceLostError(result)) 1.256 + { 1.257 + return EGL_CONTEXT_LOST; 1.258 + } 1.259 + else 1.260 + { 1.261 + return EGL_BAD_ALLOC; 1.262 + } 1.263 + } 1.264 + 1.265 + d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); 1.266 + 1.267 + // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client 1.268 + if (useSharedResource) 1.269 + { 1.270 + IDXGIResource *offscreenTextureResource = NULL; 1.271 + result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); 1.272 + 1.273 + // Fall back to no share handle on failure 1.274 + if (FAILED(result)) 1.275 + { 1.276 + ERR("Could not query offscreen texture resource: %08lX", result); 1.277 + } 1.278 + else 1.279 + { 1.280 + result = offscreenTextureResource->GetSharedHandle(&mShareHandle); 1.281 + 1.282 + if (FAILED(result)) 1.283 + { 1.284 + mShareHandle = NULL; 1.285 + ERR("Could not get offscreen texture shared handle: %08lX", result); 1.286 + } 1.287 + } 1.288 + } 1.289 + } 1.290 + 1.291 + HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); 1.292 + 1.293 + ASSERT(SUCCEEDED(result)); 1.294 + d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); 1.295 + 1.296 + result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); 1.297 + ASSERT(SUCCEEDED(result)); 1.298 + d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); 1.299 + 1.300 + if (mDepthBufferFormat != GL_NONE) 1.301 + { 1.302 + D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; 1.303 + depthStencilDesc.Width = backbufferWidth; 1.304 + depthStencilDesc.Height = backbufferHeight; 1.305 + depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); 1.306 + depthStencilDesc.MipLevels = 1; 1.307 + depthStencilDesc.ArraySize = 1; 1.308 + depthStencilDesc.SampleDesc.Count = 1; 1.309 + depthStencilDesc.SampleDesc.Quality = 0; 1.310 + depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; 1.311 + depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; 1.312 + depthStencilDesc.CPUAccessFlags = 0; 1.313 + depthStencilDesc.MiscFlags = 0; 1.314 + 1.315 + result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); 1.316 + if (FAILED(result)) 1.317 + { 1.318 + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); 1.319 + release(); 1.320 + 1.321 + if (d3d11::isDeviceLostError(result)) 1.322 + { 1.323 + return EGL_CONTEXT_LOST; 1.324 + } 1.325 + else 1.326 + { 1.327 + return EGL_BAD_ALLOC; 1.328 + } 1.329 + } 1.330 + d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); 1.331 + 1.332 + result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); 1.333 + ASSERT(SUCCEEDED(result)); 1.334 + d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); 1.335 + } 1.336 + 1.337 + mWidth = backbufferWidth; 1.338 + mHeight = backbufferHeight; 1.339 + 1.340 + if (previousOffscreenTexture != NULL) 1.341 + { 1.342 + D3D11_BOX sourceBox = {0}; 1.343 + sourceBox.left = 0; 1.344 + sourceBox.right = std::min(previousWidth, mWidth); 1.345 + sourceBox.top = std::max(previousHeight - mHeight, 0); 1.346 + sourceBox.bottom = previousHeight; 1.347 + sourceBox.front = 0; 1.348 + sourceBox.back = 1; 1.349 + 1.350 + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 1.351 + const int yoffset = std::max(mHeight - previousHeight, 0); 1.352 + deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); 1.353 + 1.354 + previousOffscreenTexture->Release(); 1.355 + 1.356 + if (mSwapChain) 1.357 + { 1.358 + swapRect(0, 0, mWidth, mHeight); 1.359 + } 1.360 + } 1.361 + 1.362 + return EGL_SUCCESS; 1.363 +} 1.364 + 1.365 +EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) 1.366 +{ 1.367 + ID3D11Device *device = mRenderer->getDevice(); 1.368 + 1.369 + if (device == NULL) 1.370 + { 1.371 + return EGL_BAD_ACCESS; 1.372 + } 1.373 + 1.374 + // Can only call resize if we have already created our swap buffer and resources 1.375 + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); 1.376 + 1.377 + if (mBackBufferTexture) 1.378 + { 1.379 + mBackBufferTexture->Release(); 1.380 + mBackBufferTexture = NULL; 1.381 + } 1.382 + 1.383 + if (mBackBufferRTView) 1.384 + { 1.385 + mBackBufferRTView->Release(); 1.386 + mBackBufferRTView = NULL; 1.387 + } 1.388 + 1.389 + // Resize swap chain 1.390 + DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); 1.391 + HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); 1.392 + 1.393 + if (FAILED(result)) 1.394 + { 1.395 + ERR("Error resizing swap chain buffers: 0x%08X", result); 1.396 + release(); 1.397 + 1.398 + if (d3d11::isDeviceLostError(result)) 1.399 + { 1.400 + return EGL_CONTEXT_LOST; 1.401 + } 1.402 + else 1.403 + { 1.404 + return EGL_BAD_ALLOC; 1.405 + } 1.406 + } 1.407 + 1.408 + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); 1.409 + ASSERT(SUCCEEDED(result)); 1.410 + if (SUCCEEDED(result)) 1.411 + { 1.412 + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); 1.413 + } 1.414 + 1.415 + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); 1.416 + ASSERT(SUCCEEDED(result)); 1.417 + if (SUCCEEDED(result)) 1.418 + { 1.419 + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); 1.420 + } 1.421 + 1.422 + return resetOffscreenTexture(backbufferWidth, backbufferHeight); 1.423 +} 1.424 + 1.425 +EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) 1.426 +{ 1.427 + ID3D11Device *device = mRenderer->getDevice(); 1.428 + 1.429 + if (device == NULL) 1.430 + { 1.431 + return EGL_BAD_ACCESS; 1.432 + } 1.433 + 1.434 + // Release specific resources to free up memory for the new render target, while the 1.435 + // old render target still exists for the purpose of preserving its contents. 1.436 + if (mSwapChain) 1.437 + { 1.438 + mSwapChain->Release(); 1.439 + mSwapChain = NULL; 1.440 + } 1.441 + 1.442 + if (mBackBufferTexture) 1.443 + { 1.444 + mBackBufferTexture->Release(); 1.445 + mBackBufferTexture = NULL; 1.446 + } 1.447 + 1.448 + if (mBackBufferRTView) 1.449 + { 1.450 + mBackBufferRTView->Release(); 1.451 + mBackBufferRTView = NULL; 1.452 + } 1.453 + 1.454 + mSwapInterval = static_cast<unsigned int>(swapInterval); 1.455 + if (mSwapInterval > 4) 1.456 + { 1.457 + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range 1.458 + return EGL_BAD_PARAMETER; 1.459 + } 1.460 + 1.461 + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains 1.462 + if (backbufferWidth < 1 || backbufferHeight < 1) 1.463 + { 1.464 + releaseOffscreenTexture(); 1.465 + return EGL_SUCCESS; 1.466 + } 1.467 + 1.468 + if (mWindow) 1.469 + { 1.470 + // We cannot create a swap chain for an HWND that is owned by a different process 1.471 + DWORD currentProcessId = GetCurrentProcessId(); 1.472 + DWORD wndProcessId; 1.473 + GetWindowThreadProcessId(mWindow, &wndProcessId); 1.474 + 1.475 + if (currentProcessId != wndProcessId) 1.476 + { 1.477 + ERR("Could not create swap chain, window owned by different process"); 1.478 + release(); 1.479 + return EGL_BAD_NATIVE_WINDOW; 1.480 + } 1.481 + 1.482 + IDXGIFactory *factory = mRenderer->getDxgiFactory(); 1.483 + 1.484 + DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; 1.485 + swapChainDesc.BufferCount = 2; 1.486 + swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); 1.487 + swapChainDesc.BufferDesc.Width = backbufferWidth; 1.488 + swapChainDesc.BufferDesc.Height = backbufferHeight; 1.489 + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 1.490 + swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 1.491 + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; 1.492 + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; 1.493 + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 1.494 + swapChainDesc.Flags = 0; 1.495 + swapChainDesc.OutputWindow = mWindow; 1.496 + swapChainDesc.SampleDesc.Count = 1; 1.497 + swapChainDesc.SampleDesc.Quality = 0; 1.498 + swapChainDesc.Windowed = TRUE; 1.499 + 1.500 + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); 1.501 + 1.502 + if (FAILED(result)) 1.503 + { 1.504 + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); 1.505 + release(); 1.506 + 1.507 + if (d3d11::isDeviceLostError(result)) 1.508 + { 1.509 + return EGL_CONTEXT_LOST; 1.510 + } 1.511 + else 1.512 + { 1.513 + return EGL_BAD_ALLOC; 1.514 + } 1.515 + } 1.516 + 1.517 + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); 1.518 + ASSERT(SUCCEEDED(result)); 1.519 + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); 1.520 + 1.521 + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); 1.522 + ASSERT(SUCCEEDED(result)); 1.523 + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); 1.524 + } 1.525 + 1.526 + // If we are resizing the swap chain, we don't wish to recreate all the static resources 1.527 + if (!mPassThroughResourcesInit) 1.528 + { 1.529 + mPassThroughResourcesInit = true; 1.530 + initPassThroughResources(); 1.531 + } 1.532 + 1.533 + return resetOffscreenTexture(backbufferWidth, backbufferHeight); 1.534 +} 1.535 + 1.536 +void SwapChain11::initPassThroughResources() 1.537 +{ 1.538 + ID3D11Device *device = mRenderer->getDevice(); 1.539 + 1.540 + ASSERT(device != NULL); 1.541 + 1.542 + // Make sure our resources are all not allocated, when we create 1.543 + ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); 1.544 + ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); 1.545 + 1.546 + D3D11_BUFFER_DESC vbDesc; 1.547 + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; 1.548 + vbDesc.Usage = D3D11_USAGE_DYNAMIC; 1.549 + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 1.550 + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 1.551 + vbDesc.MiscFlags = 0; 1.552 + vbDesc.StructureByteStride = 0; 1.553 + 1.554 + HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); 1.555 + ASSERT(SUCCEEDED(result)); 1.556 + d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); 1.557 + 1.558 + D3D11_SAMPLER_DESC samplerDesc; 1.559 + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; 1.560 + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; 1.561 + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; 1.562 + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; 1.563 + samplerDesc.MipLODBias = 0.0f; 1.564 + samplerDesc.MaxAnisotropy = 0; 1.565 + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; 1.566 + samplerDesc.BorderColor[0] = 0.0f; 1.567 + samplerDesc.BorderColor[1] = 0.0f; 1.568 + samplerDesc.BorderColor[2] = 0.0f; 1.569 + samplerDesc.BorderColor[3] = 0.0f; 1.570 + samplerDesc.MinLOD = 0; 1.571 + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; 1.572 + 1.573 + result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); 1.574 + ASSERT(SUCCEEDED(result)); 1.575 + d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); 1.576 + 1.577 + D3D11_INPUT_ELEMENT_DESC quadLayout[] = 1.578 + { 1.579 + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 1.580 + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 1.581 + }; 1.582 + 1.583 + result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL); 1.584 + ASSERT(SUCCEEDED(result)); 1.585 + d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); 1.586 + 1.587 + result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS); 1.588 + ASSERT(SUCCEEDED(result)); 1.589 + d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); 1.590 + 1.591 + result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS); 1.592 + ASSERT(SUCCEEDED(result)); 1.593 + d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); 1.594 +} 1.595 + 1.596 +// parameters should be validated/clamped by caller 1.597 +EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) 1.598 +{ 1.599 + if (!mSwapChain) 1.600 + { 1.601 + return EGL_SUCCESS; 1.602 + } 1.603 + 1.604 + ID3D11Device *device = mRenderer->getDevice(); 1.605 + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); 1.606 + 1.607 + // Set vertices 1.608 + D3D11_MAPPED_SUBRESOURCE mappedResource; 1.609 + HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); 1.610 + if (FAILED(result)) 1.611 + { 1.612 + return EGL_BAD_ACCESS; 1.613 + } 1.614 + 1.615 + d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData); 1.616 + 1.617 + // Create a quad in homogeneous coordinates 1.618 + float x1 = (x / float(mWidth)) * 2.0f - 1.0f; 1.619 + float y1 = (y / float(mHeight)) * 2.0f - 1.0f; 1.620 + float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; 1.621 + float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; 1.622 + 1.623 + float u1 = x / float(mWidth); 1.624 + float v1 = y / float(mHeight); 1.625 + float u2 = (x + width) / float(mWidth); 1.626 + float v2 = (y + height) / float(mHeight); 1.627 + 1.628 + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); 1.629 + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); 1.630 + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); 1.631 + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); 1.632 + 1.633 + deviceContext->Unmap(mQuadVB, 0); 1.634 + 1.635 + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); 1.636 + static UINT startIdx = 0; 1.637 + deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); 1.638 + 1.639 + // Apply state 1.640 + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); 1.641 + 1.642 + static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; 1.643 + deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); 1.644 + 1.645 + deviceContext->RSSetState(NULL); 1.646 + 1.647 + // Apply shaders 1.648 + deviceContext->IASetInputLayout(mPassThroughIL); 1.649 + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); 1.650 + deviceContext->VSSetShader(mPassThroughVS, NULL, 0); 1.651 + deviceContext->PSSetShader(mPassThroughPS, NULL, 0); 1.652 + deviceContext->GSSetShader(NULL, NULL, 0); 1.653 + 1.654 + // Apply render targets 1.655 + mRenderer->setOneTimeRenderTarget(mBackBufferRTView); 1.656 + 1.657 + // Set the viewport 1.658 + D3D11_VIEWPORT viewport; 1.659 + viewport.TopLeftX = 0; 1.660 + viewport.TopLeftY = 0; 1.661 + viewport.Width = mWidth; 1.662 + viewport.Height = mHeight; 1.663 + viewport.MinDepth = 0.0f; 1.664 + viewport.MaxDepth = 1.0f; 1.665 + deviceContext->RSSetViewports(1, &viewport); 1.666 + 1.667 + // Apply textures 1.668 + deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); 1.669 + deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); 1.670 + 1.671 + // Draw 1.672 + deviceContext->Draw(4, 0); 1.673 + result = mSwapChain->Present(mSwapInterval, 0); 1.674 + 1.675 + if (result == DXGI_ERROR_DEVICE_REMOVED) 1.676 + { 1.677 + HRESULT removedReason = device->GetDeviceRemovedReason(); 1.678 + ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); 1.679 + return EGL_CONTEXT_LOST; 1.680 + } 1.681 + else if (result == DXGI_ERROR_DEVICE_RESET) 1.682 + { 1.683 + ERR("Present failed: the D3D11 device was reset from a bad command."); 1.684 + return EGL_CONTEXT_LOST; 1.685 + } 1.686 + else if (FAILED(result)) 1.687 + { 1.688 + ERR("Present failed with error code 0x%08X", result); 1.689 + } 1.690 + 1.691 + // Unbind 1.692 + static ID3D11ShaderResourceView *const nullSRV = NULL; 1.693 + deviceContext->PSSetShaderResources(0, 1, &nullSRV); 1.694 + 1.695 + mRenderer->unapplyRenderTargets(); 1.696 + mRenderer->markAllStateDirty(); 1.697 + 1.698 + return EGL_SUCCESS; 1.699 +} 1.700 + 1.701 +// Increments refcount on texture. 1.702 +// caller must Release() the returned texture 1.703 +ID3D11Texture2D *SwapChain11::getOffscreenTexture() 1.704 +{ 1.705 + if (mOffscreenTexture) 1.706 + { 1.707 + mOffscreenTexture->AddRef(); 1.708 + } 1.709 + 1.710 + return mOffscreenTexture; 1.711 +} 1.712 + 1.713 +// Increments refcount on view. 1.714 +// caller must Release() the returned view 1.715 +ID3D11RenderTargetView *SwapChain11::getRenderTarget() 1.716 +{ 1.717 + if (mOffscreenRTView) 1.718 + { 1.719 + mOffscreenRTView->AddRef(); 1.720 + } 1.721 + 1.722 + return mOffscreenRTView; 1.723 +} 1.724 + 1.725 +// Increments refcount on view. 1.726 +// caller must Release() the returned view 1.727 +ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() 1.728 +{ 1.729 + if (mOffscreenSRView) 1.730 + { 1.731 + mOffscreenSRView->AddRef(); 1.732 + } 1.733 + 1.734 + return mOffscreenSRView; 1.735 +} 1.736 + 1.737 +// Increments refcount on view. 1.738 +// caller must Release() the returned view 1.739 +ID3D11DepthStencilView *SwapChain11::getDepthStencil() 1.740 +{ 1.741 + if (mDepthStencilDSView) 1.742 + { 1.743 + mDepthStencilDSView->AddRef(); 1.744 + } 1.745 + 1.746 + return mDepthStencilDSView; 1.747 +} 1.748 + 1.749 +ID3D11Texture2D *SwapChain11::getDepthStencilTexture() 1.750 +{ 1.751 + if (mDepthStencilTexture) 1.752 + { 1.753 + mDepthStencilTexture->AddRef(); 1.754 + } 1.755 + 1.756 + return mDepthStencilTexture; 1.757 +} 1.758 + 1.759 +SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) 1.760 +{ 1.761 + ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); 1.762 + return static_cast<rx::SwapChain11*>(swapChain); 1.763 +} 1.764 + 1.765 +void SwapChain11::recreate() 1.766 +{ 1.767 + // possibly should use this method instead of reset 1.768 +} 1.769 + 1.770 +}