Bug 1531766 - don't clear Skia DTs backing Canvas2D if it is already clearing. r=nical

This commit is contained in:
Lee Salzman 2019-03-01 10:45:37 -05:00
Родитель 417c4b8b8a
Коммит cbcaadbda8
2 изменённых файлов: 30 добавлений и 24 удалений

Просмотреть файл

@ -222,25 +222,25 @@ class CanvasLinearGradient : public CanvasGradient {
};
bool CanvasRenderingContext2D::PatternIsOpaque(
CanvasRenderingContext2D::Style aStyle) const {
CanvasRenderingContext2D::Style aStyle, bool* aIsColor) const {
const ContextState& state = CurrentState();
if (state.globalAlpha < 1.0) {
return false;
bool opaque = false;
bool color = false;
if (state.globalAlpha >= 1.0) {
if (state.patternStyles[aStyle] && state.patternStyles[aStyle]->mSurface) {
opaque = IsOpaque(state.patternStyles[aStyle]->mSurface->GetFormat());
} else if (!state.gradientStyles[aStyle]) {
// TODO: for gradient patterns we could check that all stops are opaque
// colors.
// it's a color pattern.
opaque = Color::FromABGR(state.colorStyles[aStyle]).a >= 1.0;
color = true;
}
}
if (state.patternStyles[aStyle] && state.patternStyles[aStyle]->mSurface) {
return IsOpaque(state.patternStyles[aStyle]->mSurface->GetFormat());
if (aIsColor) {
*aIsColor = color;
}
// TODO: for gradient patterns we could check that all stops are opaque
// colors.
if (!state.gradientStyles[aStyle]) {
// it's a color pattern.
return Color::FromABGR(state.colorStyles[aStyle]).a >= 1.0;
}
return false;
return opaque;
}
// This class is named 'GeneralCanvasPattern' instead of just
@ -1167,7 +1167,8 @@ void CanvasRenderingContext2D::RestoreClipsAndTransformToTarget() {
}
}
bool CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect) {
bool CanvasRenderingContext2D::EnsureTarget(
const gfx::Rect* aCoveredRect, bool aWillClear) {
if (AlreadyShutDown()) {
gfxCriticalError() << "Attempt to render into a Canvas2d after shutdown.";
SetErrorState();
@ -1241,7 +1242,7 @@ bool CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect) {
MOZ_ASSERT(newProvider);
bool needsClear = !canDiscardContent;
if (newTarget->GetBackendType() == gfx::BackendType::SKIA) {
if (newTarget->GetBackendType() == gfx::BackendType::SKIA && (needsClear || !aWillClear)) {
// Skia expects the unused X channel to contains 0xFF even for opaque
// operations so we can't skip clearing in that case, even if we are going
// to cover the entire canvas in the next drawing operation.
@ -2346,7 +2347,7 @@ void CanvasRenderingContext2D::ClearRect(double aX, double aY, double aW,
gfx::Rect clearRect(aX, aY, aW, aH);
EnsureTarget(&clearRect);
EnsureTarget(&clearRect, RenderingMode::DefaultBackendMode, true);
if (!IsTargetValid()) {
return;
}
@ -2413,11 +2414,14 @@ void CanvasRenderingContext2D::FillRect(double aX, double aY, double aW,
state = nullptr;
CompositionOp op = UsedOperation();
bool isColor;
bool discardContent =
PatternIsOpaque(Style::FILL) &&
PatternIsOpaque(Style::FILL, &isColor) &&
(op == CompositionOp::OP_OVER || op == CompositionOp::OP_SOURCE);
const gfx::Rect fillRect(aX, aY, aW, aH);
EnsureTarget(discardContent ? &fillRect : nullptr);
EnsureTarget(discardContent ? &fillRect : nullptr,
RenderingMode::DefaultBackendMode,
discardContent && isColor);
if (!IsTargetValid()) {
return;
}

Просмотреть файл

@ -607,7 +607,9 @@ class CanvasRenderingContext2D final : public nsICanvasRenderingContextInternal,
*
* Returns true on success.
*/
bool EnsureTarget(const gfx::Rect* aCoveredRect = nullptr);
bool EnsureTarget(
const gfx::Rect* aCoveredRect = nullptr,
bool aWillClear = false);
void RestoreClipsAndTransformToTarget();
@ -664,9 +666,9 @@ class CanvasRenderingContext2D final : public nsICanvasRenderingContextInternal,
/**
* Returns true if we know for sure that the pattern for a given style is
* opaque. Usefull to know if we can discard the content below in certain
* situations.
* situations. Optionally checks if the pattern is a color pattern.
*/
bool PatternIsOpaque(Style aStyle) const;
bool PatternIsOpaque(Style aStyle, bool* aIsColor = nullptr) const;
nsLayoutUtils::SurfaceFromElementResult CachedSurfaceFromElement(
Element* aElement);