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
--- 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);
}