Bug 1265112 - When rendering blend modes with CompositorOGL, use NV_texture_barrier (if available) to sample directly from the framebuffer. r?jrmuizel draft
authorMarkus Stange <mstange@themasta.com>
Fri, 15 Apr 2016 18:53:35 -0400
changeset 357987 cda6b7c2bcff88f3a25ce155048f6e8759205734
parent 357986 3ed2598c8083848e5d8b2552301de807a1189783
child 519754 63f3475d03a78ea8fa2513fa28fdc70a748ee5c7
push id16900
push usermstange@themasta.com
push dateFri, 29 Apr 2016 22:23:16 +0000
reviewersjrmuizel
bugs1265112
milestone49.0a1
Bug 1265112 - When rendering blend modes with CompositorOGL, use NV_texture_barrier (if available) to sample directly from the framebuffer. r?jrmuizel MozReview-Commit-ID: fWSgFOTmhS
gfx/layers/opengl/CompositorOGL.cpp
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -1087,16 +1087,17 @@ CompositorOGL::DrawQuad(const Rect& aRec
     color.g *= opacity;
     color.b *= opacity;
     color.a = opacity;
 
     // We can fold opacity into the color, so no need to consider it further.
     aOpacity = 1.f;
   }
 
+  bool createdMixBlendBackdropTexture = false;
   GLuint mixBlendBackdrop = 0;
   gfx::CompositionOp blendMode = gfx::CompositionOp::OP_OVER;
 
   if (aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE]) {
     EffectBlendMode *blendEffect =
       static_cast<EffectBlendMode*>(aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE].get());
     blendMode = blendEffect->mBlendMode;
   }
@@ -1119,19 +1120,29 @@ CompositorOGL::DrawQuad(const Rect& aRec
   if (colorMatrix) {
       EffectColorMatrix* effectColorMatrix =
         static_cast<EffectColorMatrix*>(aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX].get());
       program->SetColorMatrix(effectColorMatrix->mColorMatrix);
   }
 
   if (BlendOpIsMixBlendMode(blendMode)) {
     gfx::Matrix4x4 backdropTransform;
-    gfx::IntRect rect = ComputeBackdropCopyRect(aRect, aClipRect, aTransform, &backdropTransform);
 
-    mixBlendBackdrop = CreateTexture(rect, true, mCurrentRenderTarget->GetFBO());
+    if (gl()->IsExtensionSupported(GLContext::NV_texture_barrier)) {
+      // The NV_texture_barrier extension lets us read directly from the
+      // backbuffer. Let's do that.
+      // We need to tell OpenGL about this, so that it can make sure everything
+      // on the GPU is happening in the right order.
+      gl()->fTextureBarrier();
+      mixBlendBackdrop = mCurrentRenderTarget->GetTextureHandle();
+    } else {
+      gfx::IntRect rect = ComputeBackdropCopyRect(aRect, aClipRect, aTransform, &backdropTransform);
+      mixBlendBackdrop = CreateTexture(rect, true, mCurrentRenderTarget->GetFBO());
+      createdMixBlendBackdropTexture = true;
+    }
     program->SetBackdropTransform(backdropTransform);
   }
 
   program->SetRenderOffset(offset.x, offset.y);
   LayerScope::SetRenderOffset(offset.x, offset.y);
 
   if (aOpacity != 1.f)
     program->SetLayerOpacity(aOpacity);
@@ -1438,17 +1449,17 @@ CompositorOGL::DrawQuad(const Rect& aRec
     MOZ_ASSERT(false, "Unhandled effect type");
     break;
   }
 
   if (didSetBlendMode) {
     gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
                              LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA);
   }
-  if (mixBlendBackdrop) {
+  if (createdMixBlendBackdropTexture) {
     gl()->fDeleteTextures(1, &mixBlendBackdrop);
   }
 
   // in case rendering has used some other GL context
   MakeCurrent();
   LayerScope::DrawEnd(mGLContext, aEffectChain, aRect.width, aRect.height);
 }