Bug 932888. Remove thebes paths from ThebesLayerBuffer (part 1). r=mattwoodrow

This commit is contained in:
Nicholas Cameron 2013-11-27 13:29:45 +13:00
parent 0006952d88
commit d6f2d86ba3
5 changed files with 160 additions and 609 deletions

View File

@ -26,6 +26,7 @@
#include "gfxContext.h"
#include "gfxColor.h"
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "Layers.h"
#include "SharedTextureImage.h"
#include "GLContext.h"
@ -814,13 +815,15 @@ PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
}
}
#ifdef DEBUG
gfxIntSize sz = mBackground->GetSize();
#ifdef DEBUG
NS_ABORT_IF_FALSE(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect),
"Update outside of background area");
#endif
nsRefPtr<gfxContext> ctx = new gfxContext(mBackground);
RefPtr<gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height));
nsRefPtr<gfxContext> ctx = new gfxContext(dt);
*aCtx = ctx.forget().get();
return NS_OK;

View File

@ -71,106 +71,6 @@ RotatedBuffer::GetSourceRectangle(XSide aXSide, YSide aYSide) const
return result;
}
/**
* @param aXSide LEFT means we draw from the left side of the buffer (which
* is drawn on the right side of mBufferRect). RIGHT means we draw from
* the right side of the buffer (which is drawn on the left side of
* mBufferRect).
* @param aYSide TOP means we draw from the top side of the buffer (which
* is drawn on the bottom side of mBufferRect). BOTTOM means we draw from
* the bottom side of the buffer (which is drawn on the top side of
* mBufferRect).
*/
void
RotatedBuffer::DrawBufferQuadrant(gfxContext* aTarget,
XSide aXSide, YSide aYSide,
ContextSource aSource,
float aOpacity,
gfxASurface* aMask,
const gfxMatrix* aMaskTransform) const
{
// The rectangle that we're going to fill. Basically we're going to
// render the buffer at mBufferRect + quadrantTranslation to get the
// pixels in the right place, but we're only going to paint within
// mBufferRect
nsIntRect quadrantRect = GetQuadrantRectangle(aXSide, aYSide);
nsIntRect fillRect;
if (!fillRect.IntersectRect(mBufferRect, quadrantRect)) {
return;
}
nsRefPtr<gfxASurface> source;
if (aSource == BUFFER_BLACK) {
if (mBuffer) {
source = mBuffer;
} else if (mDTBuffer) {
source = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDTBuffer);
} else {
NS_WARNING("Can't draw a RotatedBuffer without any buffer!");
return;
}
} else {
MOZ_ASSERT(aSource == BUFFER_WHITE);
if (mBufferOnWhite) {
source = mBufferOnWhite;
} else if (mDTBufferOnWhite) {
source = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDTBufferOnWhite);
} else {
NS_WARNING("Can't draw a RotatedBuffer without any buffer!");
return;
}
}
aTarget->NewPath();
aTarget->Rectangle(gfxRect(fillRect.x, fillRect.y,
fillRect.width, fillRect.height),
true);
gfxPoint quadrantTranslation(quadrantRect.x, quadrantRect.y);
nsRefPtr<gfxPattern> pattern = new gfxPattern(source);
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
GraphicsFilter filter = GraphicsFilter::FILTER_NEAREST;
pattern->SetFilter(filter);
#endif
gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
// Transform from user -> buffer space.
gfxMatrix transform;
transform.Translate(-quadrantTranslation);
pattern->SetMatrix(transform);
aTarget->SetPattern(pattern);
if (aMask) {
if (aOpacity == 1.0) {
aTarget->SetMatrix(*aMaskTransform);
aTarget->Mask(aMask);
} else {
aTarget->PushGroup(GFX_CONTENT_COLOR_ALPHA);
aTarget->Paint(aOpacity);
aTarget->PopGroupToSource();
aTarget->SetMatrix(*aMaskTransform);
aTarget->Mask(aMask);
}
} else {
if (aOpacity == 1.0) {
aTarget->Fill();
} else {
aTarget->Save();
aTarget->Clip();
aTarget->Paint(aOpacity);
aTarget->Restore();
}
}
nsRefPtr<gfxASurface> surf = aTarget->CurrentSurface();
surf->Flush();
}
/**
* @param aXSide LEFT means we draw from the left side of the buffer (which
* is drawn on the right side of mBufferRect). RIGHT means we draw from
@ -264,21 +164,6 @@ RotatedBuffer::DrawBufferQuadrant(gfx::DrawTarget* aTarget,
aTarget->Flush();
}
void
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, 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, ContextSource aSource,
float aOpacity,
@ -316,74 +201,42 @@ ThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
return;
}
if (aTarget->IsCairo()) {
aTarget->Save();
// If the entire buffer is valid, we can just draw the whole thing,
// no need to clip. But we'll still clip if clipping is cheap ---
// that might let us copy a smaller region of the buffer.
// Also clip to the visible region if we're told to.
if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
(ToData(aLayer)->GetClipToVisibleRegion() &&
!aLayer->GetVisibleRegion().Contains(BufferRect())) ||
IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) {
// We don't want to draw invalid stuff, so we need to clip. Might as
// well clip to the smallest area possible --- the visible region.
// Bug 599189 if there is a non-integer-translation transform in aTarget,
// we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
// and may cause gray lines.
gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion());
}
RefPtr<DrawTarget> dt = aTarget->GetDrawTarget();
MOZ_ASSERT(dt, "Did you pass a non-Azure gfxContext?");
bool clipped = false;
DrawBufferWithRotation(aTarget, BUFFER_BLACK, aOpacity, aMask, aMaskTransform);
aTarget->Restore();
} else {
RefPtr<DrawTarget> dt = aTarget->GetDrawTarget();
bool clipped = false;
// If the entire buffer is valid, we can just draw the whole thing,
// no need to clip. But we'll still clip if clipping is cheap ---
// that might let us copy a smaller region of the buffer.
// Also clip to the visible region if we're told to.
if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
(ToData(aLayer)->GetClipToVisibleRegion() &&
!aLayer->GetVisibleRegion().Contains(BufferRect())) ||
IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) {
// We don't want to draw invalid stuff, so we need to clip. Might as
// well clip to the smallest area possible --- the visible region.
// Bug 599189 if there is a non-integer-translation transform in aTarget,
// we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
// and may cause gray lines.
gfxUtils::ClipToRegionSnapped(dt, aLayer->GetEffectiveVisibleRegion());
clipped = true;
}
RefPtr<gfx::SourceSurface> mask;
if (aMask) {
mask = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aMask);
}
Matrix maskTransform;
if (aMaskTransform) {
maskTransform = ToMatrix(*aMaskTransform);
}
CompositionOp op = CompositionOpForOp(aTarget->CurrentOperator());
DrawBufferWithRotation(dt, BUFFER_BLACK, aOpacity, op, mask, &maskTransform);
if (clipped) {
dt->PopClip();
}
// If the entire buffer is valid, we can just draw the whole thing,
// no need to clip. But we'll still clip if clipping is cheap ---
// that might let us copy a smaller region of the buffer.
// Also clip to the visible region if we're told to.
if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
(ToData(aLayer)->GetClipToVisibleRegion() &&
!aLayer->GetVisibleRegion().Contains(BufferRect())) ||
IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) {
// We don't want to draw invalid stuff, so we need to clip. Might as
// well clip to the smallest area possible --- the visible region.
// Bug 599189 if there is a non-integer-translation transform in aTarget,
// we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
// and may cause gray lines.
gfxUtils::ClipToRegionSnapped(dt, aLayer->GetEffectiveVisibleRegion());
clipped = true;
}
}
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();
RefPtr<gfx::SourceSurface> mask;
if (aMask) {
mask = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aMask);
}
Matrix maskTransform;
if (aMaskTransform) {
maskTransform = ToMatrix(*aMaskTransform);
}
CompositionOp op = CompositionOpForOp(aTarget->CurrentOperator());
DrawBufferWithRotation(dt, BUFFER_BLACK, aOpacity, op, mask, &maskTransform);
if (clipped) {
dt->PopClip();
}
}
already_AddRefed<gfxContext>
@ -398,41 +251,17 @@ ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds, Context
if (!EnsureBufferOnWhite()) {
return nullptr;
}
if (mBuffer) {
MOZ_ASSERT(mBufferOnWhite);
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 {
MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite);
RefPtr<DrawTarget> dualDT = Factory::CreateDualDrawTarget(mDTBuffer, mDTBufferOnWhite);
ctx = new gfxContext(dualDT);
}
MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite);
RefPtr<DrawTarget> dualDT = Factory::CreateDualDrawTarget(mDTBuffer, mDTBufferOnWhite);
ctx = new gfxContext(dualDT);
} else if (aSource == BUFFER_WHITE) {
if (!EnsureBufferOnWhite()) {
return nullptr;
}
if (mBufferOnWhite) {
ctx = new gfxContext(mBufferOnWhite);
} else {
ctx = new gfxContext(mDTBufferOnWhite);
}
ctx = new gfxContext(mDTBufferOnWhite);
} else {
// BUFFER_BLACK, or BUFFER_BOTH with a single buffer.
if (mBuffer) {
ctx = new gfxContext(mBuffer);
} else {
ctx = new gfxContext(mDTBuffer);
}
ctx = new gfxContext(mDTBuffer);
}
// Figure out which quadrant to draw in
@ -454,9 +283,6 @@ ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds, Context
gfxContentType
ThebesLayerBuffer::BufferContentType()
{
if (mBuffer) {
return mBuffer->GetContentType();
}
if (mBufferProvider) {
return mBufferProvider->GetContentType();
}
@ -482,67 +308,38 @@ ThebesLayerBuffer::BufferSizeOkFor(const nsIntSize& aSize)
aSize < mBufferRect.Size()));
}
bool
ThebesLayerBuffer::IsAzureBuffer()
{
MOZ_ASSERT(!(mDTBuffer && mBuffer), "Trying to use Azure and Thebes in the same buffer?");
if (mDTBuffer) {
return true;
}
if (mBuffer) {
return false;
}
if (mBufferProvider) {
return gfxPlatform::GetPlatform()->SupportsAzureContentForType(
mBufferProvider->BackendType());
}
return SupportsAzureContent();
}
bool
ThebesLayerBuffer::EnsureBuffer()
{
if ((!mBuffer && !mDTBuffer) && mBufferProvider) {
if (IsAzureBuffer()) {
mDTBuffer = mBufferProvider->LockDrawTarget();
mBuffer = nullptr;
} else {
mBuffer = mBufferProvider->LockSurface();
mDTBuffer = nullptr;
}
if (!mDTBuffer && mBufferProvider) {
mDTBuffer = mBufferProvider->LockDrawTarget();
}
NS_WARN_IF_FALSE(mBuffer || mDTBuffer, "no buffer");
return mBuffer || mDTBuffer;
NS_WARN_IF_FALSE(mDTBuffer, "no buffer");
return !!mDTBuffer;
}
bool
ThebesLayerBuffer::EnsureBufferOnWhite()
{
if ((!mBufferOnWhite && !mDTBufferOnWhite) && mBufferProviderOnWhite) {
if (IsAzureBuffer()) {
mDTBufferOnWhite = mBufferProviderOnWhite->LockDrawTarget();
mBufferOnWhite = nullptr;
} else {
mBufferOnWhite = mBufferProviderOnWhite->LockSurface();
mDTBufferOnWhite = nullptr;
}
if (!mDTBufferOnWhite && mBufferProviderOnWhite) {
mDTBufferOnWhite = mBufferProviderOnWhite->LockDrawTarget();
}
NS_WARN_IF_FALSE(mBufferOnWhite || mDTBufferOnWhite, "no buffer");
return mBufferOnWhite || mDTBufferOnWhite;
NS_WARN_IF_FALSE(mDTBufferOnWhite, "no buffer");
return mDTBufferOnWhite;
}
bool
ThebesLayerBuffer::HaveBuffer() const
{
return mDTBuffer || mBuffer || mBufferProvider;
return mDTBuffer || mBufferProvider;
}
bool
ThebesLayerBuffer::HaveBufferOnWhite() const
{
return mDTBufferOnWhite || mBufferOnWhite || mBufferProviderOnWhite;
return mDTBufferOnWhite || mBufferProviderOnWhite;
}
static void
@ -680,8 +477,6 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
return result;
nsIntRect drawBounds = result.mRegionToDraw.GetBounds();
nsRefPtr<gfxASurface> destBuffer;
nsRefPtr<gfxASurface> destBufferOnWhite;
RefPtr<DrawTarget> destDTBuffer;
RefPtr<DrawTarget> destDTBufferOnWhite;
uint32_t bufferFlags = canHaveRotation ? ALLOW_REPEAT : 0;
@ -714,28 +509,16 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
if (mBufferRotation == nsIntPoint(0,0)) {
nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size());
nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
if (IsAzureBuffer()) {
MOZ_ASSERT(mDTBuffer);
mDTBuffer->CopyRect(IntRect(srcRect.x, srcRect.y, srcRect.width, srcRect.height),
IntPoint(dest.x, dest.y));
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
MOZ_ASSERT(mDTBufferOnWhite);
mDTBufferOnWhite->CopyRect(IntRect(srcRect.x, srcRect.y, srcRect.width, srcRect.height),
IntPoint(dest.x, dest.y));
}
} else {
MOZ_ASSERT(mBuffer);
mBuffer->MovePixels(srcRect, dest);
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
MOZ_ASSERT(mBufferOnWhite);
mBufferOnWhite->MovePixels(srcRect, dest);
MOZ_ASSERT(mDTBuffer);
mDTBuffer->CopyRect(IntRect(srcRect.x, srcRect.y, srcRect.width, srcRect.height),
IntPoint(dest.x, dest.y));
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
MOZ_ASSERT(mDTBufferOnWhite);
mDTBufferOnWhite->CopyRect(IntRect(srcRect.x, srcRect.y, srcRect.width, srcRect.height),
IntPoint(dest.x, dest.y));
}
result.mDidSelfCopy = true;
mDidSelfCopy = true;
@ -745,50 +528,48 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
} else {
// With azure and a data surface perform an buffer unrotate
// (SelfCopy).
if (IsAzureBuffer()) {
unsigned char* data;
IntSize size;
int32_t stride;
SurfaceFormat format;
unsigned char* data;
IntSize size;
int32_t stride;
SurfaceFormat format;
if (mDTBuffer->LockBits(&data, &size, &stride, &format)) {
if (mDTBuffer->LockBits(&data, &size, &stride, &format)) {
uint8_t bytesPerPixel = BytesPerPixel(format);
BufferUnrotate(data,
size.width * bytesPerPixel,
size.height, stride,
newRotation.x * bytesPerPixel, newRotation.y);
mDTBuffer->ReleaseBits(data);
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
MOZ_ASSERT(mDTBufferOnWhite);
mDTBufferOnWhite->LockBits(&data, &size, &stride, &format);
uint8_t bytesPerPixel = BytesPerPixel(format);
BufferUnrotate(data,
size.width * bytesPerPixel,
size.height, stride,
newRotation.x * bytesPerPixel, newRotation.y);
mDTBuffer->ReleaseBits(data);
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
MOZ_ASSERT(mDTBufferOnWhite);
mDTBufferOnWhite->LockBits(&data, &size, &stride, &format);
uint8_t bytesPerPixel = BytesPerPixel(format);
BufferUnrotate(data,
size.width * bytesPerPixel,
size.height, stride,
newRotation.x * bytesPerPixel, newRotation.y);
mDTBufferOnWhite->ReleaseBits(data);
}
// Buffer unrotate moves all the pixels, note that
// we self copied for SyncBackToFrontBuffer
result.mDidSelfCopy = true;
mDidSelfCopy = true;
mBufferRect = destBufferRect;
mBufferRotation = nsIntPoint(0, 0);
mDTBufferOnWhite->ReleaseBits(data);
}
// Buffer unrotate moves all the pixels, note that
// we self copied for SyncBackToFrontBuffer
result.mDidSelfCopy = true;
mDidSelfCopy = true;
mBufferRect = destBufferRect;
mBufferRotation = nsIntPoint(0, 0);
}
if (!result.mDidSelfCopy) {
destBufferRect = ComputeBufferRect(neededRegion.GetBounds());
CreateBuffer(contentType, destBufferRect, bufferFlags,
getter_AddRefs(destBuffer), getter_AddRefs(destBufferOnWhite),
&destDTBuffer, &destDTBufferOnWhite);
if (!destBuffer && !destDTBuffer)
if (!destDTBuffer) {
return result;
}
}
}
} else {
@ -805,10 +586,10 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
} else {
// The buffer's not big enough, so allocate a new one
CreateBuffer(contentType, destBufferRect, bufferFlags,
getter_AddRefs(destBuffer), getter_AddRefs(destBufferOnWhite),
&destDTBuffer, &destDTBufferOnWhite);
if (!destBuffer && !destDTBuffer)
if (!destDTBuffer) {
return result;
}
}
NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
@ -818,37 +599,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
// and we do not need to clear it below.
bool isClear = !HaveBuffer();
if (destBuffer) {
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));
if (!EnsureBuffer()) {
return result;
}
DrawBufferWithRotation(tmpCtx, BUFFER_BLACK);
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
NS_ASSERTION(destBufferOnWhite, "Must have a white buffer!");
nsRefPtr<gfxContext> tmpCtx = new gfxContext(destBufferOnWhite);
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpCtx->Translate(gfxPoint(offset.x, offset.y));
DrawBufferWithRotation(tmpCtx, BUFFER_WHITE);
}
}
mBuffer = destBuffer.forget();
mDTBuffer = nullptr;
mBufferRect = destBufferRect;
mBufferOnWhite = destBufferOnWhite.forget();
mDTBufferOnWhite = nullptr;
mBufferRotation = nsIntPoint(0,0);
} else if (destDTBuffer) {
if (destDTBuffer) {
if (!isClear && (mode != Layer::SURFACE_COMPONENT_ALPHA || HaveBufferOnWhite())) {
// Copy the bits
nsIntPoint offset = -destBufferRect.TopLeft();
@ -875,9 +626,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
}
mDTBuffer = destDTBuffer.forget();
mBuffer = nullptr;
mDTBufferOnWhite = destDTBufferOnWhite.forget();
mBufferOnWhite = nullptr;
mBufferRect = destBufferRect;
mBufferRotation = nsIntPoint(0,0);
}
@ -893,37 +642,20 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
result.mClip = CLIP_DRAW_SNAPPED;
if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
if (IsAzureBuffer()) {
MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite);
nsIntRegionRectIterator iter(result.mRegionToDraw);
const nsIntRect *iterRect;
while ((iterRect = iter.Next())) {
mDTBuffer->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height),
ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
mDTBufferOnWhite->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height),
ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
}
} else {
MOZ_ASSERT(mBuffer && mBufferOnWhite);
FillSurface(mBuffer, result.mRegionToDraw, topLeft, gfxRGBA(0.0, 0.0, 0.0, 1.0));
FillSurface(mBufferOnWhite, result.mRegionToDraw, topLeft, gfxRGBA(1.0, 1.0, 1.0, 1.0));
MOZ_ASSERT(mDTBuffer && mDTBufferOnWhite);
nsIntRegionRectIterator iter(result.mRegionToDraw);
const nsIntRect *iterRect;
while ((iterRect = iter.Next())) {
mDTBuffer->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height),
ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));
mDTBufferOnWhite->FillRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height),
ColorPattern(Color(1.0, 1.0, 1.0, 1.0)));
}
} else if (contentType == GFX_CONTENT_COLOR_ALPHA && !isClear) {
if (IsAzureBuffer()) {
nsIntRegionRectIterator iter(result.mRegionToDraw);
const nsIntRect *iterRect;
while ((iterRect = iter.Next())) {
result.mContext->GetDrawTarget()->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
}
// Clear will do something expensive with a complex clip pushed, so clip
// here.
} else {
MOZ_ASSERT(result.mContext->IsCairo());
result.mContext->Save();
gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
result.mContext->Paint();
result.mContext->Restore();
nsIntRegionRectIterator iter(result.mRegionToDraw);
const nsIntRect *iterRect;
while ((iterRect = iter.Next())) {
result.mContext->GetDrawTarget()->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
}
}

View File

@ -55,15 +55,6 @@ class RotatedBuffer {
public:
typedef gfxContentType ContentType;
RotatedBuffer(gfxASurface* aBuffer, gfxASurface* aBufferOnWhite,
const nsIntRect& aBufferRect,
const nsIntPoint& aBufferRotation)
: mBuffer(aBuffer)
, mBufferOnWhite(aBufferOnWhite)
, mBufferRect(aBufferRect)
, mBufferRotation(aBufferRotation)
, mDidSelfCopy(false)
{ }
RotatedBuffer(gfx::DrawTarget* aDTBuffer, gfx::DrawTarget* aDTBufferOnWhite,
const nsIntRect& aBufferRect,
const nsIntPoint& aBufferRotation)
@ -85,11 +76,6 @@ public:
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, ContextSource aSource,
float aOpacity = 1.0,
gfx::CompositionOp aOperator = gfx::OP_OVER,
@ -104,8 +90,8 @@ 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; }
virtual bool HaveBuffer() const { return mDTBuffer; }
virtual bool HaveBufferOnWhite() const { return mDTBufferOnWhite; }
protected:
@ -124,11 +110,6 @@ protected:
* buffer. aMaskTransform must be non-null if aMask is non-null, and is used
* 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,
@ -136,8 +117,6 @@ protected:
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 */
@ -196,8 +175,6 @@ public:
*/
void Clear()
{
mBuffer = nullptr;
mBufferOnWhite = nullptr;
mDTBuffer = nullptr;
mDTBufferOnWhite = nullptr;
mBufferProvider = nullptr;
@ -264,18 +241,13 @@ public:
*/
virtual void
CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface,
RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) = 0;
virtual bool SupportsAzureContent() const
{ return false; }
/**
* Get the underlying buffer, if any. This is useful because we can pass
* in the buffer as the default "reference surface" if there is one.
* Don't use it for anything else!
*/
gfxASurface* GetBuffer() { return mBuffer; }
gfxASurface* GetBufferOnWhite() { return mBufferOnWhite; }
gfx::DrawTarget* GetDTBuffer() { return mDTBuffer; }
gfx::DrawTarget* GetDTBufferOnWhite() { return mDTBufferOnWhite; }
@ -288,35 +260,11 @@ public:
gfxASurface* aMask, const gfxMatrix* aMaskTransform);
protected:
// If this buffer is currently using Azure.
bool IsAzureBuffer();
already_AddRefed<gfxASurface>
SetBuffer(gfxASurface* aBuffer,
const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation)
{
MOZ_ASSERT(!SupportsAzureContent());
nsRefPtr<gfxASurface> tmp = mBuffer.forget();
mBuffer = aBuffer;
mBufferRect = aBufferRect;
mBufferRotation = aBufferRotation;
return tmp.forget();
}
already_AddRefed<gfxASurface>
SetBufferOnWhite(gfxASurface* aBuffer)
{
MOZ_ASSERT(!SupportsAzureContent());
nsRefPtr<gfxASurface> tmp = mBufferOnWhite.forget();
mBufferOnWhite = aBuffer;
return tmp.forget();
}
TemporaryRef<gfx::DrawTarget>
SetDTBuffer(gfx::DrawTarget* aBuffer,
const nsIntRect& aBufferRect, const nsIntPoint& aBufferRotation)
const nsIntRect& aBufferRect,
const nsIntPoint& aBufferRotation)
{
MOZ_ASSERT(SupportsAzureContent());
RefPtr<gfx::DrawTarget> tmp = mDTBuffer.forget();
mDTBuffer = aBuffer;
mBufferRect = aBufferRect;
@ -327,7 +275,6 @@ protected:
TemporaryRef<gfx::DrawTarget>
SetDTBufferOnWhite(gfx::DrawTarget* aBuffer)
{
MOZ_ASSERT(SupportsAzureContent());
RefPtr<gfx::DrawTarget> tmp = mDTBufferOnWhite.forget();
mDTBufferOnWhite = aBuffer;
return tmp.forget();
@ -348,11 +295,10 @@ protected:
{
// Only this buffer provider can give us a buffer. If we
// already have one, something has gone wrong.
MOZ_ASSERT(!aClient || (!mBuffer && !mDTBuffer));
MOZ_ASSERT(!aClient || !mDTBuffer);
mBufferProvider = aClient;
if (!mBufferProvider) {
mBuffer = nullptr;
mDTBuffer = nullptr;
}
}
@ -361,11 +307,10 @@ protected:
{
// Only this buffer provider can give us a buffer. If we
// already have one, something has gone wrong.
MOZ_ASSERT(!aClient || (!mBufferOnWhite && !mDTBufferOnWhite));
MOZ_ASSERT(!aClient || !mDTBufferOnWhite);
mBufferProviderOnWhite = aClient;
if (!mBufferProviderOnWhite) {
mBufferOnWhite = nullptr;
mDTBufferOnWhite = nullptr;
}
}
@ -382,9 +327,6 @@ protected:
static bool IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion);
protected:
// Buffer helpers. Don't use mBuffer directly; instead use one of
// these helpers.
/**
* Return the buffer's content type. Requires a valid buffer or
* buffer provider.

View File

@ -82,37 +82,17 @@ void
ContentClientBasic::CreateBuffer(ContentType aType,
const nsIntRect& aRect,
uint32_t aFlags,
gfxASurface** aBlackSurface,
gfxASurface** aWhiteSurface,
RefPtr<gfx::DrawTarget>* aBlackDT,
RefPtr<gfx::DrawTarget>* aWhiteDT)
{
MOZ_ASSERT(!(aFlags & BUFFER_COMPONENT_ALPHA));
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
gfxImageFormat format =
gfxPlatform::GetPlatform()->OptimalFormatForContent(aType);
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContent());
gfxImageFormat format =
gfxPlatform::GetPlatform()->OptimalFormatForContent(aType);
*aBlackDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
IntSize(aRect.width, aRect.height),
ImageFormatToSurfaceFormat(format));
return;
}
nsRefPtr<gfxASurface> referenceSurface = GetBuffer();
if (!referenceSurface) {
gfxContext* defaultTarget = mManager->GetDefaultTarget();
if (defaultTarget) {
referenceSurface = defaultTarget->CurrentSurface();
} else {
nsIWidget* widget = mManager->GetRetainerWidget();
if (!widget || !(referenceSurface = widget->GetThebesSurface())) {
referenceSurface = mManager->GetTarget()->CurrentSurface();
}
}
}
nsRefPtr<gfxASurface> ret = referenceSurface->CreateSimilarSurface(
aType, gfxIntSize(aRect.width, aRect.height));
*aBlackSurface = ret.forget().get();
*aBlackDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
IntSize(aRect.width, aRect.height),
ImageFormatToSurfaceFormat(format));
}
void
@ -219,27 +199,10 @@ ContentClientRemoteBuffer::BuildDeprecatedTextureClients(ContentType aType,
mIsNewBuffer = true;
}
bool
ContentClientBasic::SupportsAzureContent() const
{
return gfxPlatform::GetPlatform()->SupportsAzureContent();
}
bool
ContentClientRemoteBuffer::SupportsAzureContent() const
{
MOZ_ASSERT(mDeprecatedTextureClient);
return gfxPlatform::GetPlatform()->SupportsAzureContentForType(
mDeprecatedTextureClient->BackendType());
}
void
ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
const nsIntRect& aRect,
uint32_t aFlags,
gfxASurface** aBlackSurface,
gfxASurface** aWhiteSurface,
RefPtr<gfx::DrawTarget>* aBlackDT,
RefPtr<gfx::DrawTarget>* aWhiteDT)
{
@ -248,19 +211,11 @@ ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
return;
}
if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(
mDeprecatedTextureClient->BackendType())) {
*aBlackDT = mDeprecatedTextureClient->LockDrawTarget();
if (aFlags & BUFFER_COMPONENT_ALPHA) {
*aWhiteDT = mDeprecatedTextureClientOnWhite->LockDrawTarget();
}
} else {
nsRefPtr<gfxASurface> ret = mDeprecatedTextureClient->LockSurface();
*aBlackSurface = ret.forget().get();
if (aFlags & BUFFER_COMPONENT_ALPHA) {
nsRefPtr<gfxASurface> retWhite = mDeprecatedTextureClientOnWhite->LockSurface();
*aWhiteSurface = retWhite.forget().get();
}
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContentForType(
mDeprecatedTextureClient->BackendType()));
*aBlackDT = mDeprecatedTextureClient->LockDrawTarget();
if (aFlags & BUFFER_COMPONENT_ALPHA) {
*aWhiteDT = mDeprecatedTextureClientOnWhite->LockDrawTarget();
}
}
@ -471,15 +426,6 @@ struct AutoDeprecatedTextureClient {
mTexture->Unlock();
}
}
gfxASurface* GetSurface(DeprecatedTextureClient* aTexture)
{
MOZ_ASSERT(!mTexture);
mTexture = aTexture;
if (mTexture) {
return mTexture->LockSurface();
}
return nullptr;
}
DrawTarget* GetDrawTarget(DeprecatedTextureClient* aTexture)
{
MOZ_ASSERT(!mTexture);
@ -536,25 +482,15 @@ ContentClientDoubleBuffered::SyncFrontBufferToBackBuffer()
AutoDeprecatedTextureClient autoTextureFront;
AutoDeprecatedTextureClient autoTextureFrontOnWhite;
if (SupportsAzureContent()) {
// We need to ensure that we lock these two buffers in the same
// order as the compositor to prevent deadlocks.
DrawTarget* dt = autoTextureFront.GetDrawTarget(mFrontClient);
DrawTarget* dtOnWhite = autoTextureFrontOnWhite.GetDrawTarget(mFrontClientOnWhite);
RotatedBuffer frontBuffer(dt,
dtOnWhite,
mFrontBufferRect,
mFrontBufferRotation);
UpdateDestinationFrom(frontBuffer, updateRegion);
} else {
gfxASurface* surf = autoTextureFront.GetSurface(mFrontClient);
gfxASurface* surfOnWhite = autoTextureFrontOnWhite.GetSurface(mFrontClientOnWhite);
RotatedBuffer frontBuffer(surf,
surfOnWhite,
mFrontBufferRect,
mFrontBufferRotation);
UpdateDestinationFrom(frontBuffer, updateRegion);
}
// We need to ensure that we lock these two buffers in the same
// order as the compositor to prevent deadlocks.
DrawTarget* dt = autoTextureFront.GetDrawTarget(mFrontClient);
DrawTarget* dtOnWhite = autoTextureFrontOnWhite.GetDrawTarget(mFrontClientOnWhite);
RotatedBuffer frontBuffer(dt,
dtOnWhite,
mFrontBufferRect,
mFrontBufferRotation);
UpdateDestinationFrom(frontBuffer, updateRegion);
mFrontAndBackBufferDiffer = false;
}
@ -575,12 +511,7 @@ ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
}
if (SupportsAzureContent()) {
MOZ_ASSERT(!destCtx->IsCairo());
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_BLACK, 1.0, OP_SOURCE);
} else {
aSource.DrawBufferWithRotation(destCtx, BUFFER_BLACK);
}
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_BLACK, 1.0, OP_SOURCE);
if (aSource.HaveBufferOnWhite()) {
MOZ_ASSERT(HaveBufferOnWhite());
@ -593,12 +524,7 @@ ContentClientDoubleBuffered::UpdateDestinationFrom(const RotatedBuffer& aSource,
gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
}
if (SupportsAzureContent()) {
MOZ_ASSERT(!destCtx->IsCairo());
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
} else {
aSource.DrawBufferWithRotation(destCtx, BUFFER_WHITE);
}
aSource.DrawBufferWithRotation(destCtx->GetDrawTarget(), BUFFER_WHITE, 1.0, OP_SOURCE);
}
}
@ -630,57 +556,30 @@ ContentClientSingleBuffered::SyncFrontBufferToBackBuffer()
}
mFrontAndBackBufferDiffer = false;
if (SupportsAzureContent()) {
DrawTarget* backBuffer = GetDTBuffer();
if (!backBuffer && mDeprecatedTextureClient) {
backBuffer = mDeprecatedTextureClient->LockDrawTarget();
}
if (!backBuffer) {
NS_WARNING("Could not lock texture client");
return;
}
DrawTarget* backBuffer = GetDTBuffer();
if (!backBuffer && mDeprecatedTextureClient) {
backBuffer = mDeprecatedTextureClient->LockDrawTarget();
}
if (!backBuffer) {
NS_WARNING("Could not lock texture client");
return;
}
RefPtr<DrawTarget> oldBuffer;
oldBuffer = SetDTBuffer(backBuffer,
mBufferRect,
mBufferRotation);
backBuffer = GetDTBufferOnWhite();
if (!backBuffer && mDeprecatedTextureClientOnWhite) {
backBuffer = mDeprecatedTextureClientOnWhite->LockDrawTarget();
}
if (!backBuffer) {
NS_WARNING("Could not lock texture client (on white)");
return;
}
oldBuffer = SetDTBufferOnWhite(backBuffer);
} else {
gfxASurface* backBuffer = GetBuffer();
if (!backBuffer && mDeprecatedTextureClient) {
backBuffer = mDeprecatedTextureClient->LockSurface();
}
if (!backBuffer) {
NS_WARNING("Could not lock texture client");
return;
}
nsRefPtr<gfxASurface> oldBuffer;
oldBuffer = SetBuffer(backBuffer,
RefPtr<DrawTarget> oldBuffer;
oldBuffer = SetDTBuffer(backBuffer,
mBufferRect,
mBufferRotation);
backBuffer = GetBufferOnWhite();
if (!backBuffer && mDeprecatedTextureClientOnWhite) {
backBuffer = mDeprecatedTextureClientOnWhite->LockSurface();
}
if (!backBuffer) {
NS_WARNING("Could not lock texture client (on white)");
return;
}
oldBuffer = SetBufferOnWhite(backBuffer);
backBuffer = GetDTBufferOnWhite();
if (!backBuffer && mDeprecatedTextureClientOnWhite) {
backBuffer = mDeprecatedTextureClientOnWhite->LockDrawTarget();
}
if (!backBuffer) {
NS_WARNING("Could not lock texture client (on white)");
return;
}
oldBuffer = SetDTBufferOnWhite(backBuffer);
}
static void
@ -900,39 +799,19 @@ ContentClientIncremental::BeginPaintBuffer(ThebesLayer* aLayer,
"BeginUpdate should always modify the draw region in the same way!");
FillSurface(onBlack, result.mRegionToDraw, nsIntPoint(drawBounds.x, drawBounds.y), gfxRGBA(0.0, 0.0, 0.0, 1.0));
FillSurface(onWhite, result.mRegionToDraw, nsIntPoint(drawBounds.x, drawBounds.y), gfxRGBA(1.0, 1.0, 1.0, 1.0));
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
RefPtr<DrawTarget> onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize());
RefPtr<DrawTarget> onWhiteDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onWhite, onWhite->GetSize());
RefPtr<DrawTarget> dt = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT);
result.mContext = new gfxContext(dt);
} else {
gfxASurface* surfaces[2] = { onBlack.get(), onWhite.get() };
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 = onBlack->GetDeviceOffset();
onBlack->SetDeviceOffset(gfxPoint(0, 0));
onWhite->SetDeviceOffset(gfxPoint(0, 0));
surf->SetDeviceOffset(deviceOffset);
// Using this surface as a source will likely go horribly wrong, since
// only the onBlack surface will really be used, so alpha information will
// be incorrect.
surf->SetAllowUseAsSource(false);
result.mContext = new gfxContext(surf);
}
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContent());
RefPtr<DrawTarget> onBlackDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onBlack, onBlack->GetSize());
RefPtr<DrawTarget> onWhiteDT = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(onWhite, onWhite->GetSize());
RefPtr<DrawTarget> dt = Factory::CreateDualDrawTarget(onBlackDT, onWhiteDT);
result.mContext = new gfxContext(dt);
} else {
result.mContext = nullptr;
}
} else {
nsRefPtr<gfxASurface> surf = GetUpdateSurface(BUFFER_BLACK, result.mRegionToDraw);
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize());
result.mContext = new gfxContext(dt);
} else {
result.mContext = new gfxContext(surf);
}
MOZ_ASSERT(gfxPlatform::GetPlatform()->SupportsAzureContent());
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForUpdateSurface(surf, surf->GetSize());
result.mContext = new gfxContext(dt);
}
if (!result.mContext) {
NS_WARNING("unable to get context for update");

View File

@ -154,9 +154,7 @@ public:
}
virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface,
RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
virtual bool SupportsAzureContent() const;
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
{
@ -237,11 +235,8 @@ public:
}
virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface,
RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
virtual bool SupportsAzureContent() const MOZ_OVERRIDE;
void DestroyBuffers();
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE