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