diff --git a/gfx/layers/CompositorTypes.h b/gfx/layers/CompositorTypes.h index e7eefc50d9a..20718385985 100644 --- a/gfx/layers/CompositorTypes.h +++ b/gfx/layers/CompositorTypes.h @@ -34,6 +34,8 @@ const TextureFlags AllowRepeat = 0x8; const TextureFlags NewTile = 0x10; // The host is responsible for tidying up any shared resources. const TextureFlags HostRelease = 0x20; +// The texture is part of a component-alpha pair +const TextureFlags ComponentAlpha = 0x40; /** * The kind of memory held by the texture client/host pair. This will diff --git a/gfx/layers/ThebesLayerBuffer.cpp b/gfx/layers/ThebesLayerBuffer.cpp index fc0318053aa..d392eef1dfe 100644 --- a/gfx/layers/ThebesLayerBuffer.cpp +++ b/gfx/layers/ThebesLayerBuffer.cpp @@ -10,6 +10,7 @@ #include "Layers.h" #include "gfxContext.h" #include "gfxPlatform.h" +#include "gfxTeeSurface.h" #include "gfxUtils.h" #include "ipc/AutoOpenSurface.h" #include "nsDeviceContext.h" @@ -46,6 +47,7 @@ RotatedBuffer::GetQuadrantRectangle(XSide aXSide, YSide aYSide) const void RotatedBuffer::DrawBufferQuadrant(gfxContext* aTarget, XSide aXSide, YSide aYSide, + ContextSource aSource, float aOpacity, gfxASurface* aMask, const gfxMatrix* aMaskTransform) const @@ -62,12 +64,23 @@ RotatedBuffer::DrawBufferQuadrant(gfxContext* aTarget, nsRefPtr source; - if (mBuffer) { - source = mBuffer; - } else if (mDTBuffer) { - source = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDTBuffer); + if (aSource == BUFFER_BLACK) { + if (mBuffer) { + source = mBuffer; + } else if (mDTBuffer) { + source = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDTBuffer); + } else { + NS_RUNTIMEABORT("Can't draw a RotatedBuffer without any buffer!"); + } } else { - NS_RUNTIMEABORT("Can't draw a RotatedBuffer without any buffer!"); + MOZ_ASSERT(aSource == BUFFER_WHITE); + if (mBufferOnWhite) { + source = mBufferOnWhite; + } else if (mDTBufferOnWhite) { + source = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDTBufferOnWhite); + } else { + NS_RUNTIMEABORT("Can't draw a RotatedBuffer without any buffer!"); + } } @@ -132,6 +145,7 @@ RotatedBuffer::DrawBufferQuadrant(gfxContext* aTarget, void RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget, XSide aXSide, YSide aYSide, + ContextSource aSource, float aOpacity, gfx::SourceSurface* aMask, const gfx::Matrix* aMaskTransform) const @@ -147,7 +161,13 @@ RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget, gfx::Point quadrantTranslation(quadrantRect.x, quadrantRect.y); - RefPtr snapshot = mDTBuffer->Snapshot(); + RefPtr snapshot; + if (aSource == BUFFER_BLACK) { + snapshot = mDTBuffer->Snapshot(); + } else { + MOZ_ASSERT(aSource == BUFFER_WHITE); + snapshot = mDTBufferOnWhite->Snapshot(); + } // Transform from user -> buffer space. Matrix transform; @@ -173,21 +193,23 @@ RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget, } void -RotatedBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity, +RotatedBuffer::DrawBufferWithRotation(gfxContext* aTarget, ContextSource aSource, + float aOpacity, gfxASurface* aMask, const gfxMatrix* aMaskTransform) const { PROFILER_LABEL("RotatedBuffer", "DrawBufferWithRotation"); // Draw four quadrants. We could use REPEAT_, but it's probably better // not to, to be performance-safe. - DrawBufferQuadrant(aTarget, LEFT, TOP, aOpacity, aMask, aMaskTransform); - DrawBufferQuadrant(aTarget, RIGHT, TOP, aOpacity, aMask, aMaskTransform); - DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aOpacity, aMask, aMaskTransform); - DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, LEFT, TOP, aSource, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, RIGHT, TOP, aSource, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aSource, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aSource, aOpacity, aMask, aMaskTransform); } void -RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, float aOpacity, +RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, ContextSource aSource, + float aOpacity, gfx::SourceSurface* aMask, const gfx::Matrix* aMaskTransform) const { @@ -195,10 +217,10 @@ RotatedBuffer::DrawBufferWithRotation(gfx::DrawTarget *aTarget, float aOpacity, // See above, in Azure Repeat should always be a safe, even faster choice // though! Particularly on D2D Repeat should be a lot faster, need to look // into that. TODO[Bas] - DrawBufferQuadrant(aTarget, LEFT, TOP, aOpacity, aMask, aMaskTransform); - DrawBufferQuadrant(aTarget, RIGHT, TOP, aOpacity, aMask, aMaskTransform); - DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aOpacity, aMask, aMaskTransform); - DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, LEFT, TOP, aSource, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, RIGHT, TOP, aSource, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, LEFT, BOTTOM, aSource, aOpacity, aMask, aMaskTransform); + DrawBufferQuadrant(aTarget, RIGHT, BOTTOM, aSource, aOpacity, aMask, aMaskTransform); } /* static */ bool @@ -237,7 +259,7 @@ ThebesLayerBuffer::DrawTo(ThebesLayer* aLayer, gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion()); } - DrawBufferWithRotation(aTarget, aOpacity, aMask, aMaskTransform); + DrawBufferWithRotation(aTarget, BUFFER_BLACK, aOpacity, aMask, aMaskTransform); aTarget->Restore(); } else { RefPtr dt = aTarget->GetDrawTarget(); @@ -258,21 +280,57 @@ ThebesLayerBuffer::DrawTo(ThebesLayer* aLayer, gfxUtils::ClipToRegionSnapped(dt, aLayer->GetEffectiveVisibleRegion()); } - DrawBufferWithRotation(aTarget, aOpacity, aMask, aMaskTransform); + DrawBufferWithRotation(aTarget, BUFFER_BLACK, aOpacity, aMask, aMaskTransform); aTarget->Restore(); } } +static void +FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion, + const nsIntPoint& aOffset, const gfxRGBA& aColor) +{ + nsRefPtr ctx = new gfxContext(aSurface); + ctx->Translate(-gfxPoint(aOffset.x, aOffset.y)); + gfxUtils::ClipToRegion(ctx, aRegion); + ctx->SetColor(aColor); + ctx->Paint(); +} + already_AddRefed -ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds) +ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource) { EnsureBuffer(); nsRefPtr ctx; - if (mBuffer) { - ctx = new gfxContext(mBuffer); + if (aSource == BUFFER_BOTH && HaveBufferOnWhite()) { + EnsureBufferOnWhite(); + MOZ_ASSERT(mBuffer, "We don't support azure here yet"); + gfxASurface* surfaces[2] = { mBuffer, mBufferOnWhite }; + nsRefPtr surf = new gfxTeeSurface(surfaces, ArrayLength(surfaces)); + + // XXX If the device offset is set on the individual surfaces instead of on + // the tee surface, we render in the wrong place. Why? + gfxPoint deviceOffset = mBuffer->GetDeviceOffset(); + surfaces[0]->SetDeviceOffset(gfxPoint(0, 0)); + surfaces[1]->SetDeviceOffset(gfxPoint(0, 0)); + surf->SetDeviceOffset(deviceOffset); + + surf->SetAllowUseAsSource(false); + ctx = new gfxContext(surf); + } else if (aSource == BUFFER_WHITE) { + EnsureBufferOnWhite(); + if (mBufferOnWhite) { + ctx = new gfxContext(mBufferOnWhite); + } else { + ctx = new gfxContext(mDTBufferOnWhite); + } } else { - ctx = new gfxContext(mDTBuffer); + // BUFFER_BLACK, or BUFFER_BOTH with a single buffer. + if (mBuffer) { + ctx = new gfxContext(mBuffer); + } else { + ctx = new gfxContext(mDTBuffer); + } } // Figure out which quadrant to draw in @@ -330,12 +388,30 @@ ThebesLayerBuffer::EnsureBuffer() } } +void +ThebesLayerBuffer::EnsureBufferOnWhite() +{ + if ((!mBufferOnWhite && !mDTBufferOnWhite) && mBufferProviderOnWhite) { + if (SupportsAzureContent()) { + mDTBufferOnWhite = mBufferProviderOnWhite->LockDrawTarget(); + } else { + mBufferOnWhite = mBufferProviderOnWhite->LockSurface(); + } + } +} + bool -ThebesLayerBuffer::HaveBuffer() +ThebesLayerBuffer::HaveBuffer() const { return mDTBuffer || mBuffer || mBufferProvider; } +bool +ThebesLayerBuffer::HaveBufferOnWhite() const +{ + return mDTBufferOnWhite || mBufferOnWhite || mBufferProviderOnWhite; +} + static void WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize) { @@ -370,12 +446,14 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, nsIntRegion validRegion = aLayer->GetValidRegion(); + Layer::SurfaceMode mode; ContentType contentType; nsIntRegion neededRegion; bool canReuseBuffer; nsIntRect destBufferRect; while (true) { + mode = aLayer->GetSurfaceMode(); contentType = aContentType; neededRegion = aLayer->GetVisibleRegion(); canReuseBuffer = HaveBuffer() && BufferSizeOkFor(neededRegion.GetBounds().Size()); @@ -396,18 +474,43 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, destBufferRect = ComputeBufferRect(neededRegion.GetBounds()); } + if (mode == Layer::SURFACE_COMPONENT_ALPHA) { +#if defined(MOZ_GFX_OPTIMIZE_MOBILE) || defined(MOZ_WIDGET_GONK) + mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; +#else + if (!aLayer->GetParent() || + !aLayer->GetParent()->SupportsComponentAlphaChildren() || + !aLayer->Manager()->IsCompositingCheap() || + !aLayer->AsShadowableLayer() || + !aLayer->AsShadowableLayer()->HasShadow() || + SupportsAzureContent()) { + mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; + } else { + contentType = gfxASurface::CONTENT_COLOR; + } +#endif + } + if ((aFlags & PAINT_WILL_RESAMPLE) && (!neededRegion.GetBounds().IsEqualInterior(destBufferRect) || neededRegion.GetNumRects() > 1)) { // The area we add to neededRegion might not be painted opaquely - contentType = gfxASurface::CONTENT_COLOR_ALPHA; + if (mode == Layer::SURFACE_OPAQUE) { + contentType = gfxASurface::CONTENT_COLOR_ALPHA; + mode = Layer::SURFACE_SINGLE_CHANNEL_ALPHA; + } // We need to validate the entire buffer, to make sure that only valid // pixels are sampled neededRegion = destBufferRect; } - if (HaveBuffer() && contentType != BufferContentType()) { + // If we have an existing buffer, but the content type has changed or we + // have transitioned into/out of component alpha, then we need to recreate it. + if (HaveBuffer() && + (contentType != BufferContentType() || + mode == Layer::SURFACE_COMPONENT_ALPHA) != (HaveBufferOnWhite())) { + // We're effectively clearing the valid region, so we need to draw // the entire needed region now. result.mRegionToInvalidate = aLayer->GetValidRegion(); @@ -430,8 +533,13 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, nsIntRect drawBounds = result.mRegionToDraw.GetBounds(); nsRefPtr destBuffer; + nsRefPtr destBufferOnWhite; RefPtr destDTBuffer; + RefPtr destDTBufferOnWhite; uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0; + if (mode == Layer::SURFACE_COMPONENT_ALPHA) { + bufferFlags |= BUFFER_COMPONENT_ALPHA; + } if (canReuseBuffer) { EnsureBuffer(); nsIntRect keepArea; @@ -475,7 +583,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, if (SupportsAzureContent()) { destDTBuffer = CreateDTBuffer(contentType, destBufferRect, bufferFlags); } else { - destBuffer = CreateBuffer(contentType, destBufferRect, bufferFlags); + destBuffer = CreateBuffer(contentType, destBufferRect, bufferFlags, getter_AddRefs(destBufferOnWhite)); } if (!destBuffer && !destDTBuffer) return result; @@ -496,7 +604,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, if (SupportsAzureContent()) { destDTBuffer = CreateDTBuffer(contentType, destBufferRect, bufferFlags); } else { - destBuffer = CreateBuffer(contentType, destBufferRect, bufferFlags); + destBuffer = CreateBuffer(contentType, destBufferRect, bufferFlags, getter_AddRefs(destBufferOnWhite)); } if (!destBuffer && !destDTBuffer) return result; @@ -510,28 +618,40 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, bool isClear = !HaveBuffer(); if (destBuffer) { - if (!isClear) { + if (!isClear && (mode != Layer::SURFACE_COMPONENT_ALPHA || HaveBufferOnWhite())) { // Copy the bits nsRefPtr tmpCtx = new gfxContext(destBuffer); nsIntPoint offset = -destBufferRect.TopLeft(); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); tmpCtx->Translate(gfxPoint(offset.x, offset.y)); EnsureBuffer(); - DrawBufferWithRotation(tmpCtx, 1.0, nullptr, nullptr); + DrawBufferWithRotation(tmpCtx, BUFFER_BLACK); + + if (mode == Layer::SURFACE_COMPONENT_ALPHA) { + EnsureBufferOnWhite(); + NS_ASSERTION(destBufferOnWhite, "Must have a white buffer!"); + nsRefPtr tmpCtx = new gfxContext(destBufferOnWhite); + nsIntPoint offset = -destBufferRect.TopLeft(); + tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); + tmpCtx->Translate(gfxPoint(offset.x, offset.y)); + DrawBufferWithRotation(tmpCtx, BUFFER_WHITE); + } } mBuffer = destBuffer.forget(); mBufferRect = destBufferRect; + mBufferOnWhite = destBufferOnWhite.forget(); mBufferRotation = nsIntPoint(0,0); } else if (destDTBuffer) { - if (!isClear) { + if (!isClear && (mode != Layer::SURFACE_COMPONENT_ALPHA || HaveBufferOnWhite())) { + MOZ_ASSERT(mode != Layer::SURFACE_COMPONENT_ALPHA, "We don't support azure here yet"); // Copy the bits nsIntPoint offset = -destBufferRect.TopLeft(); Matrix mat; mat.Translate(offset.x, offset.y); destDTBuffer->SetTransform(mat); EnsureBuffer(); - DrawBufferWithRotation(destDTBuffer, 1.0, nullptr, nullptr); + DrawBufferWithRotation(destDTBuffer, BUFFER_BLACK); destDTBuffer->SetTransform(Matrix()); } @@ -546,9 +666,13 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, invalidate.Sub(aLayer->GetValidRegion(), destBufferRect); result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate); - result.mContext = GetContextForQuadrantUpdate(drawBounds); + result.mContext = GetContextForQuadrantUpdate(drawBounds, BUFFER_BOTH); - if (contentType == gfxASurface::CONTENT_COLOR_ALPHA && !isClear) { + if (mode == Layer::SURFACE_COMPONENT_ALPHA) { + MOZ_ASSERT(mBuffer && mBufferOnWhite, "Must not be using azure!"); + FillSurface(mBuffer, result.mRegionToDraw, result.mRegionToDraw.GetBounds().TopLeft(), gfxRGBA(0.0, 0.0, 0.0, 1.0)); + FillSurface(mBufferOnWhite, result.mRegionToDraw, result.mRegionToDraw.GetBounds().TopLeft(), gfxRGBA(1.0, 1.0, 1.0, 1.0)); + } else if (contentType == gfxASurface::CONTENT_COLOR_ALPHA && !isClear) { if (result.mContext->IsCairo()) { gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw); result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR); diff --git a/gfx/layers/ThebesLayerBuffer.h b/gfx/layers/ThebesLayerBuffer.h index c89b6af724a..45cd4d82dd3 100644 --- a/gfx/layers/ThebesLayerBuffer.h +++ b/gfx/layers/ThebesLayerBuffer.h @@ -11,6 +11,7 @@ #include "nsRegion.h" #include "mozilla/layers/TextureClient.h" #include "mozilla/gfx/2D.h" +#include "Layers.h" namespace mozilla { namespace layers { @@ -37,25 +38,39 @@ class RotatedBuffer { public: typedef gfxASurface::gfxContentType ContentType; - RotatedBuffer(gfxASurface* aBuffer, const nsIntRect& aBufferRect, + RotatedBuffer(gfxASurface* aBuffer, gfxASurface* aBufferOnWhite, + const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation) : mBuffer(aBuffer) + , mBufferOnWhite(aBufferOnWhite) , mBufferRect(aBufferRect) , mBufferRotation(aBufferRotation) { } - RotatedBuffer(gfx::DrawTarget* aDTBuffer, const nsIntRect& aBufferRect, + RotatedBuffer(gfx::DrawTarget* aDTBuffer, gfx::DrawTarget* aDTBufferOnWhite, + const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation) : mDTBuffer(aDTBuffer) + , mDTBufferOnWhite(aDTBufferOnWhite) , mBufferRect(aBufferRect) , mBufferRotation(aBufferRotation) { } RotatedBuffer() { } - void DrawBufferWithRotation(gfxContext* aTarget, float aOpacity = 1.0, + /* + * Which buffer should be drawn to/read from. + */ + enum ContextSource { + BUFFER_BLACK, // The normal buffer, or buffer with black background when using component alpha. + BUFFER_WHITE, // The buffer with white background, only valid with component alpha. + BUFFER_BOTH // The combined black/white buffers, only valid for writing operations, not reading. + }; + void DrawBufferWithRotation(gfxContext* aTarget, ContextSource aSource, + float aOpacity = 1.0, gfxASurface* aMask = nullptr, const gfxMatrix* aMaskTransform = nullptr) const; - void DrawBufferWithRotation(gfx::DrawTarget* aTarget, float aOpacity = 1.0, + void DrawBufferWithRotation(gfx::DrawTarget* aTarget, ContextSource aSource, + float aOpacity = 1.0, gfx::SourceSurface* aMask = nullptr, const gfx::Matrix* aMaskTransform = nullptr) const; @@ -67,6 +82,9 @@ public: const nsIntRect& BufferRect() const { return mBufferRect; } const nsIntPoint& BufferRotation() const { return mBufferRotation; } + virtual bool HaveBuffer() const { return mBuffer || mDTBuffer; } + virtual bool HaveBufferOnWhite() const { return mBufferOnWhite || mDTBufferOnWhite; } + protected: enum XSide { @@ -83,16 +101,20 @@ protected: * to adjust the coordinate space of the mask. */ void DrawBufferQuadrant(gfxContext* aTarget, XSide aXSide, YSide aYSide, + ContextSource aSource, float aOpacity, gfxASurface* aMask, const gfxMatrix* aMaskTransform) const; void DrawBufferQuadrant(gfx::DrawTarget* aTarget, XSide aXSide, YSide aYSide, + ContextSource aSource, float aOpacity, gfx::SourceSurface* aMask, const gfx::Matrix* aMaskTransform) const; nsRefPtr mBuffer; + nsRefPtr mBufferOnWhite; RefPtr mDTBuffer; + RefPtr mDTBufferOnWhite; /** The area of the ThebesLayer that is covered by the buffer as a whole */ nsIntRect mBufferRect; /** @@ -130,6 +152,7 @@ public: ThebesLayerBuffer(BufferSizePolicy aBufferSizePolicy) : mBufferProvider(nullptr) + , mBufferProviderOnWhite(nullptr) , mBufferSizePolicy(aBufferSizePolicy) { MOZ_COUNT_CTOR(ThebesLayerBuffer); @@ -146,8 +169,11 @@ public: void Clear() { mBuffer = nullptr; + mBufferOnWhite = nullptr; mDTBuffer = nullptr; + mDTBufferOnWhite = nullptr; mBufferProvider = nullptr; + mBufferProviderOnWhite = nullptr; mBufferRect.SetEmpty(); } @@ -195,7 +221,9 @@ public: uint32_t aFlags); enum { - ALLOW_REPEAT = 0x01 + ALLOW_REPEAT = 0x01, + BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with + // component alpha. }; /** * Return a new surface of |aSize| and |aType|. @@ -203,7 +231,7 @@ public: * to allow repeat-mode, otherwise it should be in pad (clamp) mode */ virtual already_AddRefed - CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) = 0; + CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, gfxASurface** aWhiteSurface) = 0; virtual TemporaryRef CreateDTBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) { NS_RUNTIMEABORT("CreateDTBuffer not implemented on this platform!"); return nullptr; } @@ -216,6 +244,7 @@ public: * Don't use it for anything else! */ gfxASurface* GetBuffer() { return mBuffer; } + gfxASurface* GetBufferOnWhite() { return mBufferOnWhite; } /** * Complete the drawing operation. The region to draw must have been @@ -238,6 +267,14 @@ protected: return tmp.forget(); } + already_AddRefed + SetBufferOnWhite(gfxASurface* aBuffer) + { + nsRefPtr tmp = mBufferOnWhite.forget(); + mBufferOnWhite = aBuffer; + return tmp.forget(); + } + /** * Set the texture client only. This is used with surfaces that * require explicit lock/unlock, which |aClient| is used to do on @@ -261,13 +298,26 @@ protected: mDTBuffer = nullptr; } } + + void SetBufferProviderOnWhite(TextureClient* aClient) + { + // Only this buffer provider can give us a buffer. If we + // already have one, something has gone wrong. + MOZ_ASSERT(!aClient || (!mBufferOnWhite && !mDTBufferOnWhite)); + + mBufferProviderOnWhite = aClient; + if (!mBufferProviderOnWhite) { + mBufferOnWhite = nullptr; + mDTBufferOnWhite = nullptr; + } + } /** * Get a context at the specified resolution for updating |aBounds|, * which must be contained within a single quadrant. */ already_AddRefed - GetContextForQuadrantUpdate(const nsIntRect& aBounds); + GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource); static bool IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion); @@ -285,11 +335,13 @@ protected: * If the buffer hasn't been mapped, map it. */ void EnsureBuffer(); + void EnsureBufferOnWhite(); /** * True if we have a buffer where we can get it (but not necessarily * mapped currently). */ - bool HaveBuffer(); + virtual bool HaveBuffer() const; + virtual bool HaveBufferOnWhite() const; /** * These members are only set transiently. They're used to map mBuffer @@ -297,6 +349,7 @@ protected: * may be used at a time. */ TextureClient* mBufferProvider; + TextureClient* mBufferProviderOnWhite; BufferSizePolicy mBufferSizePolicy; }; diff --git a/gfx/layers/basic/BasicThebesLayer.cpp b/gfx/layers/basic/BasicThebesLayer.cpp index 3de5cabaf05..afbc52ff1d2 100644 --- a/gfx/layers/basic/BasicThebesLayer.cpp +++ b/gfx/layers/basic/BasicThebesLayer.cpp @@ -347,7 +347,7 @@ public: protected: virtual already_AddRefed - CreateBuffer(ContentType, const nsIntRect&, uint32_t) + CreateBuffer(ContentType, const nsIntRect&, uint32_t, gfxASurface**) { NS_RUNTIMEABORT("ShadowThebesLayer can't paint content"); return nullptr; diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index 7bb8bdfe232..5c0b3556fe3 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -37,7 +37,8 @@ ContentClientBasic::ContentClientBasic(CompositableForwarder* aForwarder, already_AddRefed ContentClientBasic::CreateBuffer(ContentType aType, const nsIntRect& aRect, - uint32_t aFlags) + uint32_t aFlags, + gfxASurface**) { nsRefPtr referenceSurface = GetBuffer(); if (!referenceSurface) { @@ -74,6 +75,7 @@ ContentClientRemote::DestroyBuffers() MOZ_ASSERT(mTextureClient->GetAccessMode() == TextureClient::ACCESS_READ_WRITE); mTextureClient = nullptr; + mTextureClientOnWhite = nullptr; DestroyFrontBuffer(); @@ -88,6 +90,9 @@ ContentClientRemote::BeginPaint() if (mTextureClient) { SetBufferProvider(mTextureClient); } + if (mTextureClientOnWhite) { + SetBufferProviderOnWhite(mTextureClientOnWhite); + } } void @@ -96,15 +101,19 @@ ContentClientRemote::EndPaint() // XXX: We might still not have a texture client if PaintThebes // decided we didn't need one yet because the region to draw was empty. SetBufferProvider(nullptr); + SetBufferProviderOnWhite(nullptr); mOldTextures.Clear(); if (mTextureClient) { mTextureClient->Unlock(); } + if (mTextureClientOnWhite) { + mTextureClientOnWhite->Unlock(); + } } void -ContentClientRemote::BuildTextureClient(ContentType aType, +ContentClientRemote::BuildTextureClients(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) { @@ -115,15 +124,26 @@ ContentClientRemote::BuildTextureClient(ContentType aType, if (mTextureClient) { mOldTextures.AppendElement(mTextureClient); + if (mTextureClientOnWhite) { + mOldTextures.AppendElement(mTextureClientOnWhite); + } DestroyBuffers(); } mTextureInfo.mTextureFlags = aFlags | HostRelease; mTextureClient = CreateTextureClient(TEXTURE_CONTENT); + if (aFlags & BUFFER_COMPONENT_ALPHA) { + mTextureClientOnWhite = CreateTextureClient(TEXTURE_CONTENT); + mTextureInfo.mTextureFlags |= ComponentAlpha; + } mContentType = aType; mSize = gfx::IntSize(aRect.width, aRect.height); mTextureClient->EnsureAllocated(mSize, mContentType); MOZ_ASSERT(IsSurfaceDescriptorValid(*mTextureClient->GetDescriptor())); + if (mTextureClientOnWhite) { + mTextureClientOnWhite->EnsureAllocated(mSize, mContentType); + MOZ_ASSERT(IsSurfaceDescriptorValid(*mTextureClientOnWhite->GetDescriptor())); + } CreateFrontBufferAndNotify(aRect); } @@ -133,7 +153,8 @@ ContentClientRemote::CreateDTBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) { - BuildTextureClient(aType, aRect, aFlags); + MOZ_ASSERT(!(aFlags & BUFFER_COMPONENT_ALPHA), "We don't support component alpha here!"); + BuildTextureClients(aType, aRect, aFlags); RefPtr ret = mTextureClient->LockDrawTarget(); return ret.forget(); @@ -142,11 +163,15 @@ ContentClientRemote::CreateDTBuffer(ContentType aType, already_AddRefed ContentClientRemote::CreateBuffer(ContentType aType, const nsIntRect& aRect, - uint32_t aFlags) + uint32_t aFlags, + gfxASurface** aWhiteSurface) { - BuildTextureClient(aType, aRect, aFlags); + BuildTextureClients(aType, aRect, aFlags); nsRefPtr ret = mTextureClient->LockSurface(); + if (aFlags & BUFFER_COMPONENT_ALPHA) { + *aWhiteSurface = mTextureClientOnWhite->LockSurface(); + } return ret.forget(); } @@ -188,6 +213,9 @@ ContentClientRemote::Updated(const nsIntRegion& aRegionToDraw, MOZ_ASSERT(mTextureClient); mTextureClient->SetAccessMode(TextureClient::ACCESS_NONE); + if (mTextureClientOnWhite) { + mTextureClientOnWhite->SetAccessMode(TextureClient::ACCESS_NONE); + } LockFrontBuffer(); mForwarder->UpdateTextureRegion(this, ThebesBufferData(BufferRect(), @@ -199,25 +227,14 @@ void ContentClientRemote::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) { MOZ_ASSERT(mTextureClient->GetAccessMode() == TextureClient::ACCESS_NONE); + MOZ_ASSERT(!mTextureClientOnWhite || mTextureClientOnWhite->GetAccessMode() == TextureClient::ACCESS_NONE); MOZ_ASSERT(mTextureClient); mFrontAndBackBufferDiffer = true; mTextureClient->SetAccessMode(TextureClient::ACCESS_READ_WRITE); -} - -void -ContentClientRemote::SetBackingBuffer(gfxASurface* aBuffer, - const nsIntRect& aRect, - const nsIntPoint& aRotation) -{ -#ifdef DEBUG - gfxIntSize prevSize = gfxIntSize(BufferRect().width, BufferRect().height); - gfxIntSize newSize = aBuffer->GetSize(); - NS_ABORT_IF_FALSE(newSize == prevSize, - "Swapped-in buffer size doesn't match old buffer's!"); -#endif - nsRefPtr oldBuffer; - oldBuffer = SetBuffer(aBuffer, aRect, aRotation); + if (mTextureClientOnWhite) { + mTextureClientOnWhite->SetAccessMode(TextureClient::ACCESS_READ_WRITE); + } } ContentClientDoubleBuffered::~ContentClientDoubleBuffered() @@ -227,6 +244,11 @@ ContentClientDoubleBuffered::~ContentClientDoubleBuffered() mTextureClient->SetDescriptor(SurfaceDescriptor()); mFrontClient->SetDescriptor(SurfaceDescriptor()); } + if (mTextureClientOnWhite) { + MOZ_ASSERT(mFrontClientOnWhite); + mTextureClientOnWhite->SetDescriptor(SurfaceDescriptor()); + mFrontClientOnWhite->SetDescriptor(SurfaceDescriptor()); + } } void @@ -238,10 +260,17 @@ ContentClientDoubleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBuffer mFrontBufferRect = aBufferRect; mFrontBufferRotation = nsIntPoint(); + if (mTextureInfo.mTextureFlags & ComponentAlpha) { + mFrontClientOnWhite = CreateTextureClient(TEXTURE_CONTENT); + mFrontClientOnWhite->EnsureAllocated(mSize, mContentType); + } + mForwarder->CreatedDoubleBuffer(this, *mFrontClient->GetDescriptor(), *mTextureClient->GetDescriptor(), - mTextureInfo); + mTextureInfo, + mFrontClientOnWhite ? mFrontClientOnWhite->GetDescriptor() : nullptr, + mTextureClientOnWhite ? mTextureClientOnWhite->GetDescriptor() : nullptr); } void @@ -251,6 +280,7 @@ ContentClientDoubleBuffered::DestroyFrontBuffer() MOZ_ASSERT(mFrontClient->GetAccessMode() != TextureClient::ACCESS_NONE); mFrontClient = nullptr; + mFrontClientOnWhite = nullptr; } void @@ -258,6 +288,9 @@ ContentClientDoubleBuffered::LockFrontBuffer() { MOZ_ASSERT(mFrontClient); mFrontClient->SetAccessMode(TextureClient::ACCESS_NONE); + if (mFrontClientOnWhite) { + mFrontClientOnWhite->SetAccessMode(TextureClient::ACCESS_NONE); + } } void @@ -269,6 +302,10 @@ ContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) mTextureClient = mFrontClient; mFrontClient = oldBack; + oldBack = mTextureClientOnWhite; + mTextureClientOnWhite = mFrontClientOnWhite; + mFrontClientOnWhite = oldBack; + nsIntRect oldBufferRect = mBufferRect; mBufferRect = mFrontBufferRect; mFrontBufferRect = oldBufferRect; @@ -279,6 +316,9 @@ ContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_ASSERT(mFrontClient); mFrontClient->SetAccessMode(TextureClient::ACCESS_READ_ONLY); + if (mFrontClientOnWhite) { + mFrontClientOnWhite->SetAccessMode(TextureClient::ACCESS_READ_ONLY); + } ContentClientRemote::SwapBuffers(aFrontUpdatedRegion); } @@ -297,13 +337,19 @@ struct AutoTextureClient { { MOZ_ASSERT(!mTexture); mTexture = aTexture; - return mTexture->LockSurface(); + if (mTexture) { + return mTexture->LockSurface(); + } + return nullptr; } DrawTarget* GetDrawTarget(TextureClient* aTexture) { MOZ_ASSERT(!mTexture); mTexture = aTexture; - return mTexture->LockDrawTarget(); + if (mTexture) { + return mTexture->LockDrawTarget(); + } + return nullptr; } private: TextureClient* mTexture; @@ -317,6 +363,8 @@ ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer() } MOZ_ASSERT(mFrontClient); MOZ_ASSERT(mFrontClient->GetAccessMode() == TextureClient::ACCESS_READ_ONLY); + MOZ_ASSERT(!mFrontClientOnWhite || + mFrontClientOnWhite->GetAccessMode() == TextureClient::ACCESS_READ_ONLY); MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back ", this, @@ -355,13 +403,16 @@ ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer() } AutoTextureClient autoTextureFront; + AutoTextureClient autoTextureFrontOnWhite; if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { RotatedBuffer frontBuffer(autoTextureFront.GetDrawTarget(mFrontClient), + autoTextureFrontOnWhite.GetDrawTarget(mFrontClientOnWhite), mFrontBufferRect, mFrontBufferRotation); UpdateDestinationFrom(frontBuffer, updateRegion); } else { RotatedBuffer frontBuffer(autoTextureFront.GetSurface(mFrontClient), + autoTextureFrontOnWhite.GetSurface(mFrontClientOnWhite), mFrontBufferRect, mFrontBufferRotation); UpdateDestinationFrom(frontBuffer, updateRegion); @@ -376,7 +427,7 @@ ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource, const nsIntRegion& aUpdateRegion) { nsRefPtr destCtx = - GetContextForQuadrantUpdate(aUpdateRegion.GetBounds()); + GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_BLACK); destCtx->SetOperator(gfxContext::OPERATOR_SOURCE); bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion); @@ -390,9 +441,32 @@ ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource, if (destCtx->GetDrawTarget()->GetFormat() == FORMAT_B8G8R8A8) { destCtx->GetDrawTarget()->ClearRect(Rect(0, 0, mFrontBufferRect.width, mFrontBufferRect.height)); } - aSource.DrawBufferWithRotation(destCtx->GetDrawTarget()); + aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_BLACK); } else { - aSource.DrawBufferWithRotation(destCtx); + aSource.DrawBufferWithRotation(destCtx, BUFFER_BLACK); + } + + if (aSource.HaveBufferOnWhite()) { + MOZ_ASSERT(HaveBufferOnWhite()); + nsRefPtr destCtx = + GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(), BUFFER_WHITE); + destCtx->SetOperator(gfxContext::OPERATOR_SOURCE); + + bool isClippingCheap = IsClippingCheap(destCtx, aUpdateRegion); + if (isClippingCheap) { + gfxUtils::ClipToRegion(destCtx, aUpdateRegion); + } + + if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { + MOZ_ASSERT(!destCtx->IsCairo()); + + if (destCtx->GetDrawTarget()->GetFormat() == FORMAT_B8G8R8A8) { + destCtx->GetDrawTarget()->ClearRect(Rect(0, 0, mFrontBufferRect.width, mFrontBufferRect.height)); + } + aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE); + } else { + aSource.DrawBufferWithRotation(destCtx, BUFFER_WHITE); + } } } @@ -401,6 +475,9 @@ ContentClientSingleBuffered::~ContentClientSingleBuffered() if (mTextureClient) { mTextureClient->SetDescriptor(SurfaceDescriptor()); } + if (mTextureClientOnWhite) { + mTextureClientOnWhite->SetDescriptor(SurfaceDescriptor()); + } } void @@ -408,7 +485,8 @@ ContentClientSingleBuffered::CreateFrontBufferAndNotify(const nsIntRect& aBuffer { mForwarder->CreatedSingleBuffer(this, *mTextureClient->GetDescriptor(), - mTextureInfo); + mTextureInfo, + mTextureClientOnWhite ? mTextureClientOnWhite->GetDescriptor() : nullptr); } void @@ -428,6 +506,13 @@ ContentClientSingleBuffered::SyncFrontBufferToBackBuffer() mBufferRect, mBufferRotation); + backBuffer = GetBufferOnWhite(); + if (!backBuffer && mTextureClientOnWhite) { + backBuffer = mTextureClientOnWhite->LockSurface(); + } + + oldBuffer = SetBufferOnWhite(backBuffer); + mIsNewBuffer = false; mFrontAndBackBufferDiffer = false; } diff --git a/gfx/layers/client/ContentClient.h b/gfx/layers/client/ContentClient.h index 7914b95d32b..905f07d43af 100644 --- a/gfx/layers/client/ContentClient.h +++ b/gfx/layers/client/ContentClient.h @@ -114,7 +114,8 @@ public: virtual already_AddRefed CreateBuffer(ContentType aType, const nsIntRect& aRect, - uint32_t aFlags) MOZ_OVERRIDE; + uint32_t aFlags, + gfxASurface**) MOZ_OVERRIDE; virtual TemporaryRef CreateDTBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags); @@ -185,7 +186,8 @@ public: virtual already_AddRefed CreateBuffer(ContentType aType, const nsIntRect& aRect, - uint32_t aFlags) MOZ_OVERRIDE; + uint32_t aFlags, + gfxASurface** aWhiteSurface) MOZ_OVERRIDE; virtual TemporaryRef CreateDTBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) MOZ_OVERRIDE; @@ -203,21 +205,14 @@ public: } protected: - /** - * Swap out the old backing buffer for |aBuffer| and attributes. - */ - void SetBackingBuffer(gfxASurface* aBuffer, - const nsIntRect& aRect, - const nsIntPoint& aRotation); - virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw, const nsIntRegion& aVisibleRegion, bool aDidSelfCopy); // create and configure mTextureClient - void BuildTextureClient(ContentType aType, - const nsIntRect& aRect, - uint32_t aFlags); + void BuildTextureClients(ContentType aType, + const nsIntRect& aRect, + uint32_t aFlags); // Create the front buffer for the ContentClient/Host pair if necessary // and notify the compositor that we have created the buffer(s). @@ -228,6 +223,7 @@ protected: virtual void LockFrontBuffer() {} RefPtr mTextureClient; + RefPtr mTextureClientOnWhite; // keep a record of texture clients we have created and need to keep // around, then unlock when we are done painting nsTArray > mOldTextures; @@ -270,20 +266,11 @@ protected: virtual void LockFrontBuffer() MOZ_OVERRIDE; private: - // The size policy doesn't really matter here; this constructor is - // intended to be used for creating temporaries - ContentClientDoubleBuffered(gfxASurface* aBuffer, - const nsIntRect& aRect, - const nsIntPoint& aRotation) - : ContentClientRemote(nullptr) - { - SetBuffer(aBuffer, aRect, aRotation); - } - void UpdateDestinationFrom(const RotatedBuffer& aSource, const nsIntRegion& aUpdateRegion); RefPtr mFrontClient; + RefPtr mFrontClientOnWhite; nsIntRegion mFrontUpdatedRegion; nsIntRect mFrontBufferRect; nsIntPoint mFrontBufferRotation; diff --git a/gfx/layers/ipc/CompositableForwarder.h b/gfx/layers/ipc/CompositableForwarder.h index b71ba7f032e..870fdc2b4bc 100644 --- a/gfx/layers/ipc/CompositableForwarder.h +++ b/gfx/layers/ipc/CompositableForwarder.h @@ -58,11 +58,14 @@ public: */ virtual void CreatedSingleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aDescriptor, - const TextureInfo& aTextureInfo) = 0; + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aDescriptorOnWhite = nullptr) = 0; virtual void CreatedDoubleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aFrontDescriptor, const SurfaceDescriptor& aBackDescriptor, - const TextureInfo& aTextureInfo) = 0; + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aFrontDescriptorOnWhite = nullptr, + const SurfaceDescriptor* aBackDescriptorOnWhite = nullptr) = 0; /** * Tell the compositor that a Compositable is killing its buffer(s), diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h index d36fa8a4445..e59a759cc6b 100644 --- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -255,13 +255,16 @@ public: // thebes layers which don't support async updates. virtual void CreatedSingleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aDescriptor, - const TextureInfo& aTextureInfo) MOZ_OVERRIDE { + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aDescriptorOnWhite = nullptr) MOZ_OVERRIDE { NS_RUNTIMEABORT("should not be called"); } virtual void CreatedDoubleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aFrontDescriptor, const SurfaceDescriptor& aBackDescriptor, - const TextureInfo& aTextureInfo) MOZ_OVERRIDE { + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aFrontDescriptorOnWhite = nullptr, + const SurfaceDescriptor* aBackDescriptorOnWhite = nullptr) MOZ_OVERRIDE { NS_RUNTIMEABORT("should not be called"); } virtual void DestroyThebesBuffer(CompositableClient* aCompositable) MOZ_OVERRIDE { diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index e57ec019bbe..a3efb27c2aa 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -683,7 +683,8 @@ ShadowLayerForwarder::Connect(CompositableClient* aCompositable) void ShadowLayerForwarder::CreatedSingleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aDescriptor, - const TextureInfo& aTextureInfo) + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aDescriptorOnWhite) { MOZ_ASSERT(aDescriptor.type() != SurfaceDescriptor::T__None && aDescriptor.type() != SurfaceDescriptor::Tnull_t); @@ -691,13 +692,21 @@ ShadowLayerForwarder::CreatedSingleBuffer(CompositableClient* aCompositable, TextureFront, aDescriptor, aTextureInfo)); + if (aDescriptorOnWhite) { + mTxn->AddEdit(OpCreatedTexture(nullptr, aCompositable->GetIPDLActor(), + TextureOnWhiteFront, + *aDescriptorOnWhite, + aTextureInfo)); + } } void ShadowLayerForwarder::CreatedDoubleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aFrontDescriptor, const SurfaceDescriptor& aBackDescriptor, - const TextureInfo& aTextureInfo) + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aFrontDescriptorOnWhite, + const SurfaceDescriptor* aBackDescriptorOnWhite) { MOZ_ASSERT(aFrontDescriptor.type() != SurfaceDescriptor::T__None && aBackDescriptor.type() != SurfaceDescriptor::T__None && @@ -711,6 +720,17 @@ ShadowLayerForwarder::CreatedDoubleBuffer(CompositableClient* aCompositable, TextureBack, aBackDescriptor, aTextureInfo)); + if (aFrontDescriptorOnWhite) { + MOZ_ASSERT(aBackDescriptorOnWhite); + mTxn->AddEdit(OpCreatedTexture(nullptr, aCompositable->GetIPDLActor(), + TextureOnWhiteFront, + *aFrontDescriptorOnWhite, + aTextureInfo)); + mTxn->AddEdit(OpCreatedTexture(nullptr, aCompositable->GetIPDLActor(), + TextureOnWhiteBack, + *aBackDescriptorOnWhite, + aTextureInfo)); + } } void diff --git a/gfx/layers/ipc/ShadowLayers.h b/gfx/layers/ipc/ShadowLayers.h index 7d266395c5b..bf8441020a7 100644 --- a/gfx/layers/ipc/ShadowLayers.h +++ b/gfx/layers/ipc/ShadowLayers.h @@ -155,11 +155,14 @@ public: virtual void CreatedSingleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aDescriptor, - const TextureInfo& aTextureInfo) MOZ_OVERRIDE; + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aDescriptorOnWhite = nullptr) MOZ_OVERRIDE; virtual void CreatedDoubleBuffer(CompositableClient* aCompositable, const SurfaceDescriptor& aFrontDescriptor, const SurfaceDescriptor& aBackDescriptor, - const TextureInfo& aTextureInfo) MOZ_OVERRIDE; + const TextureInfo& aTextureInfo, + const SurfaceDescriptor* aFrontDescriptorOnWhite = nullptr, + const SurfaceDescriptor* aBackDescriptorOnWhite = nullptr) MOZ_OVERRIDE; virtual void DestroyThebesBuffer(CompositableClient* aCompositable) MOZ_OVERRIDE; /** diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp index 3a906acd3a5..078f74b15ca 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -332,7 +332,7 @@ public: // ThebesLayerBuffer interface virtual already_AddRefed - CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) + CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, gfxASurface**) { NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color");