void GLScreenBuffer::Attach(SharedSurface* surface, const gfx::IntSize& size) { ScopedBindFramebuffer autoFB(mGL); SharedSurface_GL* surf = SharedSurface_GL::Cast(surface); if (mRead && SharedSurf()) SharedSurf()->UnlockProd(); surf->LockProd(); if (mRead && surf->AttachType() == SharedSurf()->AttachType() && size == Size()) { // Same size, same type, ready for reuse! mRead->Attach(surf); } else { // Else something changed, so resize: DrawBuffer* draw = CreateDraw(size); // Can be null. ReadBuffer* read = CreateRead(surf); MOZ_ASSERT(read); // Should never fail if SwapProd succeeded. delete mDraw; delete mRead; mDraw = draw; mRead = read; } // Check that we're all set up. MOZ_ASSERT(SharedSurf() == surf); if (!PreserveBuffer()) { // DiscardFramebuffer here could help perf on some mobile platforms. } }
// |src| must begin and end locked, though we may // temporarily unlock it if we need to. void SharedSurface_GL::ProdCopy(SharedSurface_GL* src, SharedSurface_GL* dest, SurfaceFactory_GL* factory) { GLContext* gl = src->GL(); gl->MakeCurrent(); if (src->AttachType() == AttachmentType::Screen && dest->AttachType() == AttachmentType::Screen) { // Here, we actually need to blit through a temp surface, so let's make one. nsAutoPtr<SharedSurface_GLTexture> tempSurf( SharedSurface_GLTexture::Create(gl, gl, factory->Formats(), src->Size(), factory->Caps().alpha)); ProdCopy(src, tempSurf, factory); ProdCopy(tempSurf, dest, factory); return; } if (src->AttachType() == AttachmentType::Screen) { SharedSurface_GL* origLocked = gl->GetLockedSurface(); bool srcNeedsUnlock = false; bool origNeedsRelock = false; if (origLocked != src) { if (origLocked) { origLocked->UnlockProd(); origNeedsRelock = true; } src->LockProd(); srcNeedsUnlock = true; } if (dest->AttachType() == AttachmentType::GLTexture) { GLuint destTex = dest->ProdTexture(); GLenum destTarget = dest->ProdTextureTarget(); gl->BlitHelper()->BlitFramebufferToTexture(0, destTex, src->Size(), dest->Size(), destTarget); } else if (dest->AttachType() == AttachmentType::GLRenderbuffer) { GLuint destRB = dest->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); gl->BlitHelper()->BlitFramebufferToFramebuffer(0, destWrapper.FB(), src->Size(), dest->Size()); } else { MOZ_CRASH("Unhandled dest->AttachType()."); } if (srcNeedsUnlock) src->UnlockProd(); if (origNeedsRelock) origLocked->LockProd(); return; } if (dest->AttachType() == AttachmentType::Screen) { SharedSurface_GL* origLocked = gl->GetLockedSurface(); bool destNeedsUnlock = false; bool origNeedsRelock = false; if (origLocked != dest) { if (origLocked) { origLocked->UnlockProd(); origNeedsRelock = true; } dest->LockProd(); destNeedsUnlock = true; } if (src->AttachType() == AttachmentType::GLTexture) { GLuint srcTex = src->ProdTexture(); GLenum srcTarget = src->ProdTextureTarget(); gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0, src->Size(), dest->Size(), srcTarget); } else if (src->AttachType() == AttachmentType::GLRenderbuffer) { GLuint srcRB = src->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB); gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), 0, src->Size(), dest->Size()); } else { MOZ_CRASH("Unhandled src->AttachType()."); } if (destNeedsUnlock) dest->UnlockProd(); if (origNeedsRelock) origLocked->LockProd(); return; } // Alright, done with cases involving Screen types. // Only {src,dest}x{texture,renderbuffer} left. if (src->AttachType() == AttachmentType::GLTexture) { GLuint srcTex = src->ProdTexture(); GLenum srcTarget = src->ProdTextureTarget(); if (dest->AttachType() == AttachmentType::GLTexture) { GLuint destTex = dest->ProdTexture(); GLenum destTarget = dest->ProdTextureTarget(); gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex, src->Size(), dest->Size(), srcTarget, destTarget); return; } if (dest->AttachType() == AttachmentType::GLRenderbuffer) { GLuint destRB = dest->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(), src->Size(), dest->Size(), srcTarget); return; } MOZ_CRASH("Unhandled dest->AttachType()."); } if (src->AttachType() == AttachmentType::GLRenderbuffer) { GLuint srcRB = src->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB); if (dest->AttachType() == AttachmentType::GLTexture) { GLuint destTex = dest->ProdTexture(); GLenum destTarget = dest->ProdTextureTarget(); gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex, src->Size(), dest->Size(), destTarget); return; } if (dest->AttachType() == AttachmentType::GLRenderbuffer) { GLuint destRB = dest->ProdRenderbuffer(); ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), destWrapper.FB(), src->Size(), dest->Size()); return; } MOZ_CRASH("Unhandled dest->AttachType()."); } MOZ_CRASH("Unhandled src->AttachType()."); }