mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 809273 - Add code handling dual buffers in ThebesLayerBuffer. r=roc
This commit is contained in:
parent
2a7f252e64
commit
f3afacc43a
@ -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
|
||||
|
@ -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<gfxASurface> 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<SourceSurface> snapshot = mDTBuffer->Snapshot();
|
||||
RefPtr<SourceSurface> 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<DrawTarget> 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<gfxContext> ctx = new gfxContext(aSurface);
|
||||
ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
|
||||
gfxUtils::ClipToRegion(ctx, aRegion);
|
||||
ctx->SetColor(aColor);
|
||||
ctx->Paint();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxContext>
|
||||
ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds)
|
||||
ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource)
|
||||
{
|
||||
EnsureBuffer();
|
||||
|
||||
nsRefPtr<gfxContext> 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<gfxTeeSurface> 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<gfxASurface> destBuffer;
|
||||
nsRefPtr<gfxASurface> destBufferOnWhite;
|
||||
RefPtr<DrawTarget> destDTBuffer;
|
||||
RefPtr<DrawTarget> 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<gfxContext> 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<gfxContext> 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);
|
||||
|
@ -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<gfxASurface> mBuffer;
|
||||
nsRefPtr<gfxASurface> mBufferOnWhite;
|
||||
RefPtr<gfx::DrawTarget> mDTBuffer;
|
||||
RefPtr<gfx::DrawTarget> 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<gfxASurface>
|
||||
CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) = 0;
|
||||
CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, gfxASurface** aWhiteSurface) = 0;
|
||||
virtual TemporaryRef<gfx::DrawTarget>
|
||||
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<gfxASurface>
|
||||
SetBufferOnWhite(gfxASurface* aBuffer)
|
||||
{
|
||||
nsRefPtr<gfxASurface> 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<gfxContext>
|
||||
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;
|
||||
};
|
||||
|
@ -347,7 +347,7 @@ public:
|
||||
|
||||
protected:
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
CreateBuffer(ContentType, const nsIntRect&, uint32_t)
|
||||
CreateBuffer(ContentType, const nsIntRect&, uint32_t, gfxASurface**)
|
||||
{
|
||||
NS_RUNTIMEABORT("ShadowThebesLayer can't paint content");
|
||||
return nullptr;
|
||||
|
@ -37,7 +37,8 @@ ContentClientBasic::ContentClientBasic(CompositableForwarder* aForwarder,
|
||||
already_AddRefed<gfxASurface>
|
||||
ContentClientBasic::CreateBuffer(ContentType aType,
|
||||
const nsIntRect& aRect,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags,
|
||||
gfxASurface**)
|
||||
{
|
||||
nsRefPtr<gfxASurface> 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<DrawTarget> ret = mTextureClient->LockDrawTarget();
|
||||
return ret.forget();
|
||||
@ -142,11 +163,15 @@ ContentClientRemote::CreateDTBuffer(ContentType aType,
|
||||
already_AddRefed<gfxASurface>
|
||||
ContentClientRemote::CreateBuffer(ContentType aType,
|
||||
const nsIntRect& aRect,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags,
|
||||
gfxASurface** aWhiteSurface)
|
||||
{
|
||||
BuildTextureClient(aType, aRect, aFlags);
|
||||
BuildTextureClients(aType, aRect, aFlags);
|
||||
|
||||
nsRefPtr<gfxASurface> 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<gfxASurface> 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 <x=%d,y=%d,w=%d,h=%d>",
|
||||
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<gfxContext> 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<gfxContext> 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;
|
||||
}
|
||||
|
@ -114,7 +114,8 @@ public:
|
||||
|
||||
virtual already_AddRefed<gfxASurface> CreateBuffer(ContentType aType,
|
||||
const nsIntRect& aRect,
|
||||
uint32_t aFlags) MOZ_OVERRIDE;
|
||||
uint32_t aFlags,
|
||||
gfxASurface**) MOZ_OVERRIDE;
|
||||
virtual TemporaryRef<gfx::DrawTarget>
|
||||
CreateDTBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags);
|
||||
|
||||
@ -185,7 +186,8 @@ public:
|
||||
|
||||
virtual already_AddRefed<gfxASurface> CreateBuffer(ContentType aType,
|
||||
const nsIntRect& aRect,
|
||||
uint32_t aFlags) MOZ_OVERRIDE;
|
||||
uint32_t aFlags,
|
||||
gfxASurface** aWhiteSurface) MOZ_OVERRIDE;
|
||||
virtual TemporaryRef<gfx::DrawTarget> 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<TextureClient> mTextureClient;
|
||||
RefPtr<TextureClient> mTextureClientOnWhite;
|
||||
// keep a record of texture clients we have created and need to keep
|
||||
// around, then unlock when we are done painting
|
||||
nsTArray<RefPtr<TextureClient> > 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<TextureClient> mFrontClient;
|
||||
RefPtr<TextureClient> mFrontClientOnWhite;
|
||||
nsIntRegion mFrontUpdatedRegion;
|
||||
nsIntRect mFrontBufferRect;
|
||||
nsIntPoint mFrontBufferRotation;
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -332,7 +332,7 @@ public:
|
||||
|
||||
// ThebesLayerBuffer interface
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
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");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user