Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 "SharedSurfaceGL.h"
7 #include "GLContext.h"
8 #include "GLBlitHelper.h"
9 #include "ScopedGLHelpers.h"
10 #include "gfxImageSurface.h"
11 #include "mozilla/gfx/2D.h"
12 #include "GLReadTexImageHelper.h"
14 using namespace mozilla::gfx;
16 namespace mozilla {
17 namespace gl {
19 // |src| must begin and end locked, though we may
20 // temporarily unlock it if we need to.
21 void
22 SharedSurface_GL::ProdCopy(SharedSurface_GL* src, SharedSurface_GL* dest,
23 SurfaceFactory_GL* factory)
24 {
25 GLContext* gl = src->GL();
27 gl->MakeCurrent();
29 if (src->AttachType() == AttachmentType::Screen &&
30 dest->AttachType() == AttachmentType::Screen)
31 {
32 // Here, we actually need to blit through a temp surface, so let's make one.
33 nsAutoPtr<SharedSurface_GLTexture> tempSurf(
34 SharedSurface_GLTexture::Create(gl, gl,
35 factory->Formats(),
36 src->Size(),
37 factory->Caps().alpha));
39 ProdCopy(src, tempSurf, factory);
40 ProdCopy(tempSurf, dest, factory);
41 return;
42 }
44 if (src->AttachType() == AttachmentType::Screen) {
45 SharedSurface_GL* origLocked = gl->GetLockedSurface();
46 bool srcNeedsUnlock = false;
47 bool origNeedsRelock = false;
48 if (origLocked != src) {
49 if (origLocked) {
50 origLocked->UnlockProd();
51 origNeedsRelock = true;
52 }
54 src->LockProd();
55 srcNeedsUnlock = true;
56 }
58 if (dest->AttachType() == AttachmentType::GLTexture) {
59 GLuint destTex = dest->ProdTexture();
60 GLenum destTarget = dest->ProdTextureTarget();
62 gl->BlitHelper()->BlitFramebufferToTexture(0, destTex, src->Size(), dest->Size(), destTarget);
63 } else if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
64 GLuint destRB = dest->ProdRenderbuffer();
65 ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
67 gl->BlitHelper()->BlitFramebufferToFramebuffer(0, destWrapper.FB(),
68 src->Size(), dest->Size());
69 } else {
70 MOZ_CRASH("Unhandled dest->AttachType().");
71 }
73 if (srcNeedsUnlock)
74 src->UnlockProd();
76 if (origNeedsRelock)
77 origLocked->LockProd();
79 return;
80 }
82 if (dest->AttachType() == AttachmentType::Screen) {
83 SharedSurface_GL* origLocked = gl->GetLockedSurface();
84 bool destNeedsUnlock = false;
85 bool origNeedsRelock = false;
86 if (origLocked != dest) {
87 if (origLocked) {
88 origLocked->UnlockProd();
89 origNeedsRelock = true;
90 }
92 dest->LockProd();
93 destNeedsUnlock = true;
94 }
96 if (src->AttachType() == AttachmentType::GLTexture) {
97 GLuint srcTex = src->ProdTexture();
98 GLenum srcTarget = src->ProdTextureTarget();
100 gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0, src->Size(), dest->Size(), srcTarget);
101 } else if (src->AttachType() == AttachmentType::GLRenderbuffer) {
102 GLuint srcRB = src->ProdRenderbuffer();
103 ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
105 gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), 0,
106 src->Size(), dest->Size());
107 } else {
108 MOZ_CRASH("Unhandled src->AttachType().");
109 }
111 if (destNeedsUnlock)
112 dest->UnlockProd();
114 if (origNeedsRelock)
115 origLocked->LockProd();
117 return;
118 }
120 // Alright, done with cases involving Screen types.
121 // Only {src,dest}x{texture,renderbuffer} left.
123 if (src->AttachType() == AttachmentType::GLTexture) {
124 GLuint srcTex = src->ProdTexture();
125 GLenum srcTarget = src->ProdTextureTarget();
127 if (dest->AttachType() == AttachmentType::GLTexture) {
128 GLuint destTex = dest->ProdTexture();
129 GLenum destTarget = dest->ProdTextureTarget();
131 gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex,
132 src->Size(), dest->Size(),
133 srcTarget, destTarget);
135 return;
136 }
138 if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
139 GLuint destRB = dest->ProdRenderbuffer();
140 ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
142 gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(),
143 src->Size(), dest->Size(), srcTarget);
145 return;
146 }
148 MOZ_CRASH("Unhandled dest->AttachType().");
149 }
151 if (src->AttachType() == AttachmentType::GLRenderbuffer) {
152 GLuint srcRB = src->ProdRenderbuffer();
153 ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
155 if (dest->AttachType() == AttachmentType::GLTexture) {
156 GLuint destTex = dest->ProdTexture();
157 GLenum destTarget = dest->ProdTextureTarget();
159 gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex,
160 src->Size(), dest->Size(), destTarget);
162 return;
163 }
165 if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
166 GLuint destRB = dest->ProdRenderbuffer();
167 ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
169 gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), destWrapper.FB(),
170 src->Size(), dest->Size());
172 return;
173 }
175 MOZ_CRASH("Unhandled dest->AttachType().");
176 }
178 MOZ_CRASH("Unhandled src->AttachType().");
179 }
181 void
182 SharedSurface_GL::LockProd()
183 {
184 MOZ_ASSERT(!mIsLocked);
186 LockProdImpl();
188 mGL->LockSurface(this);
189 mIsLocked = true;
190 }
192 void
193 SharedSurface_GL::UnlockProd()
194 {
195 if (!mIsLocked)
196 return;
198 UnlockProdImpl();
200 mGL->UnlockSurface(this);
201 mIsLocked = false;
202 }
205 SurfaceFactory_GL::SurfaceFactory_GL(GLContext* gl,
206 SharedSurfaceType type,
207 const SurfaceCaps& caps)
208 : SurfaceFactory(type, caps)
209 , mGL(gl)
210 , mFormats(gl->ChooseGLFormats(caps))
211 {
212 ChooseBufferBits(caps, mDrawCaps, mReadCaps);
213 }
215 void
216 SurfaceFactory_GL::ChooseBufferBits(const SurfaceCaps& caps,
217 SurfaceCaps& drawCaps,
218 SurfaceCaps& readCaps) const
219 {
220 SurfaceCaps screenCaps;
222 screenCaps.color = caps.color;
223 screenCaps.alpha = caps.alpha;
224 screenCaps.bpp16 = caps.bpp16;
226 screenCaps.depth = caps.depth;
227 screenCaps.stencil = caps.stencil;
229 screenCaps.antialias = caps.antialias;
230 screenCaps.preserve = caps.preserve;
232 if (caps.antialias) {
233 drawCaps = screenCaps;
234 readCaps.Clear();
236 // Color caps need to be duplicated in readCaps.
237 readCaps.color = caps.color;
238 readCaps.alpha = caps.alpha;
239 readCaps.bpp16 = caps.bpp16;
240 } else {
241 drawCaps.Clear();
242 readCaps = screenCaps;
243 }
244 }
247 SharedSurface_Basic*
248 SharedSurface_Basic::Create(GLContext* gl,
249 const GLFormats& formats,
250 const IntSize& size,
251 bool hasAlpha)
252 {
253 gl->MakeCurrent();
254 GLuint tex = CreateTexture(gl, formats.color_texInternalFormat,
255 formats.color_texFormat,
256 formats.color_texType,
257 size);
259 SurfaceFormat format = SurfaceFormat::B8G8R8X8;
260 switch (formats.color_texInternalFormat) {
261 case LOCAL_GL_RGB:
262 case LOCAL_GL_RGB8:
263 if (formats.color_texType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
264 format = SurfaceFormat::R5G6B5;
265 else
266 format = SurfaceFormat::B8G8R8X8;
267 break;
268 case LOCAL_GL_RGBA:
269 case LOCAL_GL_RGBA8:
270 format = SurfaceFormat::B8G8R8A8;
271 break;
272 default:
273 MOZ_CRASH("Unhandled Tex format.");
274 }
275 return new SharedSurface_Basic(gl, size, hasAlpha, format, tex);
276 }
278 SharedSurface_Basic::SharedSurface_Basic(GLContext* gl,
279 const IntSize& size,
280 bool hasAlpha,
281 SurfaceFormat format,
282 GLuint tex)
283 : SharedSurface_GL(SharedSurfaceType::Basic,
284 AttachmentType::GLTexture,
285 gl,
286 size,
287 hasAlpha)
288 , mTex(tex), mFB(0)
289 {
290 mGL->MakeCurrent();
291 mGL->fGenFramebuffers(1, &mFB);
293 ScopedBindFramebuffer autoFB(mGL, mFB);
294 mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
295 LOCAL_GL_COLOR_ATTACHMENT0,
296 LOCAL_GL_TEXTURE_2D,
297 mTex,
298 0);
300 GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
301 if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
302 mGL->fDeleteFramebuffers(1, &mFB);
303 mFB = 0;
304 }
306 mData = Factory::CreateDataSourceSurfaceWithStride(size, format,
307 GetAlignedStride<4>(size.width * BytesPerPixel(format)));
308 }
310 SharedSurface_Basic::~SharedSurface_Basic()
311 {
312 if (!mGL->MakeCurrent())
313 return;
315 if (mFB)
316 mGL->fDeleteFramebuffers(1, &mFB);
318 mGL->fDeleteTextures(1, &mTex);
319 }
321 void
322 SharedSurface_Basic::Fence()
323 {
324 mGL->MakeCurrent();
326 ScopedBindFramebuffer autoFB(mGL, mFB);
328 DataSourceSurface::MappedSurface map;
329 mData->Map(DataSourceSurface::MapType::WRITE, &map);
330 nsRefPtr<gfxImageSurface> wrappedData =
331 new gfxImageSurface(map.mData,
332 ThebesIntSize(mData->GetSize()),
333 map.mStride,
334 SurfaceFormatToImageFormat(mData->GetFormat()));
335 ReadPixelsIntoImageSurface(mGL, wrappedData);
336 mData->Unmap();
337 }
341 SharedSurface_GLTexture*
342 SharedSurface_GLTexture::Create(GLContext* prodGL,
343 GLContext* consGL,
344 const GLFormats& formats,
345 const gfx::IntSize& size,
346 bool hasAlpha,
347 GLuint texture)
348 {
349 MOZ_ASSERT(prodGL);
350 MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL));
352 prodGL->MakeCurrent();
354 GLuint tex = texture;
356 bool ownsTex = false;
358 if (!tex) {
359 tex = CreateTextureForOffscreen(prodGL, formats, size);
360 ownsTex = true;
361 }
363 return new SharedSurface_GLTexture(prodGL, consGL, size, hasAlpha, tex, ownsTex);
364 }
366 SharedSurface_GLTexture::~SharedSurface_GLTexture()
367 {
368 if (!mGL->MakeCurrent())
369 return;
371 if (mOwnsTex) {
372 mGL->fDeleteTextures(1, &mTex);
373 }
375 if (mSync) {
376 mGL->fDeleteSync(mSync);
377 }
378 }
380 void
381 SharedSurface_GLTexture::Fence()
382 {
383 MutexAutoLock lock(mMutex);
384 mGL->MakeCurrent();
386 if (mConsGL && mGL->IsExtensionSupported(GLContext::ARB_sync)) {
387 if (mSync) {
388 mGL->fDeleteSync(mSync);
389 mSync = 0;
390 }
392 mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
393 if (mSync) {
394 mGL->fFlush();
395 return;
396 }
397 }
398 MOZ_ASSERT(!mSync);
400 mGL->fFinish();
401 }
403 bool
404 SharedSurface_GLTexture::WaitSync()
405 {
406 MutexAutoLock lock(mMutex);
407 if (!mSync) {
408 // We must have used glFinish instead of glFenceSync.
409 return true;
410 }
412 mConsGL->MakeCurrent();
413 MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
415 mConsGL->fWaitSync(mSync,
416 0,
417 LOCAL_GL_TIMEOUT_IGNORED);
418 mConsGL->fDeleteSync(mSync);
419 mSync = 0;
421 return true;
422 }
424 GLuint
425 SharedSurface_GLTexture::ConsTexture(GLContext* consGL)
426 {
427 MutexAutoLock lock(mMutex);
428 MOZ_ASSERT(consGL);
429 MOZ_ASSERT(mGL->SharesWith(consGL));
430 MOZ_ASSERT_IF(mConsGL, consGL == mConsGL);
432 mConsGL = consGL;
434 return mTex;
435 }
437 } /* namespace gfx */
438 } /* namespace mozilla */