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