Bug 1937751 - Remember AAStroke mode when caching stroked path. r=jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D232781
This commit is contained in:
@@ -2822,13 +2822,11 @@ static inline bool HasMatchingScale(const Matrix& aTransform1,
|
||||
|
||||
// Determines if an existing path cache entry matches an incoming path and
|
||||
// pattern.
|
||||
inline bool PathCacheEntry::MatchesPath(const QuantizedPath& aPath,
|
||||
const Pattern* aPattern,
|
||||
const StrokeOptions* aStrokeOptions,
|
||||
const Matrix& aTransform,
|
||||
const IntRect& aBounds,
|
||||
const Point& aOrigin, HashNumber aHash,
|
||||
float aSigma) {
|
||||
inline bool PathCacheEntry::MatchesPath(
|
||||
const QuantizedPath& aPath, const Pattern* aPattern,
|
||||
const StrokeOptions* aStrokeOptions, AAStrokeMode aStrokeMode,
|
||||
const Matrix& aTransform, const IntRect& aBounds, const Point& aOrigin,
|
||||
HashNumber aHash, float aSigma) {
|
||||
return aHash == mHash && HasMatchingScale(aTransform, mTransform) &&
|
||||
// Ensure the clipped relative bounds fit inside those of the entry
|
||||
aBounds.x - aOrigin.x >= mBounds.x - mOrigin.x &&
|
||||
@@ -2841,12 +2839,14 @@ inline bool PathCacheEntry::MatchesPath(const QuantizedPath& aPath,
|
||||
(!aPattern ? !mPattern : mPattern && *aPattern == *mPattern) &&
|
||||
(!aStrokeOptions
|
||||
? !mStrokeOptions
|
||||
: mStrokeOptions && *aStrokeOptions == *mStrokeOptions) &&
|
||||
: mStrokeOptions && *aStrokeOptions == *mStrokeOptions &&
|
||||
mAAStrokeMode == aStrokeMode) &&
|
||||
aSigma == mSigma;
|
||||
}
|
||||
|
||||
PathCacheEntry::PathCacheEntry(QuantizedPath&& aPath, Pattern* aPattern,
|
||||
StoredStrokeOptions* aStrokeOptions,
|
||||
AAStrokeMode aStrokeMode,
|
||||
const Matrix& aTransform, const IntRect& aBounds,
|
||||
const Point& aOrigin, HashNumber aHash,
|
||||
float aSigma)
|
||||
@@ -2855,6 +2855,7 @@ PathCacheEntry::PathCacheEntry(QuantizedPath&& aPath, Pattern* aPattern,
|
||||
mOrigin(aOrigin),
|
||||
mPattern(aPattern),
|
||||
mStrokeOptions(aStrokeOptions),
|
||||
mAAStrokeMode(aStrokeMode),
|
||||
mSigma(aSigma) {}
|
||||
|
||||
// Attempt to find a matching entry in the path cache. If one isn't found,
|
||||
@@ -2863,13 +2864,14 @@ PathCacheEntry::PathCacheEntry(QuantizedPath&& aPath, Pattern* aPattern,
|
||||
// or just reuse the cached texture.
|
||||
already_AddRefed<PathCacheEntry> PathCache::FindOrInsertEntry(
|
||||
QuantizedPath aPath, const Pattern* aPattern,
|
||||
const StrokeOptions* aStrokeOptions, const Matrix& aTransform,
|
||||
const IntRect& aBounds, const Point& aOrigin, float aSigma) {
|
||||
const StrokeOptions* aStrokeOptions, AAStrokeMode aStrokeMode,
|
||||
const Matrix& aTransform, const IntRect& aBounds, const Point& aOrigin,
|
||||
float aSigma) {
|
||||
HashNumber hash =
|
||||
PathCacheEntry::HashPath(aPath, aPattern, aTransform, aBounds, aOrigin);
|
||||
for (const RefPtr<PathCacheEntry>& entry : GetChain(hash)) {
|
||||
if (entry->MatchesPath(aPath, aPattern, aStrokeOptions, aTransform, aBounds,
|
||||
aOrigin, hash, aSigma)) {
|
||||
if (entry->MatchesPath(aPath, aPattern, aStrokeOptions, aStrokeMode,
|
||||
aTransform, aBounds, aOrigin, hash, aSigma)) {
|
||||
return do_AddRef(entry);
|
||||
}
|
||||
}
|
||||
@@ -2888,8 +2890,8 @@ already_AddRefed<PathCacheEntry> PathCache::FindOrInsertEntry(
|
||||
}
|
||||
}
|
||||
RefPtr<PathCacheEntry> entry =
|
||||
new PathCacheEntry(std::move(aPath), pattern, strokeOptions, aTransform,
|
||||
aBounds, aOrigin, hash, aSigma);
|
||||
new PathCacheEntry(std::move(aPath), pattern, strokeOptions, aStrokeMode,
|
||||
aTransform, aBounds, aOrigin, hash, aSigma);
|
||||
Insert(entry);
|
||||
return entry.forget();
|
||||
}
|
||||
@@ -3224,12 +3226,6 @@ inline bool DrawTargetWebgl::ShouldAccelPath(
|
||||
return mWebglValid && SupportsDrawOptions(aOptions) && PrepareContext();
|
||||
}
|
||||
|
||||
enum class AAStrokeMode {
|
||||
Unsupported,
|
||||
Geometry,
|
||||
Mask,
|
||||
};
|
||||
|
||||
// For now, we only directly support stroking solid color patterns to limit
|
||||
// artifacts from blending of overlapping geometry generated by AAStroke. Other
|
||||
// types of patterns may be partially supported by rendering to a temporary
|
||||
@@ -3403,6 +3399,11 @@ bool SharedContextWebgl::DrawPathAccel(
|
||||
: (aPattern.GetType() == PatternType::COLOR
|
||||
? Some(static_cast<const ColorPattern&>(aPattern).mColor)
|
||||
: Nothing());
|
||||
AAStrokeMode aaStrokeMode =
|
||||
aStrokeOptions && mPathAAStroke
|
||||
? SupportsAAStroke(aPattern, aOptions, *aStrokeOptions,
|
||||
aAllowStrokeAlpha)
|
||||
: AAStrokeMode::Unsupported;
|
||||
// Look for an existing path cache entry, if possible, or otherwise create
|
||||
// one. If the draw request is not cacheable, then don't create an entry.
|
||||
RefPtr<PathCacheEntry> entry;
|
||||
@@ -3420,7 +3421,7 @@ bool SharedContextWebgl::DrawPathAccel(
|
||||
}
|
||||
entry = mPathCache->FindOrInsertEntry(
|
||||
std::move(*qp), color ? nullptr : &aPattern, aStrokeOptions,
|
||||
currentTransform, intBounds, quantizedOrigin,
|
||||
aaStrokeMode, currentTransform, intBounds, quantizedOrigin,
|
||||
aShadow ? aShadow->mSigma : -1.0f);
|
||||
if (!entry) {
|
||||
return false;
|
||||
@@ -3502,9 +3503,7 @@ bool SharedContextWebgl::DrawPathAccel(
|
||||
mRasterizationTruncates, outputBuffer, outputBufferCapacity);
|
||||
}
|
||||
} else {
|
||||
if (mPathAAStroke &&
|
||||
SupportsAAStroke(aPattern, aOptions, *aStrokeOptions,
|
||||
aAllowStrokeAlpha) != AAStrokeMode::Unsupported) {
|
||||
if (aaStrokeMode != AAStrokeMode::Unsupported) {
|
||||
auto scaleFactors = currentTransform.ScaleFactors();
|
||||
if (scaleFactors.AreScalesSame()) {
|
||||
strokeVB = GenerateStrokeVertexBuffer(
|
||||
@@ -3582,9 +3581,7 @@ bool SharedContextWebgl::DrawPathAccel(
|
||||
} else {
|
||||
AAStroke::aa_stroke_vertex_buffer_release(strokeVB.ref());
|
||||
}
|
||||
if (strokeVB && aStrokeOptions &&
|
||||
SupportsAAStroke(aPattern, aOptions, *aStrokeOptions,
|
||||
aAllowStrokeAlpha) == AAStrokeMode::Mask) {
|
||||
if (strokeVB && aaStrokeMode == AAStrokeMode::Mask) {
|
||||
// Attempt to generate a stroke mask for path.
|
||||
if (RefPtr<TextureHandle> handle =
|
||||
DrawStrokeMask(vertexRange, intBounds.Size())) {
|
||||
|
||||
@@ -389,6 +389,12 @@ struct PathVertexRange {
|
||||
bool IsValid() const { return mLength > 0; }
|
||||
};
|
||||
|
||||
enum class AAStrokeMode {
|
||||
Unsupported,
|
||||
Geometry,
|
||||
Mask,
|
||||
};
|
||||
|
||||
// PathCacheEntry stores a rasterized version of a supplied path with a given
|
||||
// pattern.
|
||||
class PathCacheEntry : public CacheEntryImpl<PathCacheEntry> {
|
||||
@@ -396,14 +402,15 @@ class PathCacheEntry : public CacheEntryImpl<PathCacheEntry> {
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathCacheEntry, override)
|
||||
|
||||
PathCacheEntry(QuantizedPath&& aPath, Pattern* aPattern,
|
||||
StoredStrokeOptions* aStrokeOptions, const Matrix& aTransform,
|
||||
const IntRect& aBounds, const Point& aOrigin, HashNumber aHash,
|
||||
float aSigma = -1.0f);
|
||||
StoredStrokeOptions* aStrokeOptions, AAStrokeMode aStrokeMode,
|
||||
const Matrix& aTransform, const IntRect& aBounds,
|
||||
const Point& aOrigin, HashNumber aHash, float aSigma = -1.0f);
|
||||
|
||||
bool MatchesPath(const QuantizedPath& aPath, const Pattern* aPattern,
|
||||
const StrokeOptions* aStrokeOptions,
|
||||
const Matrix& aTransform, const IntRect& aBounds,
|
||||
const Point& aOrigin, HashNumber aHash, float aSigma);
|
||||
AAStrokeMode aStrokeMode, const Matrix& aTransform,
|
||||
const IntRect& aBounds, const Point& aOrigin,
|
||||
HashNumber aHash, float aSigma);
|
||||
|
||||
static HashNumber HashPath(const QuantizedPath& aPath,
|
||||
const Pattern* aPattern, const Matrix& aTransform,
|
||||
@@ -428,6 +435,8 @@ class PathCacheEntry : public CacheEntryImpl<PathCacheEntry> {
|
||||
UniquePtr<Pattern> mPattern;
|
||||
// The StrokeOptions used for stroked paths, if applicable
|
||||
UniquePtr<StoredStrokeOptions> mStrokeOptions;
|
||||
// The AAStroke mode used for rendering a stroked path.
|
||||
AAStrokeMode mAAStrokeMode = AAStrokeMode::Unsupported;
|
||||
// The shadow blur sigma
|
||||
float mSigma;
|
||||
// If the path has cached geometry in the vertex buffer.
|
||||
@@ -440,8 +449,9 @@ class PathCache : public CacheImpl<PathCacheEntry, true> {
|
||||
|
||||
already_AddRefed<PathCacheEntry> FindOrInsertEntry(
|
||||
QuantizedPath aPath, const Pattern* aPattern,
|
||||
const StrokeOptions* aStrokeOptions, const Matrix& aTransform,
|
||||
const IntRect& aBounds, const Point& aOrigin, float aSigma = -1.0f);
|
||||
const StrokeOptions* aStrokeOptions, AAStrokeMode aStrokeMode,
|
||||
const Matrix& aTransform, const IntRect& aBounds, const Point& aOrigin,
|
||||
float aSigma = -1.0f);
|
||||
|
||||
void ClearVertexRanges();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<canvas id=dest height="768" width="1024"></canvas>
|
||||
<script>
|
||||
|
||||
var c=document.getElementById("dest");
|
||||
var ctx=c.getContext("2d");
|
||||
ctx.setTransform(1,0,0,1,0,0);
|
||||
|
||||
ctx.transform(1,0,0,1,512,384);
|
||||
ctx.globalAlpha=0.5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0,324);
|
||||
|
||||
ctx.lineTo(239.66624210637872,84.6706564587356);
|
||||
ctx.lineTo(78.17543855489896,-213.5804865149861);
|
||||
ctx.lineTo(-136.36617853185373,-262.93052317185794);
|
||||
ctx.lineTo(-195.91764235680165,51.60583806061618);
|
||||
ctx.lineTo(0,324);
|
||||
|
||||
ctx.closePath();
|
||||
ctx.fillStyle="rgba(0,0,0,0)";
|
||||
ctx.fill();
|
||||
ctx.lineWidth=40;
|
||||
ctx.lineCap="butt";
|
||||
ctx.lineJoin="miter";
|
||||
ctx.miterLimit="10";
|
||||
ctx.strokeStyle="#555555";
|
||||
ctx.stroke();
|
||||
</script>
|
||||
52
dom/canvas/test/reftest/1937751-cached-stroked-paths-1.html
Normal file
52
dom/canvas/test/reftest/1937751-cached-stroked-paths-1.html
Normal file
@@ -0,0 +1,52 @@
|
||||
<canvas id=dest height="768" width="1024"></canvas>
|
||||
<script>
|
||||
|
||||
var c=document.getElementById("dest");
|
||||
var ctx=c.getContext("2d");
|
||||
ctx.setTransform(1,0,0,1,0,0);
|
||||
|
||||
ctx.transform(1,0,0,1,512,384);
|
||||
ctx.globalAlpha=1;
|
||||
ctx.beginPath();
|
||||
|
||||
ctx.moveTo(0,324);
|
||||
|
||||
ctx.lineTo(239.66624210637872,84.6706564587356);
|
||||
ctx.lineTo(78.17543855489896,-213.5804865149861);
|
||||
ctx.lineTo(-136.36617853185373,-262.93052317185794);
|
||||
ctx.lineTo(-195.91764235680165,51.60583806061618);
|
||||
ctx.lineTo(0,324);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle="rgba(0,0,0,0)";
|
||||
ctx.fill();
|
||||
ctx.lineWidth=40;
|
||||
ctx.lineCap="butt";
|
||||
ctx.lineJoin="miter";
|
||||
ctx.miterLimit="10";
|
||||
ctx.strokeStyle="#555555";
|
||||
ctx.stroke();
|
||||
ctx.setTransform(1,0,0,1,0,0);
|
||||
ctx.clearRect(0,0,1024,768);
|
||||
|
||||
|
||||
ctx.transform(1,0,0,1,512,384);
|
||||
ctx.globalAlpha=0.5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0,324);
|
||||
|
||||
ctx.lineTo(239.66624210637872,84.6706564587356);
|
||||
ctx.lineTo(78.17543855489896,-213.5804865149861);
|
||||
ctx.lineTo(-136.36617853185373,-262.93052317185794);
|
||||
ctx.lineTo(-195.91764235680165,51.60583806061618);
|
||||
ctx.lineTo(0,324);
|
||||
|
||||
ctx.closePath();
|
||||
ctx.fillStyle="rgba(0,0,0,0)";
|
||||
ctx.fill();
|
||||
ctx.lineWidth=40;
|
||||
ctx.lineCap="butt";
|
||||
ctx.lineJoin="miter";
|
||||
ctx.miterLimit="10";
|
||||
ctx.strokeStyle="#555555";
|
||||
ctx.stroke();
|
||||
</script>
|
||||
@@ -246,3 +246,4 @@ skip-if(isDebugBuild) == draw-large-image.html draw-large-image-ref.html
|
||||
== 1758968-1.html 1758968-1-ref.html
|
||||
== 1768521-1.html 1768521-1-ref.html
|
||||
== 1851943.html 1851943-ref.html
|
||||
== 1937751-cached-stroked-paths-1.html 1937751-cached-stroked-paths-1-ref.html
|
||||
|
||||
Reference in New Issue
Block a user