Bug 1880523 - Use aa_stroke_filled_circle in DrawTargetWebgl. r=jrmuizel

WGR is fairly slow at generating specialized circle geometry, whereas we can
generate similar geometry much faster using the AAStroke filled circle
implementation now.

Differential Revision: https://phabricator.services.mozilla.com/D201939
This commit is contained in:
Lee Salzman 2024-02-15 17:33:15 +00:00
parent f49ecf937b
commit ce3d9e5437
3 changed files with 51 additions and 21 deletions

View File

@ -3406,9 +3406,26 @@ bool SharedContextWebgl::DrawPathAccel(
Maybe<WGR::VertexBuffer> wgrVB;
Maybe<AAStroke::VertexBuffer> strokeVB;
if (!aStrokeOptions) {
wgrVB = GeneratePathVertexBuffer(
entry->GetPath(), IntRect(-intBounds.TopLeft(), mViewportSize),
mRasterizationTruncates, outputBuffer, outputBufferCapacity);
if (aPath == mUnitCirclePath) {
auto scaleFactors = pathXform.ScaleFactors();
if (scaleFactors.AreScalesSame()) {
Point center = pathXform.GetTranslation() - quantBounds.TopLeft();
float radius = scaleFactors.xScale;
AAStroke::VertexBuffer vb = AAStroke::aa_stroke_filled_circle(
center.x, center.y, radius, (AAStroke::OutputVertex*)outputBuffer,
outputBufferCapacity);
if (!vb.len || (outputBuffer && vb.len > outputBufferCapacity)) {
AAStroke::aa_stroke_vertex_buffer_release(vb);
} else {
strokeVB = Some(vb);
}
}
}
if (!strokeVB) {
wgrVB = GeneratePathVertexBuffer(
entry->GetPath(), IntRect(-intBounds.TopLeft(), mViewportSize),
mRasterizationTruncates, outputBuffer, outputBufferCapacity);
}
} else {
if (mPathAAStroke &&
SupportsAAStroke(aPattern, aOptions, *aStrokeOptions,
@ -3490,7 +3507,7 @@ bool SharedContextWebgl::DrawPathAccel(
} else {
AAStroke::aa_stroke_vertex_buffer_release(strokeVB.ref());
}
if (strokeVB &&
if (strokeVB && aStrokeOptions &&
SupportsAAStroke(aPattern, aOptions, *aStrokeOptions,
aAllowStrokeAlpha) == AAStrokeMode::Mask) {
// Attempt to generate a stroke mask for path.
@ -3651,24 +3668,30 @@ void DrawTargetWebgl::DrawPath(const Path* aPath, const Pattern& aPattern,
}
}
// DrawCircle is a more specialized version of DrawPath that attempts to cache
// a unit circle.
// DrawCircleAccel is a more specialized version of DrawPathAccel that attempts
// to cache a unit circle.
bool SharedContextWebgl::DrawCircleAccel(const Point& aCenter, float aRadius,
const Pattern& aPattern,
const DrawOptions& aOptions,
const StrokeOptions* aStrokeOptions) {
// Cache a unit circle and transform it to avoid creating a path repeatedly.
if (!mUnitCirclePath) {
mUnitCirclePath = MakePathForCircle(*mCurrentTarget, Point(0, 0), 1);
}
// Scale and translate the circle to the desired shape.
Matrix circleXform(aRadius, 0, 0, aRadius, aCenter.x, aCenter.y);
return DrawPathAccel(mUnitCirclePath, aPattern, aOptions, aStrokeOptions,
true, nullptr, true, &circleXform);
}
void DrawTargetWebgl::DrawCircle(const Point& aOrigin, float aRadius,
const Pattern& aPattern,
const DrawOptions& aOptions,
const StrokeOptions* aStrokeOptions) {
if (ShouldAccelPath(aOptions, aStrokeOptions)) {
// Cache a unit circle and transform it to avoid creating a path repeatedly.
if (!mUnitCirclePath) {
mUnitCirclePath = MakePathForCircle(*this, Point(0, 0), 1);
}
// Scale and translate the circle to the desired shape.
Matrix circleXform(aRadius, 0, 0, aRadius, aOrigin.x, aOrigin.y);
if (mSharedContext->DrawPathAccel(mUnitCirclePath, aPattern, aOptions,
aStrokeOptions, true, nullptr, true,
&circleXform)) {
return;
}
if (ShouldAccelPath(aOptions, aStrokeOptions) &&
mSharedContext->DrawCircleAccel(aOrigin, aRadius, aPattern, aOptions,
aStrokeOptions)) {
return;
}
MarkSkiaChanged(aOptions);

View File

@ -219,6 +219,9 @@ class SharedContextWebgl : public mozilla::RefCounted<SharedContextWebgl>,
// value to restore it to when exiting the scope.
Maybe<bool> mTlsScope;
// Cached unit circle path
RefPtr<Path> mUnitCirclePath;
bool Initialize();
bool CreateShaders();
void ResetPathVertexBuffer(bool aChanged = true);
@ -308,6 +311,10 @@ class SharedContextWebgl : public mozilla::RefCounted<SharedContextWebgl>,
bool aCacheable = true,
const Matrix* aPathXform = nullptr);
bool DrawCircleAccel(const Point& aCenter, float aRadius,
const Pattern& aPattern, const DrawOptions& aOptions,
const StrokeOptions* aStrokeOptions = nullptr);
bool DrawGlyphsAccel(ScaledFont* aFont, const GlyphBuffer& aBuffer,
const Pattern& aPattern, const DrawOptions& aOptions,
const StrokeOptions* aStrokeOptions,
@ -386,9 +393,6 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
RefPtr<TextureHandle> mSnapshotTexture;
// Cached unit circle path
RefPtr<Path> mUnitCirclePath;
// Store a log of clips currently pushed so that they can be used to init
// the clip state of temporary DTs.
struct ClipStack {

View File

@ -40,6 +40,9 @@ void aa_stroke_curve_to(Stroker* s, float c1x, float c1y, float c2x, float c2y,
float x, float y, bool end);
void aa_stroke_close(Stroker* s);
VertexBuffer aa_stroke_finish(Stroker* s);
VertexBuffer aa_stroke_filled_circle(float cx, float cy, float radius,
OutputVertex* output_ptr = nullptr,
size_t output_capacity = 0);
void aa_stroke_vertex_buffer_release(VertexBuffer vb);
void aa_stroke_release(Stroker* s);
};