1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2012 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrSoftwarePathRenderer.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrAuditTrail.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrClip.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrContextPriv.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrDeferredProxyUploader.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrGpuResourcePriv.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrOpFlushState.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrOpList.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrProxyProvider.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrSWMaskHelper.h"
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMakeUnique.h"
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSemaphore.h"
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTaskGroup.h"
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTraceEvent.h"
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "ops/GrDrawOp.h"
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "ops/GrRectOpFactory.h"
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot////////////////////////////////////////////////////////////////////////////////
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrPathRenderer::CanDrawPath
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrSoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Pass on any style that applies. The caller will apply the style if a suitable renderer is
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // not found and try again with the new GrShape.
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!args.fShape->style().applies() && SkToBool(fProxyProvider) &&
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        (args.fAAType == GrAAType::kCoverage || args.fAAType == GrAAType::kNone)) {
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // This is the fallback renderer for when a path is too complicated for the GPU ones.
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return CanDrawPath::kAsBackup;
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return CanDrawPath::kNo;
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot////////////////////////////////////////////////////////////////////////////////
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool get_unclipped_shape_dev_bounds(const GrShape& shape, const SkMatrix& matrix,
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           SkIRect* devBounds) {
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect shapeBounds = shape.styledBounds();
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (shapeBounds.isEmpty()) {
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect shapeDevBounds;
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    matrix.mapRect(&shapeDevBounds, shapeBounds);
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Even though these are "unclipped" bounds we still clip to the int32_t range.
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // This is the largest int32_t that is representable exactly as a float. The next 63 larger ints
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // would round down to this value when cast to a float, but who really cares.
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // INT32_MIN is exactly representable.
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static constexpr int32_t kMaxInt = 2147483520;
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!shapeDevBounds.intersect(SkRect::MakeLTRB(INT32_MIN, INT32_MIN, kMaxInt, kMaxInt))) {
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Make sure that the resulting SkIRect can have representable width and height
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (SkScalarRoundToInt(shapeDevBounds.width()) > kMaxInt ||
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalarRoundToInt(shapeDevBounds.height()) > kMaxInt) {
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    shapeDevBounds.roundOut(devBounds);
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Gets the shape bounds, the clip bounds, and the intersection (if any). Returns false if there
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// is no intersection.
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool get_shape_and_clip_bounds(int width, int height,
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      const GrClip& clip,
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      const GrShape& shape,
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      const SkMatrix& matrix,
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      SkIRect* unclippedDevShapeBounds,
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      SkIRect* clippedDevShapeBounds,
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      SkIRect* devClipBounds) {
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // compute bounds as intersection of rt size, clip, and path
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    clip.getConservativeBounds(width, height, devClipBounds);
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!get_unclipped_shape_dev_bounds(shape, matrix, unclippedDevShapeBounds)) {
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *unclippedDevShapeBounds = SkIRect::EmptyIRect();
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *clippedDevShapeBounds = SkIRect::EmptyIRect();
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!clippedDevShapeBounds->intersect(*devClipBounds, *unclippedDevShapeBounds)) {
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *clippedDevShapeBounds = SkIRect::EmptyIRect();
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot////////////////////////////////////////////////////////////////////////////////
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrSoftwarePathRenderer::DrawNonAARect(GrRenderTargetContext* renderTargetContext,
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           GrPaint&& paint,
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const GrUserStencilSettings& userStencilSettings,
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const GrClip& clip,
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const SkMatrix& viewMatrix,
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const SkRect& rect,
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           const SkMatrix& localMatrix) {
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    renderTargetContext->addDrawOp(clip,
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           std::move(paint), viewMatrix, localMatrix, rect,
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                           GrAAType::kNone, &userStencilSettings));
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrSoftwarePathRenderer::DrawAroundInvPath(GrRenderTargetContext* renderTargetContext,
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               GrPaint&& paint,
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               const GrUserStencilSettings& userStencilSettings,
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               const GrClip& clip,
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               const SkMatrix& viewMatrix,
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               const SkIRect& devClipBounds,
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               const SkIRect& devPathBounds) {
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix invert;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!viewMatrix.invert(&invert)) {
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect rect;
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (devClipBounds.fTop < devPathBounds.fTop) {
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        rect.iset(devClipBounds.fLeft, devClipBounds.fTop,
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                  devClipBounds.fRight, devPathBounds.fTop);
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        DrawNonAARect(renderTargetContext, GrPaint::Clone(paint), userStencilSettings, clip,
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkMatrix::I(), rect, invert);
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (devClipBounds.fLeft < devPathBounds.fLeft) {
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        rect.iset(devClipBounds.fLeft, devPathBounds.fTop,
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                  devPathBounds.fLeft, devPathBounds.fBottom);
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        DrawNonAARect(renderTargetContext, GrPaint::Clone(paint), userStencilSettings, clip,
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkMatrix::I(), rect, invert);
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (devClipBounds.fRight > devPathBounds.fRight) {
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        rect.iset(devPathBounds.fRight, devPathBounds.fTop,
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                  devClipBounds.fRight, devPathBounds.fBottom);
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        DrawNonAARect(renderTargetContext, GrPaint::Clone(paint), userStencilSettings, clip,
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkMatrix::I(), rect, invert);
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (devClipBounds.fBottom > devPathBounds.fBottom) {
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        rect.iset(devClipBounds.fLeft, devPathBounds.fBottom,
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                  devClipBounds.fRight, devClipBounds.fBottom);
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        DrawNonAARect(renderTargetContext, std::move(paint), userStencilSettings, clip,
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                      SkMatrix::I(), rect, invert);
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrSoftwarePathRenderer::DrawToTargetWithShapeMask(
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<GrTextureProxy> proxy,
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrRenderTargetContext* renderTargetContext,
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrPaint&& paint,
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const GrUserStencilSettings& userStencilSettings,
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const GrClip& clip,
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkMatrix& viewMatrix,
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkIPoint& textureOriginInDeviceSpace,
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const SkIRect& deviceSpaceRectToDraw) {
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix invert;
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!viewMatrix.invert(&invert)) {
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return;
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect dstRect = SkRect::Make(deviceSpaceRectToDraw);
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // We use device coords to compute the texture coordinates. We take the device coords and apply
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // a translation so that the top-left of the device bounds maps to 0,0, and then a scaling
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // matrix to normalized coords.
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix maskMatrix = SkMatrix::MakeTrans(SkIntToScalar(-textureOriginInDeviceSpace.fX),
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              SkIntToScalar(-textureOriginInDeviceSpace.fY));
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    maskMatrix.preConcat(viewMatrix);
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.addCoverageFragmentProcessor(GrSimpleTextureEffect::Make(
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            std::move(proxy), maskMatrix, GrSamplerState::Filter::kNearest));
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    DrawNonAARect(renderTargetContext, std::move(paint), userStencilSettings, clip, SkMatrix::I(),
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                  dstRect, invert);
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<GrTextureProxy> make_deferred_mask_texture_proxy(GrContext* context, SkBackingFit fit,
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                              int width, int height) {
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrProxyProvider* proxyProvider = context->contextPriv().proxyProvider();
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrSurfaceDesc desc;
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fOrigin = kTopLeft_GrSurfaceOrigin;
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fWidth = width;
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fHeight = height;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    desc.fConfig = kAlpha_8_GrPixelConfig;
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // MDB TODO: We're going to fill this proxy with an ASAP upload (which is out of order wrt to
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // ops), so it can't have any pending IO.
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return proxyProvider->createProxy(desc, fit, SkBudgeted::kYes,
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      GrResourceProvider::kNoPendingIO_Flag);
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace {
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Payload class for use with GrTDeferredProxyUploader. The software path renderer only draws
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * a single path into the mask texture. This stores all of the information needed by the worker
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * thread's call to drawShape (see below, in onDrawPath).
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SoftwarePathData {
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SoftwarePathData(const SkIRect& maskBounds, const SkMatrix& viewMatrix, const GrShape& shape,
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                     GrAA aa)
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            : fMaskBounds(maskBounds)
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fViewMatrix(viewMatrix)
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fShape(shape)
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            , fAA(aa) {}
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkIRect& getMaskBounds() const { return fMaskBounds; }
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkMatrix* getViewMatrix() const { return &fViewMatrix; }
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrShape& getShape() const { return fShape; }
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrAA getAA() const { return fAA; }
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkIRect fMaskBounds;
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkMatrix fViewMatrix;
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrShape fShape;
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrAA fAA;
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// When the SkPathRef genID changes, invalidate a corresponding GrResource described by key.
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass PathInvalidator : public SkPathRef::GenIDChangeListener {
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {}
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrUniqueKeyInvalidatedMessage fMsg;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onChange() override {
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot////////////////////////////////////////////////////////////////////////////////
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// return true on success; false on failure
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                              "GrSoftwarePathRenderer::onDrawPath");
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!fProxyProvider) {
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // We really need to know if the shape will be inverse filled or not
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool inverseFilled = false;
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTLazy<GrShape> tmpShape;
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(!args.fShape->style().applies());
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // If the path is hairline, ignore inverse fill.
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    inverseFilled = args.fShape->inverseFilled() &&
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    !IsStrokeHairlineOrEquivalent(args.fShape->style(), *args.fViewMatrix, nullptr);
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkIRect unclippedDevShapeBounds, clippedDevShapeBounds, devClipBounds;
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // To prevent overloading the cache with entries during animations we limit the cache of masks
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // to cases where the matrix preserves axis alignment.
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool useCache = fAllowCaching && !inverseFilled && args.fViewMatrix->preservesAxisAlignment() &&
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    args.fShape->hasUnstyledKey() && GrAAType::kCoverage == args.fAAType;
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!get_shape_and_clip_bounds(args.fRenderTargetContext->width(),
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   args.fRenderTargetContext->height(),
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   *args.fClip, *args.fShape,
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   *args.fViewMatrix, &unclippedDevShapeBounds,
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   &clippedDevShapeBounds,
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                   &devClipBounds)) {
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (inverseFilled) {
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            DrawAroundInvPath(args.fRenderTargetContext, std::move(args.fPaint),
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                              *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                              devClipBounds, unclippedDevShapeBounds);
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkIRect* boundsForMask = &clippedDevShapeBounds;
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (useCache) {
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Use the cache only if >50% of the path is visible.
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int unclippedWidth = unclippedDevShapeBounds.width();
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int unclippedHeight = unclippedDevShapeBounds.height();
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int64_t unclippedArea = sk_64_mul(unclippedWidth, unclippedHeight);
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int64_t clippedArea = sk_64_mul(clippedDevShapeBounds.width(),
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                        clippedDevShapeBounds.height());
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int maxTextureSize = args.fRenderTargetContext->caps()->maxTextureSize();
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (unclippedArea > 2 * clippedArea || unclippedWidth > maxTextureSize ||
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            unclippedHeight > maxTextureSize) {
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            useCache = false;
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            boundsForMask = &unclippedDevShapeBounds;
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrUniqueKey maskKey;
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (useCache) {
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // We require the upper left 2x2 of the matrix to match exactly for a cache hit.
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar sx = args.fViewMatrix->get(SkMatrix::kMScaleX);
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar sy = args.fViewMatrix->get(SkMatrix::kMScaleY);
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar kx = args.fViewMatrix->get(SkMatrix::kMSkewX);
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar ky = args.fViewMatrix->get(SkMatrix::kMSkewY);
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Fractional translate does not affect caching on Android. This is done for better cache
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // hit ratio and speed, but it is matching HWUI behavior, which doesn't consider the matrix
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // at all when caching paths.
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrUniqueKey::Builder builder(&maskKey, kDomain, 4 + args.fShape->unstyledKeySize());
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar tx = args.fViewMatrix->get(SkMatrix::kMTransX);
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar ty = args.fViewMatrix->get(SkMatrix::kMTransY);
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Allow 8 bits each in x and y of subpixel positioning.
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrUniqueKey::Builder builder(&maskKey, kDomain, 5 + args.fShape->unstyledKeySize());
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        builder[0] = SkFloat2Bits(sx);
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        builder[1] = SkFloat2Bits(sy);
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        builder[2] = SkFloat2Bits(kx);
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        builder[3] = SkFloat2Bits(ky);
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        args.fShape->writeUnstyledKey(&builder[4]);
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        builder[4] = fracX | (fracY >> 8);
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        args.fShape->writeUnstyledKey(&builder[5]);
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<GrTextureProxy> proxy;
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (useCache) {
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        proxy = fProxyProvider->findOrCreateProxyByUniqueKey(maskKey, kTopLeft_GrSurfaceOrigin);
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!proxy) {
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkBackingFit fit = useCache ? SkBackingFit::kExact : SkBackingFit::kApprox;
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GrAA aa = GrAAType::kCoverage == args.fAAType ? GrAA::kYes : GrAA::kNo;
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTaskGroup* taskGroup = args.fContext->contextPriv().getTaskGroup();
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (taskGroup) {
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            proxy = make_deferred_mask_texture_proxy(args.fContext, fit,
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     boundsForMask->width(),
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     boundsForMask->height());
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (!proxy) {
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return false;
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            auto uploader = skstd::make_unique<GrTDeferredProxyUploader<SoftwarePathData>>(
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    *boundsForMask, *args.fViewMatrix, *args.fShape, aa);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrTDeferredProxyUploader<SoftwarePathData>* uploaderRaw = uploader.get();
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            auto drawAndUploadMask = [uploaderRaw] {
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                TRACE_EVENT0("skia", "Threaded SW Mask Render");
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                GrSWMaskHelper helper(uploaderRaw->getPixels());
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (helper.init(uploaderRaw->data().getMaskBounds())) {
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    helper.drawShape(uploaderRaw->data().getShape(),
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     *uploaderRaw->data().getViewMatrix(),
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                     SkRegion::kReplace_Op, uploaderRaw->data().getAA(), 0xFF);
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDEBUGFAIL("Unable to allocate SW mask.");
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                uploaderRaw->signalAndFreeData();
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            };
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            taskGroup->add(std::move(drawAndUploadMask));
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            proxy->texPriv().setDeferredUploader(std::move(uploader));
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrSWMaskHelper helper;
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (!helper.init(*boundsForMask)) {
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return false;
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            helper.drawShape(*args.fShape, *args.fViewMatrix, SkRegion::kReplace_Op, aa, 0xFF);
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            proxy = helper.toTextureProxy(args.fContext, fit);
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!proxy) {
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (useCache) {
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(proxy->origin() == kTopLeft_GrSurfaceOrigin);
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fProxyProvider->assignUniqueKeyToProxy(maskKey, proxy.get());
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            args.fShape->addGenIDChangeListener(new PathInvalidator(maskKey));
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (inverseFilled) {
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        DrawAroundInvPath(args.fRenderTargetContext, GrPaint::Clone(args.fPaint),
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                          *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix, devClipBounds,
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                          unclippedDevShapeBounds);
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    DrawToTargetWithShapeMask(
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            std::move(proxy), args.fRenderTargetContext, std::move(args.fPaint),
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *args.fUserStencilSettings, *args.fClip, *args.fViewMatrix,
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkIPoint{boundsForMask->fLeft, boundsForMask->fTop}, *boundsForMask);
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
380