Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | List of all members
skgpu::ganesh::SoftwarePathRenderer Class Referencefinal

#include <SoftwarePathRenderer.h>

Inheritance diagram for skgpu::ganesh::SoftwarePathRenderer:
skgpu::ganesh::PathRenderer SkRefCnt SkRefCntBase

Public Member Functions

const char * name () const override
 
 SoftwarePathRenderer (GrProxyProvider *proxyProvider, bool allowCaching)
 
- Public Member Functions inherited from skgpu::ganesh::PathRenderer
 PathRenderer ()=default
 
StencilSupport getStencilSupport (const GrStyledShape &shape) const
 
CanDrawPath canDrawPath (const CanDrawPathArgs &args) const
 
bool drawPath (const DrawPathArgs &args)
 
void stencilPath (const StencilPathArgs &args)
 
- Public Member Functions inherited from SkRefCntBase
 SkRefCntBase ()
 
virtual ~SkRefCntBase ()
 
bool unique () const
 
void ref () const
 
void unref () const
 

Static Public Member Functions

static bool GetShapeAndClipBounds (SurfaceDrawContext *, const GrClip *, const GrStyledShape &, const SkMatrix &viewMatrix, SkIRect *unclippedDevShapeBounds, SkIRect *clippedDevShapeBounds, SkIRect *devClipBounds)
 

Private Member Functions

StencilSupport onGetStencilSupport (const GrStyledShape &) const override
 
CanDrawPath onCanDrawPath (const CanDrawPathArgs &) const override
 
bool onDrawPath (const DrawPathArgs &) override
 

Additional Inherited Members

- Public Types inherited from skgpu::ganesh::PathRenderer
enum  StencilSupport { kNoSupport_StencilSupport , kStencilOnly_StencilSupport , kNoRestriction_StencilSupport }
 
enum class  CanDrawPath { kNo , kAsBackup , kYes }
 
- Static Protected Member Functions inherited from skgpu::ganesh::PathRenderer
static void GetPathDevBounds (const SkPath &path, SkISize devSize, const SkMatrix &matrix, SkRect *bounds)
 

Detailed Description

This class uses the software side to render a path to an SkBitmap and then uploads the result to the gpu

Definition at line 22 of file SoftwarePathRenderer.h.

Constructor & Destructor Documentation

◆ SoftwarePathRenderer()

skgpu::ganesh::SoftwarePathRenderer::SoftwarePathRenderer ( GrProxyProvider proxyProvider,
bool  allowCaching 
)
inline

Definition at line 26 of file SoftwarePathRenderer.h.

27 : fProxyProvider(proxyProvider)
28 , fAllowCaching(allowCaching) {
29 }

Member Function Documentation

◆ GetShapeAndClipBounds()

bool skgpu::ganesh::SoftwarePathRenderer::GetShapeAndClipBounds ( SurfaceDrawContext sdc,
const GrClip clip,
const GrStyledShape shape,
const SkMatrix viewMatrix,
SkIRect unclippedDevShapeBounds,
SkIRect clippedDevShapeBounds,
SkIRect devClipBounds 
)
static

Definition at line 130 of file SoftwarePathRenderer.cpp.

136 {
137 // compute bounds as intersection of rt size, clip, and path
138 *devClipBounds = clip ? clip->getConservativeBounds()
139 : SkIRect::MakeWH(sdc->width(), sdc->height());
140
141 if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
142 *unclippedDevShapeBounds = SkIRect::MakeEmpty();
143 *clippedDevShapeBounds = SkIRect::MakeEmpty();
144 return false;
145 }
146 if (!clippedDevShapeBounds->intersect(*devClipBounds, *unclippedDevShapeBounds)) {
147 *clippedDevShapeBounds = SkIRect::MakeEmpty();
148 return false;
149 }
150 return true;
151}
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
bool intersect(const SkIRect &r)
Definition SkRect.h:513
static constexpr SkIRect MakeEmpty()
Definition SkRect.h:45
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition SkRect.h:56

◆ name()

const char * skgpu::ganesh::SoftwarePathRenderer::name ( ) const
inlineoverridevirtual

Implements skgpu::ganesh::PathRenderer.

Definition at line 24 of file SoftwarePathRenderer.h.

24{ return "SW"; }

