Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "SharedSurfaceANGLE.h"
8 #include "GLContextEGL.h"
10 using namespace mozilla::gfx;
12 namespace mozilla {
13 namespace gl {
15 SurfaceFactory_ANGLEShareHandle*
16 SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl,
17 ID3D10Device1* d3d,
18 const SurfaceCaps& caps)
19 {
20 GLLibraryEGL* egl = &sEGLLibrary;
21 if (!egl)
22 return nullptr;
24 if (!egl->IsExtensionSupported(
25 GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle))
26 {
27 return nullptr;
28 }
30 return new SurfaceFactory_ANGLEShareHandle(gl, egl, d3d, caps);
31 }
33 EGLDisplay
34 SharedSurface_ANGLEShareHandle::Display()
35 {
36 return mEGL->Display();
37 }
40 SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle()
41 {
42 mEGL->fDestroySurface(Display(), mPBuffer);
43 }
45 void
46 SharedSurface_ANGLEShareHandle::LockProdImpl()
47 {
48 GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(mPBuffer);
49 }
51 void
52 SharedSurface_ANGLEShareHandle::UnlockProdImpl()
53 {
54 }
57 void
58 SharedSurface_ANGLEShareHandle::Fence()
59 {
60 mGL->fFinish();
61 }
63 bool
64 SharedSurface_ANGLEShareHandle::WaitSync()
65 {
66 // Since we glFinish in Fence(), we're always going to be resolved here.
67 return true;
68 }
70 static void
71 FillPBufferAttribs_ByBits(nsTArray<EGLint>& aAttrs,
72 int redBits, int greenBits,
73 int blueBits, int alphaBits,
74 int depthBits, int stencilBits)
75 {
76 aAttrs.Clear();
78 #if defined(A1) || defined(A2)
79 #error The temp-macro names we want are already defined.
80 #endif
82 #define A1(_x) do { aAttrs.AppendElement(_x); } while (0)
83 #define A2(_x,_y) do { A1(_x); A1(_y); } while (0)
85 A2(LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT);
86 A2(LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT);
88 A2(LOCAL_EGL_RED_SIZE, redBits);
89 A2(LOCAL_EGL_GREEN_SIZE, greenBits);
90 A2(LOCAL_EGL_BLUE_SIZE, blueBits);
91 A2(LOCAL_EGL_ALPHA_SIZE, alphaBits);
93 A2(LOCAL_EGL_DEPTH_SIZE, depthBits);
94 A2(LOCAL_EGL_STENCIL_SIZE, stencilBits);
96 A1(LOCAL_EGL_NONE);
97 #undef A1
98 #undef A2
99 }
101 static void
102 FillPBufferAttribs_BySizes(nsTArray<EGLint>& attribs,
103 bool bpp16, bool hasAlpha,
104 int depthBits, int stencilBits)
105 {
106 int red = 0;
107 int green = 0;
108 int blue = 0;
109 int alpha = 0;
111 if (bpp16) {
112 if (hasAlpha) {
113 red = green = blue = alpha = 4;
114 } else {
115 red = 5;
116 green = 6;
117 blue = 5;
118 }
119 } else {
120 red = green = blue = 8;
121 if (hasAlpha)
122 alpha = 8;
123 }
125 FillPBufferAttribs_ByBits(attribs,
126 red, green, blue, alpha,
127 depthBits, stencilBits);
128 }
130 static EGLConfig
131 ChooseConfig(GLContext* gl,
132 GLLibraryEGL* egl,
133 const SurfaceCaps& caps)
134 {
135 MOZ_ASSERT(egl);
136 MOZ_ASSERT(caps.color);
138 // We might want 24-bit depth, but we're only (fairly) sure to get 16-bit.
139 int depthBits = caps.depth ? 16 : 0;
140 int stencilBits = caps.stencil ? 8 : 0;
142 // Ok, now we have everything.
143 nsTArray<EGLint> attribs(32);
144 FillPBufferAttribs_BySizes(attribs,
145 caps.bpp16, caps.alpha,
146 depthBits, stencilBits);
148 // Time to try to get this config:
149 EGLConfig configs[64];
150 int numConfigs = sizeof(configs)/sizeof(EGLConfig);
151 int foundConfigs = 0;
153 if (!egl->fChooseConfig(egl->Display(),
154 attribs.Elements(),
155 configs, numConfigs,
156 &foundConfigs) ||
157 !foundConfigs)
158 {
159 NS_WARNING("No configs found for the requested formats.");
160 return EGL_NO_CONFIG;
161 }
163 // TODO: Pick a config progamatically instead of hoping that
164 // the first config will be minimally matching our request.
165 EGLConfig config = configs[0];
167 if (gl->DebugMode()) {
168 egl->DumpEGLConfig(config);
169 }
171 return config;
172 }
175 // Returns EGL_NO_SURFACE on error.
176 static EGLSurface CreatePBufferSurface(GLLibraryEGL* egl,
177 EGLDisplay display,
178 EGLConfig config,
179 const gfx::IntSize& size)
180 {
181 EGLint attribs[] = {
182 LOCAL_EGL_WIDTH, size.width,
183 LOCAL_EGL_HEIGHT, size.height,
184 LOCAL_EGL_NONE
185 };
187 EGLSurface surface = egl->fCreatePbufferSurface(display, config, attribs);
189 return surface;
190 }
192 SharedSurface_ANGLEShareHandle*
193 SharedSurface_ANGLEShareHandle::Create(GLContext* gl, ID3D10Device1* d3d,
194 EGLContext context, EGLConfig config,
195 const gfx::IntSize& size, bool hasAlpha)
196 {
197 GLLibraryEGL* egl = &sEGLLibrary;
198 MOZ_ASSERT(egl);
199 MOZ_ASSERT(egl->IsExtensionSupported(
200 GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle));
202 if (!context || !config)
203 return nullptr;
205 EGLDisplay display = egl->Display();
206 EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size);
207 if (!pbuffer)
208 return nullptr;
211 // Declare everything before 'goto's.
212 HANDLE shareHandle = nullptr;
213 nsRefPtr<ID3D10Texture2D> texture;
214 nsRefPtr<ID3D10ShaderResourceView> srv;
216 // On failure, goto CleanUpIfFailed.
217 // If |failed|, CleanUpIfFailed will clean up and return null.
218 bool failed = true;
219 HRESULT hr;
221 // Off to the races!
222 if (!egl->fQuerySurfacePointerANGLE(
223 display,
224 pbuffer,
225 LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
226 &shareHandle))
227 {
228 NS_ERROR("Failed to grab ShareHandle for PBuffer!");
229 goto CleanUpIfFailed;
230 }
232 // Ok, we have a valid PBuffer with ShareHandle.
233 // Let's attach it to D3D.
234 hr = d3d->OpenSharedResource(shareHandle,
235 __uuidof(ID3D10Texture2D),
236 getter_AddRefs(texture));
237 if (FAILED(hr)) {
238 NS_ERROR("Failed to open shared resource!");
239 goto CleanUpIfFailed;
240 }
242 hr = d3d->CreateShaderResourceView(texture, nullptr, getter_AddRefs(srv));
243 if (FAILED(hr)) {
244 NS_ERROR("Failed to create SRV!");
245 goto CleanUpIfFailed;
246 }
248 failed = false;
250 CleanUpIfFailed:
251 if (failed) {
252 NS_WARNING("CleanUpIfFailed");
253 egl->fDestroySurface(egl->Display(), pbuffer);
254 return nullptr;
255 }
257 return new SharedSurface_ANGLEShareHandle(gl, egl,
258 size, hasAlpha,
259 context, pbuffer,
260 texture, srv);
261 }
264 SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl,
265 GLLibraryEGL* egl,
266 ID3D10Device1* d3d,
267 const SurfaceCaps& caps)
268 : SurfaceFactory_GL(gl, SharedSurfaceType::EGLSurfaceANGLE, caps)
269 , mProdGL(gl)
270 , mEGL(egl)
271 , mConsD3D(d3d)
272 {
273 mConfig = ChooseConfig(mProdGL, mEGL, mReadCaps);
274 mContext = GLContextEGL::Cast(mProdGL)->GetEGLContext();
275 MOZ_ASSERT(mConfig && mContext);
276 }
278 } /* namespace gl */
279 } /* namespace mozilla */