Bug 1382104 - Update CompositorOGL handling of offscreen GLContext default framebuffers. - r=mattwoodrow
MozReview-Commit-ID: BMT1zVq601z
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2962,10 +2962,20 @@ GLContext::ResetSyncCallCount(const char
if (ShouldSpew()) {
printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n",
resetReason, mSyncGLCallCount);
}
mSyncGLCallCount = 0;
}
+void
+GLContext::BindDefaultFramebuffer()
+{
+ if (mScreen) {
+ mScreen->BindAsFramebuffer();
+ return;
+ }
+ fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, GetDefaultFramebuffer());
+}
+
} /* namespace gl */
} /* namespace mozilla */
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -301,16 +301,18 @@ public:
/**
* Get the default framebuffer for this context.
*/
virtual GLuint GetDefaultFramebuffer() {
return 0;
}
+ void BindDefaultFramebuffer();
+
protected:
bool mIsOffscreen;
bool mContextLost;
const bool mUseTLSIsCurrent;
/**
* mVersion store the OpenGL's version, multiplied by 100. For example, if
* the context is an OpenGL 2.1 context, mVersion value will be 210.
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
@@ -40,18 +40,17 @@ CompositingRenderTargetOGL::BindRenderTa
if (mInitParams.mStatus != InitParams::INITIALIZED) {
InitializeImpl();
if (mInitParams.mInit == INIT_MODE_CLEAR) {
needsClear = true;
mClearOnBind = false;
}
} else {
MOZ_ASSERT(mInitParams.mStatus == InitParams::INITIALIZED);
- GLuint fbo = mFBO == 0 ? mGL->GetDefaultFramebuffer() : mFBO;
- mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
+ mCompositor->BindFramebuffer(mFBO);
GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
// The main framebuffer (0) of non-offscreen contexts
// might be backed by a EGLSurface that needs to be renewed.
if (mFBO == 0 && !mGL->IsOffscreen()) {
mGL->RenewSurface(mCompositor->GetWidget());
result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
}
@@ -89,25 +88,21 @@ CompositingRenderTargetOGL::Dump(Composi
}
#endif
void
CompositingRenderTargetOGL::InitializeImpl()
{
MOZ_ASSERT(mInitParams.mStatus == InitParams::READY);
- //TODO: call mGL->GetBackbufferFB(), use that
- GLuint fbo = mFBO == 0 ? mGL->GetDefaultFramebuffer() : mFBO;
- mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fbo);
- mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
- LOCAL_GL_COLOR_ATTACHMENT0,
- mInitParams.mFBOTextureTarget,
- mTextureHandle,
- 0);
-
+ mCompositor->BindFramebuffer(mFBO);
+ if (mFBO) {
+ mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ mInitParams.mFBOTextureTarget, mTextureHandle, 0);
+ }
// Making this call to fCheckFramebufferStatus prevents a crash on
// PowerVR. See bug 695246.
GLenum result = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
if (result != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
nsAutoCString msg;
msg.AppendPrintf("Framebuffer not complete -- error 0x%x, aFBOTextureTarget 0x%x, mFBO %d, mTextureHandle %d, aRect.width %d, aRect.height %d",
result, mInitParams.mFBOTextureTarget, mFBO, mTextureHandle, mInitParams.mSize.width, mInitParams.mSize.height);
NS_ERROR(msg.get());
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -189,18 +189,16 @@ CompositorOGL::CleanupResources()
for (std::map<ShaderConfigOGL, ShaderProgramOGL *>::iterator iter = mPrograms.begin();
iter != mPrograms.end();
iter++) {
delete iter->second;
}
mPrograms.clear();
- ctx->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
-
if (mQuadVBO) {
ctx->fDeleteBuffers(1, &mQuadVBO);
mQuadVBO = 0;
}
if (mTriangleVBO) {
ctx->fDeleteBuffers(1, &mTriangleVBO);
mTriangleVBO = 0;
@@ -304,17 +302,17 @@ CompositorOGL::Initialize(nsCString* con
0,
LOCAL_GL_RGBA,
LOCAL_GL_UNSIGNED_BYTE,
nullptr);
// unbind this texture, in preparation for binding it to the FBO
mGLContext->fBindTexture(target, 0);
- mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, testFBO);
+ const gl::ScopedBindFramebuffer bindFB(mGLContext, testFBO);
mGLContext->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_COLOR_ATTACHMENT0,
target,
testTexture,
0);
if (mGLContext->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) ==
LOCAL_GL_FRAMEBUFFER_COMPLETE)
@@ -336,19 +334,16 @@ CompositorOGL::Initialize(nsCString* con
*out_failureReason = "FEATURE_FAILURE_OPENGL_NO_TEXTURE_TARGET";
return false;
}
} else {
// not trying to work around driver bugs, so TEXTURE_2D should just work
mFBOTextureTarget = LOCAL_GL_TEXTURE_2D;
}
- // back to default framebuffer, to avoid confusion
- mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
-
if (mFBOTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB) {
/* If we're using TEXTURE_RECTANGLE, then we must have the ARB
* extension -- the EXT variant does not provide support for
* texture rectangle access inside GLSL (sampler2DRect,
* texture2DRect).
*/
if (!mGLContext->IsExtensionSupported(gl::GLContext::ARB_texture_rectangle)){
*out_failureReason = "FEATURE_FAILURE_OPENGL_ARB_EXT";
@@ -710,16 +705,26 @@ CompositorOGL::CreateFBOWithTexture(cons
GLuint *aFBO, GLuint *aTexture,
gfx::IntSize* aAllocSize)
{
*aTexture = CreateTexture(aRect, aCopyFromSource, aSourceFrameBuffer,
aAllocSize);
mGLContext->fGenFramebuffers(1, aFBO);
}
+void
+CompositorOGL::BindFramebuffer(const GLuint aFB) const
+{
+ if (aFB) {
+ mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aFB);
+ } else {
+ mGLContext->BindDefaultFramebuffer();
+ }
+}
+
GLuint
CompositorOGL::CreateTexture(const IntRect& aRect, bool aCopyFromSource,
GLuint aSourceFrameBuffer, IntSize* aAllocSize)
{
// we're about to create a framebuffer backed by textures to use as an intermediate
// surface. What to do if its size (as given by aRect) would exceed the
// maximum texture size supported by the GL? The present code chooses the compromise
// of just clamping the framebuffer's size to the max supported size.
@@ -734,17 +739,17 @@ CompositorOGL::CreateTexture(const IntRe
mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
mGLContext->fGenTextures(1, &tex);
mGLContext->fBindTexture(mFBOTextureTarget, tex);
if (aCopyFromSource) {
GLuint curFBO = mCurrentRenderTarget->GetFBO();
if (curFBO != aSourceFrameBuffer) {
- mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aSourceFrameBuffer);
+ BindFramebuffer(aSourceFrameBuffer);
}
// We're going to create an RGBA temporary fbo. But to
// CopyTexImage() from the current framebuffer, the framebuffer's
// format has to be compatible with the new texture's. So we
// check the format of the framebuffer here and take a slow path
// if it's incompatible.
GLenum format =
@@ -1650,23 +1655,17 @@ CompositorOGL::CopyToTarget(DrawTarget*
GLint width = rect.Width();
GLint height = rect.Height();
if ((int64_t(width) * int64_t(height) * int64_t(4)) > INT32_MAX) {
NS_ERROR("Widget size too big - integer overflow!");
return;
}
- mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
-
- if (!mGLContext->IsGLES()) {
- // GLES2 promises that binding to any custom FBO will attach
- // to GL_COLOR_ATTACHMENT0 attachment point.
- mGLContext->fReadBuffer(LOCAL_GL_BACK);
- }
+ mGLContext->BindDefaultFramebuffer();
RefPtr<DataSourceSurface> source =
Factory::CreateDataSourceSurface(rect.Size(), gfx::SurfaceFormat::B8G8R8A8);
if (NS_WARN_IF(!source)) {
return;
}
ReadPixelsIntoDataSurface(mGLContext, source);
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -210,16 +210,18 @@ public:
}
virtual void Pause() override;
virtual bool Resume() override;
GLContext* gl() const { return mGLContext; }
GLContext* GetGLContext() const override { return mGLContext; }
+ void BindFramebuffer(GLuint aFB) const;
+
/**
* Clear the program state. This must be called
* before operating on the GLContext directly. */
void ResetProgram();
gfx::SurfaceFormat GetFBOFormat() const {
return gfx::SurfaceFormat::R8G8B8A8;
}
--- a/gfx/layers/opengl/GLBlitTextureImageHelper.cpp
+++ b/gfx/layers/opengl/GLBlitTextureImageHelper.cpp
@@ -41,18 +41,17 @@ void
GLBlitTextureImageHelper::BlitTextureImage(TextureImage *aSrc, const gfx::IntRect& aSrcRect,
TextureImage *aDst, const gfx::IntRect& aDstRect)
{
GLContext *gl = mCompositor->gl();
if (!aSrc || !aDst || aSrcRect.IsEmpty() || aDstRect.IsEmpty())
return;
- int savedFb = 0;
- gl->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &savedFb);
+ const ScopedBindFramebuffer saveFB(gl);
ScopedGLState scopedScissorTestState(gl, LOCAL_GL_SCISSOR_TEST, false);
ScopedGLState scopedBlendState(gl, LOCAL_GL_BLEND, false);
// 2.0 means scale up by two
float blitScaleX = float(aDstRect.Width()) / float(aSrcRect.Width());
float blitScaleY = float(aDstRect.Height()) / float(aSrcRect.Height());
@@ -156,18 +155,16 @@ GLBlitTextureImageHelper::BlitTextureIma
gl->fDrawArrays(LOCAL_GL_TRIANGLES, 0, rects.elements());
} while (aSrc->NextTile());
} while (aDst->NextTile());
// unbind the previous texture from the framebuffer
SetBlitFramebufferForDestTexture(0);
-
- gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, savedFb);
}
void
GLBlitTextureImageHelper::SetBlitFramebufferForDestTexture(GLuint aTexture)
{
GLContext *gl = mCompositor->gl();
if (!mBlitFramebuffer) {
gl->fGenFramebuffers(1, &mBlitFramebuffer);