gfx/angle/src/libGLESv2/renderer/SwapChain11.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial