Bug 1044702 - Part 2: Convert gfxSurfaceDrawable::Draw to use Moz2D directly. r=Bas

--HG--
extra : rebase_source : 364616efdf06d9fc26017e56f17885f1489c1720
This commit is contained in:
Matt Woodrow 2014-07-29 12:07:32 +12:00
parent f718291cc8
commit fc4fffcb3c

View File

@ -8,6 +8,7 @@
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "gfxColor.h"
#include "gfx2DGlue.h"
#ifdef MOZ_X11
#include "cairo.h"
#include "gfxXlibSurface.h"
@ -25,86 +26,6 @@ gfxSurfaceDrawable::gfxSurfaceDrawable(SourceSurface* aSurface,
{
}
static gfxMatrix
DeviceToImageTransform(gfxContext* aContext,
const gfxMatrix& aUserSpaceToImageSpace)
{
gfxFloat deviceX, deviceY;
nsRefPtr<gfxASurface> currentTarget =
aContext->CurrentSurface(&deviceX, &deviceY);
gfxMatrix currentMatrix = aContext->CurrentMatrix();
gfxMatrix deviceToUser = currentMatrix;
if (!deviceToUser.Invert()) {
return gfxMatrix(0, 0, 0, 0, 0, 0); // singular
}
deviceToUser.Translate(-gfxPoint(-deviceX, -deviceY));
return deviceToUser * aUserSpaceToImageSpace;
}
static void
PreparePatternForUntiledDrawing(gfxPattern* aPattern,
const gfxMatrix& aDeviceToImage,
gfxASurface *currentTarget,
const GraphicsFilter aDefaultFilter)
{
if (!currentTarget) {
// This happens if we're dealing with an Azure target.
aPattern->SetExtend(gfxPattern::EXTEND_PAD);
aPattern->SetFilter(aDefaultFilter);
return;
}
// In theory we can handle this using cairo's EXTEND_PAD,
// but implementation limitations mean we have to consult
// the surface type.
switch (currentTarget->GetType()) {
#ifdef MOZ_X11
case gfxSurfaceType::Xlib:
{
// See bugs 324698, 422179, and 468496. This is a workaround for
// XRender's RepeatPad not being implemented correctly on old X
// servers.
//
// In this situation, cairo avoids XRender and instead reads back
// to perform EXTEND_PAD with pixman. This is too slow so we
// avoid EXTEND_PAD and set the filter to CAIRO_FILTER_FAST ---
// otherwise, pixman's sampling will sample transparency for the
// outside edges and we'll get blurry edges.
//
// But don't do this for simple downscales because it's horrible.
// Downscaling means that device-space coordinates are
// scaled *up* to find the image pixel coordinates.
//
// Cairo, and hence Gecko, can use RepeatPad on Xorg 1.7. We
// enable EXTEND_PAD provided that we're running on a recent
// enough X server.
if (static_cast<gfxXlibSurface*>(currentTarget)->IsPadSlow()) {
bool isDownscale =
aDeviceToImage._11 >= 1.0 && aDeviceToImage._22 >= 1.0 &&
aDeviceToImage._21 == 0.0 && aDeviceToImage._12 == 0.0;
GraphicsFilter filter =
isDownscale ? aDefaultFilter : (const GraphicsFilter)GraphicsFilter::FILTER_FAST;
aPattern->SetFilter(filter);
// Use the default EXTEND_NONE
break;
}
// else fall through to EXTEND_PAD and the default filter.
}
#endif
default:
// turn on EXTEND_PAD.
// This is what we really want for all surface types, if the
// implementation was universally good.
aPattern->SetExtend(gfxPattern::EXTEND_PAD);
aPattern->SetFilter(aDefaultFilter);
break;
}
}
bool
gfxSurfaceDrawable::Draw(gfxContext* aContext,
const gfxRect& aFillRect,
@ -112,35 +33,35 @@ gfxSurfaceDrawable::Draw(gfxContext* aContext,
const GraphicsFilter& aFilter,
const gfxMatrix& aTransform)
{
nsRefPtr<gfxPattern> pattern = new gfxPattern(mSourceSurface, Matrix());
ExtendMode extend = ExtendMode::CLAMP;
if (aRepeat) {
pattern->SetExtend(gfxPattern::EXTEND_REPEAT);
pattern->SetFilter(aFilter);
} else {
GraphicsFilter filter = aFilter;
if (aContext->CurrentMatrix().HasOnlyIntegerTranslation() &&
aTransform.HasOnlyIntegerTranslation())
{
// If we only have integer translation, no special filtering needs to
// happen and we explicitly use FILTER_FAST. This is fast for some
// backends.
filter = GraphicsFilter::FILTER_FAST;
}
nsRefPtr<gfxASurface> currentTarget = aContext->CurrentSurface();
gfxMatrix deviceSpaceToImageSpace =
DeviceToImageTransform(aContext, aTransform);
PreparePatternForUntiledDrawing(pattern, deviceSpaceToImageSpace,
currentTarget, filter);
extend = ExtendMode::REPEAT;
}
Matrix patternTransform = ToMatrix(aTransform * mTransform);
patternTransform.Invert();
SurfacePattern pattern(mSourceSurface, extend,
patternTransform, ToFilter(aFilter));
Rect fillRect = ToRect(aFillRect);
DrawTarget* dt = aContext->GetDrawTarget();
if (aContext->CurrentOperator() == gfxContext::OPERATOR_CLEAR) {
dt->ClearRect(fillRect);
} else if (aContext->CurrentOperator() == gfxContext::OPERATOR_SOURCE) {
// Emulate cairo operator source which is bound by mask!
dt->ClearRect(fillRect);
dt->FillRect(fillRect, pattern);
} else {
CompositionOp op = CompositionOpForOp(aContext->CurrentOperator());
AntialiasMode aaMode =
aContext->CurrentAntialiasMode() == gfxContext::MODE_ALIASED ?
AntialiasMode::NONE :
AntialiasMode::SUBPIXEL;
dt->FillRect(fillRect, pattern, DrawOptions(1.0f, op, aaMode));
}
pattern->SetMatrix(aTransform * mTransform);
aContext->NewPath();
aContext->SetPattern(pattern);
aContext->Rectangle(aFillRect);
aContext->Fill();
// clear the pattern so that the snapshot is released before the
// drawable is destroyed
aContext->SetDeviceColor(gfxRGBA(0.0, 0.0, 0.0, 0.0));
return true;
}