Skip to content

Commit c3bdd1c

Browse files
rphilliSkia Commit-Bot
authored andcommitted
Separate mask creation from drawing in draw_shape_with_mask_filter
This starts pulling apart draw_shape_with_mask_filter so we can share HW-generated blur masks with DDL recording threads. Change-Id: I2ff3ed8557e979dce342f4dd0156112d47f8a6a7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/322479 Reviewed-by: Adlai Holler <adlai@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
1 parent 98ce8ae commit c3bdd1c

File tree

1 file changed

+95
-70
lines changed

1 file changed

+95
-70
lines changed

src/gpu/GrBlurUtils.cpp

Lines changed: 95 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -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

463488
void GrBlurUtils::drawShapeWithMaskFilter(GrRecordingContext* context,

0 commit comments

Comments
 (0)