1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/gl/GLScreenBuffer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,704 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "GLScreenBuffer.h" 1.10 + 1.11 +#include <cstring> 1.12 +#include "gfxImageSurface.h" 1.13 +#include "GLContext.h" 1.14 +#include "GLBlitHelper.h" 1.15 +#include "GLReadTexImageHelper.h" 1.16 +#include "SharedSurfaceGL.h" 1.17 +#include "SurfaceStream.h" 1.18 +#ifdef MOZ_WIDGET_GONK 1.19 +#include "SharedSurfaceGralloc.h" 1.20 +#include "nsXULAppAPI.h" 1.21 +#endif 1.22 +#ifdef XP_MACOSX 1.23 +#include "SharedSurfaceIO.h" 1.24 +#endif 1.25 +#include "ScopedGLHelpers.h" 1.26 +#include "gfx2DGlue.h" 1.27 + 1.28 +using namespace mozilla::gfx; 1.29 + 1.30 +namespace mozilla { 1.31 +namespace gl { 1.32 + 1.33 +GLScreenBuffer* 1.34 +GLScreenBuffer::Create(GLContext* gl, 1.35 + const gfx::IntSize& size, 1.36 + const SurfaceCaps& caps) 1.37 +{ 1.38 + if (caps.antialias && 1.39 + !gl->IsSupported(GLFeature::framebuffer_multisample)) 1.40 + { 1.41 + return nullptr; 1.42 + } 1.43 + 1.44 + SurfaceFactory_GL* factory = nullptr; 1.45 + 1.46 +#ifdef MOZ_WIDGET_GONK 1.47 + /* On B2G, we want a Gralloc factory, and we want one right at the start */ 1.48 + if (!factory && 1.49 + caps.surfaceAllocator && 1.50 + XRE_GetProcessType() != GeckoProcessType_Default) 1.51 + { 1.52 + factory = new SurfaceFactory_Gralloc(gl, caps); 1.53 + } 1.54 +#endif 1.55 +#ifdef XP_MACOSX 1.56 + /* On OSX, we want an IOSurface factory, and we want one right at the start */ 1.57 + if (!factory) 1.58 + { 1.59 + factory = new SurfaceFactory_IOSurface(gl, caps); 1.60 + } 1.61 +#endif 1.62 + 1.63 + if (!factory) 1.64 + factory = new SurfaceFactory_Basic(gl, caps); 1.65 + 1.66 + SurfaceStream* stream = SurfaceStream::CreateForType( 1.67 + SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread, 1.68 + caps.preserve), 1.69 + gl, 1.70 + nullptr); 1.71 + 1.72 + return new GLScreenBuffer(gl, caps, factory, stream); 1.73 +} 1.74 + 1.75 +GLScreenBuffer::~GLScreenBuffer() 1.76 +{ 1.77 + delete mDraw; 1.78 + delete mRead; 1.79 + 1.80 + // bug 914823: it is crucial to destroy the Factory _after_ we destroy 1.81 + // the SharedSurfaces around here! Reason: the shared surfaces will want 1.82 + // to ask the Allocator (e.g. the ClientLayerManager) to destroy their 1.83 + // buffers, but that Allocator may be kept alive by the Factory, 1.84 + // as it currently the case in SurfaceFactory_Gralloc holding a nsRefPtr 1.85 + // to the Allocator! 1.86 + delete mFactory; 1.87 +} 1.88 + 1.89 + 1.90 +void 1.91 +GLScreenBuffer::BindAsFramebuffer(GLContext* const gl, GLenum target) const 1.92 +{ 1.93 + GLuint drawFB = DrawFB(); 1.94 + GLuint readFB = ReadFB(); 1.95 + 1.96 + if (!gl->IsSupported(GLFeature::framebuffer_blit)) { 1.97 + MOZ_ASSERT(drawFB == readFB); 1.98 + gl->raw_fBindFramebuffer(target, readFB); 1.99 + return; 1.100 + } 1.101 + 1.102 + switch (target) { 1.103 + case LOCAL_GL_FRAMEBUFFER: 1.104 + gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB); 1.105 + gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB); 1.106 + break; 1.107 + 1.108 + case LOCAL_GL_DRAW_FRAMEBUFFER_EXT: 1.109 + if (!gl->IsSupported(GLFeature::framebuffer_blit)) 1.110 + NS_WARNING("DRAW_FRAMEBUFFER requested but unavailable."); 1.111 + 1.112 + gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB); 1.113 + break; 1.114 + 1.115 + case LOCAL_GL_READ_FRAMEBUFFER_EXT: 1.116 + if (!gl->IsSupported(GLFeature::framebuffer_blit)) 1.117 + NS_WARNING("READ_FRAMEBUFFER requested but unavailable."); 1.118 + 1.119 + gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB); 1.120 + break; 1.121 + 1.122 + default: 1.123 + MOZ_CRASH("Bad `target` for BindFramebuffer."); 1.124 + } 1.125 +} 1.126 + 1.127 +void 1.128 +GLScreenBuffer::BindFB(GLuint fb) 1.129 +{ 1.130 + GLuint drawFB = DrawFB(); 1.131 + GLuint readFB = ReadFB(); 1.132 + 1.133 + mUserDrawFB = fb; 1.134 + mUserReadFB = fb; 1.135 + mInternalDrawFB = (fb == 0) ? drawFB : fb; 1.136 + mInternalReadFB = (fb == 0) ? readFB : fb; 1.137 + 1.138 + if (mInternalDrawFB == mInternalReadFB) { 1.139 + mGL->raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mInternalDrawFB); 1.140 + } else { 1.141 + MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); 1.142 + mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); 1.143 + mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); 1.144 + } 1.145 + 1.146 +#ifdef DEBUG 1.147 + mInInternalMode_DrawFB = false; 1.148 + mInInternalMode_ReadFB = false; 1.149 +#endif 1.150 +} 1.151 + 1.152 +void 1.153 +GLScreenBuffer::BindDrawFB(GLuint fb) 1.154 +{ 1.155 + if (!mGL->IsSupported(GLFeature::framebuffer_blit)) { 1.156 + NS_WARNING("DRAW_FRAMEBUFFER requested, but unsupported."); 1.157 + 1.158 + mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, fb); 1.159 + } else { 1.160 + GLuint drawFB = DrawFB(); 1.161 + mUserDrawFB = fb; 1.162 + mInternalDrawFB = (fb == 0) ? drawFB : fb; 1.163 + 1.164 + mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); 1.165 + } 1.166 + 1.167 +#ifdef DEBUG 1.168 + mInInternalMode_DrawFB = false; 1.169 +#endif 1.170 +} 1.171 + 1.172 +void 1.173 +GLScreenBuffer::BindReadFB(GLuint fb) 1.174 +{ 1.175 + if (!mGL->IsSupported(GLFeature::framebuffer_blit)) { 1.176 + NS_WARNING("READ_FRAMEBUFFER requested, but unsupported."); 1.177 + 1.178 + mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, fb); 1.179 + } else { 1.180 + GLuint readFB = ReadFB(); 1.181 + mUserReadFB = fb; 1.182 + mInternalReadFB = (fb == 0) ? readFB : fb; 1.183 + 1.184 + mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); 1.185 + } 1.186 + 1.187 +#ifdef DEBUG 1.188 + mInInternalMode_ReadFB = false; 1.189 +#endif 1.190 +} 1.191 + 1.192 +void 1.193 +GLScreenBuffer::BindDrawFB_Internal(GLuint fb) 1.194 +{ 1.195 + mInternalDrawFB = mUserDrawFB = fb; 1.196 + mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); 1.197 + 1.198 +#ifdef DEBUG 1.199 + mInInternalMode_DrawFB = true; 1.200 +#endif 1.201 +} 1.202 + 1.203 +void 1.204 +GLScreenBuffer::BindReadFB_Internal(GLuint fb) 1.205 +{ 1.206 + mInternalReadFB = mUserReadFB = fb; 1.207 + mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); 1.208 + 1.209 +#ifdef DEBUG 1.210 + mInInternalMode_ReadFB = true; 1.211 +#endif 1.212 +} 1.213 + 1.214 + 1.215 +GLuint 1.216 +GLScreenBuffer::GetDrawFB() const 1.217 +{ 1.218 +#ifdef DEBUG 1.219 + MOZ_ASSERT(mGL->IsCurrent()); 1.220 + MOZ_ASSERT(!mInInternalMode_DrawFB); 1.221 + 1.222 + // Don't need a branch here, because: 1.223 + // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6 1.224 + // We use raw_ here because this is debug code and we need to see what 1.225 + // the driver thinks. 1.226 + GLuint actual = 0; 1.227 + mGL->raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual); 1.228 + 1.229 + GLuint predicted = mInternalDrawFB; 1.230 + if (predicted != actual) { 1.231 + printf_stderr("Misprediction: Bound draw FB predicted: %d. Was: %d.\n", 1.232 + predicted, actual); 1.233 + MOZ_ASSERT(false, "Draw FB binding misprediction!"); 1.234 + } 1.235 +#endif 1.236 + 1.237 + return mUserDrawFB; 1.238 +} 1.239 + 1.240 +GLuint 1.241 +GLScreenBuffer::GetReadFB() const 1.242 +{ 1.243 +#ifdef DEBUG 1.244 + MOZ_ASSERT(mGL->IsCurrent()); 1.245 + MOZ_ASSERT(!mInInternalMode_ReadFB); 1.246 + 1.247 + // We use raw_ here because this is debug code and we need to see what 1.248 + // the driver thinks. 1.249 + GLuint actual = 0; 1.250 + if (mGL->IsSupported(GLFeature::framebuffer_blit)) 1.251 + mGL->raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual); 1.252 + else 1.253 + mGL->raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)&actual); 1.254 + 1.255 + GLuint predicted = mInternalReadFB; 1.256 + if (predicted != actual) { 1.257 + printf_stderr("Misprediction: Bound read FB predicted: %d. Was: %d.\n", 1.258 + predicted, actual); 1.259 + MOZ_ASSERT(false, "Read FB binding misprediction!"); 1.260 + } 1.261 +#endif 1.262 + 1.263 + return mUserReadFB; 1.264 +} 1.265 + 1.266 +GLuint 1.267 +GLScreenBuffer::GetFB() const 1.268 +{ 1.269 + MOZ_ASSERT(GetDrawFB() == GetReadFB()); 1.270 + return GetDrawFB(); 1.271 +} 1.272 + 1.273 + 1.274 +void 1.275 +GLScreenBuffer::DeletingFB(GLuint fb) 1.276 +{ 1.277 + if (fb == mInternalDrawFB) { 1.278 + mInternalDrawFB = 0; 1.279 + mUserDrawFB = 0; 1.280 + } 1.281 + if (fb == mInternalReadFB) { 1.282 + mInternalReadFB = 0; 1.283 + mUserReadFB = 0; 1.284 + } 1.285 +} 1.286 + 1.287 + 1.288 +void 1.289 +GLScreenBuffer::AfterDrawCall() 1.290 +{ 1.291 + if (mUserDrawFB != 0) 1.292 + return; 1.293 + 1.294 + RequireBlit(); 1.295 +} 1.296 + 1.297 +void 1.298 +GLScreenBuffer::BeforeReadCall() 1.299 +{ 1.300 + if (mUserReadFB != 0) 1.301 + return; 1.302 + 1.303 + AssureBlitted(); 1.304 +} 1.305 + 1.306 +bool 1.307 +GLScreenBuffer::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, 1.308 + GLenum format, GLenum type, GLvoid *pixels) 1.309 +{ 1.310 + // If the currently bound framebuffer is backed by a SharedSurface_GL 1.311 + // then it might want to override how we read pixel data from it. 1.312 + // This is normally only the default framebuffer, but we can also 1.313 + // have SharedSurfaces bound to other framebuffers when doing 1.314 + // readback for BasicLayers. 1.315 + SharedSurface_GL* surf; 1.316 + if (GetReadFB() == 0) { 1.317 + surf = SharedSurf(); 1.318 + } else { 1.319 + surf = mGL->mFBOMapping[GetReadFB()]; 1.320 + } 1.321 + if (surf) { 1.322 + return surf->ReadPixels(x, y, width, height, format, type, pixels); 1.323 + } 1.324 + 1.325 + return false; 1.326 +} 1.327 + 1.328 +void 1.329 +GLScreenBuffer::RequireBlit() 1.330 +{ 1.331 + mNeedsBlit = true; 1.332 +} 1.333 + 1.334 +void 1.335 +GLScreenBuffer::AssureBlitted() 1.336 +{ 1.337 + if (!mNeedsBlit) 1.338 + return; 1.339 + 1.340 + if (mDraw) { 1.341 + GLuint drawFB = DrawFB(); 1.342 + GLuint readFB = ReadFB(); 1.343 + 1.344 + MOZ_ASSERT(drawFB != 0); 1.345 + MOZ_ASSERT(drawFB != readFB); 1.346 + MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); 1.347 + MOZ_ASSERT(mDraw->Size() == mRead->Size()); 1.348 + 1.349 + ScopedBindFramebuffer boundFB(mGL); 1.350 + ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false); 1.351 + 1.352 + BindReadFB_Internal(drawFB); 1.353 + BindDrawFB_Internal(readFB); 1.354 + 1.355 + const gfx::IntSize& srcSize = mDraw->Size(); 1.356 + const gfx::IntSize& destSize = mRead->Size(); 1.357 + 1.358 + mGL->raw_fBlitFramebuffer(0, 0, srcSize.width, srcSize.height, 1.359 + 0, 0, destSize.width, destSize.height, 1.360 + LOCAL_GL_COLOR_BUFFER_BIT, 1.361 + LOCAL_GL_NEAREST); 1.362 + // Done! 1.363 + } 1.364 + 1.365 + mNeedsBlit = false; 1.366 +} 1.367 + 1.368 +void 1.369 +GLScreenBuffer::Morph(SurfaceFactory_GL* newFactory, SurfaceStreamType streamType) 1.370 +{ 1.371 + MOZ_ASSERT(mStream); 1.372 + 1.373 + if (newFactory) { 1.374 + delete mFactory; 1.375 + mFactory = newFactory; 1.376 + } 1.377 + 1.378 + if (mStream->mType == streamType) 1.379 + return; 1.380 + 1.381 + SurfaceStream* newStream = SurfaceStream::CreateForType(streamType, mGL, mStream); 1.382 + MOZ_ASSERT(newStream); 1.383 + 1.384 + mStream = newStream; 1.385 +} 1.386 + 1.387 +void 1.388 +GLScreenBuffer::Attach(SharedSurface* surface, const gfx::IntSize& size) 1.389 +{ 1.390 + ScopedBindFramebuffer autoFB(mGL); 1.391 + 1.392 + SharedSurface_GL* surf = SharedSurface_GL::Cast(surface); 1.393 + if (mRead && SharedSurf()) 1.394 + SharedSurf()->UnlockProd(); 1.395 + 1.396 + surf->LockProd(); 1.397 + 1.398 + if (mRead && 1.399 + surf->AttachType() == SharedSurf()->AttachType() && 1.400 + size == Size()) 1.401 + { 1.402 + // Same size, same type, ready for reuse! 1.403 + mRead->Attach(surf); 1.404 + } else { 1.405 + // Else something changed, so resize: 1.406 + DrawBuffer* draw = CreateDraw(size); // Can be null. 1.407 + ReadBuffer* read = CreateRead(surf); 1.408 + MOZ_ASSERT(read); // Should never fail if SwapProd succeeded. 1.409 + 1.410 + delete mDraw; 1.411 + delete mRead; 1.412 + 1.413 + mDraw = draw; 1.414 + mRead = read; 1.415 + } 1.416 + 1.417 + // Check that we're all set up. 1.418 + MOZ_ASSERT(SharedSurf() == surf); 1.419 + 1.420 + if (!PreserveBuffer()) { 1.421 + // DiscardFramebuffer here could help perf on some mobile platforms. 1.422 + } 1.423 +} 1.424 + 1.425 +bool 1.426 +GLScreenBuffer::Swap(const gfx::IntSize& size) 1.427 +{ 1.428 + SharedSurface* nextSurf = mStream->SwapProducer(mFactory, size); 1.429 + if (!nextSurf) { 1.430 + SurfaceFactory_Basic basicFactory(mGL, mFactory->Caps()); 1.431 + nextSurf = mStream->SwapProducer(&basicFactory, size); 1.432 + if (!nextSurf) 1.433 + return false; 1.434 + 1.435 + NS_WARNING("SwapProd failed for sophisticated Factory type, fell back to Basic."); 1.436 + } 1.437 + MOZ_ASSERT(nextSurf); 1.438 + 1.439 + Attach(nextSurf, size); 1.440 + 1.441 + return true; 1.442 +} 1.443 + 1.444 +bool 1.445 +GLScreenBuffer::PublishFrame(const gfx::IntSize& size) 1.446 +{ 1.447 + AssureBlitted(); 1.448 + 1.449 + bool good = Swap(size); 1.450 + return good; 1.451 +} 1.452 + 1.453 +bool 1.454 +GLScreenBuffer::Resize(const gfx::IntSize& size) 1.455 +{ 1.456 + SharedSurface* surface = mStream->Resize(mFactory, size); 1.457 + if (!surface) 1.458 + return false; 1.459 + 1.460 + Attach(surface, size); 1.461 + return true; 1.462 +} 1.463 + 1.464 +DrawBuffer* 1.465 +GLScreenBuffer::CreateDraw(const gfx::IntSize& size) 1.466 +{ 1.467 + GLContext* gl = mFactory->GL(); 1.468 + const GLFormats& formats = mFactory->Formats(); 1.469 + const SurfaceCaps& caps = mFactory->DrawCaps(); 1.470 + 1.471 + return DrawBuffer::Create(gl, caps, formats, size); 1.472 +} 1.473 + 1.474 +ReadBuffer* 1.475 +GLScreenBuffer::CreateRead(SharedSurface_GL* surf) 1.476 +{ 1.477 + GLContext* gl = mFactory->GL(); 1.478 + const GLFormats& formats = mFactory->Formats(); 1.479 + const SurfaceCaps& caps = mFactory->ReadCaps(); 1.480 + 1.481 + return ReadBuffer::Create(gl, caps, formats, surf); 1.482 +} 1.483 + 1.484 +void 1.485 +GLScreenBuffer::Readback(SharedSurface_GL* src, DataSourceSurface* dest) 1.486 +{ 1.487 + MOZ_ASSERT(src && dest); 1.488 + DataSourceSurface::MappedSurface ms; 1.489 + dest->Map(DataSourceSurface::MapType::READ, &ms); 1.490 + nsRefPtr<gfxImageSurface> wrappedDest = 1.491 + new gfxImageSurface(ms.mData, 1.492 + ThebesIntSize(dest->GetSize()), 1.493 + ms.mStride, 1.494 + SurfaceFormatToImageFormat(dest->GetFormat())); 1.495 + DeprecatedReadback(src, wrappedDest); 1.496 + dest->Unmap(); 1.497 +} 1.498 + 1.499 +void 1.500 +GLScreenBuffer::DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest) 1.501 +{ 1.502 + MOZ_ASSERT(src && dest); 1.503 + MOZ_ASSERT(ToIntSize(dest->GetSize()) == src->Size()); 1.504 + MOZ_ASSERT(dest->Format() == (src->HasAlpha() ? gfxImageFormat::ARGB32 1.505 + : gfxImageFormat::RGB24)); 1.506 + 1.507 + mGL->MakeCurrent(); 1.508 + 1.509 + bool needsSwap = src != SharedSurf(); 1.510 + if (needsSwap) { 1.511 + SharedSurf()->UnlockProd(); 1.512 + src->LockProd(); 1.513 + } 1.514 + 1.515 + ReadBuffer* buffer = CreateRead(src); 1.516 + MOZ_ASSERT(buffer); 1.517 + 1.518 + ScopedBindFramebuffer autoFB(mGL, buffer->FB()); 1.519 + ReadPixelsIntoImageSurface(mGL, dest); 1.520 + 1.521 + delete buffer; 1.522 + 1.523 + if (needsSwap) { 1.524 + src->UnlockProd(); 1.525 + SharedSurf()->LockProd(); 1.526 + } 1.527 +} 1.528 + 1.529 +DrawBuffer* 1.530 +DrawBuffer::Create(GLContext* const gl, 1.531 + const SurfaceCaps& caps, 1.532 + const GLFormats& formats, 1.533 + const gfx::IntSize& size) 1.534 +{ 1.535 + if (!caps.color) { 1.536 + MOZ_ASSERT(!caps.alpha && !caps.depth && !caps.stencil); 1.537 + 1.538 + // Nothing is needed. 1.539 + return nullptr; 1.540 + } 1.541 + 1.542 + GLuint colorMSRB = 0; 1.543 + GLuint depthRB = 0; 1.544 + GLuint stencilRB = 0; 1.545 + 1.546 + GLuint* pColorMSRB = caps.antialias ? &colorMSRB : nullptr; 1.547 + GLuint* pDepthRB = caps.depth ? &depthRB : nullptr; 1.548 + GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr; 1.549 + 1.550 + if (!formats.color_rbFormat) 1.551 + pColorMSRB = nullptr; 1.552 + 1.553 + if (pDepthRB && pStencilRB) { 1.554 + if (!formats.depth && !formats.depthStencil) 1.555 + pDepthRB = nullptr; 1.556 + 1.557 + if (!formats.stencil && !formats.depthStencil) 1.558 + pStencilRB = nullptr; 1.559 + } else { 1.560 + if (!formats.depth) 1.561 + pDepthRB = nullptr; 1.562 + 1.563 + if (!formats.stencil) 1.564 + pStencilRB = nullptr; 1.565 + } 1.566 + 1.567 + CreateRenderbuffersForOffscreen(gl, formats, size, caps.antialias, 1.568 + pColorMSRB, pDepthRB, pStencilRB); 1.569 + 1.570 + GLuint fb = 0; 1.571 + gl->fGenFramebuffers(1, &fb); 1.572 + gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb); 1.573 + MOZ_ASSERT(gl->IsFramebufferComplete(fb)); 1.574 + 1.575 + return new DrawBuffer(gl, size, fb, colorMSRB, depthRB, stencilRB); 1.576 +} 1.577 + 1.578 +DrawBuffer::~DrawBuffer() 1.579 +{ 1.580 + mGL->MakeCurrent(); 1.581 + 1.582 + GLuint fb = mFB; 1.583 + GLuint rbs[] = { 1.584 + mColorMSRB, 1.585 + mDepthRB, 1.586 + mStencilRB 1.587 + }; 1.588 + 1.589 + mGL->fDeleteFramebuffers(1, &fb); 1.590 + mGL->fDeleteRenderbuffers(3, rbs); 1.591 +} 1.592 + 1.593 + 1.594 + 1.595 + 1.596 + 1.597 + 1.598 +ReadBuffer* 1.599 +ReadBuffer::Create(GLContext* gl, 1.600 + const SurfaceCaps& caps, 1.601 + const GLFormats& formats, 1.602 + SharedSurface_GL* surf) 1.603 +{ 1.604 + MOZ_ASSERT(surf); 1.605 + 1.606 + if (surf->AttachType() == AttachmentType::Screen) { 1.607 + // Don't need anything. Our read buffer will be the 'screen'. 1.608 + 1.609 + return new ReadBuffer(gl, 1.610 + 0, 0, 0, 1.611 + surf); 1.612 + } 1.613 + 1.614 + GLuint depthRB = 0; 1.615 + GLuint stencilRB = 0; 1.616 + 1.617 + GLuint* pDepthRB = caps.depth ? &depthRB : nullptr; 1.618 + GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr; 1.619 + 1.620 + CreateRenderbuffersForOffscreen(gl, formats, surf->Size(), caps.antialias, 1.621 + nullptr, pDepthRB, pStencilRB); 1.622 + 1.623 + GLuint colorTex = 0; 1.624 + GLuint colorRB = 0; 1.625 + GLenum target = 0; 1.626 + 1.627 + switch (surf->AttachType()) { 1.628 + case AttachmentType::GLTexture: 1.629 + colorTex = surf->ProdTexture(); 1.630 + target = surf->ProdTextureTarget(); 1.631 + break; 1.632 + case AttachmentType::GLRenderbuffer: 1.633 + colorRB = surf->ProdRenderbuffer(); 1.634 + break; 1.635 + default: 1.636 + MOZ_CRASH("Unknown attachment type?"); 1.637 + } 1.638 + MOZ_ASSERT(colorTex || colorRB); 1.639 + 1.640 + GLuint fb = 0; 1.641 + gl->fGenFramebuffers(1, &fb); 1.642 + gl->AttachBuffersToFB(colorTex, colorRB, depthRB, stencilRB, fb, target); 1.643 + gl->mFBOMapping[fb] = surf; 1.644 + 1.645 + MOZ_ASSERT(gl->IsFramebufferComplete(fb)); 1.646 + 1.647 + return new ReadBuffer(gl, 1.648 + fb, depthRB, stencilRB, 1.649 + surf); 1.650 +} 1.651 + 1.652 +ReadBuffer::~ReadBuffer() 1.653 +{ 1.654 + mGL->MakeCurrent(); 1.655 + 1.656 + GLuint fb = mFB; 1.657 + GLuint rbs[] = { 1.658 + mDepthRB, 1.659 + mStencilRB 1.660 + }; 1.661 + 1.662 + mGL->fDeleteFramebuffers(1, &fb); 1.663 + mGL->fDeleteRenderbuffers(2, rbs); 1.664 + mGL->mFBOMapping.erase(mFB); 1.665 +} 1.666 + 1.667 +void 1.668 +ReadBuffer::Attach(SharedSurface_GL* surf) 1.669 +{ 1.670 + MOZ_ASSERT(surf && mSurf); 1.671 + MOZ_ASSERT(surf->AttachType() == mSurf->AttachType()); 1.672 + MOZ_ASSERT(surf->Size() == mSurf->Size()); 1.673 + 1.674 + // Nothing else is needed for AttachType Screen. 1.675 + if (surf->AttachType() != AttachmentType::Screen) { 1.676 + GLuint colorTex = 0; 1.677 + GLuint colorRB = 0; 1.678 + GLenum target = 0; 1.679 + 1.680 + switch (surf->AttachType()) { 1.681 + case AttachmentType::GLTexture: 1.682 + colorTex = surf->ProdTexture(); 1.683 + target = surf->ProdTextureTarget(); 1.684 + break; 1.685 + case AttachmentType::GLRenderbuffer: 1.686 + colorRB = surf->ProdRenderbuffer(); 1.687 + break; 1.688 + default: 1.689 + MOZ_CRASH("Unknown attachment type?"); 1.690 + } 1.691 + 1.692 + mGL->AttachBuffersToFB(colorTex, colorRB, 0, 0, mFB, target); 1.693 + mGL->mFBOMapping[mFB] = surf; 1.694 + MOZ_ASSERT(mGL->IsFramebufferComplete(mFB)); 1.695 + } 1.696 + 1.697 + mSurf = surf; 1.698 +} 1.699 + 1.700 +const gfx::IntSize& 1.701 +ReadBuffer::Size() const 1.702 +{ 1.703 + return mSurf->Size(); 1.704 +} 1.705 + 1.706 +} /* namespace gl */ 1.707 +} /* namespace mozilla */