◆ onCanDrawPath()

PathRenderer::CanDrawPath skgpu::ganesh::SoftwarePathRenderer::onCanDrawPath ( const CanDrawPathArgs args) const
overrideprivatevirtual

Subclass implementation of canDrawPath()

Implements skgpu::ganesh::PathRenderer.

Definition at line 115 of file SoftwarePathRenderer.cpp.

115 {
116 // Pass on any style that applies. The caller will apply the style if a suitable renderer is
117 // not found and try again with the new GrStyledShape.
118 if (!args.fShape->style().applies() && SkToBool(fProxyProvider) &&
119 (args.fAAType == GrAAType::kCoverage || args.fAAType == GrAAType::kNone)) {
120 // This is the fallback renderer for when a path is too complicated for the GPU ones.
122 }
123 return CanDrawPath::kNo;
124}
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args

◆ onDrawPath()

bool skgpu::ganesh::SoftwarePathRenderer::onDrawPath ( const DrawPathArgs args)
overrideprivatevirtual

Subclass implementation of drawPath()

Implements skgpu::ganesh::PathRenderer.

Definition at line 238 of file SoftwarePathRenderer.cpp.

238 {
239 GR_AUDIT_TRAIL_AUTO_FRAME(args.fContext->priv().auditTrail(),
240 "SoftwarePathRenderer::onDrawPath");
241
242 if (!fProxyProvider) {
243 return false;
244 }
245
246 SkASSERT(!args.fShape->style().applies());
247 // We really need to know if the shape will be inverse filled or not
248 // If the path is hairline, ignore inverse fill.
249 bool inverseFilled = args.fShape->inverseFilled() &&
250 !GrIsStrokeHairlineOrEquivalent(args.fShape->style(),
251 *args.fViewMatrix, nullptr);
252
253 SkIRect unclippedDevShapeBounds, clippedDevShapeBounds, devClipBounds;
254 // To prevent overloading the cache with entries during animations we limit the cache of masks
255 // to cases where the matrix preserves axis alignment.
256 bool useCache = fAllowCaching && !inverseFilled && args.fViewMatrix->preservesAxisAlignment() &&
257 args.fShape->hasUnstyledKey() && (GrAAType::kCoverage == args.fAAType);
258
259 if (!GetShapeAndClipBounds(args.fSurfaceDrawContext,
260 args.fClip, *args.fShape,
261 *args.fViewMatrix, &unclippedDevShapeBounds,
262 &clippedDevShapeBounds,
263 &devClipBounds)) {
264 if (inverseFilled) {
265 DrawAroundInvPath(args.fSurfaceDrawContext, std::move(args.fPaint),
266 *args.fUserStencilSettings, args.fClip, *args.fViewMatrix,
267 devClipBounds, unclippedDevShapeBounds);
268 }
269 return true;
270 }
271
272 const SkIRect* boundsForMask = &clippedDevShapeBounds;
273 if (useCache) {
274 // Use the cache only if >50% of the path is visible.
275 int unclippedWidth = unclippedDevShapeBounds.width();
276 int unclippedHeight = unclippedDevShapeBounds.height();
277 int64_t unclippedArea = sk_64_mul(unclippedWidth, unclippedHeight);
278 int64_t clippedArea = sk_64_mul(clippedDevShapeBounds.width(),
279 clippedDevShapeBounds.height());
280 int maxTextureSize = args.fSurfaceDrawContext->caps()->maxTextureSize();
281 if (unclippedArea > 2 * clippedArea || unclippedWidth > maxTextureSize ||
282 unclippedHeight > maxTextureSize) {
283 useCache = false;
284 } else {
285 boundsForMask = &unclippedDevShapeBounds;
286 }
287 }
288
289 skgpu::UniqueKey maskKey;
290 if (useCache) {
291 // We require the upper left 2x2 of the matrix to match exactly for a cache hit.
292 SkScalar sx = args.fViewMatrix->get(SkMatrix::kMScaleX);
293 SkScalar sy = args.fViewMatrix->get(SkMatrix::kMScaleY);
294 SkScalar kx = args.fViewMatrix->get(SkMatrix::kMSkewX);
295 SkScalar ky = args.fViewMatrix->get(SkMatrix::kMSkewY);
297 skgpu::UniqueKey::Builder builder(&maskKey, kDomain, 7 + args.fShape->unstyledKeySize(),
298 "SW Path Mask");
299 builder[0] = boundsForMask->width();
300 builder[1] = boundsForMask->height();
301
302#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
303 // Fractional translate does not affect caching on Android. This is done for better cache
304 // hit ratio and speed, but it is matching HWUI behavior, which doesn't consider the matrix
305 // at all when caching paths.
306 SkFixed fracX = 0;
307 SkFixed fracY = 0;
308#else
309 SkScalar tx = args.fViewMatrix->get(SkMatrix::kMTransX);
310 SkScalar ty = args.fViewMatrix->get(SkMatrix::kMTransY);
311 // Allow 8 bits each in x and y of subpixel positioning.
312 SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
313 SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
314#endif
315 builder[2] = SkFloat2Bits(sx);
316 builder[3] = SkFloat2Bits(sy);
317 builder[4] = SkFloat2Bits(kx);
318 builder[5] = SkFloat2Bits(ky);
319 // Distinguish between hairline and filled paths. For hairlines, we also need to include
320 // the cap. (SW grows hairlines by 0.5 pixel with round and square caps). Note that
321 // stroke-and-fill of hairlines is turned into pure fill by SkStrokeRec, so this covers
322 // all cases we might see.
323 uint32_t styleBits = args.fShape->style().isSimpleHairline() ?
324 ((args.fShape->style().strokeRec().getCap() << 1) | 1) : 0;
325 builder[6] = fracX | (fracY >> 8) | (styleBits << 16);
326 args.fShape->writeUnstyledKey(&builder[7]);
327 }
328
330 if (useCache) {
331 sk_sp<GrTextureProxy> proxy = fProxyProvider->findOrCreateProxyByUniqueKey(maskKey);
332 if (proxy) {
333 skgpu::Swizzle swizzle = args.fSurfaceDrawContext->caps()->getReadSwizzle(
334 proxy->backendFormat(), GrColorType::kAlpha_8);
335 view = {std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle};
336 args.fContext->priv().stats()->incNumPathMasksCacheHits();
337 }
338 }
339 if (!view) {
341 GrAA aa = GrAA(GrAAType::kCoverage == args.fAAType);
342
343 SkTaskGroup* taskGroup = nullptr;
344 if (auto direct = args.fContext->asDirectContext()) {
345 taskGroup = direct->priv().getTaskGroup();
346 }
347
348 if (taskGroup) {
349 view = make_deferred_mask_texture_view(args.fContext, fit, boundsForMask->size());
350 if (!view) {
351 return false;
352 }
353
354 auto uploader = std::make_unique<GrTDeferredProxyUploader<SoftwarePathData>>(
355 *boundsForMask, *args.fViewMatrix, *args.fShape, aa);
356 GrTDeferredProxyUploader<SoftwarePathData>* uploaderRaw = uploader.get();
357
358 auto drawAndUploadMask = [uploaderRaw] {
359 TRACE_EVENT0("skia.gpu", "Threaded SW Mask Render");
360 GrSWMaskHelper helper(uploaderRaw->getPixels());
361 if (helper.init(uploaderRaw->data().getMaskBounds())) {
362 helper.drawShape(uploaderRaw->data().getShape(),
363 *uploaderRaw->data().getViewMatrix(),
364 uploaderRaw->data().getAA(), 0xFF);
365 } else {
366 SkDEBUGFAIL("Unable to allocate SW mask.");
367 }
368 uploaderRaw->signalAndFreeData();
369 };
370 taskGroup->add(std::move(drawAndUploadMask));
371 view.asTextureProxy()->texPriv().setDeferredUploader(std::move(uploader));
372 } else {
373 GrSWMaskHelper helper;
374 if (!helper.init(*boundsForMask)) {
375 return false;
376 }
377 helper.drawShape(*args.fShape, *args.fViewMatrix, aa, 0xFF);
378 view = helper.toTextureView(args.fContext, fit);
379 }
380
381 if (!view) {
382 return false;
383 }
384 if (useCache) {
386
387 // We will add an invalidator to the path so that if the path goes away we will
388 // delete or recycle the mask texture.
389 auto listener = GrMakeUniqueKeyInvalidationListener(&maskKey,
390 args.fContext->priv().contextID());
391 fProxyProvider->assignUniqueKeyToProxy(maskKey, view.asTextureProxy());
392 args.fShape->addGenIDChangeListener(std::move(listener));
393 }
394
395 args.fContext->priv().stats()->incNumPathMasksGenerated();
396 }
397 SkASSERT(view);
398 if (inverseFilled) {
399 DrawAroundInvPath(args.fSurfaceDrawContext, GrPaint::Clone(args.fPaint),
400 *args.fUserStencilSettings, args.fClip, *args.fViewMatrix, devClipBounds,
401 unclippedDevShapeBounds);
402 }
403 DrawToTargetWithShapeMask(std::move(view), args.fSurfaceDrawContext, std::move(args.fPaint),
404 *args.fUserStencilSettings, args.fClip, *args.fViewMatrix,
405 SkIPoint{boundsForMask->fLeft, boundsForMask->fTop}, *boundsForMask);
406
407 return true;
408}
#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename)
GrAA
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
bool GrIsStrokeHairlineOrEquivalent(const GrStyle &style, const SkMatrix &matrix, SkScalar *outCoverage)
Definition GrUtil.cpp:65
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBackingFit
int32_t SkFixed
Definition SkFixed.h:25
#define SkScalarToFixed(x)
Definition SkFixed.h:125
static uint32_t SkFloat2Bits(float value)
Definition SkFloatBits.h:41
sk_sp< SkIDChangeListener > GrMakeUniqueKeyInvalidationListener(skgpu::UniqueKey *key, uint32_t contextID)
Definition SkGr.cpp:75
static int64_t sk_64_mul(int64_t a, int64_t b)
Definition SkMath.h:33
static SkScalar SkScalarFraction(SkScalar x)
Definition SkScalar.h:67
static GrPaint Clone(const GrPaint &src)
Definition GrPaint.h:45
bool assignUniqueKeyToProxy(const skgpu::UniqueKey &, GrTextureProxy *)
sk_sp< GrTextureProxy > findOrCreateProxyByUniqueKey(const skgpu::UniqueKey &, UseAllocator=UseAllocator::kYes)
void drawShape(const GrStyledShape &, const SkMatrix &matrix, GrAA, uint8_t alpha)
bool init(const SkIRect &resultBounds)
GrSurfaceProxyView toTextureView(GrRecordingContext *, SkBackingFit fit)
GrTextureProxy * asTextureProxy() const
GrSurfaceOrigin origin() const
void setDeferredUploader(std::unique_ptr< GrDeferredProxyUploader >)
GrTextureProxyPriv texPriv()
static constexpr int kMScaleX
horizontal scale factor
Definition SkMatrix.h:353
static constexpr int kMTransY
vertical translation
Definition SkMatrix.h:358
static constexpr int kMTransX
horizontal translation
Definition SkMatrix.h:355
static constexpr int kMSkewY
vertical skew factor
Definition SkMatrix.h:356
static constexpr int kMScaleY
vertical scale factor
Definition SkMatrix.h:357
static constexpr int kMSkewX
horizontal skew factor
Definition SkMatrix.h:354
void add(std::function< void(void)> fn)
static Domain GenerateDomain()
static bool GetShapeAndClipBounds(SurfaceDrawContext *, const GrClip *, const GrStyledShape &, const SkMatrix &viewMatrix, SkIRect *unclippedDevShapeBounds, SkIRect *clippedDevShapeBounds, SkIRect *devClipBounds)
float SkScalar
Definition extension.cpp:12
constexpr SkISize size() const
Definition SkRect.h:172
constexpr int32_t height() const
Definition SkRect.h:165
constexpr int32_t width() const
Definition SkRect.h:158
#define TRACE_EVENT0(category_group, name)

◆ onGetStencilSupport()

StencilSupport skgpu::ganesh::SoftwarePathRenderer::onGetStencilSupport ( const GrStyledShape ) const
inlineoverrideprivatevirtual

Subclass overrides if it has any limitations of stenciling support.

Reimplemented from skgpu::ganesh::PathRenderer.

Definition at line 67 of file SoftwarePathRenderer.h.


The documentation for this class was generated from the following files: