Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Unified Diff: src/gpu/GrSoftwarePathRenderer.cpp

Issue 2335343008: Add optional sw generated path coverage mask caching (Closed)
Patch Set: Add .fs to literals in new gm Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/GrSoftwarePathRenderer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrSoftwarePathRenderer.cpp
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 05b3ef8853bc42ded0f52972466e16c7462be75d..c22ce66005478ae7cce4f2665af99f8209ceee96 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -9,6 +9,7 @@
#include "GrAuditTrail.h"
#include "GrClip.h"
#include "GrPipelineBuilder.h"
+#include "GrGpuResourcePriv.h"
#include "GrSWMaskHelper.h"
#include "GrTextureProvider.h"
#include "batches/GrRectBatchFactory.h"
@@ -20,39 +21,38 @@ bool GrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
return !args.fShape->style().applies() && SkToBool(fTexProvider);
}
-namespace {
-
////////////////////////////////////////////////////////////////////////////////
-// gets device coord bounds of path (not considering the fill) and clip. The
-// path bounds will be a subset of the clip bounds. returns false if
-// path bounds would be empty.
-bool get_shape_and_clip_bounds(int width, int height,
- const GrClip& clip,
- const GrShape& shape,
- const SkMatrix& matrix,
- SkIRect* devShapeBounds,
- SkIRect* devClipBounds) {
+static bool get_unclipped_shape_dev_bounds(const GrShape& shape, const SkMatrix& matrix,
+ SkIRect* devBounds) {
+ SkRect shapeBounds = shape.styledBounds();
+ if (shapeBounds.isEmpty()) {
+ return false;
+ }
+ SkRect shapeDevBounds;
+ matrix.mapRect(&shapeDevBounds, shapeBounds);
+ shapeDevBounds.roundOut(devBounds);
+ return true;
+}
+
+// Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there
+// is no intersection.
+static bool get_shape_and_clip_bounds(int width, int height,
+ const GrClip& clip,
+ const GrShape& shape,
+ const SkMatrix& matrix,
+ SkIRect* unclippedDevShapeBounds,
+ SkIRect* clippedDevShapeBounds,
+ SkIRect* devClipBounds) {
// compute bounds as intersection of rt size, clip, and path
clip.getConservativeBounds(width, height, devClipBounds);
- if (devClipBounds->isEmpty()) {
- *devShapeBounds = SkIRect::MakeWH(width, height);
+ if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
+ *unclippedDevShapeBounds = SkIRect::EmptyIRect();
+ *clippedDevShapeBounds = SkIRect::EmptyIRect();
return false;
}
- SkRect shapeBounds = shape.styledBounds();
- if (!shapeBounds.isEmpty()) {
- SkRect shapeSBounds;
- matrix.mapRect(&shapeSBounds, shapeBounds);
- SkIRect shapeIBounds;
- shapeSBounds.roundOut(&shapeIBounds);
- *devShapeBounds = *devClipBounds;
- if (!devShapeBounds->intersect(shapeIBounds)) {
- // set the correct path bounds, as this would be used later.
- *devShapeBounds = shapeIBounds;
- return false;
- }
- } else {
- *devShapeBounds = SkIRect::EmptyIRect();
+ if (!clippedDevShapeBounds->intersect(*devClipBounds, *unclippedDevShapeBounds)) {
+ *clippedDevShapeBounds = SkIRect::EmptyIRect();
return false;
}
return true;
@@ -60,8 +60,6 @@ bool get_shape_and_clip_bounds(int width, int height,
////////////////////////////////////////////////////////////////////////////////
-}
-
void GrSoftwarePathRenderer::DrawNonAARect(GrDrawContext* drawContext,
const GrPaint& paint,
const GrUserStencilSettings& userStencilSettings,
@@ -133,35 +131,97 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
SkASSERT(!args.fShape->style().applies());
inverseFilled = args.fShape->inverseFilled();
- SkIRect devShapeBounds, devClipBounds;
+ SkIRect unclippedDevShapeBounds, clippedDevShapeBounds, devClipBounds;
+ // To prevent overloading the cache with entries during animations we limit the cache of masks
+ // to cases where the matrix preserves axis alignment.
+ bool useCache = fAllowCaching && !inverseFilled && args.fViewMatrix->preservesAxisAlignment() &&
+ args.fShape->hasUnstyledKey() && args.fAntiAlias;
+
if (!get_shape_and_clip_bounds(args.fDrawContext->width(), args.fDrawContext->height(),
*args.fClip, *args.fShape,
- *args.fViewMatrix, &devShapeBounds, &devClipBounds)) {
+ *args.fViewMatrix, &unclippedDevShapeBounds,
+ &clippedDevShapeBounds,
+ &devClipBounds)) {
if (inverseFilled) {
DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStencilSettings,
*args.fClip,
- *args.fViewMatrix, devClipBounds, devShapeBounds);
+ *args.fViewMatrix, devClipBounds, unclippedDevShapeBounds);
}
return true;
}
- SkAutoTUnref<GrTexture> texture(
- GrSWMaskHelper::DrawShapeMaskToTexture(fTexProvider, *args.fShape, devShapeBounds,
- args.fAntiAlias, args.fViewMatrix));
+ const SkIRect* boundsForMask = &clippedDevShapeBounds;
+ if (useCache) {
+ // Use the cache only if >50% of the path is visible.
+ int unclippedWidth = unclippedDevShapeBounds.width();
+ int unclippedHeight = unclippedDevShapeBounds.height();
+ int unclippedArea = unclippedWidth * unclippedHeight;
+ int clippedArea = clippedDevShapeBounds.width() * clippedDevShapeBounds.height();
+ int maxTextureSize = args.fDrawContext->caps()->maxTextureSize();
+ if (unclippedArea > 2 * clippedArea || unclippedWidth > maxTextureSize ||
+ unclippedHeight > maxTextureSize) {
+ useCache = false;
+ } else {
+ boundsForMask = &unclippedDevShapeBounds;
+ }
+ }
+
+ GrUniqueKey maskKey;
+ struct KeyData {
+ SkScalar fFractionalTranslateX;
+ SkScalar fFractionalTranslateY;
+ };
+
+ if (useCache) {
+ // We require the upper left 2x2 of the matrix to match exactly for a cache hit.
+ SkScalar sx = args.fViewMatrix->get(SkMatrix::kMScaleX);
+ SkScalar sy = args.fViewMatrix->get(SkMatrix::kMScaleY);
+ SkScalar kx = args.fViewMatrix->get(SkMatrix::kMSkewX);
+ SkScalar ky = args.fViewMatrix->get(SkMatrix::kMSkewY);
+ SkScalar tx = args.fViewMatrix->get(SkMatrix::kMTransX);
+ SkScalar ty = args.fViewMatrix->get(SkMatrix::kMTransY);
+ // Allow 8 bits each in x and y of subpixel positioning.
+ SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
+ SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
+ static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
+ GrUniqueKey::Builder builder(&maskKey, kDomain, 5 + args.fShape->unstyledKeySize());
+ builder[0] = SkFloat2Bits(sx);
+ builder[1] = SkFloat2Bits(sy);
+ builder[2] = SkFloat2Bits(kx);
+ builder[3] = SkFloat2Bits(ky);
+ builder[4] = fracX | (fracY >> 8);
+ args.fShape->writeUnstyledKey(&builder[5]);
+ }
+
+ sk_sp<GrTexture> texture;
+ if (useCache) {
+ texture.reset(args.fResourceProvider->findAndRefTextureByUniqueKey(maskKey));
+ }
if (!texture) {
- return false;
+ GrSWMaskHelper::TextureType type = useCache ? GrSWMaskHelper::TextureType::kExactFit
+ : GrSWMaskHelper::TextureType::kApproximateFit;
+ texture.reset(GrSWMaskHelper::DrawShapeMaskToTexture(fTexProvider, *args.fShape,
+ *boundsForMask, args.fAntiAlias,
+ type, args.fViewMatrix));
+ if (!texture) {
+ return false;
+ }
+ if (useCache) {
+ texture->resourcePriv().setUniqueKey(maskKey);
+ }
}
- GrSWMaskHelper::DrawToTargetWithShapeMask(texture, args.fDrawContext, *args.fPaint,
+ GrSWMaskHelper::DrawToTargetWithShapeMask(texture.get(), args.fDrawContext, *args.fPaint,
*args.fUserStencilSettings,
*args.fClip, *args.fViewMatrix,
- devShapeBounds);
+ SkIPoint {boundsForMask->fLeft, boundsForMask->fTop},
+ *boundsForMask);
if (inverseFilled) {
DrawAroundInvPath(args.fDrawContext, *args.fPaint, *args.fUserStencilSettings,
*args.fClip,
- *args.fViewMatrix, devClipBounds, devShapeBounds);
+ *args.fViewMatrix, devClipBounds, unclippedDevShapeBounds);
}
return true;
« no previous file with comments | « src/gpu/GrSoftwarePathRenderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698