зеркало из https://github.com/mozilla/gecko-dev.git
Bug 778367 - Part 1: Minimize intermediate surface size. r=jrmuizel
This commit is contained in:
Родитель
dc56f442df
Коммит
d7cbdea701
|
@ -44,10 +44,10 @@ public:
|
|||
Matrix transform = state.surfTransform;
|
||||
|
||||
if (state.patternTransformChanged) {
|
||||
Matrix mat = mContext->mDT->GetTransform();
|
||||
Matrix mat = mContext->mTransform;
|
||||
mat.Invert();
|
||||
|
||||
transform = mat * state.patternTransform * transform;
|
||||
transform = transform * state.patternTransform * mat;
|
||||
}
|
||||
|
||||
mPattern = new (mSurfacePattern.addr())
|
||||
|
@ -183,7 +183,7 @@ gfxContext::Save()
|
|||
if (mCairo) {
|
||||
cairo_save(mCairo);
|
||||
} else {
|
||||
CurrentState().transform = mDT->GetTransform();
|
||||
CurrentState().transform = mTransform;
|
||||
mStateStack.AppendElement(AzureState(CurrentState()));
|
||||
CurrentState().clipWasReset = false;
|
||||
CurrentState().pushedClips.Clear();
|
||||
|
@ -212,11 +212,13 @@ gfxContext::Restore()
|
|||
// the restore. We don't currently have users that do this and we should
|
||||
// make sure there will not be any. Sadly we can't assert this easily.
|
||||
mTransformChanged = true;
|
||||
mPathTransform = mDT->GetTransform();
|
||||
mPathTransform = mTransform;
|
||||
}
|
||||
|
||||
mDT = CurrentState().drawTarget;
|
||||
mDT->SetTransform(CurrentState().transform);
|
||||
|
||||
mTransform = CurrentState().transform;
|
||||
mDT->SetTransform(GetDTTransform());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,7 +462,7 @@ gfxContext::Rectangle(const gfxRect& rect, bool snapToPixels)
|
|||
if (snapToPixels) {
|
||||
gfxRect newRect(rect);
|
||||
if (UserToDevicePixelSnapped(newRect, true)) {
|
||||
gfxMatrix mat = ThebesMatrix(mDT->GetTransform());
|
||||
gfxMatrix mat = ThebesMatrix(mTransform);
|
||||
mat.Invert();
|
||||
|
||||
// We need the user space rect.
|
||||
|
@ -552,7 +554,7 @@ gfxContext::Translate(const gfxPoint& pt)
|
|||
if (mCairo) {
|
||||
cairo_translate(mCairo, pt.x, pt.y);
|
||||
} else {
|
||||
Matrix newMatrix = mDT->GetTransform();
|
||||
Matrix newMatrix = mTransform;
|
||||
|
||||
ChangeTransform(newMatrix.Translate(Float(pt.x), Float(pt.y)));
|
||||
}
|
||||
|
@ -564,7 +566,7 @@ gfxContext::Scale(gfxFloat x, gfxFloat y)
|
|||
if (mCairo) {
|
||||
cairo_scale(mCairo, x, y);
|
||||
} else {
|
||||
Matrix newMatrix = mDT->GetTransform();
|
||||
Matrix newMatrix = mTransform;
|
||||
|
||||
ChangeTransform(newMatrix.Scale(Float(x), Float(y)));
|
||||
}
|
||||
|
@ -577,7 +579,7 @@ gfxContext::Rotate(gfxFloat angle)
|
|||
cairo_rotate(mCairo, angle);
|
||||
} else {
|
||||
Matrix rotation = Matrix::Rotation(Float(angle));
|
||||
ChangeTransform(rotation * mDT->GetTransform());
|
||||
ChangeTransform(rotation * mTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -588,7 +590,7 @@ gfxContext::Multiply(const gfxMatrix& matrix)
|
|||
const cairo_matrix_t& mat = reinterpret_cast<const cairo_matrix_t&>(matrix);
|
||||
cairo_transform(mCairo, &mat);
|
||||
} else {
|
||||
ChangeTransform(ToMatrix(matrix) * mDT->GetTransform());
|
||||
ChangeTransform(ToMatrix(matrix) * mTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,7 +602,7 @@ gfxContext::MultiplyAndNudgeToIntegers(const gfxMatrix& matrix)
|
|||
cairo_transform(mCairo, &mat);
|
||||
// XXX nudging to integers not currently supported for Thebes
|
||||
} else {
|
||||
Matrix transform = ToMatrix(matrix) * mDT->GetTransform();
|
||||
Matrix transform = ToMatrix(matrix) * mTransform;
|
||||
transform.NudgeToIntegers();
|
||||
ChangeTransform(transform);
|
||||
}
|
||||
|
@ -613,6 +615,8 @@ gfxContext::SetMatrix(const gfxMatrix& matrix)
|
|||
const cairo_matrix_t& mat = reinterpret_cast<const cairo_matrix_t&>(matrix);
|
||||
cairo_set_matrix(mCairo, &mat);
|
||||
} else {
|
||||
Matrix mat;
|
||||
mat.Translate(-CurrentState().deviceOffset.x, -CurrentState().deviceOffset.y);
|
||||
ChangeTransform(ToMatrix(matrix));
|
||||
}
|
||||
}
|
||||
|
@ -635,7 +639,7 @@ gfxContext::CurrentMatrix() const
|
|||
cairo_get_matrix(mCairo, &mat);
|
||||
return gfxMatrix(*reinterpret_cast<gfxMatrix*>(&mat));
|
||||
} else {
|
||||
return ThebesMatrix(mDT->GetTransform());
|
||||
return ThebesMatrix(mTransform);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -650,7 +654,7 @@ gfxContext::NudgeCurrentMatrixToIntegers()
|
|||
} else {
|
||||
gfxMatrix matrix = ThebesMatrix(mTransform);
|
||||
matrix.NudgeToIntegers();
|
||||
mTransform = ToMatrix(matrix);
|
||||
ChangeTransform(ToMatrix(matrix));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -662,7 +666,7 @@ gfxContext::DeviceToUser(const gfxPoint& point) const
|
|||
cairo_device_to_user(mCairo, &ret.x, &ret.y);
|
||||
return ret;
|
||||
} else {
|
||||
Matrix matrix = mDT->GetTransform();
|
||||
Matrix matrix = mTransform;
|
||||
|
||||
matrix.Invert();
|
||||
|
||||
|
@ -678,7 +682,7 @@ gfxContext::DeviceToUser(const gfxSize& size) const
|
|||
cairo_device_to_user_distance(mCairo, &ret.width, &ret.height);
|
||||
return ret;
|
||||
} else {
|
||||
Matrix matrix = mDT->GetTransform();
|
||||
Matrix matrix = mTransform;
|
||||
|
||||
matrix.Invert();
|
||||
|
||||
|
@ -695,7 +699,7 @@ gfxContext::DeviceToUser(const gfxRect& rect) const
|
|||
cairo_device_to_user_distance(mCairo, &ret.width, &ret.height);
|
||||
return ret;
|
||||
} else {
|
||||
Matrix matrix = mDT->GetTransform();
|
||||
Matrix matrix = mTransform;
|
||||
|
||||
matrix.Invert();
|
||||
|
||||
|
@ -711,7 +715,7 @@ gfxContext::UserToDevice(const gfxPoint& point) const
|
|||
cairo_user_to_device(mCairo, &ret.x, &ret.y);
|
||||
return ret;
|
||||
} else {
|
||||
return ThebesPoint(mDT->GetTransform() * ToPoint(point));
|
||||
return ThebesPoint(mTransform * ToPoint(point));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,7 +727,7 @@ gfxContext::UserToDevice(const gfxSize& size) const
|
|||
cairo_user_to_device_distance(mCairo, &ret.width, &ret.height);
|
||||
return ret;
|
||||
} else {
|
||||
const Matrix &matrix = mDT->GetTransform();
|
||||
const Matrix &matrix = mTransform;
|
||||
|
||||
gfxSize newSize = size;
|
||||
newSize.width = newSize.width * matrix._11 + newSize.height * matrix._12;
|
||||
|
@ -756,7 +760,7 @@ gfxContext::UserToDevice(const gfxRect& rect) const
|
|||
|
||||
return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin);
|
||||
} else {
|
||||
const Matrix &matrix = mDT->GetTransform();
|
||||
const Matrix &matrix = mTransform;
|
||||
return ThebesRect(matrix.TransformBounds(ToRect(rect)));
|
||||
}
|
||||
}
|
||||
|
@ -780,7 +784,7 @@ gfxContext::UserToDevicePixelSnapped(gfxRect& rect, bool ignoreScale) const
|
|||
!WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0)))
|
||||
return false;
|
||||
} else {
|
||||
Matrix mat = mDT->GetTransform();
|
||||
Matrix mat = mTransform;
|
||||
if (!ignoreScale &&
|
||||
(!WITHIN_E(mat._11,1.0) || !WITHIN_E(mat._22,1.0) ||
|
||||
!WITHIN_E(mat._12,0.0) || !WITHIN_E(mat._21,0.0)))
|
||||
|
@ -830,7 +834,7 @@ gfxContext::UserToDevicePixelSnapped(gfxPoint& pt, bool ignoreScale) const
|
|||
!WITHIN_E(mat.xy,0.0) || !WITHIN_E(mat.yx,0.0)))
|
||||
return false;
|
||||
} else {
|
||||
Matrix mat = mDT->GetTransform();
|
||||
Matrix mat = mTransform;
|
||||
if (!ignoreScale &&
|
||||
(!WITHIN_E(mat._11,1.0) || !WITHIN_E(mat._22,1.0) ||
|
||||
!WITHIN_E(mat._12,0.0) || !WITHIN_E(mat._21,0.0)))
|
||||
|
@ -1121,7 +1125,7 @@ gfxContext::Clip(const gfxRect& rect)
|
|||
cairo_rectangle(mCairo, rect.X(), rect.Y(), rect.Width(), rect.Height());
|
||||
cairo_clip(mCairo);
|
||||
} else {
|
||||
AzureState::PushedClip clip = { NULL, ToRect(rect), mDT->GetTransform() };
|
||||
AzureState::PushedClip clip = { NULL, ToRect(rect), mTransform };
|
||||
CurrentState().pushedClips.AppendElement(clip);
|
||||
mDT->PushClipRect(ToRect(rect));
|
||||
NewPath();
|
||||
|
@ -1135,13 +1139,13 @@ gfxContext::Clip()
|
|||
cairo_clip_preserve(mCairo);
|
||||
} else {
|
||||
if (mPathIsRect && !mTransformChanged) {
|
||||
AzureState::PushedClip clip = { NULL, mRect, mDT->GetTransform() };
|
||||
AzureState::PushedClip clip = { NULL, mRect, mTransform };
|
||||
CurrentState().pushedClips.AppendElement(clip);
|
||||
mDT->PushClipRect(mRect);
|
||||
} else {
|
||||
EnsurePath();
|
||||
mDT->PushClip(mPath);
|
||||
AzureState::PushedClip clip = { mPath, Rect(), mDT->GetTransform() };
|
||||
AzureState::PushedClip clip = { mPath, Rect(), mTransform };
|
||||
CurrentState().pushedClips.AppendElement(clip);
|
||||
}
|
||||
}
|
||||
|
@ -1188,31 +1192,13 @@ gfxContext::GetClipExtents()
|
|||
cairo_clip_extents(mCairo, &xmin, &ymin, &xmax, &ymax);
|
||||
return gfxRect(xmin, ymin, xmax - xmin, ymax - ymin);
|
||||
} else {
|
||||
unsigned int lastReset = 0;
|
||||
for (int i = mStateStack.Length() - 1; i > 0; i--) {
|
||||
if (mStateStack[i].clipWasReset) {
|
||||
lastReset = i;
|
||||
}
|
||||
}
|
||||
|
||||
Rect rect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height));
|
||||
for (unsigned int i = lastReset; i < mStateStack.Length(); i++) {
|
||||
for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
|
||||
AzureState::PushedClip &clip = mStateStack[i].pushedClips[c];
|
||||
if (clip.path) {
|
||||
Rect bounds = clip.path->GetBounds(clip.transform);
|
||||
rect.IntersectRect(rect, bounds);
|
||||
} else {
|
||||
rect.IntersectRect(rect, clip.transform.TransformBounds(clip.rect));
|
||||
}
|
||||
}
|
||||
}
|
||||
Rect rect = GetAzureDeviceSpaceClipBounds();
|
||||
|
||||
if (rect.width == 0 || rect.height == 0) {
|
||||
return gfxRect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
Matrix mat = mDT->GetTransform();
|
||||
Matrix mat = mTransform;
|
||||
mat.Invert();
|
||||
rect = mat.TransformBounds(rect);
|
||||
|
||||
|
@ -1469,15 +1455,23 @@ gfxContext::PushGroup(gfxASurface::gfxContentType content)
|
|||
if (mCairo) {
|
||||
cairo_push_group_with_content(mCairo, (cairo_content_t) content);
|
||||
} else {
|
||||
Rect clipBounds = GetAzureDeviceSpaceClipBounds();
|
||||
clipBounds.RoundOut();
|
||||
|
||||
clipBounds.width = NS_MAX(1.0f, clipBounds.width);
|
||||
clipBounds.height = NS_MAX(1.0f, clipBounds.height);
|
||||
|
||||
RefPtr<DrawTarget> newDT =
|
||||
mDT->CreateSimilarDrawTarget(mDT->GetSize(), gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content));
|
||||
mDT->CreateSimilarDrawTarget(IntSize(int32_t(clipBounds.width), int32_t(clipBounds.height)),
|
||||
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(content));
|
||||
|
||||
Save();
|
||||
|
||||
CurrentState().drawTarget = newDT;
|
||||
CurrentState().deviceOffset = clipBounds.TopLeft();
|
||||
|
||||
PushClipsToDT(newDT);
|
||||
newDT->SetTransform(mDT->GetTransform());
|
||||
newDT->SetTransform(GetDTTransform());
|
||||
mDT = newDT;
|
||||
}
|
||||
}
|
||||
|
@ -1549,7 +1543,7 @@ gfxContext::PushGroupAndCopyBackground(gfxASurface::gfxContentType content)
|
|||
PushGroup(content);
|
||||
Rect surfRect(0, 0, Float(mDT->GetSize().width), Float(mDT->GetSize().height));
|
||||
Matrix oldTransform = mDT->GetTransform();
|
||||
mDT->SetTransform(Matrix());
|
||||
mDT->SetTransform(GetDeviceTransform());
|
||||
mDT->DrawSurface(source, surfRect, surfRect);
|
||||
mDT->SetTransform(oldTransform);
|
||||
mDT->SetOpaqueRect(oldDT->GetOpaqueRect());
|
||||
|
@ -1570,12 +1564,17 @@ gfxContext::PopGroup()
|
|||
return wrapper;
|
||||
} else {
|
||||
RefPtr<SourceSurface> src = mDT->Snapshot();
|
||||
Point deviceOffset = CurrentState().deviceOffset;
|
||||
|
||||
Restore();
|
||||
|
||||
Matrix mat = mDT->GetTransform();
|
||||
Matrix mat = mTransform;
|
||||
mat.Invert();
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(src, mat);
|
||||
|
||||
Matrix deviceOffsetTranslation;
|
||||
deviceOffsetTranslation.Translate(deviceOffset.x, deviceOffset.y);
|
||||
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(src, deviceOffsetTranslation * mat);
|
||||
|
||||
return pat.forget();
|
||||
}
|
||||
|
@ -1588,15 +1587,19 @@ gfxContext::PopGroupToSource()
|
|||
cairo_pop_group_to_source(mCairo);
|
||||
} else {
|
||||
RefPtr<SourceSurface> src = mDT->Snapshot();
|
||||
Point deviceOffset = CurrentState().deviceOffset;
|
||||
Restore();
|
||||
CurrentState().sourceSurfCairo = NULL;
|
||||
CurrentState().sourceSurface = src;
|
||||
CurrentState().pattern = NULL;
|
||||
CurrentState().patternTransformChanged = false;
|
||||
|
||||
Matrix mat = mDT->GetTransform();
|
||||
Matrix mat = mTransform;
|
||||
mat.Invert();
|
||||
CurrentState().surfTransform = mat;
|
||||
|
||||
Matrix deviceOffsetTranslation;
|
||||
deviceOffsetTranslation.Translate(deviceOffset.x, deviceOffset.y);
|
||||
CurrentState().surfTransform = deviceOffsetTranslation * mat;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1922,7 +1925,7 @@ gfxContext::EnsurePath()
|
|||
|
||||
if (mPath) {
|
||||
if (mTransformChanged) {
|
||||
Matrix mat = mDT->GetTransform();
|
||||
Matrix mat = mTransform;
|
||||
mat.Invert();
|
||||
mat = mPathTransform * mat;
|
||||
mPathBuilder = mPath->TransformedCopyToBuilder(mat, CurrentState().fillRule);
|
||||
|
@ -1970,7 +1973,7 @@ gfxContext::EnsurePathBuilder()
|
|||
mPathBuilder->Close();
|
||||
} else if (mPathIsRect) {
|
||||
mTransformChanged = false;
|
||||
Matrix mat = mDT->GetTransform();
|
||||
Matrix mat = mTransform;
|
||||
mat.Invert();
|
||||
mat = mPathTransform * mat;
|
||||
mPathBuilder->MoveTo(mat * mRect.TopLeft());
|
||||
|
@ -2028,7 +2031,7 @@ gfxContext::PushClipsToDT(DrawTarget *aDT)
|
|||
// reset to the clip before ours.
|
||||
for (unsigned int i = lastReset; i < mStateStack.Length() - 1; i++) {
|
||||
for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
|
||||
aDT->SetTransform(mStateStack[i].pushedClips[c].transform);
|
||||
aDT->SetTransform(mStateStack[i].pushedClips[c].transform * GetDeviceTransform());
|
||||
if (mStateStack[i].pushedClips[c].path) {
|
||||
aDT->PushClip(mStateStack[i].pushedClips[c].path);
|
||||
} else {
|
||||
|
@ -2080,7 +2083,7 @@ gfxContext::ChangeTransform(const Matrix &aNewMatrix)
|
|||
|
||||
if ((state.pattern || state.sourceSurface)
|
||||
&& !state.patternTransformChanged) {
|
||||
state.patternTransform = mDT->GetTransform();
|
||||
state.patternTransform = mTransform;
|
||||
state.patternTransformChanged = true;
|
||||
}
|
||||
|
||||
|
@ -2089,7 +2092,7 @@ gfxContext::ChangeTransform(const Matrix &aNewMatrix)
|
|||
|
||||
invMatrix.Invert();
|
||||
|
||||
Matrix toNewUS = mDT->GetTransform() * invMatrix;
|
||||
Matrix toNewUS = mTransform * invMatrix;
|
||||
|
||||
if (toNewUS.IsRectilinear() && mPathIsRect) {
|
||||
mRect = toNewUS.TransformBounds(mRect);
|
||||
|
@ -2111,5 +2114,51 @@ gfxContext::ChangeTransform(const Matrix &aNewMatrix)
|
|||
mTransformChanged = false;
|
||||
}
|
||||
|
||||
mDT->SetTransform(aNewMatrix);
|
||||
mTransform = aNewMatrix;
|
||||
|
||||
mDT->SetTransform(GetDTTransform());
|
||||
}
|
||||
|
||||
Rect
|
||||
gfxContext::GetAzureDeviceSpaceClipBounds()
|
||||
{
|
||||
unsigned int lastReset = 0;
|
||||
for (int i = mStateStack.Length() - 1; i > 0; i--) {
|
||||
if (mStateStack[i].clipWasReset) {
|
||||
lastReset = i;
|
||||
}
|
||||
}
|
||||
|
||||
Rect rect(CurrentState().deviceOffset.x, CurrentState().deviceOffset.y,
|
||||
Float(mDT->GetSize().width), Float(mDT->GetSize().height));
|
||||
for (unsigned int i = lastReset; i < mStateStack.Length(); i++) {
|
||||
for (unsigned int c = 0; c < mStateStack[i].pushedClips.Length(); c++) {
|
||||
AzureState::PushedClip &clip = mStateStack[i].pushedClips[c];
|
||||
if (clip.path) {
|
||||
Rect bounds = clip.path->GetBounds(clip.transform);
|
||||
rect.IntersectRect(rect, bounds);
|
||||
} else {
|
||||
rect.IntersectRect(rect, clip.transform.TransformBounds(clip.rect));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
Matrix
|
||||
gfxContext::GetDeviceTransform() const
|
||||
{
|
||||
Matrix mat;
|
||||
mat.Translate(-CurrentState().deviceOffset.x, -CurrentState().deviceOffset.y);
|
||||
return mat;
|
||||
}
|
||||
|
||||
Matrix
|
||||
gfxContext::GetDTTransform() const
|
||||
{
|
||||
Matrix mat = mTransform;
|
||||
mat._31 -= CurrentState().deviceOffset.x;
|
||||
mat._32 -= CurrentState().deviceOffset.y;
|
||||
return mat;
|
||||
}
|
|
@ -738,6 +738,8 @@ private:
|
|||
mozilla::gfx::AntialiasMode aaMode;
|
||||
bool patternTransformChanged;
|
||||
Matrix patternTransform;
|
||||
// This is used solely for using minimal intermediate surface size.
|
||||
mozilla::gfx::Point deviceOffset;
|
||||
};
|
||||
|
||||
// This ensures mPath contains a valid path (in user space!)
|
||||
|
@ -748,6 +750,9 @@ private:
|
|||
void PushClipsToDT(mozilla::gfx::DrawTarget *aDT);
|
||||
CompositionOp GetOp();
|
||||
void ChangeTransform(const mozilla::gfx::Matrix &aNewMatrix);
|
||||
Rect GetAzureDeviceSpaceClipBounds();
|
||||
Matrix GetDeviceTransform() const;
|
||||
Matrix GetDTTransform() const;
|
||||
|
||||
bool mPathIsRect;
|
||||
bool mTransformChanged;
|
||||
|
|
Загрузка…
Ссылка в новой задаче