gfx/angle/src/libGLESv2/renderer/SwapChain9.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 // SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
michael@0 9
michael@0 10 #include "libGLESv2/renderer/SwapChain9.h"
michael@0 11 #include "libGLESv2/renderer/renderer9_utils.h"
michael@0 12 #include "libGLESv2/renderer/Renderer9.h"
michael@0 13
michael@0 14 namespace rx
michael@0 15 {
michael@0 16
michael@0 17 SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle,
michael@0 18 GLenum backBufferFormat, GLenum depthBufferFormat)
michael@0 19 : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
michael@0 20 {
michael@0 21 mSwapChain = NULL;
michael@0 22 mBackBuffer = NULL;
michael@0 23 mDepthStencil = NULL;
michael@0 24 mRenderTarget = NULL;
michael@0 25 mOffscreenTexture = NULL;
michael@0 26 mWidth = -1;
michael@0 27 mHeight = -1;
michael@0 28 mSwapInterval = -1;
michael@0 29 }
michael@0 30
michael@0 31 SwapChain9::~SwapChain9()
michael@0 32 {
michael@0 33 release();
michael@0 34 }
michael@0 35
michael@0 36 void SwapChain9::release()
michael@0 37 {
michael@0 38 if (mSwapChain)
michael@0 39 {
michael@0 40 mSwapChain->Release();
michael@0 41 mSwapChain = NULL;
michael@0 42 }
michael@0 43
michael@0 44 if (mBackBuffer)
michael@0 45 {
michael@0 46 mBackBuffer->Release();
michael@0 47 mBackBuffer = NULL;
michael@0 48 }
michael@0 49
michael@0 50 if (mDepthStencil)
michael@0 51 {
michael@0 52 mDepthStencil->Release();
michael@0 53 mDepthStencil = NULL;
michael@0 54 }
michael@0 55
michael@0 56 if (mRenderTarget)
michael@0 57 {
michael@0 58 mRenderTarget->Release();
michael@0 59 mRenderTarget = NULL;
michael@0 60 }
michael@0 61
michael@0 62 if (mOffscreenTexture)
michael@0 63 {
michael@0 64 mOffscreenTexture->Release();
michael@0 65 mOffscreenTexture = NULL;
michael@0 66 }
michael@0 67
michael@0 68 if (mWindow)
michael@0 69 mShareHandle = NULL;
michael@0 70 }
michael@0 71
michael@0 72 static DWORD convertInterval(EGLint interval)
michael@0 73 {
michael@0 74 switch(interval)
michael@0 75 {
michael@0 76 case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
michael@0 77 case 1: return D3DPRESENT_INTERVAL_ONE;
michael@0 78 case 2: return D3DPRESENT_INTERVAL_TWO;
michael@0 79 case 3: return D3DPRESENT_INTERVAL_THREE;
michael@0 80 case 4: return D3DPRESENT_INTERVAL_FOUR;
michael@0 81 default: UNREACHABLE();
michael@0 82 }
michael@0 83
michael@0 84 return D3DPRESENT_INTERVAL_DEFAULT;
michael@0 85 }
michael@0 86
michael@0 87 EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight)
michael@0 88 {
michael@0 89 // D3D9 does not support resizing swap chains without recreating them
michael@0 90 return reset(backbufferWidth, backbufferHeight, mSwapInterval);
michael@0 91 }
michael@0 92
michael@0 93 EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
michael@0 94 {
michael@0 95 IDirect3DDevice9 *device = mRenderer->getDevice();
michael@0 96
michael@0 97 if (device == NULL)
michael@0 98 {
michael@0 99 return EGL_BAD_ACCESS;
michael@0 100 }
michael@0 101
michael@0 102 // Evict all non-render target textures to system memory and release all resources
michael@0 103 // before reallocating them to free up as much video memory as possible.
michael@0 104 device->EvictManagedResources();
michael@0 105
michael@0 106 HRESULT result;
michael@0 107
michael@0 108 // Release specific resources to free up memory for the new render target, while the
michael@0 109 // old render target still exists for the purpose of preserving its contents.
michael@0 110 if (mSwapChain)
michael@0 111 {
michael@0 112 mSwapChain->Release();
michael@0 113 mSwapChain = NULL;
michael@0 114 }
michael@0 115
michael@0 116 if (mBackBuffer)
michael@0 117 {
michael@0 118 mBackBuffer->Release();
michael@0 119 mBackBuffer = NULL;
michael@0 120 }
michael@0 121
michael@0 122 if (mOffscreenTexture)
michael@0 123 {
michael@0 124 mOffscreenTexture->Release();
michael@0 125 mOffscreenTexture = NULL;
michael@0 126 }
michael@0 127
michael@0 128 if (mDepthStencil)
michael@0 129 {
michael@0 130 mDepthStencil->Release();
michael@0 131 mDepthStencil = NULL;
michael@0 132 }
michael@0 133
michael@0 134 HANDLE *pShareHandle = NULL;
michael@0 135 if (!mWindow && mRenderer->getShareHandleSupport())
michael@0 136 {
michael@0 137 pShareHandle = &mShareHandle;
michael@0 138 }
michael@0 139
michael@0 140 result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
michael@0 141 gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT,
michael@0 142 &mOffscreenTexture, pShareHandle);
michael@0 143 if (FAILED(result))
michael@0 144 {
michael@0 145 ERR("Could not create offscreen texture: %08lX", result);
michael@0 146 release();
michael@0 147
michael@0 148 if (d3d9::isDeviceLostError(result))
michael@0 149 {
michael@0 150 return EGL_CONTEXT_LOST;
michael@0 151 }
michael@0 152 else
michael@0 153 {
michael@0 154 return EGL_BAD_ALLOC;
michael@0 155 }
michael@0 156 }
michael@0 157
michael@0 158 IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
michael@0 159
michael@0 160 result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
michael@0 161 ASSERT(SUCCEEDED(result));
michael@0 162
michael@0 163 if (oldRenderTarget)
michael@0 164 {
michael@0 165 RECT rect =
michael@0 166 {
michael@0 167 0, 0,
michael@0 168 mWidth, mHeight
michael@0 169 };
michael@0 170
michael@0 171 if (rect.right > static_cast<LONG>(backbufferWidth))
michael@0 172 {
michael@0 173 rect.right = backbufferWidth;
michael@0 174 }
michael@0 175
michael@0 176 if (rect.bottom > static_cast<LONG>(backbufferHeight))
michael@0 177 {
michael@0 178 rect.bottom = backbufferHeight;
michael@0 179 }
michael@0 180
michael@0 181 mRenderer->endScene();
michael@0 182
michael@0 183 result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
michael@0 184 ASSERT(SUCCEEDED(result));
michael@0 185
michael@0 186 oldRenderTarget->Release();
michael@0 187 }
michael@0 188
michael@0 189 if (mWindow)
michael@0 190 {
michael@0 191 D3DPRESENT_PARAMETERS presentParameters = {0};
michael@0 192 presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat);
michael@0 193 presentParameters.BackBufferCount = 1;
michael@0 194 presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat);
michael@0 195 presentParameters.EnableAutoDepthStencil = FALSE;
michael@0 196 presentParameters.Flags = 0;
michael@0 197 presentParameters.hDeviceWindow = mWindow;
michael@0 198 presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
michael@0 199 presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
michael@0 200 presentParameters.PresentationInterval = convertInterval(swapInterval);
michael@0 201 presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
michael@0 202 presentParameters.Windowed = TRUE;
michael@0 203 presentParameters.BackBufferWidth = backbufferWidth;
michael@0 204 presentParameters.BackBufferHeight = backbufferHeight;
michael@0 205
michael@0 206 // http://crbug.com/140239
michael@0 207 // http://crbug.com/143434
michael@0 208 //
michael@0 209 // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
michael@0 210 // when using the integrated Intel. This rounds the width up rather than down.
michael@0 211 //
michael@0 212 // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
michael@0 213 // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
michael@0 214 if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL)
michael@0 215 {
michael@0 216 presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
michael@0 217 }
michael@0 218
michael@0 219 result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
michael@0 220
michael@0 221 if (FAILED(result))
michael@0 222 {
michael@0 223 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
michael@0 224
michael@0 225 ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
michael@0 226 release();
michael@0 227
michael@0 228 if (d3d9::isDeviceLostError(result))
michael@0 229 {
michael@0 230 return EGL_CONTEXT_LOST;
michael@0 231 }
michael@0 232 else
michael@0 233 {
michael@0 234 return EGL_BAD_ALLOC;
michael@0 235 }
michael@0 236 }
michael@0 237
michael@0 238 result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
michael@0 239 ASSERT(SUCCEEDED(result));
michael@0 240 InvalidateRect(mWindow, NULL, FALSE);
michael@0 241 }
michael@0 242
michael@0 243 if (mDepthBufferFormat != GL_NONE)
michael@0 244 {
michael@0 245 result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
michael@0 246 gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat),
michael@0 247 D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL);
michael@0 248
michael@0 249 if (FAILED(result))
michael@0 250 {
michael@0 251 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
michael@0 252
michael@0 253 ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
michael@0 254 release();
michael@0 255
michael@0 256 if (d3d9::isDeviceLostError(result))
michael@0 257 {
michael@0 258 return EGL_CONTEXT_LOST;
michael@0 259 }
michael@0 260 else
michael@0 261 {
michael@0 262 return EGL_BAD_ALLOC;
michael@0 263 }
michael@0 264 }
michael@0 265 }
michael@0 266
michael@0 267 mWidth = backbufferWidth;
michael@0 268 mHeight = backbufferHeight;
michael@0 269 mSwapInterval = swapInterval;
michael@0 270
michael@0 271 return EGL_SUCCESS;
michael@0 272 }
michael@0 273
michael@0 274 // parameters should be validated/clamped by caller
michael@0 275 EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
michael@0 276 {
michael@0 277 if (!mSwapChain)
michael@0 278 {
michael@0 279 return EGL_SUCCESS;
michael@0 280 }
michael@0 281
michael@0 282 IDirect3DDevice9 *device = mRenderer->getDevice();
michael@0 283
michael@0 284 // Disable all pipeline operations
michael@0 285 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
michael@0 286 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
michael@0 287 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
michael@0 288 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
michael@0 289 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
michael@0 290 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
michael@0 291 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
michael@0 292 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
michael@0 293 device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
michael@0 294 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
michael@0 295 device->SetPixelShader(NULL);
michael@0 296 device->SetVertexShader(NULL);
michael@0 297
michael@0 298 device->SetRenderTarget(0, mBackBuffer);
michael@0 299 device->SetDepthStencilSurface(NULL);
michael@0 300
michael@0 301 device->SetTexture(0, mOffscreenTexture);
michael@0 302 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
michael@0 303 device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
michael@0 304 device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
michael@0 305 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
michael@0 306 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
michael@0 307 device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
michael@0 308 device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
michael@0 309 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
michael@0 310
michael@0 311 D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
michael@0 312 device->SetViewport(&viewport);
michael@0 313
michael@0 314 float x1 = x - 0.5f;
michael@0 315 float y1 = (mHeight - y - height) - 0.5f;
michael@0 316 float x2 = (x + width) - 0.5f;
michael@0 317 float y2 = (mHeight - y) - 0.5f;
michael@0 318
michael@0 319 float u1 = x / float(mWidth);
michael@0 320 float v1 = y / float(mHeight);
michael@0 321 float u2 = (x + width) / float(mWidth);
michael@0 322 float v2 = (y + height) / float(mHeight);
michael@0 323
michael@0 324 float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
michael@0 325 {x2, y1, 0.0f, 1.0f, u2, v2},
michael@0 326 {x2, y2, 0.0f, 1.0f, u2, v1},
michael@0 327 {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v
michael@0 328
michael@0 329 mRenderer->startScene();
michael@0 330 device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
michael@0 331 mRenderer->endScene();
michael@0 332
michael@0 333 device->SetTexture(0, NULL);
michael@0 334
michael@0 335 RECT rect =
michael@0 336 {
michael@0 337 x, mHeight - y - height,
michael@0 338 x + width, mHeight - y
michael@0 339 };
michael@0 340
michael@0 341 HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
michael@0 342
michael@0 343 mRenderer->markAllStateDirty();
michael@0 344
michael@0 345 if (d3d9::isDeviceLostError(result))
michael@0 346 {
michael@0 347 return EGL_CONTEXT_LOST;
michael@0 348 }
michael@0 349
michael@0 350 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
michael@0 351 {
michael@0 352 return EGL_BAD_ALLOC;
michael@0 353 }
michael@0 354
michael@0 355 ASSERT(SUCCEEDED(result));
michael@0 356
michael@0 357 return EGL_SUCCESS;
michael@0 358 }
michael@0 359
michael@0 360 // Increments refcount on surface.
michael@0 361 // caller must Release() the returned surface
michael@0 362 IDirect3DSurface9 *SwapChain9::getRenderTarget()
michael@0 363 {
michael@0 364 if (mRenderTarget)
michael@0 365 {
michael@0 366 mRenderTarget->AddRef();
michael@0 367 }
michael@0 368
michael@0 369 return mRenderTarget;
michael@0 370 }
michael@0 371
michael@0 372 // Increments refcount on surface.
michael@0 373 // caller must Release() the returned surface
michael@0 374 IDirect3DSurface9 *SwapChain9::getDepthStencil()
michael@0 375 {
michael@0 376 if (mDepthStencil)
michael@0 377 {
michael@0 378 mDepthStencil->AddRef();
michael@0 379 }
michael@0 380
michael@0 381 return mDepthStencil;
michael@0 382 }
michael@0 383
michael@0 384 // Increments refcount on texture.
michael@0 385 // caller must Release() the returned texture
michael@0 386 IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
michael@0 387 {
michael@0 388 if (mOffscreenTexture)
michael@0 389 {
michael@0 390 mOffscreenTexture->AddRef();
michael@0 391 }
michael@0 392
michael@0 393 return mOffscreenTexture;
michael@0 394 }
michael@0 395
michael@0 396 SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain)
michael@0 397 {
michael@0 398 ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain));
michael@0 399 return static_cast<rx::SwapChain9*>(swapChain);
michael@0 400 }
michael@0 401
michael@0 402 void SwapChain9::recreate()
michael@0 403 {
michael@0 404 if (!mSwapChain)
michael@0 405 {
michael@0 406 return;
michael@0 407 }
michael@0 408
michael@0 409 IDirect3DDevice9 *device = mRenderer->getDevice();
michael@0 410 if (device == NULL)
michael@0 411 {
michael@0 412 return;
michael@0 413 }
michael@0 414
michael@0 415 D3DPRESENT_PARAMETERS presentParameters;
michael@0 416 HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
michael@0 417 ASSERT(SUCCEEDED(result));
michael@0 418
michael@0 419 IDirect3DSwapChain9* newSwapChain = NULL;
michael@0 420 result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
michael@0 421 if (FAILED(result))
michael@0 422 {
michael@0 423 return;
michael@0 424 }
michael@0 425
michael@0 426 mSwapChain->Release();
michael@0 427 mSwapChain = newSwapChain;
michael@0 428
michael@0 429 mBackBuffer->Release();
michael@0 430 result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
michael@0 431 ASSERT(SUCCEEDED(result));
michael@0 432 }
michael@0 433
michael@0 434 }

mercurial