@@ -69,31 +69,24 @@ static void mask_release_proc(void* addr, void* /*context*/) {
6969 SkMask::FreeImage (addr);
7070}
7171
72- static bool sw_draw_with_mask_filter (GrRecordingContext* rContext,
73- GrRenderTargetContext* renderTargetContext,
74- const GrClip* clipData,
75- const SkMatrix& viewMatrix,
76- const GrStyledShape& shape,
77- const SkMaskFilter* filter,
78- const SkIRect& clipBounds,
79- GrPaint&& paint,
80- const GrUniqueKey& key) {
72+ static GrSurfaceProxyView sw_create_filtered_mask (GrRecordingContext* rContext,
73+ const SkMatrix& viewMatrix,
74+ const GrStyledShape& shape,
75+ const SkMaskFilter* filter,
76+ const SkIRect& clipBounds,
77+ SkIRect* drawRect,
78+ const GrUniqueKey& key) {
8179 SkASSERT (filter);
8280 SkASSERT (!shape.style ().applies ());
8381
8482 auto threadSafeViewCache = rContext->priv ().threadSafeViewCache ();
8583
8684 GrSurfaceProxyView filteredMaskView;
8785
88- SkStrokeRec::InitStyle fillOrHairline = shape.style ().isSimpleHairline ()
89- ? SkStrokeRec::kHairline_InitStyle
90- : SkStrokeRec::kFill_InitStyle ;
91-
9286 if (key.isValid ()) {
9387 filteredMaskView = threadSafeViewCache->find (key);
9488 }
9589
96- SkIRect drawRect;
9790 if (filteredMaskView) {
9891 SkASSERT (kMaskOrigin == filteredMaskView.origin ());
9992
@@ -104,21 +97,25 @@ static bool sw_draw_with_mask_filter(GrRecordingContext* rContext,
10497 SkMask srcM, dstM;
10598 if (!SkDraw::ComputeMaskBounds (devBounds, &clipBounds, filter, &viewMatrix,
10699 &srcM.fBounds )) {
107- return false ;
100+ return {} ;
108101 }
109102
110103 srcM.fFormat = SkMask::kA8_Format ;
111104
112105 if (!as_MFB (filter)->filterMask (&dstM, srcM, viewMatrix, nullptr )) {
113- return false ;
106+ return {} ;
114107 }
115108
116109 // Unfortunately, we cannot double check that the computed bounds (i.e., dstM.fBounds)
117110 // match the stored bounds of the mask bc the proxy may have been recreated and,
118111 // when it is recreated, it just gets the bounds of the underlying GrTexture (which
119112 // might be a loose fit).
120- drawRect = dstM.fBounds ;
113+ * drawRect = dstM.fBounds ;
121114 } else {
115+ SkStrokeRec::InitStyle fillOrHairline = shape.style ().isSimpleHairline ()
116+ ? SkStrokeRec::kHairline_InitStyle
117+ : SkStrokeRec::kFill_InitStyle ;
118+
122119 // TODO: it seems like we could create an SkDraw here and set its fMatrix field rather
123120 // than explicitly transforming the path to device space.
124121 SkPath devPath;
@@ -130,48 +127,47 @@ static bool sw_draw_with_mask_filter(GrRecordingContext* rContext,
130127 SkMask srcM, dstM;
131128 if (!SkDraw::DrawToMask (devPath, &clipBounds, filter, &viewMatrix, &srcM,
132129 SkMask::kComputeBoundsAndRenderImage_CreateMode , fillOrHairline)) {
133- return false ;
130+ return {} ;
134131 }
135132 SkAutoMaskFreeImage autoSrc (srcM.fImage );
136133
137134 SkASSERT (SkMask::kA8_Format == srcM.fFormat );
138135
139136 if (!as_MFB (filter)->filterMask (&dstM, srcM, viewMatrix, nullptr )) {
140- return false ;
137+ return {} ;
141138 }
142139 // this will free-up dstM when we're done (allocated in filterMask())
143140 SkAutoMaskFreeImage autoDst (dstM.fImage );
144141
145142 if (clip_bounds_quick_reject (clipBounds, dstM.fBounds )) {
146- return false ;
143+ return {} ;
147144 }
148145
149146 // we now have a device-aligned 8bit mask in dstM, ready to be drawn using
150147 // the current clip (and identity matrix) and GrPaint settings
151148 SkBitmap bm;
152149 if (!bm.installPixels (SkImageInfo::MakeA8 (dstM.fBounds .width (), dstM.fBounds .height ()),
153150 autoDst.release (), dstM.fRowBytes , mask_release_proc, nullptr )) {
154- return false ;
151+ return {} ;
155152 }
156153 bm.setImmutable ();
157154
158155 GrBitmapTextureMaker maker (rContext, bm, SkBackingFit::kApprox );
159156 filteredMaskView = maker.view (GrMipmapped::kNo );
160157 if (!filteredMaskView.proxy ()) {
161- return false ;
158+ return {} ;
162159 }
163160
164161 SkASSERT (kMaskOrigin == filteredMaskView.origin ());
165162
166- drawRect = dstM.fBounds ;
163+ * drawRect = dstM.fBounds ;
167164
168165 if (key.isValid ()) {
169166 filteredMaskView = threadSafeViewCache->add (key, filteredMaskView);
170167 }
171168 }
172169
173- return draw_mask (renderTargetContext, clipData, viewMatrix, drawRect, std::move (paint),
174- std::move (filteredMaskView));
170+ return filteredMaskView;
175171}
176172
177173// Create a mask of 'shape' and return the resulting renderTargetContext
@@ -345,7 +341,60 @@ static bool compute_key_and_clip_bounds(GrUniqueKey* maskKey,
345341 return true ;
346342}
347343
348- static void draw_shape_with_mask_filter (GrRecordingContext* context,
344+ static GrSurfaceProxyView hw_create_filtered_mask (GrRecordingContext* rContext,
345+ GrRenderTargetContext* renderTargetContext,
346+ const SkMatrix& viewMatrix,
347+ const GrStyledShape& shape,
348+ const SkMaskFilterBase* filter,
349+ const SkIRect& unclippedDevShapeBounds,
350+ const SkIRect& clipBounds,
351+ SkIRect* maskRect,
352+ const GrUniqueKey& key) {
353+ GrSurfaceProxyView filteredMaskView;
354+
355+ if (filter->canFilterMaskGPU (shape,
356+ unclippedDevShapeBounds,
357+ clipBounds,
358+ viewMatrix,
359+ maskRect)) {
360+ if (clip_bounds_quick_reject (clipBounds, *maskRect)) {
361+ // clipped out
362+ return {};
363+ }
364+
365+ GrProxyProvider* proxyProvider = rContext->priv ().proxyProvider ();
366+
367+ // TODO: this path should also use the thread-safe proxy-view cache!
368+ if (key.isValid ()) {
369+ filteredMaskView = find_filtered_mask (proxyProvider, key);
370+ }
371+
372+ if (!filteredMaskView) {
373+ std::unique_ptr<GrRenderTargetContext> maskRTC (create_mask_GPU (
374+ rContext,
375+ *maskRect,
376+ viewMatrix,
377+ shape,
378+ renderTargetContext->numSamples ()));
379+ if (maskRTC) {
380+ filteredMaskView = filter->filterMaskGPU (rContext,
381+ maskRTC->readSurfaceView (),
382+ maskRTC->colorInfo ().colorType (),
383+ maskRTC->colorInfo ().alphaType (),
384+ viewMatrix,
385+ *maskRect);
386+ if (filteredMaskView && key.isValid ()) {
387+ SkASSERT (filteredMaskView.asTextureProxy ());
388+ proxyProvider->assignUniqueKeyToProxy (key, filteredMaskView.asTextureProxy ());
389+ }
390+ }
391+ }
392+ }
393+
394+ return filteredMaskView;
395+ }
396+
397+ static void draw_shape_with_mask_filter (GrRecordingContext* rContext,
349398 GrRenderTargetContext* renderTargetContext,
350399 const GrClip* clip,
351400 GrPaint&& paint,
@@ -371,7 +420,7 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context,
371420 shape = tmpShape.get ();
372421 }
373422
374- if (maskFilter->directFilterMaskGPU (context , renderTargetContext, std::move (paint), clip,
423+ if (maskFilter->directFilterMaskGPU (rContext , renderTargetContext, std::move (paint), clip,
375424 viewMatrix, *shape)) {
376425 // the mask filter was able to draw itself directly, so there's nothing
377426 // left to do.
@@ -401,51 +450,17 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context,
401450 maskFilter, *shape,
402451 unclippedDevShapeBounds,
403452 devClipBounds)) {
404- return ;
453+ return ; // 'shape' was entirely clipped out
405454 }
406455
456+ GrSurfaceProxyView filteredMaskView;
407457 SkIRect maskRect;
408- if (maskFilter->canFilterMaskGPU (*shape,
409- unclippedDevShapeBounds,
410- boundsForClip,
411- viewMatrix,
412- &maskRect)) {
413- if (clip_bounds_quick_reject (boundsForClip, maskRect)) {
414- // clipped out
415- return ;
416- }
417-
418- GrSurfaceProxyView filteredMaskView;
419-
420- GrProxyProvider* proxyProvider = context->priv ().proxyProvider ();
421-
422- // TODO: this path should also use the thread-safe proxy-view cache!
423- if (maskKey.isValid ()) {
424- filteredMaskView = find_filtered_mask (proxyProvider, maskKey);
425- }
426-
427- if (!filteredMaskView) {
428- std::unique_ptr<GrRenderTargetContext> maskRTC (create_mask_GPU (
429- context,
430- maskRect,
431- viewMatrix,
432- *shape,
433- renderTargetContext->numSamples ()));
434- if (maskRTC) {
435- filteredMaskView = maskFilter->filterMaskGPU (context,
436- maskRTC->readSurfaceView (),
437- maskRTC->colorInfo ().colorType (),
438- maskRTC->colorInfo ().alphaType (),
439- viewMatrix,
440- maskRect);
441- if (filteredMaskView.proxy () && maskKey.isValid ()) {
442- SkASSERT (filteredMaskView.asTextureProxy ());
443- proxyProvider->assignUniqueKeyToProxy (maskKey,
444- filteredMaskView.asTextureProxy ());
445- }
446- }
447- }
448458
459+ if (rContext->asDirectContext ()) {
460+ filteredMaskView = hw_create_filtered_mask (rContext, renderTargetContext,
461+ viewMatrix, *shape, maskFilter,
462+ unclippedDevShapeBounds, boundsForClip,
463+ &maskRect, maskKey);
449464 if (filteredMaskView) {
450465 if (draw_mask (renderTargetContext, clip, viewMatrix, maskRect, std::move (paint),
451466 std::move (filteredMaskView))) {
@@ -456,8 +471,18 @@ static void draw_shape_with_mask_filter(GrRecordingContext* context,
456471 }
457472 }
458473
459- sw_draw_with_mask_filter (context, renderTargetContext, clip, viewMatrix, *shape,
460- maskFilter, boundsForClip, std::move (paint), maskKey);
474+ // Either HW mask rendering failed or we're in a DDL recording thread
475+ filteredMaskView = sw_create_filtered_mask (rContext,
476+ viewMatrix, *shape, maskFilter,
477+ boundsForClip,
478+ &maskRect, maskKey);
479+ if (filteredMaskView) {
480+ if (draw_mask (renderTargetContext, clip, viewMatrix, maskRect, std::move (paint),
481+ std::move (filteredMaskView))) {
482+ return ;
483+ }
484+ assert_alive (paint);
485+ }
461486}
462487
463488void GrBlurUtils::drawShapeWithMaskFilter (GrRecordingContext* context,
0 commit comments