blob: ce8945bdc1a56b25601f668ecf4ad55030279b88 [file] [log] [blame]
robertphillipsea461502015-05-26 11:38:03 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkDrawable.h"
9#include "include/gpu/GrBackendSemaphore.h"
10#include "include/gpu/GrRenderTarget.h"
11#include "include/private/GrAuditTrail.h"
12#include "include/private/GrColor.h"
13#include "include/private/GrOpList.h"
14#include "include/private/GrRecordingContext.h"
15#include "include/private/SkShadowFlags.h"
16#include "include/utils/SkShadowUtils.h"
Brian Salomoncd734f62019-05-10 16:32:54 -040017#include "src/core/SkAutoPixmapStorage.h"
18#include "src/core/SkConvertPixels.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/core/SkDrawShadowInfo.h"
20#include "src/core/SkGlyphRunPainter.h"
21#include "src/core/SkLatticeIter.h"
22#include "src/core/SkMatrixPriv.h"
23#include "src/core/SkRRectPriv.h"
24#include "src/core/SkSurfacePriv.h"
25#include "src/gpu/GrAppliedClip.h"
26#include "src/gpu/GrBlurUtils.h"
27#include "src/gpu/GrCaps.h"
28#include "src/gpu/GrContextPriv.h"
29#include "src/gpu/GrDrawingManager.h"
30#include "src/gpu/GrFixedClip.h"
31#include "src/gpu/GrGpuResourcePriv.h"
32#include "src/gpu/GrMemoryPool.h"
33#include "src/gpu/GrPathRenderer.h"
34#include "src/gpu/GrQuad.h"
35#include "src/gpu/GrRecordingContextPriv.h"
Mike Kleinad44dd52019-05-14 14:01:39 -050036#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050037#include "src/gpu/GrRenderTargetContextPriv.h"
38#include "src/gpu/GrResourceProvider.h"
39#include "src/gpu/GrShape.h"
40#include "src/gpu/GrStencilAttachment.h"
41#include "src/gpu/GrStyle.h"
42#include "src/gpu/GrTracing.h"
43#include "src/gpu/SkGr.h"
44#include "src/gpu/effects/GrRRectEffect.h"
45#include "src/gpu/effects/GrTextureDomain.h"
46#include "src/gpu/ops/GrAtlasTextOp.h"
47#include "src/gpu/ops/GrClearOp.h"
48#include "src/gpu/ops/GrClearStencilClipOp.h"
49#include "src/gpu/ops/GrDebugMarkerOp.h"
50#include "src/gpu/ops/GrDrawAtlasOp.h"
51#include "src/gpu/ops/GrDrawOp.h"
52#include "src/gpu/ops/GrDrawVerticesOp.h"
53#include "src/gpu/ops/GrDrawableOp.h"
54#include "src/gpu/ops/GrFillRRectOp.h"
55#include "src/gpu/ops/GrFillRectOp.h"
56#include "src/gpu/ops/GrLatticeOp.h"
57#include "src/gpu/ops/GrOp.h"
58#include "src/gpu/ops/GrOvalOpFactory.h"
59#include "src/gpu/ops/GrRegionOp.h"
60#include "src/gpu/ops/GrSemaphoreOp.h"
61#include "src/gpu/ops/GrShadowRRectOp.h"
62#include "src/gpu/ops/GrStencilPathOp.h"
63#include "src/gpu/ops/GrStrokeRectOp.h"
64#include "src/gpu/ops/GrTextureOp.h"
Brian Salomonab32f652019-05-10 14:24:50 -040065#include "src/gpu/ops/GrTransferFromOp.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050066#include "src/gpu/text/GrTextContext.h"
67#include "src/gpu/text/GrTextTarget.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040068
Herb Derbyc1b482c2018-08-09 15:02:27 -040069class GrRenderTargetContext::TextTarget : public GrTextTarget {
Brian Salomonf18b1d82017-10-27 11:30:49 -040070public:
71 TextTarget(GrRenderTargetContext* renderTargetContext)
Herb Derbyc1b482c2018-08-09 15:02:27 -040072 : GrTextTarget(renderTargetContext->width(), renderTargetContext->height(),
Robert Phillips7e90be92019-02-15 12:22:59 -050073 renderTargetContext->colorSpaceInfo())
Herb Derby74c6ed32018-07-28 18:07:54 -040074 , fRenderTargetContext(renderTargetContext)
Herb Derby65956872018-08-21 16:55:04 -040075 , fGlyphPainter{*renderTargetContext}{}
Brian Salomonf18b1d82017-10-27 11:30:49 -040076
Robert Phillips7c525e62018-06-12 10:11:12 -040077 void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
Brian Salomonf18b1d82017-10-27 11:30:49 -040078 fRenderTargetContext->addDrawOp(clip, std::move(op));
79 }
80
Robert Phillips46a13382018-08-23 13:53:01 -040081 void drawShape(const GrClip& clip, const SkPaint& paint,
82 const SkMatrix& viewMatrix, const GrShape& shape) override {
Robert Phillips27927a52018-08-20 13:18:12 -040083 GrBlurUtils::drawShapeWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
84 clip, paint, viewMatrix, shape);
Brian Salomonf18b1d82017-10-27 11:30:49 -040085 }
86
87 void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
Robert Phillips7c525e62018-06-12 10:11:12 -040088 GrPaint* grPaint) override {
Robert Phillips69893702019-02-22 11:16:30 -050089 auto context = fRenderTargetContext->fContext;
Brian Salomonf18b1d82017-10-27 11:30:49 -040090 const GrColorSpaceInfo& colorSpaceInfo = fRenderTargetContext->colorSpaceInfo();
91 if (kARGB_GrMaskFormat == maskFormat) {
92 SkPaintToGrPaintWithPrimitiveColor(context, colorSpaceInfo, skPaint, grPaint);
93 } else {
94 SkPaintToGrPaint(context, colorSpaceInfo, skPaint, viewMatrix, grPaint);
95 }
96 }
97
Robert Phillips69893702019-02-22 11:16:30 -050098 GrRecordingContext* getContext() override {
Robert Phillips7c525e62018-06-12 10:11:12 -040099 return fRenderTargetContext->fContext;
100 }
101
Herb Derby65956872018-08-21 16:55:04 -0400102 SkGlyphRunListPainter* glyphPainter() override {
103 return &fGlyphPainter;
Herb Derby74c6ed32018-07-28 18:07:54 -0400104 }
105
Brian Salomonf18b1d82017-10-27 11:30:49 -0400106private:
107 GrRenderTargetContext* fRenderTargetContext;
Herb Derby65956872018-08-21 16:55:04 -0400108 SkGlyphRunListPainter fGlyphPainter;
Herb Derby74c6ed32018-07-28 18:07:54 -0400109
Brian Salomonf18b1d82017-10-27 11:30:49 -0400110};
joshualittbc907352016-01-13 06:45:40 -0800111
Robert Phillips72152832017-01-25 17:31:35 -0500112#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -0800113#define ASSERT_SINGLE_OWNER \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -0400114 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
robertphillips391395d2016-03-02 09:26:36 -0800115#define ASSERT_SINGLE_OWNER_PRIV \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -0400116 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
Robert Phillips69893702019-02-22 11:16:30 -0500117#define RETURN_IF_ABANDONED if (fContext->priv().abandoned()) { return; }
118#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->priv().abandoned()) { return; }
119#define RETURN_FALSE_IF_ABANDONED if (fContext->priv().abandoned()) { return false; }
120#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->priv().abandoned()) { return false; }
121#define RETURN_NULL_IF_ABANDONED if (fContext->priv().abandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -0700122
Brian Salomone225b562017-06-14 13:00:03 -0400123//////////////////////////////////////////////////////////////////////////////
124
robertphillipsea461502015-05-26 11:38:03 -0700125class AutoCheckFlush {
126public:
halcanary9d524f22016-03-29 09:03:52 -0700127 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -0700128 SkASSERT(fDrawingManager);
129 }
bsalomonb77a9072016-09-07 10:02:04 -0700130 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -0700131
132private:
robertphillips77a2e522015-10-17 07:43:27 -0700133 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -0700134};
135
Robert Phillipsf2361d22016-10-25 14:20:06 -0400136// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -0400137// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -0400138// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -0400139// when the renderTargetContext attempts to use it (via getOpList).
Robert Phillips69893702019-02-22 11:16:30 -0500140GrRenderTargetContext::GrRenderTargetContext(GrRecordingContext* context,
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400141 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -0400142 sk_sp<SkColorSpace> colorSpace,
143 const SkSurfaceProps* surfaceProps,
Robert Phillips941d1442017-06-14 16:37:02 -0400144 bool managedOpList)
Robert Phillips0d075de2019-03-04 11:08:13 -0500145 : GrSurfaceContext(context, rtp->config(), std::move(colorSpace))
Brian Salomonf3569f02017-10-24 12:52:33 -0400146 , fRenderTargetProxy(std::move(rtp))
147 , fOpList(sk_ref_sp(fRenderTargetProxy->getLastRenderTargetOpList()))
Brian Salomonf3569f02017-10-24 12:52:33 -0400148 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
149 , fManagedOpList(managedOpList) {
Brian Salomonf18b1d82017-10-27 11:30:49 -0400150 fTextTarget.reset(new TextTarget(this));
robertphillips2e1e51f2015-10-15 08:01:48 -0700151 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700152}
153
robertphillips2e1e51f2015-10-15 08:01:48 -0700154#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -0400155void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400156 SkASSERT(fRenderTargetProxy);
157 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -0700158
Robert Phillipsf2361d22016-10-25 14:20:06 -0400159 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsdc83b892017-04-13 12:23:54 -0400160 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList.get());
robertphillipsa106c622015-10-16 09:07:06 -0700161 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700162}
163#endif
164
Brian Osman11052242016-10-27 14:47:55 -0400165GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800166 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700167}
168
Chris Dalton7d6748e2019-03-13 00:34:52 -0600169inline GrAAType GrRenderTargetContext::chooseAAType(GrAA aa) {
170 auto fsaaType = this->fsaaType();
171 if (GrAA::kNo == aa) {
172 // On some devices we cannot disable MSAA if it is enabled so we make the AA type reflect
173 // that.
174 if (fsaaType == GrFSAAType::kUnifiedMSAA && !this->caps()->multisampleDisableSupport()) {
175 return GrAAType::kMSAA;
176 }
177 return GrAAType::kNone;
178 }
179 switch (fsaaType) {
180 case GrFSAAType::kNone:
181 case GrFSAAType::kMixedSamples:
182 return GrAAType::kCoverage;
183 case GrFSAAType::kUnifiedMSAA:
184 return GrAAType::kMSAA;
185 }
186 SK_ABORT("Unexpected fsaa type");
187 return GrAAType::kNone;
188}
189
190static inline GrPathRenderer::AATypeFlags choose_path_aa_type_flags(
191 GrAA aa, GrFSAAType fsaaType, const GrCaps& caps) {
192 using AATypeFlags = GrPathRenderer::AATypeFlags;
193 if (GrAA::kNo == aa) {
194 // On some devices we cannot disable MSAA if it is enabled so we make the AA type flags
195 // reflect that.
196 if (fsaaType == GrFSAAType::kUnifiedMSAA && !caps.multisampleDisableSupport()) {
197 return AATypeFlags::kMSAA;
198 }
199 return AATypeFlags::kNone;
200 }
201 switch (fsaaType) {
202 case GrFSAAType::kNone:
203 return AATypeFlags::kCoverage;
204 case GrFSAAType::kMixedSamples:
205 return AATypeFlags::kCoverage | AATypeFlags::kMixedSampledStencilThenCover;
206 case GrFSAAType::kUnifiedMSAA:
207 return AATypeFlags::kMSAA;
208 }
209 SK_ABORT("Invalid GrFSAAType.");
210 return AATypeFlags::kNone;
211}
212
Robert Phillipsf200a902017-01-30 13:27:37 -0500213GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000214 return fRenderTargetProxy->asTextureProxy();
215}
216
Greg Daniele252f082017-10-23 16:05:23 -0400217const GrTextureProxy* GrRenderTargetContext::asTextureProxy() const {
218 return fRenderTargetProxy->asTextureProxy();
219}
220
Robert Phillipsf200a902017-01-30 13:27:37 -0500221sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
222 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
223}
224
Greg Daniele252f082017-10-23 16:05:23 -0400225GrMipMapped GrRenderTargetContext::mipMapped() const {
226 if (const GrTextureProxy* proxy = this->asTextureProxy()) {
227 return proxy->mipMapped();
228 }
229 return GrMipMapped::kNo;
230}
231
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400232GrRenderTargetOpList* GrRenderTargetContext::getRTOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800233 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700234 SkDEBUGCODE(this->validate();)
235
Robert Phillipsf2361d22016-10-25 14:20:06 -0400236 if (!fOpList || fOpList->isClosed()) {
Michael Ludwig6e17f1d2019-05-15 14:00:20 +0000237 fOpList = this->drawingManager()->newRTOpList(fRenderTargetProxy, fManagedOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700238 }
239
Robert Phillipsdc83b892017-04-13 12:23:54 -0400240 return fOpList.get();
robertphillipsa106c622015-10-16 09:07:06 -0700241}
242
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400243GrOpList* GrRenderTargetContext::getOpList() {
244 return this->getRTOpList();
robertphillipsea461502015-05-26 11:38:03 -0700245}
246
Herb Derbycddab252018-07-16 11:19:04 -0400247void GrRenderTargetContext::drawGlyphRunList(
248 const GrClip& clip, const SkMatrix& viewMatrix,
Robert Phillipse4643cc2018-08-14 13:01:29 -0400249 const SkGlyphRunList& blob) {
joshualitt1de610a2016-01-06 08:26:09 -0800250 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700251 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700252 SkDEBUGCODE(this->validate();)
Herb Derbycddab252018-07-16 11:19:04 -0400253 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -0700254
Greg Danielbe7fc462019-01-03 16:40:42 -0500255 // Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan
256 // secondary command buffers because it would require stopping and starting a render pass which
257 // we don't have access to.
258 if (this->wrapsVkSecondaryCB()) {
259 return;
260 }
261
Herb Derby26cbe512018-05-24 14:39:01 -0400262 GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
Herb Derbycddab252018-07-16 11:19:04 -0400263 atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
Robert Phillipse4643cc2018-08-14 13:01:29 -0400264 fSurfaceProps, blob);
robertphillipsea461502015-05-26 11:38:03 -0700265}
266
Brian Osman11052242016-10-27 14:47:55 -0400267void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800268 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700269 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700270 SkDEBUGCODE(this->validate();)
Robert Phillips6b47c7d2017-08-29 07:24:09 -0400271 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700272
Robert Phillips72152832017-01-25 17:31:35 -0500273 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400274
Robert Phillips380b90c2017-08-30 07:41:07 -0400275 this->getRTOpList()->discard();
robertphillipsea461502015-05-26 11:38:03 -0700276}
277
Brian Osman11052242016-10-27 14:47:55 -0400278void GrRenderTargetContext::clear(const SkIRect* rect,
Brian Osman9a9baae2018-11-05 15:06:26 -0500279 const SkPMColor4f& color,
Chris Dalton344e9032017-12-11 15:42:09 -0700280 CanClearFullscreen canClearFullscreen) {
joshualitt1de610a2016-01-06 08:26:09 -0800281 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700282 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700283 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400284 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
robertphillipsea461502015-05-26 11:38:03 -0700285
Robert Phillips72152832017-01-25 17:31:35 -0500286 AutoCheckFlush acf(this->drawingManager());
Chris Dalton344e9032017-12-11 15:42:09 -0700287 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color,
288 canClearFullscreen);
csmartdalton29df7602016-08-31 11:55:52 -0700289}
robertphillips9199a9f2016-07-13 07:48:43 -0700290
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500291void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
292 const SkPMColor4f& color,
293 CanClearFullscreen canClearFullscreen) {
294 ASSERT_SINGLE_OWNER_PRIV
295 RETURN_IF_ABANDONED_PRIV
296 SkDEBUGCODE(fRenderTargetContext->validate();)
297 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
298 fRenderTargetContext->fContext);
299
300 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
301 fRenderTargetContext->internalClear(clip, color, canClearFullscreen);
302}
303
304static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) {
305 paint->setColor4f(color);
306 if (color.isOpaque()) {
307 // Can just rely on the src-over blend mode to do the right thing
308 paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
309 } else {
310 // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
311 // were src blended
312 paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
313 }
314}
315
316void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
317 const SkPMColor4f& color,
318 CanClearFullscreen canClearFullscreen) {
319 bool isFull = false;
320 if (!clip.hasWindowRectangles()) {
Robert Phillips0e35ce22019-04-05 10:57:28 -0400321 // TODO: wrt the shouldInitializeTextures path, it would be more performant to
322 // only clear the entire target if we knew it had not been cleared before. As
323 // is this could end up doing a lot of redundant clears.
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500324 isFull = !clip.scissorEnabled() ||
325 (CanClearFullscreen::kYes == canClearFullscreen &&
Robert Phillips0e35ce22019-04-05 10:57:28 -0400326 (this->caps()->preferFullscreenClears() || this->caps()->shouldInitializeTextures())) ||
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500327 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
328 }
329
330 if (isFull) {
331 if (this->getRTOpList()->resetForFullscreenClear() &&
332 !this->caps()->performColorClearsAsDraws()) {
333 // The op list was emptied and native clears are allowed, so just use the load op
334 this->getRTOpList()->setColorLoadOp(GrLoadOp::kClear, color);
335 return;
336 } else {
337 // Will use an op for the clear, reset the load op to discard since the op will
338 // blow away the color buffer contents
339 this->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
340 }
341
342 // Must add an op to the list (either because we couldn't use a load op, or because the
343 // clear load op isn't supported)
344 if (this->caps()->performColorClearsAsDraws()) {
345 SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
346 GrPaint paint;
347 clear_to_grpaint(color, &paint);
348 this->addDrawOp(GrFixedClip::Disabled(),
349 GrFillRectOp::Make(fContext, std::move(paint),
350 GrAAType::kNone, SkMatrix::I(), rtRect));
351 } else {
352 this->getRTOpList()->addOp(GrClearOp::Make(fContext, SkIRect::MakeEmpty(), color,
353 /* fullscreen */ true), *this->caps());
354 }
355 } else {
356 if (this->caps()->performPartialClearsAsDraws()) {
357 // performPartialClearsAsDraws() also returns true if any clear has to be a draw.
358 SkRect scissor = SkRect::Make(clip.scissorRect());
359 GrPaint paint;
360 clear_to_grpaint(color, &paint);
361
362 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), GrAAType::kNone,
363 SkMatrix::I(), scissor));
364 } else {
365 std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
366 this->asSurfaceProxy()));
367 // This version of the clear op factory can return null if the clip doesn't intersect
368 // with the surface proxy's boundary
369 if (!op) {
370 return;
371 }
372 this->getRTOpList()->addOp(std::move(op), *this->caps());
373 }
374 }
375}
376
Brian Osman9a9baae2018-11-05 15:06:26 -0500377void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const SkPMColor4f& color) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500378 ASSERT_SINGLE_OWNER_PRIV
379 RETURN_IF_ABANDONED_PRIV
380 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400381 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "absClear",
382 fRenderTargetContext->fContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500383
Robert Phillips72152832017-01-25 17:31:35 -0500384 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500385
Brian Salomonbb5711a2017-05-17 13:49:59 -0400386 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(),
387 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500388
389 if (clearRect) {
390 if (clearRect->contains(rtRect)) {
391 clearRect = nullptr; // full screen
392 } else {
393 if (!rtRect.intersect(*clearRect)) {
394 return;
395 }
396 }
397 }
398
399 // TODO: in a post-MDB world this should be handled at the OpList level.
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500400 // This makes sure to always add an op to the list, instead of marking the clear as a load op.
401 // This code follows very similar logic to internalClear() below, but critical differences are
402 // highlighted in line related to absClear()'s unique behavior.
403 if (clearRect) {
404 if (fRenderTargetContext->caps()->performPartialClearsAsDraws()) {
Ethan Nicholas56d19a52018-10-15 11:26:20 -0400405 GrPaint paint;
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500406 clear_to_grpaint(color, &paint);
407
408 // Use the disabled clip; the rect geometry already matches the clear rectangle and
409 // if it were added to a scissor, that would be intersected with the logical surface
410 // bounds and not the worst case dimensions required here.
411 fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
412 GrFillRectOp::Make(fRenderTargetContext->fContext,
413 std::move(paint),
414 GrAAType::kNone,
415 SkMatrix::I(),
416 SkRect::Make(rtRect)));
417 } else {
418 // Must use the ClearOp factory that takes a boolean (false) instead of a surface
419 // proxy. The surface proxy variant would intersect the clip rect with its logical
420 // bounds, which is not desired in this special case.
421 fRenderTargetContext->getRTOpList()->addOp(
422 GrClearOp::Make(fRenderTargetContext->fContext, rtRect, color,
423 /* fullscreen */ false),
424 *fRenderTargetContext->caps());
csmartdalton29df7602016-08-31 11:55:52 -0700425 }
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500426 } else {
427 // Reset the oplist like in internalClear(), but do not rely on a load op for the clear
428 fRenderTargetContext->getRTOpList()->resetForFullscreenClear();
429 fRenderTargetContext->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
430
431 if (fRenderTargetContext->caps()->performColorClearsAsDraws()) {
432 // This draws a quad covering the worst case dimensions instead of just the logical
433 // width and height like in internalClear().
434 GrPaint paint;
435 clear_to_grpaint(color, &paint);
436 fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
437 GrFillRectOp::Make(fRenderTargetContext->fContext,
438 std::move(paint),
439 GrAAType::kNone,
440 SkMatrix::I(),
441 SkRect::Make(rtRect)));
442 } else {
443 // Nothing special about this path in absClear compared to internalClear()
444 fRenderTargetContext->getRTOpList()->addOp(
445 GrClearOp::Make(fRenderTargetContext->fContext, SkIRect::MakeEmpty(), color,
446 /* fullscreen */ true),
447 *fRenderTargetContext->caps());
Ethan Nicholas56d19a52018-10-15 11:26:20 -0400448 }
robertphillips9199a9f2016-07-13 07:48:43 -0700449 }
robertphillipsea461502015-05-26 11:38:03 -0700450}
451
Brian Osman11052242016-10-27 14:47:55 -0400452void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500453 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400454 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800455 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700456 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700457 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400458 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPaint", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700459
robertphillipsea461502015-05-26 11:38:03 -0700460 // set rect to be big enough to fill the space, but not super-huge, so we
461 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700462
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400463 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700464
Michael Ludwig61a16512019-01-15 11:15:13 -0500465 // Check if we can optimize a clipped drawPaint(). We only do the transformation when there are
466 // no fragment processors because they may depend on having correct local coords and this path
467 // draws in device space without a local matrix. It currently handles converting clipRRect()
468 // to drawRRect() and solid colors to screen-filling drawRects() (which are then converted into
469 // clears if possible in drawRect).
Michael Ludwig3d6390e2018-10-09 11:45:16 -0400470 if (!paint.numTotalFragmentProcessors()) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500471 SkRRect rrect;
472 GrAA aa = GrAA::kNo;
473 if (clip.isRRect(r, &rrect, &aa)) {
474 if (rrect.isRect()) {
475 // Use drawFilledRect() with no clip and the reduced rectangle
476 this->drawFilledRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect.rect());
477 } else {
478 // Use drawRRect() with no clip
479 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
480 GrStyle::SimpleFill());
481 }
482 } else {
483 // Use drawFilledRect() with no view matrix to draw a fullscreen quad, but preserve
484 // the clip. Since the paint has no FPs we can drop the view matrix without worrying
485 // about local coordinates. If the clip is simple, drawFilledRect() will turn this into
486 // a clear or a scissored clear.
487 this->drawFilledRect(clip, std::move(paint), aa, SkMatrix::I(), r);
Michael Ludwig3d6390e2018-10-09 11:45:16 -0400488 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500489 return;
bsalomoncb31e512016-08-26 10:48:19 -0700490 }
491
Michael Ludwig61a16512019-01-15 11:15:13 -0500492 // Since the paint is not trivial, there's no way at this point drawRect() could have converted
493 // this drawPaint() into an optimized clear. drawRect() would then use GrFillRectOp without
494 // a local matrix, so we can simplify things and use the local matrix variant to draw a screen
495 // filling rect with the inverse view matrix for local coords, which works for all matrix
496 // conditions.
497 SkMatrix localMatrix;
498 if (!viewMatrix.invert(&localMatrix)) {
499 return;
robertphillipsea461502015-05-26 11:38:03 -0700500 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500501
502 AutoCheckFlush acf(this->drawingManager());
503 std::unique_ptr<GrDrawOp> op = GrFillRectOp::MakeWithLocalMatrix(
504 fContext, std::move(paint), GrAAType::kNone, SkMatrix::I(), localMatrix, r);
505 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700506}
507
robertphillipsea461502015-05-26 11:38:03 -0700508static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
509 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
510 point.fY >= rect.fTop && point.fY <= rect.fBottom;
511}
512
csmartdalton97f6cd52016-07-13 13:37:08 -0700513// Attempts to crop a rect and optional local rect to the clip boundaries.
514// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700515static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700516 const SkMatrix& viewMatrix, SkRect* rect,
517 SkRect* localRect = nullptr) {
518 if (!viewMatrix.rectStaysRect()) {
519 return true;
520 }
521
csmartdalton97f6cd52016-07-13 13:37:08 -0700522 SkIRect clipDevBounds;
523 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700524
robertphillips13a7eee2016-08-31 15:06:24 -0700525 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700526 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
527 return false;
528 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700529
530 if (localRect) {
531 if (!rect->intersects(clipBounds)) {
532 return false;
533 }
Michael Ludwig904657d2019-04-12 10:57:24 -0400534 // localRect is force-sorted after clipping, so this is a sanity check to make sure callers
535 // aren't intentionally using inverted local rectangles.
536 SkASSERT(localRect->isSorted());
csmartdalton97f6cd52016-07-13 13:37:08 -0700537 const SkScalar dx = localRect->width() / rect->width();
538 const SkScalar dy = localRect->height() / rect->height();
539 if (clipBounds.fLeft > rect->fLeft) {
540 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
541 rect->fLeft = clipBounds.fLeft;
542 }
543 if (clipBounds.fTop > rect->fTop) {
544 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
545 rect->fTop = clipBounds.fTop;
546 }
547 if (clipBounds.fRight < rect->fRight) {
548 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
549 rect->fRight = clipBounds.fRight;
550 }
551 if (clipBounds.fBottom < rect->fBottom) {
552 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
553 rect->fBottom = clipBounds.fBottom;
554 }
Michael Ludwig904657d2019-04-12 10:57:24 -0400555 // Ensure local coordinates remain sorted after clipping. If the original dstRect was very
556 // large, numeric precision can invert the localRect
557 localRect->sort();
csmartdalton97f6cd52016-07-13 13:37:08 -0700558 return true;
559 }
560
561 return rect->intersect(clipBounds);
562}
563
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400564GrQuadAAFlags set_edge_flag(GrQuadAAFlags currentFlags, GrQuadAAFlags edge, GrAA edgeState) {
565 if (edgeState == GrAA::kNo) {
566 // Turn off 'edge' in currentFlags
567 return currentFlags & (~edge);
568 } else {
569 // Turn on 'edge' in currentFlags
570 return currentFlags | edge;
571 }
572}
573
Michael Ludwig61a16512019-01-15 11:15:13 -0500574bool GrRenderTargetContext::drawFilledRectAsClear(const GrClip& clip, GrPaint&& paint, GrAA aa,
575 const SkMatrix& viewMatrix, const SkRect& rect) {
576 // Rules for a filled rect to become a clear [+scissor]:
577 // 1. The paint is a constant blend color with no other FPs
578 // 2. The view matrix maps rectangles to rectangles, or the transformed quad fully covers
579 // the render target (or clear region in #3).
580 // 3. The clip is an intersection of rectangles, so the clear region will be the
581 // intersection of the clip and the provided rect.
582 // 4. The clear region aligns with pixel bounds
583 // 5. There are no user stencil settings (and since the clip was IOR, the clip won't need
584 // to use the stencil either).
585 // If all conditions pass, the filled rect can either be a fullscreen clear (if it's big
586 // enough), or the rectangle geometry will be used as the scissor clip on the clear.
587 // If everything passes but rule #4, this submits a simplified fill rect op instead so that the
588 // rounding differences between clip and draws don't fight each other.
589 // NOTE: we route draws into clear() regardless of performColorClearsAsDraws() since the
590 // clear call is allowed to reset the oplist even when it also happens to use a GrFillRectOp.
591
592 SkPMColor4f clearColor;
593 if (paint.numCoverageFragmentProcessors() > 0 || !paint.isConstantBlendedColor(&clearColor)) {
594 return false;
595 }
596
597 const SkRect rtRect = fRenderTargetProxy->getBoundsRect();
598 // Will be the intersection of render target, clip, and quad
599 SkRect combinedRect = rtRect;
600
601 SkRRect clipRRect;
602 GrAA clipAA;
603 if (!clip.quickContains(rtRect)) {
604 // If the clip is an rrect with no rounding, then it can replace the full RT bounds as the
605 // limiting region, although we will have to worry about AA. If the clip is anything
606 // more complicated, just punt to the regular fill rect op.
607 if (!clip.isRRect(rtRect, &clipRRect, &clipAA) || !clipRRect.isRect()) {
608 return false;
609 }
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400610
611 if (clipAA == GrAA::kNo) {
612 // Must round the coordinates to be consistent with GrReducedClip's non-aa clip rect
613 // to scissor rect code.
614 SkIRect rounded;
615 clipRRect.rect().round(&rounded);
616 combinedRect = SkRect::Make(rounded);
617 } else {
618 combinedRect = clipRRect.rect();
619 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500620 } else {
621 // The clip is outside the render target, so the clip can be ignored
622 clipAA = GrAA::kNo;
623 }
624
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400625 GrQuadAAFlags edgeFlags; // To account for clip and draw mixing AA modes
Michael Ludwig61a16512019-01-15 11:15:13 -0500626 if (viewMatrix.rectStaysRect()) {
627 // Skip the extra overhead of inverting the view matrix to see if rtRect is contained in the
628 // drawn rectangle, and instead just intersect rtRect with the transformed rect. It will be
629 // the new clear region.
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400630 SkRect drawRect = viewMatrix.mapRect(rect);
631 if (!combinedRect.intersect(drawRect)) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500632 // No intersection means nothing should be drawn, so return true but don't add an op
633 return true;
634 }
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400635
636 // In this case, edge flags start based on draw's AA and then switch per-edge to the clip's
637 // AA setting if that edge was inset.
638 edgeFlags = aa == GrAA::kNo ? GrQuadAAFlags::kNone : GrQuadAAFlags::kAll;
639 if (combinedRect.fLeft > drawRect.fLeft) {
640 edgeFlags = set_edge_flag(edgeFlags, GrQuadAAFlags::kLeft, clipAA);
641 }
642 if (combinedRect.fTop > drawRect.fTop) {
643 edgeFlags = set_edge_flag(edgeFlags, GrQuadAAFlags::kTop, clipAA);
644 }
645 if (combinedRect.fRight < drawRect.fRight) {
646 edgeFlags = set_edge_flag(edgeFlags, GrQuadAAFlags::kRight, clipAA);
647 }
648 if (combinedRect.fBottom < drawRect.fBottom) {
649 edgeFlags = set_edge_flag(edgeFlags, GrQuadAAFlags::kBottom, clipAA);
650 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500651 } else {
652 // If the transformed rectangle does not contain the combined rt and clip, the draw is too
653 // complex to be implemented as a clear
654 SkMatrix invM;
655 if (!viewMatrix.invert(&invM)) {
656 return false;
657 }
658 // The clip region in the rect's local space, so the test becomes the local rect containing
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400659 // the quad's points. If clip is non-AA, test rounded out region to avoid the scenario where
660 // the draw contains the unrounded non-aa clip, but does not contain the rounded version. Be
661 // conservative since we don't know how the GPU would round.
662 SkRect conservative;
663 if (clipAA == GrAA::kNo) {
664 conservative = SkRect::Make(combinedRect.roundOut());
665 } else {
666 conservative = combinedRect;
667 }
668 GrQuad quad = GrQuad::MakeFromRect(conservative, invM);
Michael Ludwig61a16512019-01-15 11:15:13 -0500669 if (!rect_contains_inclusive(rect, quad.point(0)) ||
670 !rect_contains_inclusive(rect, quad.point(1)) ||
671 !rect_contains_inclusive(rect, quad.point(2)) ||
672 !rect_contains_inclusive(rect, quad.point(3))) {
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400673 // No containment, so combinedRect can't be filled by a solid color
Michael Ludwig61a16512019-01-15 11:15:13 -0500674 return false;
675 }
676 // combinedRect can be filled by a solid color but doesn't need to be modified since it's
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400677 // inside the quad to be drawn, which also means the edge AA flags respect the clip AA
678 edgeFlags = clipAA == GrAA::kNo ? GrQuadAAFlags::kNone : GrQuadAAFlags::kAll;
Michael Ludwig61a16512019-01-15 11:15:13 -0500679 }
680
681 // Almost every condition is met; now it requires that the combined rect align with pixel
682 // boundaries in order for it to become a scissor-clear. Ignore the AA status in this case
683 // since non-AA with partial-pixel coordinates can be rounded differently on the GPU,
684 // leading to unexpected differences between a scissor test and a rasterized quad.
685 // Also skip very small rectangles since the scissor+clear doesn't by us much then.
686 if (combinedRect.contains(rtRect)) {
687 // Full screen clear
688 this->clear(nullptr, clearColor, CanClearFullscreen::kYes);
689 return true;
690 } else if (GrClip::IsPixelAligned(combinedRect) &&
691 combinedRect.width() > 256 && combinedRect.height() > 256) {
692 // Scissor + clear (round shouldn't do anything since we are pixel aligned)
693 SkIRect scissorRect;
694 combinedRect.round(&scissorRect);
695 this->clear(&scissorRect, clearColor, CanClearFullscreen::kNo);
696 return true;
697 }
698
699 // If we got here, we can't use a scissor + clear, but combinedRect represents the correct
700 // geometry combination of quad + clip so we can perform a simplified fill rect op. We do this
701 // mostly to avoid mismatches in rounding logic on the CPU vs. the GPU, which frequently appears
702 // when drawing and clipping something to the same non-AA rect that never-the-less has
703 // non-integer coordinates.
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400704 aa = edgeFlags == GrQuadAAFlags::kNone ? GrAA::kNo : GrAA::kYes;
Chris Dalton7d6748e2019-03-13 00:34:52 -0600705 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig61a16512019-01-15 11:15:13 -0500706 this->addDrawOp(GrFixedClip::Disabled(),
Michael Ludwig76ec80a2019-05-13 13:30:53 -0400707 GrFillRectOp::MakePerEdge(fContext, std::move(paint), aaType, edgeFlags,
708 SkMatrix::I(), combinedRect));
Michael Ludwig61a16512019-01-15 11:15:13 -0500709 return true;
710}
711
712void GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500713 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500714 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400715 const SkMatrix& viewMatrix,
716 const SkRect& rect,
717 const GrUserStencilSettings* ss) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500718
719 if (!ss) {
720 if (this->drawFilledRectAsClear(clip, std::move(paint), aa, viewMatrix, rect)) {
721 return;
722 }
723 // Fall through to fill rect op
724 assert_alive(paint);
725 }
726
csmartdalton97f6cd52016-07-13 13:37:08 -0700727 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500728 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500729 // The rectangle would not be drawn, so no need to add a draw op to the list
730 return;
csmartdalton97f6cd52016-07-13 13:37:08 -0700731 }
robertphillips44302392016-07-08 14:43:03 -0700732
Chris Dalton7d6748e2019-03-13 00:34:52 -0600733 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500734 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), aaType, viewMatrix,
735 croppedRect, ss));
robertphillips391395d2016-03-02 09:26:36 -0800736}
737
Brian Osman11052242016-10-27 14:47:55 -0400738void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500739 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500740 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400741 const SkMatrix& viewMatrix,
742 const SkRect& rect,
743 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700744 if (!style) {
745 style = &GrStyle::SimpleFill();
746 }
joshualitt1de610a2016-01-06 08:26:09 -0800747 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700748 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700749 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400750 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700751
bsalomon6663acf2016-05-10 09:14:17 -0700752 // Path effects should've been devolved to a path in SkGpuDevice
753 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700754
Robert Phillips72152832017-01-25 17:31:35 -0500755 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700756
bsalomon6663acf2016-05-10 09:14:17 -0700757 const SkStrokeRec& stroke = style->strokeRec();
Robert Phillips8c8b0462018-08-24 16:18:03 -0400758 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500759 this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect);
760 return;
bsalomona7d85ba2016-07-06 11:54:59 -0700761 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
762 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
763 if ((!rect.width() || !rect.height()) &&
764 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
765 SkScalar r = stroke.getWidth() / 2;
766 // TODO: Move these stroke->fill fallbacks to GrShape?
767 switch (stroke.getJoin()) {
768 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500769 this->drawRect(
770 clip, std::move(paint), aa, viewMatrix,
771 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
772 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700773 return;
774 case SkPaint::kRound_Join:
775 // Raster draws nothing when both dimensions are empty.
776 if (rect.width() || rect.height()){
777 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500778 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
779 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700780 return;
781 }
782 case SkPaint::kBevel_Join:
783 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500784 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700785 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
786 &GrStyle::SimpleFill());
787 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500788 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700789 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
790 &GrStyle::SimpleFill());
791 }
792 return;
793 }
794 }
robertphillips44302392016-07-08 14:43:03 -0700795
Brian Salomonbaaf4392017-06-15 09:59:23 -0400796 std::unique_ptr<GrDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700797
Chris Dalton7d6748e2019-03-13 00:34:52 -0600798 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500799 op = GrStrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
800 // op may be null if the stroke is not supported or if using coverage aa and the view matrix
801 // does not preserve rectangles.
Brian Salomon42521e82016-12-07 16:44:58 -0500802 if (op) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400803 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700804 return;
robertphillips4bc31812016-03-01 12:22:49 -0800805 }
robertphillips4bc31812016-03-01 12:22:49 -0800806 }
Mike Klein16885072018-12-11 09:54:31 -0500807 assert_alive(paint);
Brian Salomon2fad74a2017-12-20 13:28:55 -0500808 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(rect, *style));
robertphillipsea461502015-05-26 11:38:03 -0700809}
810
Michael Ludwig69858532018-11-28 15:34:34 -0500811void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa,
812 const SkMatrix& viewMatrix, const QuadSetEntry quads[],
813 int cnt) {
Chris Dalton7d6748e2019-03-13 00:34:52 -0600814 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig69858532018-11-28 15:34:34 -0500815 this->addDrawOp(clip, GrFillRectOp::MakeSet(fContext, std::move(paint), aaType, viewMatrix,
816 quads, cnt));
817}
818
Robert Phillipsec2249f2016-11-09 08:54:35 -0500819int GrRenderTargetContextPriv::maxWindowRectangles() const {
820 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400821 *fRenderTargetContext->caps());
Robert Phillipsec2249f2016-11-09 08:54:35 -0500822}
823
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000824void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700825 ASSERT_SINGLE_OWNER_PRIV
826 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400827 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400828 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
829 fRenderTargetContext->fContext);
robertphillips976f5f02016-06-03 10:59:20 -0700830
Robert Phillips72152832017-01-25 17:31:35 -0500831 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400832
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500833 fRenderTargetContext->internalStencilClear(clip, insideStencilMask);
834}
835
836void GrRenderTargetContext::internalStencilClear(const GrFixedClip& clip, bool insideStencilMask) {
837 if (this->caps()->performStencilClearsAsDraws()) {
838 const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);
839 SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
840
841 // Configure the paint to have no impact on the color buffer
842 GrPaint paint;
843 paint.setColor4f({0.f, 0.f, 0.f, 0.f});
844 paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
845
Michael Ludwig6e17f1d2019-05-15 14:00:20 +0000846 // Mark stencil usage here before addDrawOp() so that it doesn't try to re-call
847 // internalStencilClear() just because the op has stencil settings.
848 this->setNeedsStencil();
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500849 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint),
850 GrAAType::kNone, SkMatrix::I(), rtRect, ss));
851 } else {
852 std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask,
853 fRenderTargetProxy.get()));
854 if (!op) {
855 return;
856 }
857 this->getRTOpList()->addOp(std::move(op), *this->caps());
Robert Phillipse60ad622016-11-17 10:22:48 -0500858 }
robertphillips976f5f02016-06-03 10:59:20 -0700859}
860
Chris Daltonbbfd5162017-11-07 13:35:22 -0700861void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
Chris Dalton09e56892019-03-13 00:22:01 -0600862 GrAA doStencilMSAA,
Brian Osman11052242016-10-27 14:47:55 -0400863 const SkMatrix& viewMatrix,
864 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500865 ASSERT_SINGLE_OWNER_PRIV
866 RETURN_IF_ABANDONED_PRIV
867 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400868 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
869 fRenderTargetContext->fContext);
Brian Salomon467921e2017-03-06 16:17:12 -0500870
Brian Salomon467921e2017-03-06 16:17:12 -0500871 // TODO: extract portions of checkDraw that are relevant to path stenciling.
872 SkASSERT(path);
873 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
874
875 // FIXME: Use path bounds instead of this WAR once
876 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
877 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
878
879 // Setup clip
Chris Daltonbbfd5162017-11-07 13:35:22 -0700880 GrAppliedHardClip appliedClip;
881 if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
882 &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500883 return;
884 }
885
Michael Ludwig6e17f1d2019-05-15 14:00:20 +0000886 fRenderTargetContext->setNeedsStencil();
887
Robert Phillips7c525e62018-06-12 10:11:12 -0400888 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
889 viewMatrix,
Chris Dalton09e56892019-03-13 00:22:01 -0600890 GrAA::kYes == doStencilMSAA,
Brian Salomon467921e2017-03-06 16:17:12 -0500891 path->getFillType(),
892 appliedClip.hasStencilClip(),
Brian Salomon467921e2017-03-06 16:17:12 -0500893 appliedClip.scissorState(),
Brian Salomon467921e2017-03-06 16:17:12 -0500894 path);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400895 if (!op) {
896 return;
897 }
Brian Salomon97180af2017-03-14 13:42:58 -0400898 op->setClippedBounds(bounds);
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400899 fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -0700900}
901
Chris Daltonbbfd5162017-11-07 13:35:22 -0700902void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400903 const GrUserStencilSettings* ss,
Chris Dalton09e56892019-03-13 00:22:01 -0600904 GrAA doStencilMSAA,
Brian Osman11052242016-10-27 14:47:55 -0400905 const SkMatrix& viewMatrix,
906 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700907 ASSERT_SINGLE_OWNER_PRIV
908 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400909 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400910 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilRect",
911 fRenderTargetContext->fContext);
912
Robert Phillips72152832017-01-25 17:31:35 -0500913 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700914
915 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500916 paint.setXPFactory(GrDisableColorXPFactory::Get());
Chris Dalton09e56892019-03-13 00:22:01 -0600917 auto aaType = (GrAA::kYes == doStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
Michael Ludwig72ab3462018-12-10 12:43:36 -0500918 std::unique_ptr<GrDrawOp> op = GrFillRectOp::Make(
919 fRenderTargetContext->fContext, std::move(paint), aaType, viewMatrix, rect, ss);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400920 fRenderTargetContext->addDrawOp(clip, std::move(op));
robertphillips976f5f02016-06-03 10:59:20 -0700921}
922
Chris Daltonbbfd5162017-11-07 13:35:22 -0700923bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400924 const GrUserStencilSettings* ss,
925 SkRegion::Op op,
926 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500927 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400928 const SkMatrix& viewMatrix,
929 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800930 ASSERT_SINGLE_OWNER_PRIV
931 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400932 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400933 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
934 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -0800935
Robert Phillips72152832017-01-25 17:31:35 -0500936 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800937
938 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800939 paint.setCoverageSetOpXPFactory(op, invert);
940
Michael Ludwig61a16512019-01-15 11:15:13 -0500941 // This will always succeed to draw a rectangle
942 fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss);
943 return true;
robertphillips391395d2016-03-02 09:26:36 -0800944}
945
Michael Ludwig136f45a2019-02-19 11:44:41 -0500946void GrRenderTargetContext::fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
Michael Ludwig75451902019-01-23 11:14:29 -0500947 GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
Michael Ludwig136f45a2019-02-19 11:44:41 -0500948 const SkRect& rect, const SkRect* localRect) {
Michael Ludwig75451902019-01-23 11:14:29 -0500949 ASSERT_SINGLE_OWNER
950 RETURN_IF_ABANDONED
951 SkDEBUGCODE(this->validate();)
952 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithEdgeAA", fContext);
953
Chris Dalton7d6748e2019-03-13 00:34:52 -0600954 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig136f45a2019-02-19 11:44:41 -0500955 std::unique_ptr<GrDrawOp> op;
Michael Ludwig75451902019-01-23 11:14:29 -0500956
Michael Ludwig136f45a2019-02-19 11:44:41 -0500957 if (localRect) {
958 // If local coordinates are provided, skip the optimization check to go through
959 // drawFilledRect, and also calculate clipped local coordinates
960 SkRect croppedRect = rect;
961 SkRect croppedLocalRect = *localRect;
962 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect,
963 &croppedLocalRect)) {
964 return;
965 }
966 op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType, edgeAA,
967 viewMatrix, croppedRect, croppedLocalRect);
968 } else {
969 // If aaType turns into MSAA, make sure to keep quads with no AA edges as MSAA. Sending
970 // those to drawFilledRect() would have it turn off MSAA in that case, which breaks seaming
971 // with any partial AA edges that kept MSAA.
972 if (aaType != GrAAType::kMSAA &&
973 (edgeAA == GrQuadAAFlags::kNone || edgeAA == GrQuadAAFlags::kAll)) {
974 // This is equivalent to a regular filled rect draw, so route through there to take
975 // advantage of draw->clear optimizations
976 this->drawFilledRect(clip, std::move(paint), GrAA(edgeAA == GrQuadAAFlags::kAll),
977 viewMatrix, rect);
978 return;
979 }
980
981 SkRect croppedRect = rect;
982 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
983 return;
984 }
985 op = GrFillRectOp::MakePerEdge(fContext, std::move(paint), aaType, edgeAA, viewMatrix,
986 croppedRect);
Michael Ludwig75451902019-01-23 11:14:29 -0500987 }
988
989 AutoCheckFlush acf(this->drawingManager());
Michael Ludwig136f45a2019-02-19 11:44:41 -0500990 this->addDrawOp(clip, std::move(op));
Michael Ludwig75451902019-01-23 11:14:29 -0500991}
992
Michael Ludwigce62dec2019-02-19 11:48:46 -0500993void GrRenderTargetContext::fillQuadWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
994 GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
995 const SkPoint quad[4], const SkPoint localQuad[4]) {
996 ASSERT_SINGLE_OWNER
997 RETURN_IF_ABANDONED
998 SkDEBUGCODE(this->validate();)
999 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillQuadWithEdgeAA", fContext);
1000
Chris Dalton7d6748e2019-03-13 00:34:52 -06001001 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001002
1003 AutoCheckFlush acf(this->drawingManager());
1004 // MakePerEdgeQuad automatically does the right thing if localQuad is null or not
1005 this->addDrawOp(clip, GrFillRectOp::MakePerEdgeQuad(fContext, std::move(paint), aaType, edgeAA,
1006 viewMatrix, quad, localQuad));
1007}
1008
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001009// Creates a paint for GrFillRectOp that matches behavior of GrTextureOp
1010static void draw_texture_to_grpaint(sk_sp<GrTextureProxy> proxy, const SkRect* domain,
1011 GrSamplerState::Filter filter, SkBlendMode mode,
1012 const SkPMColor4f& color, sk_sp<GrColorSpaceXform> csXform,
1013 GrPaint* paint) {
1014 paint->setColor4f(color);
1015 paint->setXPFactory(SkBlendMode_AsXPFactory(mode));
1016
1017 std::unique_ptr<GrFragmentProcessor> fp;
1018 if (domain) {
Michael Ludwigce62dec2019-02-19 11:48:46 -05001019 SkRect correctedDomain = *domain;
1020 if (filter == GrSamplerState::Filter::kBilerp) {
1021 // Inset by 1/2 pixel, which GrTextureOp and GrTextureAdjuster handle automatically
1022 correctedDomain.inset(0.5f, 0.5f);
1023 }
1024 fp = GrTextureDomainEffect::Make(std::move(proxy), SkMatrix::I(), correctedDomain,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001025 GrTextureDomain::kClamp_Mode, filter);
1026 } else {
1027 fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I(), filter);
1028 }
1029
1030 fp = GrColorSpaceXformEffect::Make(std::move(fp), csXform);
1031 paint->addColorFragmentProcessor(std::move(fp));
1032}
1033
Brian Salomonbe3c1d22018-05-21 12:54:39 -04001034void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001035 GrSamplerState::Filter filter, SkBlendMode mode,
1036 const SkPMColor4f& color, const SkRect& srcRect,
Michael Ludwig136f45a2019-02-19 11:44:41 -05001037 const SkRect& dstRect, GrAA aa, GrQuadAAFlags aaFlags,
Brian Salomonb80ffee2018-05-23 16:39:39 -04001038 SkCanvas::SrcRectConstraint constraint,
Brian Salomonbe3c1d22018-05-21 12:54:39 -04001039 const SkMatrix& viewMatrix,
Brian Osman3d139a42018-11-19 10:42:10 -05001040 sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
Brian Salomon34169692017-08-28 15:32:01 -04001041 ASSERT_SINGLE_OWNER
1042 RETURN_IF_ABANDONED
1043 SkDEBUGCODE(this->validate();)
Brian Salomonbe3c1d22018-05-21 12:54:39 -04001044 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexture", fContext);
Brian Salomonf1709042018-10-03 11:57:00 -04001045 if (constraint == SkCanvas::kStrict_SrcRectConstraint &&
1046 srcRect.contains(proxy->getWorstCaseBoundsRect())) {
1047 constraint = SkCanvas::kFast_SrcRectConstraint;
Brian Salomon34169692017-08-28 15:32:01 -04001048 }
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001049
Chris Dalton7d6748e2019-03-13 00:34:52 -06001050 GrAAType aaType = this->chooseAAType(aa);
Brian Salomonff9d6d32017-08-30 10:27:49 -04001051 SkRect clippedDstRect = dstRect;
1052 SkRect clippedSrcRect = srcRect;
1053 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &clippedDstRect,
1054 &clippedSrcRect)) {
1055 return;
1056 }
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001057
1058 AutoCheckFlush acf(this->drawingManager());
1059
1060 std::unique_ptr<GrDrawOp> op;
1061 if (mode != SkBlendMode::kSrcOver) {
1062 // Emulation mode with GrPaint and GrFillRectOp
1063 if (filter != GrSamplerState::Filter::kNearest &&
1064 !GrTextureOp::GetFilterHasEffect(viewMatrix, clippedSrcRect, clippedDstRect)) {
1065 filter = GrSamplerState::Filter::kNearest;
1066 }
1067
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001068 GrPaint paint;
1069 draw_texture_to_grpaint(std::move(proxy),
Michael Ludwigce62dec2019-02-19 11:48:46 -05001070 constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001071 filter, mode, color, std::move(textureColorSpaceXform), &paint);
1072 op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType, aaFlags,
1073 viewMatrix, clippedDstRect, clippedSrcRect);
1074 } else {
1075 // Can use a lighter weight op that can chain across proxies
1076 op = GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect,
1077 clippedDstRect, aaType, aaFlags, constraint, viewMatrix,
1078 std::move(textureColorSpaceXform));
1079 }
1080
Brian Salomon2213ee92018-10-02 10:44:21 -04001081 this->addDrawOp(clip, std::move(op));
Brian Salomon34169692017-08-28 15:32:01 -04001082}
1083
Michael Ludwigce62dec2019-02-19 11:48:46 -05001084void GrRenderTargetContext::drawTextureQuad(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
1085 GrSamplerState::Filter filter, SkBlendMode mode,
1086 const SkPMColor4f& color, const SkPoint srcQuad[4],
1087 const SkPoint dstQuad[4], GrAA aa,
1088 GrQuadAAFlags aaFlags, const SkRect* domain,
1089 const SkMatrix& viewMatrix,
1090 sk_sp<GrColorSpaceXform> texXform) {
1091 ASSERT_SINGLE_OWNER
1092 RETURN_IF_ABANDONED
1093 SkDEBUGCODE(this->validate();)
1094 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureQuad", fContext);
1095 if (domain && domain->contains(proxy->getWorstCaseBoundsRect())) {
1096 domain = nullptr;
1097 }
1098
Chris Dalton7d6748e2019-03-13 00:34:52 -06001099 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001100
1101 // Unlike drawTexture(), don't bother cropping or optimizing the filter type since we're
1102 // sampling an arbitrary quad of the texture.
1103 AutoCheckFlush acf(this->drawingManager());
1104 std::unique_ptr<GrDrawOp> op;
1105 if (mode != SkBlendMode::kSrcOver) {
1106 // Emulation mode, but don't bother converting to kNearest filter since it's an arbitrary
1107 // quad that is being drawn, which makes the tests too expensive here
1108 GrPaint paint;
1109 draw_texture_to_grpaint(
1110 std::move(proxy), domain, filter, mode, color, std::move(texXform), &paint);
1111 op = GrFillRectOp::MakePerEdgeQuad(fContext, std::move(paint), aaType, aaFlags, viewMatrix,
1112 dstQuad, srcQuad);
1113 } else {
1114 // Use lighter weight GrTextureOp
1115 op = GrTextureOp::MakeQuad(fContext, std::move(proxy), filter, color, srcQuad, dstQuad,
1116 aaType, aaFlags, domain, viewMatrix, std::move(texXform));
1117 }
1118
1119 this->addDrawOp(clip, std::move(op));
1120}
1121
Brian Salomond7065e72018-10-12 11:42:02 -04001122void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetEntry set[], int cnt,
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001123 GrSamplerState::Filter filter, SkBlendMode mode,
Michael Ludwig31ba7182019-04-03 10:38:06 -04001124 GrAA aa, SkCanvas::SrcRectConstraint constraint,
1125 const SkMatrix& viewMatrix,
Brian Osman3d139a42018-11-19 10:42:10 -05001126 sk_sp<GrColorSpaceXform> texXform) {
Brian Salomond7065e72018-10-12 11:42:02 -04001127 ASSERT_SINGLE_OWNER
1128 RETURN_IF_ABANDONED
1129 SkDEBUGCODE(this->validate();)
1130 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureSet", fContext);
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001131
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001132 if (mode != SkBlendMode::kSrcOver ||
Robert Phillips9da87e02019-02-04 13:26:26 -05001133 !fContext->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001134 // Draw one at a time with GrFillRectOp and a GrPaint that emulates what GrTextureOp does
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001135 SkMatrix ctm;
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001136 for (int i = 0; i < cnt; ++i) {
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001137 float alpha = set[i].fAlpha;
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001138 ctm = viewMatrix;
1139 if (set[i].fPreViewMatrix) {
1140 ctm.preConcat(*set[i].fPreViewMatrix);
1141 }
1142
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001143 if (set[i].fDstClipQuad == nullptr) {
Michael Ludwigce62dec2019-02-19 11:48:46 -05001144 // Stick with original rectangles, which allows the ops to know more about what's
1145 // being drawn.
1146 this->drawTexture(clip, set[i].fProxy, filter, mode, {alpha, alpha, alpha, alpha},
1147 set[i].fSrcRect, set[i].fDstRect, aa, set[i].fAAFlags,
Michael Ludwig31ba7182019-04-03 10:38:06 -04001148 constraint, ctm, texXform);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001149 } else {
1150 // Generate interpolated texture coordinates to match the dst clip
1151 SkPoint srcQuad[4];
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001152 GrMapRectPoints(set[i].fDstRect, set[i].fSrcRect, set[i].fDstClipQuad, srcQuad, 4);
Michael Ludwig31ba7182019-04-03 10:38:06 -04001153 const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint
1154 ? &set[i].fSrcRect : nullptr;
Michael Ludwigce62dec2019-02-19 11:48:46 -05001155 this->drawTextureQuad(clip, set[i].fProxy, filter, mode,
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001156 {alpha, alpha, alpha, alpha}, srcQuad, set[i].fDstClipQuad,
Michael Ludwig31ba7182019-04-03 10:38:06 -04001157 aa, set[i].fAAFlags, domain, ctm, texXform);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001158 }
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001159 }
1160 } else {
1161 // Can use a single op, avoiding GrPaint creation, and can batch across proxies
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001162 AutoCheckFlush acf(this->drawingManager());
Chris Dalton7d6748e2019-03-13 00:34:52 -06001163 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig31ba7182019-04-03 10:38:06 -04001164 auto op = GrTextureOp::MakeSet(fContext, set, cnt, filter, aaType, constraint, viewMatrix,
Michael Ludwig009b92e2019-02-15 16:03:53 -05001165 std::move(texXform));
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001166 this->addDrawOp(clip, std::move(op));
1167 }
Brian Salomond7065e72018-10-12 11:42:02 -04001168}
1169
Brian Osman11052242016-10-27 14:47:55 -04001170void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001171 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001172 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001173 const SkMatrix& viewMatrix,
1174 const SkRect& rectToDraw,
1175 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -08001176 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -07001177 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001178 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001179 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithLocalMatrix", fContext);
joshualittb6b513b2015-08-21 10:25:18 -07001180
csmartdalton97f6cd52016-07-13 13:37:08 -07001181 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -07001182 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -07001183 return;
1184 }
1185
Robert Phillips72152832017-01-25 17:31:35 -05001186 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001187
Chris Dalton7d6748e2019-03-13 00:34:52 -06001188 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -05001189 this->addDrawOp(clip, GrFillRectOp::MakeWithLocalMatrix(fContext, std::move(paint), aaType,
1190 viewMatrix, localMatrix, croppedRect));
robertphillipsea461502015-05-26 11:38:03 -07001191}
1192
Brian Osman11052242016-10-27 14:47:55 -04001193void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001194 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001195 const SkMatrix& viewMatrix,
Brian Osmanae0c50c2017-05-25 16:56:34 -04001196 sk_sp<SkVertices> vertices,
Ruiqi Maoc97a3392018-08-15 10:44:19 -04001197 const SkVertices::Bone bones[],
Ruiqi Mao4ec72f72018-07-10 17:21:07 -04001198 int boneCount,
Brian Osmanae0c50c2017-05-25 16:56:34 -04001199 GrPrimitiveType* overridePrimType) {
Brian Salomon199fb872017-02-06 09:41:10 -05001200 ASSERT_SINGLE_OWNER
1201 RETURN_IF_ABANDONED
1202 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001203 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
Brian Salomon199fb872017-02-06 09:41:10 -05001204
1205 AutoCheckFlush acf(this->drawingManager());
1206
1207 SkASSERT(vertices);
Chris Dalton7d6748e2019-03-13 00:34:52 -06001208 GrAAType aaType = this->chooseAAType(GrAA::kNo);
Brian Salomonf3569f02017-10-24 12:52:33 -04001209 std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
Ruiqi Mao4ec72f72018-07-10 17:21:07 -04001210 fContext, std::move(paint), std::move(vertices), bones, boneCount, viewMatrix, aaType,
Brian Salomonf3569f02017-10-24 12:52:33 -04001211 this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
Brian Salomonc2f42542017-07-12 14:11:22 -04001212 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001213}
1214
1215///////////////////////////////////////////////////////////////////////////////
1216
Brian Osman4d92b892019-03-24 00:53:23 +00001217void GrRenderTargetContext::drawAtlas(const GrClip& clip,
1218 GrPaint&& paint,
1219 const SkMatrix& viewMatrix,
1220 int spriteCount,
1221 const SkRSXform xform[],
1222 const SkRect texRect[],
1223 const SkColor colors[]) {
1224 ASSERT_SINGLE_OWNER
1225 RETURN_IF_ABANDONED
1226 SkDEBUGCODE(this->validate();)
1227 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
1228
1229 AutoCheckFlush acf(this->drawingManager());
1230
1231 GrAAType aaType = this->chooseAAType(GrAA::kNo);
1232 std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
1233 aaType, spriteCount, xform, texRect, colors);
1234 this->addDrawOp(clip, std::move(op));
1235}
1236
1237///////////////////////////////////////////////////////////////////////////////
1238
Brian Osman11052242016-10-27 14:47:55 -04001239void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -05001240 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001241 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001242 const SkMatrix& viewMatrix,
1243 const SkRRect& rrect,
1244 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001245 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001246 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001247 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001248 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
Robert Phillips85290802018-07-02 13:14:28 -04001249
1250 const SkStrokeRec& stroke = style.strokeRec();
1251 if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001252 return;
1253 }
1254
bsalomon7f0d9f32016-08-15 14:49:10 -07001255 GrNoClip noclip;
1256 const GrClip* clip = &origClip;
1257#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1258 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -05001259 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -07001260 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
1261 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
Michael Ludwig28398842019-03-25 10:24:24 -04001262 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls. This
1263 // only works for filled rrects since the stroke width outsets beyond the rrect itself.
bsalomon7f0d9f32016-08-15 14:49:10 -07001264 SkRRect devRRect;
Michael Ludwig28398842019-03-25 10:24:24 -04001265 if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.transform(viewMatrix, &devRRect) &&
1266 clip->quickContains(devRRect)) {
bsalomon7f0d9f32016-08-15 14:49:10 -07001267 clip = &noclip;
1268 }
1269#endif
bsalomon6663acf2016-05-10 09:14:17 -07001270 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -07001271
Robert Phillips72152832017-01-25 17:31:35 -05001272 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001273
Chris Dalton7d6748e2019-03-13 00:34:52 -06001274 GrAAType aaType = this->chooseAAType(aa);
Chris Dalton133944a2018-11-16 23:30:29 -05001275
Chris Dalton0dffbab2019-03-27 13:08:50 -06001276 std::unique_ptr<GrDrawOp> op;
1277 if (style.isSimpleFill()) {
1278 assert_alive(paint);
1279 op = GrFillRRectOp::Make(
1280 fContext, aaType, viewMatrix, rrect, *this->caps(), std::move(paint));
1281 }
Greg Daniel2655ede2019-04-10 00:49:28 +00001282 if (!op && GrAAType::kCoverage == aaType) {
Chris Dalton0dffbab2019-03-27 13:08:50 -06001283 assert_alive(paint);
1284 op = GrOvalOpFactory::MakeRRectOp(
Greg Daniel2655ede2019-04-10 00:49:28 +00001285 fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
1286
Chris Dalton0dffbab2019-03-27 13:08:50 -06001287 }
1288 if (op) {
1289 this->addDrawOp(*clip, std::move(op));
1290 return;
robertphillipsea461502015-05-26 11:38:03 -07001291 }
robertphillipsb56f9272016-02-25 11:03:52 -08001292
Mike Klein16885072018-12-11 09:54:31 -05001293 assert_alive(paint);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001294 this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
1295 GrShape(rrect, style));
robertphillipsea461502015-05-26 11:38:03 -07001296}
1297
Jim Van Verthc5903412016-11-17 15:27:09 -05001298///////////////////////////////////////////////////////////////////////////////
1299
Jim Van Verth3af1af92017-05-18 15:06:54 -04001300static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
1301 SkPoint3 result;
1302 m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
1303 result.fZ = pt.fZ;
1304 return result;
1305}
1306
1307bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
Jim Van Verth3af1af92017-05-18 15:06:54 -04001308 const SkMatrix& viewMatrix,
1309 const SkPath& path,
1310 const SkDrawShadowRec& rec) {
Jim Van Verthc5903412016-11-17 15:27:09 -05001311 ASSERT_SINGLE_OWNER
Robert Phillips6a6de562019-02-15 15:19:15 -05001312 if (fContext->priv().abandoned()) {
Jim Van Verth3af1af92017-05-18 15:06:54 -04001313 return true;
1314 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001315 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001316 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001317
1318 // check z plane
1319 bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
1320 !SkScalarNearlyZero(rec.fZPlaneParams.fY));
1321 bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1322 if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
1323 return false;
1324 }
1325
1326 SkRRect rrect;
1327 SkRect rect;
1328 // we can only handle rects, circles, and rrects with circular corners
Mike Reed242135a2018-02-22 13:41:39 -05001329 bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsSimpleCircular(rrect) &&
Jim Van Verth3af1af92017-05-18 15:06:54 -04001330 rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
1331 if (!isRRect &&
1332 path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
1333 rect.width() > SK_ScalarNearlyZero) {
1334 rrect.setOval(rect);
1335 isRRect = true;
1336 }
1337 if (!isRRect && path.isRect(&rect)) {
1338 rrect.setRect(rect);
1339 isRRect = true;
1340 }
1341
1342 if (!isRRect) {
1343 return false;
1344 }
1345
Jim Van Verthc5903412016-11-17 15:27:09 -05001346 if (rrect.isEmpty()) {
Jim Van Verth3af1af92017-05-18 15:06:54 -04001347 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -05001348 }
1349
Robert Phillips72152832017-01-25 17:31:35 -05001350 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001351
Jim Van Verth3af1af92017-05-18 15:06:54 -04001352 // transform light
1353 SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
1354
1355 // 1/scale
1356 SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
1357 SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) :
1358 sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
1359 viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
1360
1361 SkScalar occluderHeight = rec.fZPlaneParams.fZ;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001362 bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1363
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001364 if (SkColorGetA(rec.fAmbientColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001365 SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1366 const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1367 const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001368
1369 // Outset the shadow rrect to the border of the penumbra
1370 SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1371 SkRRect ambientRRect;
1372 SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1373 // If the rrect was an oval then its outset will also be one.
1374 // We set it explicitly to avoid errors.
1375 if (rrect.isOval()) {
1376 ambientRRect = SkRRect::MakeOval(outsetRect);
1377 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001378 SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001379 ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1380 }
1381
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001382 GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001383 if (transparent) {
1384 // set a large inset to force a fill
1385 devSpaceInsetWidth = ambientRRect.width();
1386 }
Jim Van Verth39e71652018-04-23 18:08:45 +00001387
Robert Phillips7c525e62018-06-12 10:11:12 -04001388 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1389 ambientColor,
1390 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001391 ambientRRect,
1392 devSpaceAmbientBlur,
Jim Van Verthfb186392018-09-11 11:37:46 -04001393 devSpaceInsetWidth);
Robert Phillipse5763782019-04-17 14:38:24 -04001394 if (op) {
1395 this->addDrawOp(clip, std::move(op));
1396 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001397 }
Jim Van Verth3af1af92017-05-18 15:06:54 -04001398
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001399 if (SkColorGetA(rec.fSpotColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001400 SkScalar devSpaceSpotBlur;
1401 SkScalar spotScale;
1402 SkVector spotOffset;
1403 SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1404 devLightPos.fZ, rec.fLightRadius,
1405 &devSpaceSpotBlur, &spotScale, &spotOffset);
1406 // handle scale of radius due to CTM
Jim Van Verth3af1af92017-05-18 15:06:54 -04001407 const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1408
Jim Van Verth3af1af92017-05-18 15:06:54 -04001409 // Adjust translate for the effect of the scale.
1410 spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1411 spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1412 // This offset is in dev space, need to transform it into source space.
1413 SkMatrix ctmInverse;
1414 if (viewMatrix.invert(&ctmInverse)) {
1415 ctmInverse.mapPoints(&spotOffset, 1);
1416 } else {
1417 // Since the matrix is a similarity, this should never happen, but just in case...
1418 SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1419 SkASSERT(false);
1420 }
1421
1422 // Compute the transformed shadow rrect
1423 SkRRect spotShadowRRect;
1424 SkMatrix shadowTransform;
1425 shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1426 rrect.transform(shadowTransform, &spotShadowRRect);
Mike Reed242135a2018-02-22 13:41:39 -05001427 SkScalar spotRadius = SkRRectPriv::GetSimpleRadii(spotShadowRRect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001428
1429 // Compute the insetWidth
Jim Van Verth1af03d42017-07-31 09:34:58 -04001430 SkScalar blurOutset = srcSpaceSpotBlur;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001431 SkScalar insetWidth = blurOutset;
1432 if (transparent) {
1433 // If transparent, just do a fill
1434 insetWidth += spotShadowRRect.width();
1435 } else {
1436 // For shadows, instead of using a stroke we specify an inset from the penumbra
1437 // border. We want to extend this inset area so that it meets up with the caster
1438 // geometry. The inset geometry will by default already be inset by the blur width.
1439 //
1440 // We compare the min and max corners inset by the radius between the original
1441 // rrect and the shadow rrect. The distance between the two plus the difference
1442 // between the scaled radius and the original radius gives the distance from the
1443 // transformed shadow shape to the original shape in that corner. The max
1444 // of these gives the maximum distance we need to cover.
1445 //
1446 // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1447 // that to get the full insetWidth.
1448 SkScalar maxOffset;
1449 if (rrect.isRect()) {
1450 // Manhattan distance works better for rects
1451 maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft -
1452 rrect.rect().fLeft),
1453 SkTAbs(spotShadowRRect.rect().fTop -
1454 rrect.rect().fTop)),
1455 SkTMax(SkTAbs(spotShadowRRect.rect().fRight -
1456 rrect.rect().fRight),
1457 SkTAbs(spotShadowRRect.rect().fBottom -
1458 rrect.rect().fBottom)));
1459 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001460 SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001461 SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1462 rrect.rect().fLeft + dr,
1463 spotShadowRRect.rect().fTop -
1464 rrect.rect().fTop + dr);
1465 SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1466 rrect.rect().fRight - dr,
1467 spotShadowRRect.rect().fBottom -
1468 rrect.rect().fBottom - dr);
Cary Clarkdf429f32017-11-08 11:44:31 -05001469 maxOffset = SkScalarSqrt(SkTMax(SkPointPriv::LengthSqd(upperLeftOffset),
1470 SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001471 }
Jim Van Verth4c8c1e82018-04-23 17:14:48 -04001472 insetWidth += SkTMax(blurOutset, maxOffset);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001473 }
1474
1475 // Outset the shadow rrect to the border of the penumbra
1476 SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1477 if (spotShadowRRect.isOval()) {
1478 spotShadowRRect = SkRRect::MakeOval(outsetRect);
1479 } else {
1480 SkScalar outsetRad = spotRadius + blurOutset;
1481 spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1482 }
1483
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001484 GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
Jim Van Verth34d6e4b2017-06-09 11:09:03 -04001485
Robert Phillips7c525e62018-06-12 10:11:12 -04001486 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1487 spotColor,
1488 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001489 spotShadowRRect,
Jim Van Verth1af03d42017-07-31 09:34:58 -04001490 2.0f * devSpaceSpotBlur,
Brian Salomon05969092017-07-13 11:20:51 -04001491 insetWidth);
Robert Phillipse5763782019-04-17 14:38:24 -04001492 if (op) {
1493 this->addDrawOp(clip, std::move(op));
1494 }
Jim Van Verth3af1af92017-05-18 15:06:54 -04001495 }
1496
1497 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -05001498}
1499
1500///////////////////////////////////////////////////////////////////////////////
1501
Brian Osman11052242016-10-27 14:47:55 -04001502bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001503 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001504 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001505 const SkMatrix& viewMatrix,
1506 const SkRRect& origOuter,
1507 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001508 SkASSERT(!origInner.isEmpty());
1509 SkASSERT(!origOuter.isEmpty());
1510
Brian Salomon65749212017-12-01 16:01:47 -05001511 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1512
Chris Dalton7d6748e2019-03-13 00:34:52 -06001513 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon45839f92017-12-04 09:02:35 -05001514
1515 if (GrAAType::kMSAA == aaType) {
1516 return false;
1517 }
1518
Greg Daniel2655ede2019-04-10 00:49:28 +00001519 if (GrAAType::kCoverage == aaType && SkRRectPriv::IsCircle(*inner)
1520 && SkRRectPriv::IsCircle(*outer)) {
Brian Salomon65749212017-12-01 16:01:47 -05001521 auto outerR = outer->width() / 2.f;
1522 auto innerR = inner->width() / 2.f;
1523 auto cx = outer->getBounds().fLeft + outerR;
1524 auto cy = outer->getBounds().fTop + outerR;
1525 if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
1526 SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
1527 auto avgR = (innerR + outerR) / 2.f;
1528 auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
1529 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
1530 stroke.setStrokeStyle(outerR - innerR);
Greg Daniel2655ede2019-04-10 00:49:28 +00001531 auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix,
Robert Phillips7c525e62018-06-12 10:11:12 -04001532 circleBounds, GrStyle(stroke, nullptr),
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001533 this->caps()->shaderCaps());
Brian Salomon65749212017-12-01 16:01:47 -05001534 if (op) {
1535 this->addDrawOp(clip, std::move(op));
1536 return true;
1537 }
Mike Klein16885072018-12-11 09:54:31 -05001538 assert_alive(paint);
Brian Salomon65749212017-12-01 16:01:47 -05001539 }
1540 }
1541
Ethan Nicholas0f3c7322017-11-09 14:51:17 -05001542 GrClipEdgeType innerEdgeType, outerEdgeType;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001543 if (GrAAType::kCoverage == aaType) {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001544 innerEdgeType = GrClipEdgeType::kInverseFillAA;
1545 outerEdgeType = GrClipEdgeType::kFillAA;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001546 } else {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001547 innerEdgeType = GrClipEdgeType::kInverseFillBW;
1548 outerEdgeType = GrClipEdgeType::kFillBW;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001549 }
robertphillips00095892016-02-29 13:50:40 -08001550
robertphillips00095892016-02-29 13:50:40 -08001551 SkMatrix inverseVM;
1552 if (!viewMatrix.isIdentity()) {
1553 if (!origInner.transform(viewMatrix, inner.writable())) {
1554 return false;
1555 }
1556 if (!origOuter.transform(viewMatrix, outer.writable())) {
1557 return false;
1558 }
1559 if (!viewMatrix.invert(&inverseVM)) {
1560 return false;
1561 }
1562 } else {
1563 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001564 }
robertphillips00095892016-02-29 13:50:40 -08001565
Ethan Nicholaseace9352018-10-15 20:09:54 +00001566 const auto& caps = *this->caps()->shaderCaps();
robertphillips00095892016-02-29 13:50:40 -08001567 // TODO these need to be a geometry processors
Ethan Nicholaseace9352018-10-15 20:09:54 +00001568 auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
robertphillips00095892016-02-29 13:50:40 -08001569 if (!innerEffect) {
1570 return false;
1571 }
1572
Ethan Nicholaseace9352018-10-15 20:09:54 +00001573 auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
robertphillips00095892016-02-29 13:50:40 -08001574 if (!outerEffect) {
1575 return false;
1576 }
1577
Brian Salomon82f44312017-01-11 13:42:54 -05001578 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1579 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001580
1581 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001582 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001583 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1584 }
halcanary9d524f22016-03-29 09:03:52 -07001585
Brian Salomon82f44312017-01-11 13:42:54 -05001586 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1587 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001588 return true;
1589}
1590
Brian Osman11052242016-10-27 14:47:55 -04001591void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001592 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001593 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001594 const SkMatrix& viewMatrix,
1595 const SkRRect& outer,
1596 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001597 ASSERT_SINGLE_OWNER
1598 RETURN_IF_ABANDONED
1599 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001600 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
robertphillips00095892016-02-29 13:50:40 -08001601
1602 SkASSERT(!outer.isEmpty());
1603 SkASSERT(!inner.isEmpty());
1604
Robert Phillips72152832017-01-25 17:31:35 -05001605 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001606
Brian Salomon82f44312017-01-11 13:42:54 -05001607 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001608 return;
1609 }
Mike Klein16885072018-12-11 09:54:31 -05001610 assert_alive(paint);
robertphillips00095892016-02-29 13:50:40 -08001611
1612 SkPath path;
1613 path.setIsVolatile(true);
1614 path.addRRect(inner);
1615 path.addRRect(outer);
1616 path.setFillType(SkPath::kEvenOdd_FillType);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001617 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path));
robertphillips00095892016-02-29 13:50:40 -08001618}
1619
robertphillipsea461502015-05-26 11:38:03 -07001620///////////////////////////////////////////////////////////////////////////////
1621
Brian Osman11052242016-10-27 14:47:55 -04001622void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001623 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001624 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001625 const SkMatrix& viewMatrix,
1626 const SkRegion& region,
Stan Iliev73d8fd92017-08-02 15:36:24 -04001627 const GrStyle& style,
1628 const GrUserStencilSettings* ss) {
msarettcc319b92016-08-25 18:07:18 -07001629 ASSERT_SINGLE_OWNER
1630 RETURN_IF_ABANDONED
1631 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001632 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
msarettcc319b92016-08-25 18:07:18 -07001633
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001634 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001635 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001636 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001637 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
Brian Salomon34169692017-08-28 15:32:01 -04001638 SkScalarIsInt(viewMatrix.getTranslateX()) &&
1639 SkScalarIsInt(viewMatrix.getTranslateY())) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001640 aa = GrAA::kNo;
1641 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001642 }
msarettcc319b92016-08-25 18:07:18 -07001643 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001644 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001645 SkPath path;
1646 region.getBoundaryPath(&path);
Robert Phillips46a13382018-08-23 13:53:01 -04001647 path.setIsVolatile(true);
1648
Brian Salomon82f44312017-01-11 13:42:54 -05001649 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001650 }
1651
Chris Dalton7d6748e2019-03-13 00:34:52 -06001652 GrAAType aaType = this->chooseAAType(GrAA::kNo);
Robert Phillips7c525e62018-06-12 10:11:12 -04001653 std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
1654 aaType, ss);
Brian Salomonf0366322017-07-11 15:53:05 -04001655 this->addDrawOp(clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001656}
1657
Brian Osman11052242016-10-27 14:47:55 -04001658void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001659 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001660 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001661 const SkMatrix& viewMatrix,
1662 const SkRect& oval,
1663 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001664 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001665 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001666 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001667 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -07001668
Robert Phillips7484d202018-07-03 09:09:08 -04001669 const SkStrokeRec& stroke = style.strokeRec();
1670
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001671 if (oval.isEmpty() && !style.pathEffect()) {
Robert Phillips7484d202018-07-03 09:09:08 -04001672 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
1673 return;
1674 }
1675
1676 this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001677 return;
robertphillipsea461502015-05-26 11:38:03 -07001678 }
1679
Robert Phillips72152832017-01-25 17:31:35 -05001680 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001681
Chris Dalton7d6748e2019-03-13 00:34:52 -06001682 GrAAType aaType = this->chooseAAType(aa);
Chris Dalton0dffbab2019-03-27 13:08:50 -06001683
1684 std::unique_ptr<GrDrawOp> op;
1685 if (style.isSimpleFill()) {
Chris Dalton82eb9e72019-03-21 14:26:39 -06001686 // GrFillRRectOp has special geometry and a fragment-shader branch to conditionally evaluate
1687 // the arc equation. This same special geometry and fragment branch also turn out to be a
1688 // substantial optimization for drawing ovals (namely, by not evaluating the arc equation
1689 // inside the oval's inner diamond). Given these optimizations, it's a clear win to draw
1690 // ovals the exact same way we do round rects.
Chris Daltonebc38c92018-11-28 16:58:09 -07001691 //
Greg Daniel2655ede2019-04-10 00:49:28 +00001692 // However, we still don't draw true circles as round rects in coverage mode, because it can
1693 // cause perf regressions on some platforms as compared to the dedicated circle Op.
1694 if (GrAAType::kCoverage != aaType || oval.height() != oval.width()) {
Chris Daltonbf341ae2019-03-27 00:28:22 +00001695 assert_alive(paint);
Chris Dalton0dffbab2019-03-27 13:08:50 -06001696 op = GrFillRRectOp::Make(fContext, aaType, viewMatrix, SkRRect::MakeOval(oval),
1697 *this->caps(), std::move(paint));
Chris Daltonbf341ae2019-03-27 00:28:22 +00001698 }
Chris Dalton0dffbab2019-03-27 13:08:50 -06001699 }
Greg Daniel2655ede2019-04-10 00:49:28 +00001700 if (!op && GrAAType::kCoverage == aaType) {
Chris Dalton0dffbab2019-03-27 13:08:50 -06001701 assert_alive(paint);
Greg Daniel2655ede2019-04-10 00:49:28 +00001702 op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
1703 this->caps()->shaderCaps());
Chris Dalton0dffbab2019-03-27 13:08:50 -06001704 }
1705 if (op) {
1706 this->addDrawOp(clip, std::move(op));
1707 return;
robertphillipsea461502015-05-26 11:38:03 -07001708 }
robertphillipsb56f9272016-02-25 11:03:52 -08001709
Mike Klein16885072018-12-11 09:54:31 -05001710 assert_alive(paint);
Brian Salomon5209d7f2018-04-20 16:52:42 -04001711 this->drawShapeUsingPathRenderer(
1712 clip, std::move(paint), aa, viewMatrix,
1713 GrShape(SkRRect::MakeOval(oval), SkPath::kCW_Direction, 2, false, style));
robertphillipsea461502015-05-26 11:38:03 -07001714}
1715
Brian Osman11052242016-10-27 14:47:55 -04001716void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001717 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001718 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001719 const SkMatrix& viewMatrix,
1720 const SkRect& oval,
1721 SkScalar startAngle,
1722 SkScalar sweepAngle,
1723 bool useCenter,
1724 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001725 ASSERT_SINGLE_OWNER
1726 RETURN_IF_ABANDONED
1727 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001728 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001729
1730 AutoCheckFlush acf(this->drawingManager());
1731
Chris Dalton7d6748e2019-03-13 00:34:52 -06001732 GrAAType aaType = this->chooseAAType(aa);
Greg Daniel2655ede2019-04-10 00:49:28 +00001733 if (GrAAType::kCoverage == aaType) {
1734 const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
1735 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
1736 std::move(paint),
1737 viewMatrix,
1738 oval,
1739 startAngle,
1740 sweepAngle,
1741 useCenter,
1742 style,
1743 shaderCaps);
1744 if (op) {
1745 this->addDrawOp(clip, std::move(op));
1746 return;
1747 }
1748 assert_alive(paint);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001749 }
Brian Salomone4949402018-04-26 15:22:04 -04001750 this->drawShapeUsingPathRenderer(
1751 clip, std::move(paint), aa, viewMatrix,
1752 GrShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001753}
1754
Brian Osman11052242016-10-27 14:47:55 -04001755void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001756 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001757 const SkMatrix& viewMatrix,
Brian Salomon2a943df2018-05-04 13:43:19 -04001758 sk_sp<GrTextureProxy> image,
1759 sk_sp<GrColorSpaceXform> csxf,
1760 GrSamplerState::Filter filter,
Brian Osman11052242016-10-27 14:47:55 -04001761 std::unique_ptr<SkLatticeIter> iter,
1762 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001763 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001764 RETURN_IF_ABANDONED
1765 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001766 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
joshualitt33a5fce2015-11-18 13:28:51 -08001767
Robert Phillips72152832017-01-25 17:31:35 -05001768 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001769
Brian Salomon2a943df2018-05-04 13:43:19 -04001770 std::unique_ptr<GrDrawOp> op =
Robert Phillips7c525e62018-06-12 10:11:12 -04001771 GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(image),
1772 std::move(csxf), filter, std::move(iter), dst);
Brian Salomon815486c2017-07-11 08:52:13 -04001773 this->addDrawOp(clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001774}
1775
Greg Daniel64cc9aa2018-10-19 13:54:56 -04001776void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
1777 const SkRect& bounds) {
1778 std::unique_ptr<GrOp> op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
1779 SkASSERT(op);
1780 this->getRTOpList()->addOp(std::move(op), *this->caps());
1781}
1782
Brian Salomonab32f652019-05-10 14:24:50 -04001783bool GrRenderTargetContext::asyncReadPixels(SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
1784 const SkIRect& srcRect, ReadPixelsCallback callback,
1785 ReadPixelsContext context) {
1786 auto direct = fContext->priv().asDirectContext();
1787 if (!direct) {
1788 return false;
1789 }
1790 if (!this->caps()->transferBufferSupport()) {
1791 return false;
1792 }
1793 if (fRenderTargetProxy->wrapsVkSecondaryCB()) {
1794 return false;
1795 }
1796 // We currently don't know our own alpha type, we assume it's premul if we have an alpha channel
1797 // and opaque otherwise.
1798 if (!GrPixelConfigIsAlphaOnly(fRenderTargetProxy->config()) && at != kPremul_SkAlphaType) {
1799 return false;
1800 }
Brian Salomonab32f652019-05-10 14:24:50 -04001801 auto dstCT = SkColorTypeToGrColorType(ct);
1802 auto readCT = this->caps()->supportedReadPixelsColorType(fRenderTargetProxy->config(), dstCT);
Brian Salomoncd734f62019-05-10 16:32:54 -04001803 // Fail if we can't do a CPU conversion from readCT to dstCT.
1804 if (GrColorTypeToSkColorType(readCT) == kUnknown_SkColorType) {
Brian Salomonab32f652019-05-10 14:24:50 -04001805 return false;
1806 }
Brian Salomoncd734f62019-05-10 16:32:54 -04001807 // Fail if readCT does not have all of readCT's color channels.
1808 if (GrColorTypeComponentFlags(dstCT) & ~GrColorTypeComponentFlags(readCT)) {
1809 return false;
1810 }
1811 // Fail if readCT is not supported for transfer buffers.
Brian Salomonab32f652019-05-10 14:24:50 -04001812 if (!this->caps()->transferFromOffsetAlignment(readCT)) {
1813 return false;
1814 }
1815
Brian Salomoncd734f62019-05-10 16:32:54 -04001816 sk_sp<GrColorSpaceXform> xform = GrColorSpaceXform::Make(this->colorSpaceInfo().colorSpace(),
1817 kPremul_SkAlphaType, cs.get(), at);
Brian Salomonab32f652019-05-10 14:24:50 -04001818
Brian Salomoncd734f62019-05-10 16:32:54 -04001819 // Insert a draw to a temporary surface if we need to do a y-flip or color space conversion.
1820 if (this->origin() == kBottomLeft_GrSurfaceOrigin || xform) {
Brian Salomonab32f652019-05-10 14:24:50 -04001821 sk_sp<GrTextureProxy> texProxy = sk_ref_sp(fRenderTargetProxy->asTextureProxy());
1822 const auto& backendFormat = fRenderTargetProxy->backendFormat();
1823 SkRect srcRectToDraw = SkRect::Make(srcRect);
1824 // If the src is not texturable first try to make a copy to a texture.
1825 if (!texProxy) {
1826 GrSurfaceDesc desc;
1827 desc.fWidth = srcRect.width();
1828 desc.fHeight = srcRect.height();
1829 desc.fConfig = fRenderTargetProxy->config();
1830 auto sContext = direct->priv().makeDeferredSurfaceContext(
1831 backendFormat, desc, this->origin(), GrMipMapped::kNo, SkBackingFit::kApprox,
1832 SkBudgeted::kNo, this->colorSpaceInfo().refColorSpace());
1833 if (!sContext) {
1834 return false;
1835 }
1836 if (!sContext->copy(fRenderTargetProxy.get(), srcRect, {0, 0})) {
1837 return false;
1838 }
1839 texProxy = sk_ref_sp(sContext->asTextureProxy());
1840 SkASSERT(texProxy);
1841 srcRectToDraw = SkRect::MakeWH(srcRect.width(), srcRect.height());
1842 }
1843 auto rtc = direct->priv().makeDeferredRenderTargetContext(
1844 backendFormat, SkBackingFit::kApprox, srcRect.width(), srcRect.height(),
1845 fRenderTargetProxy->config(), cs, 1, GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin);
1846 if (!rtc) {
1847 return false;
1848 }
1849 rtc->drawTexture(GrNoClip(), std::move(texProxy), GrSamplerState::Filter::kNearest,
1850 SkBlendMode::kSrc, SK_PMColor4fWHITE, srcRectToDraw,
1851 SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
1852 GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(),
Brian Salomoncd734f62019-05-10 16:32:54 -04001853 std::move(xform));
Brian Salomonab32f652019-05-10 14:24:50 -04001854 return rtc->asyncReadPixels(ct, at, std::move(cs),
1855 SkIRect::MakeWH(srcRect.width(), srcRect.height()), callback,
1856 context);
1857 }
Brian Salomoncd734f62019-05-10 16:32:54 -04001858
1859 size_t rowBytes = GrColorTypeBytesPerPixel(readCT) * srcRect.width();
Brian Salomonab32f652019-05-10 14:24:50 -04001860 size_t size = rowBytes * srcRect.height();
1861 auto buffer = direct->priv().resourceProvider()->createBuffer(
1862 size, GrGpuBufferType::kXferGpuToCpu, GrAccessPattern::kStream_GrAccessPattern);
1863 if (!buffer) {
1864 return false;
1865 }
Brian Salomoncd734f62019-05-10 16:32:54 -04001866 this->getRTOpList()->addOp(GrTransferFromOp::Make(fContext, srcRect, readCT, buffer, 0),
Brian Salomonab32f652019-05-10 14:24:50 -04001867 *this->caps());
1868 struct FinishContext {
Brian Salomoncd734f62019-05-10 16:32:54 -04001869 SkImageInfo fReadInfo;
1870 SkImageInfo fDstInfo;
Brian Salomonab32f652019-05-10 14:24:50 -04001871 ReadPixelsCallback* fClientCallback;
1872 ReadPixelsContext fClientContext;
1873 sk_sp<GrGpuBuffer> fBuffer;
1874 size_t fRowBytes;
1875 };
1876 // Assumption is that the caller would like to flush. We could take a parameter or require an
1877 // explicit flush from the caller. We'd have to have a way to defer attaching the finish
1878 // callback to GrGpu until after the next flush that flushes our op list, though.
Brian Salomoncd734f62019-05-10 16:32:54 -04001879 auto* finishContext =
1880 new FinishContext{SkImageInfo::Make(srcRect.width(), srcRect.height(),
1881 GrColorTypeToSkColorType(readCT), at, cs),
1882 SkImageInfo::Make(srcRect.width(), srcRect.height(), ct, at, cs),
1883 callback,
1884 context,
1885 buffer,
1886 rowBytes};
Brian Salomonab32f652019-05-10 14:24:50 -04001887 auto finishCallback = [](GrGpuFinishedContext c) {
1888 auto context = reinterpret_cast<const FinishContext*>(c);
1889 void* data = context->fBuffer->map();
Brian Salomoncd734f62019-05-10 16:32:54 -04001890 if (!data) {
1891 (*context->fClientCallback)(context->fClientContext, nullptr, 0);
1892 delete context;
1893 return;
1894 }
1895 SkAutoPixmapStorage pm;
1896 const void* callbackData = data;
1897 size_t callbackRowBytes = context->fRowBytes;
1898 if (context->fDstInfo != context->fReadInfo) {
1899 pm.alloc(context->fDstInfo);
1900 SkConvertPixels(context->fDstInfo, pm.writable_addr(), pm.rowBytes(),
1901 context->fReadInfo, data, context->fRowBytes);
1902 callbackData = pm.addr();
1903 callbackRowBytes = pm.rowBytes();
1904 }
1905 (*context->fClientCallback)(context->fClientContext, callbackData, callbackRowBytes);
Brian Salomonab32f652019-05-10 14:24:50 -04001906 if (data) {
1907 context->fBuffer->unmap();
1908 }
1909 delete context;
1910 };
1911 GrFlushInfo flushInfo;
1912 flushInfo.fFinishedContext = finishContext;
1913 flushInfo.fFinishedProc = finishCallback;
1914 this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
1915 return true;
1916}
1917
Greg Daniele6bfb7d2019-04-17 15:26:11 -04001918GrSemaphoresSubmitted GrRenderTargetContext::flush(SkSurface::BackendSurfaceAccess access,
1919 const GrFlushInfo& info) {
robertphillips8c523e02016-07-26 07:41:00 -07001920 ASSERT_SINGLE_OWNER
Robert Phillips6a6de562019-02-15 15:19:15 -05001921 if (fContext->priv().abandoned()) {
Robert Phillipsa9162df2019-02-11 14:12:03 -05001922 return GrSemaphoresSubmitted::kNo;
1923 }
robertphillips8c523e02016-07-26 07:41:00 -07001924 SkDEBUGCODE(this->validate();)
Robert Phillips15c91422019-05-07 16:54:48 -04001925 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "flush", fContext);
robertphillips8c523e02016-07-26 07:41:00 -07001926
Greg Daniele6bfb7d2019-04-17 15:26:11 -04001927 return this->drawingManager()->flushSurface(fRenderTargetProxy.get(), access, info);
Greg Daniela5cb7812017-06-16 09:45:32 -04001928}
1929
Greg Danielc64ee462017-06-15 16:59:49 -04001930bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001931 const GrBackendSemaphore waitSemaphores[]) {
Greg Daniela5cb7812017-06-16 09:45:32 -04001932 ASSERT_SINGLE_OWNER
Greg Danielc64ee462017-06-15 16:59:49 -04001933 RETURN_FALSE_IF_ABANDONED
Greg Daniela5cb7812017-06-16 09:45:32 -04001934 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001935 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
Greg Daniela5cb7812017-06-16 09:45:32 -04001936
1937 AutoCheckFlush acf(this->drawingManager());
1938
Brian Salomon9ff5acb2019-05-08 09:04:47 -04001939 if (numSemaphores && !this->caps()->semaphoreSupport()) {
Greg Danielc64ee462017-06-15 16:59:49 -04001940 return false;
1941 }
1942
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001943 auto direct = fContext->priv().asDirectContext();
1944 if (!direct) {
1945 return false;
1946 }
1947
1948 auto resourceProvider = direct->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -05001949
Greg Daniela5cb7812017-06-16 09:45:32 -04001950 for (int i = 0; i < numSemaphores; ++i) {
Robert Phillips6be756b2018-01-16 15:07:54 -05001951 sk_sp<GrSemaphore> sema = resourceProvider->wrapBackendSemaphore(
Greg Daniel17b7c052018-01-09 13:55:33 -05001952 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
1953 kAdopt_GrWrapOwnership);
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001954 std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(fContext, std::move(sema),
Robert Phillips7c525e62018-06-12 10:11:12 -04001955 fRenderTargetProxy.get()));
Greg Danielcb324152019-02-25 11:36:53 -05001956 this->getRTOpList()->addWaitOp(std::move(waitOp), *this->caps());
Greg Daniela5cb7812017-06-16 09:45:32 -04001957 }
Greg Danielc64ee462017-06-15 16:59:49 -04001958 return true;
robertphillips8c523e02016-07-26 07:41:00 -07001959}
joshualitt33a5fce2015-11-18 13:28:51 -08001960
Robert Phillips65a88fa2017-08-08 08:36:22 -04001961void GrRenderTargetContext::insertEventMarker(const SkString& str) {
Robert Phillips88a32ef2018-06-07 11:05:56 -04001962 std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fContext, fRenderTargetProxy.get(), str));
Robert Phillips65a88fa2017-08-08 08:36:22 -04001963 this->getRTOpList()->addOp(std::move(op), *this->caps());
1964}
1965
Robert Phillipsbe9aff22019-02-15 11:33:22 -05001966const GrCaps* GrRenderTargetContext::caps() const {
1967 return fContext->priv().caps();
1968}
1969
Brian Osman11052242016-10-27 14:47:55 -04001970void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001971 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001972 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001973 const SkMatrix& viewMatrix,
Brian Salomon40b77a62017-12-22 11:25:52 -05001974 const SkPath& path,
Brian Osman11052242016-10-27 14:47:55 -04001975 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001976 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001977 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001978 SkDEBUGCODE(this->validate();)
Robert Phillips20390c32018-08-17 11:01:03 -04001979 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPath", fContext);
1980
Brian Salomon40b77a62017-12-22 11:25:52 -05001981 GrShape shape(path, style);
Robert Phillips20390c32018-08-17 11:01:03 -04001982
Robert Phillips27927a52018-08-20 13:18:12 -04001983 this->drawShape(clip, std::move(paint), aa, viewMatrix, shape);
Robert Phillips20390c32018-08-17 11:01:03 -04001984}
1985
1986void GrRenderTargetContext::drawShape(const GrClip& clip,
1987 GrPaint&& paint,
1988 GrAA aa,
1989 const SkMatrix& viewMatrix,
1990 const GrShape& shape) {
1991 ASSERT_SINGLE_OWNER
1992 RETURN_IF_ABANDONED
1993 SkDEBUGCODE(this->validate();)
1994 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawShape", fContext);
1995
Brian Salomon2fad74a2017-12-20 13:28:55 -05001996 if (shape.isEmpty()) {
1997 if (shape.inverseFilled()) {
1998 this->drawPaint(clip, std::move(paint), viewMatrix);
1999 }
2000 return;
robertphillipsea461502015-05-26 11:38:03 -07002001 }
2002
Robert Phillips72152832017-01-25 17:31:35 -05002003 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07002004
Brian Salomon2fad74a2017-12-20 13:28:55 -05002005 if (!shape.style().hasPathEffect()) {
Chris Dalton7d6748e2019-03-13 00:34:52 -06002006 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon2fad74a2017-12-20 13:28:55 -05002007 SkRRect rrect;
2008 // We can ignore the starting point and direction since there is no path effect.
2009 bool inverted;
2010 if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
2011 if (rrect.isRect()) {
2012 this->drawRect(clip, std::move(paint), aa, viewMatrix, rrect.rect(),
2013 &shape.style());
2014 return;
2015 } else if (rrect.isOval()) {
2016 this->drawOval(clip, std::move(paint), aa, viewMatrix, rrect.rect(), shape.style());
robertphillipsea461502015-05-26 11:38:03 -07002017 return;
2018 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05002019 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect, shape.style());
2020 return;
Robert Phillips73653b42018-08-22 12:42:42 -04002021 } else if (GrAAType::kCoverage == aaType && shape.style().isSimpleFill() &&
2022 viewMatrix.rectStaysRect()) {
2023 // TODO: the rectStaysRect restriction could be lifted if we were willing to apply
2024 // the matrix to all the points individually rather than just to the rect
2025 SkRect rects[2];
2026 if (shape.asNestedRects(rects)) {
2027 // Concave AA paths are expensive - try to avoid them for special cases
Michael Ludwig72ab3462018-12-10 12:43:36 -05002028 std::unique_ptr<GrDrawOp> op = GrStrokeRectOp::MakeNested(
Robert Phillips73653b42018-08-22 12:42:42 -04002029 fContext, std::move(paint), viewMatrix, rects);
2030 if (op) {
2031 this->addDrawOp(clip, std::move(op));
2032 }
2033 // Returning here indicates that there is nothing to draw in this case.
2034 return;
2035 }
robertphillipsea461502015-05-26 11:38:03 -07002036 }
2037 }
robertphillips4bc31812016-03-01 12:22:49 -08002038
Brian Salomon2fad74a2017-12-20 13:28:55 -05002039 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, shape);
robertphillipsea461502015-05-26 11:38:03 -07002040}
2041
Chris Daltonbbfd5162017-11-07 13:35:22 -07002042bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -04002043 const GrUserStencilSettings* ss,
2044 SkRegion::Op op,
2045 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05002046 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04002047 const SkMatrix& viewMatrix,
2048 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08002049 ASSERT_SINGLE_OWNER_PRIV
2050 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04002051 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04002052 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
2053 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -08002054
2055 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05002056 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04002057 SkRect::MakeIWH(fRenderTargetContext->width(),
2058 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08002059 return true;
2060 }
2061
Robert Phillips72152832017-01-25 17:31:35 -05002062 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08002063
2064 // An Assumption here is that path renderer would use some form of tweaking
2065 // the src color (either the input alpha or in the frag shader) to implement
2066 // aa. If we have some future driver-mojo path AA that can do the right
2067 // thing WRT to the blend then we'll need some query on the PR.
Chris Dalton09e56892019-03-13 00:22:01 -06002068 auto aaTypeFlags = choose_path_aa_type_flags(
2069 aa, fRenderTargetContext->fsaaType(), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -07002070 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08002071
Chris Daltondb91c6e2017-09-08 16:25:08 -06002072 SkIRect clipConservativeBounds;
2073 clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(),
2074 &clipConservativeBounds, nullptr);
2075
bsalomon8acedde2016-06-24 10:42:16 -07002076 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08002077 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04002078 canDrawArgs.fCaps = fRenderTargetContext->caps();
robertphillips391395d2016-03-02 09:26:36 -08002079 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07002080 canDrawArgs.fShape = &shape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06002081 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Chris Dalton09e56892019-03-13 00:22:01 -06002082 canDrawArgs.fAATypeFlags = aaTypeFlags;
Greg Danielbe7fc462019-01-03 16:40:42 -05002083 SkASSERT(!fRenderTargetContext->wrapsVkSecondaryCB());
2084 canDrawArgs.fTargetIsWrappedVkSecondaryCB = false;
cdalton93a379b2016-05-11 13:58:08 -07002085 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08002086
2087 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05002088 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05002089 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08002090 if (!pr) {
2091 return false;
2092 }
2093
2094 GrPaint paint;
2095 paint.setCoverageSetOpXPFactory(op, invert);
2096
Brian Salomonf3569f02017-10-24 12:52:33 -04002097 GrPathRenderer::DrawPathArgs args{fRenderTargetContext->drawingManager()->getContext(),
2098 std::move(paint),
2099 ss,
2100 fRenderTargetContext,
2101 &clip,
2102 &clipConservativeBounds,
2103 &viewMatrix,
2104 &shape,
Chris Dalton09e56892019-03-13 00:22:01 -06002105 aaTypeFlags,
Brian Osman34ec3742018-07-03 10:40:57 -04002106 fRenderTargetContext->colorSpaceInfo().isLinearlyBlended()};
robertphillips391395d2016-03-02 09:26:36 -08002107 pr->drawPath(args);
2108 return true;
2109}
2110
Brian Osman11052242016-10-27 14:47:55 -04002111SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07002112 ASSERT_SINGLE_OWNER_PRIV
2113
Robert Phillips6a6de562019-02-15 15:19:15 -05002114 if (fRenderTargetContext->fContext->priv().abandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07002115 return SkBudgeted::kNo;
2116 }
2117
Brian Osman11052242016-10-27 14:47:55 -04002118 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07002119
Robert Phillipsc7635fa2016-10-28 13:25:24 -04002120 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07002121}
2122
Brian Salomon2fad74a2017-12-20 13:28:55 -05002123void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
2124 GrPaint&& paint,
2125 GrAA aa,
2126 const SkMatrix& viewMatrix,
2127 const GrShape& originalShape) {
joshualitt1de610a2016-01-06 08:26:09 -08002128 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07002129 RETURN_IF_ABANDONED
Brian Salomondcbb9d92017-07-19 10:53:20 -04002130 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
2131
Jim Van Verthf86073a2018-10-02 13:05:38 -04002132 if (!viewMatrix.isFinite() || !originalShape.bounds().isFinite()) {
2133 return;
2134 }
2135
Chris Daltondb91c6e2017-09-08 16:25:08 -06002136 SkIRect clipConservativeBounds;
2137 clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr);
2138
Brian Salomon2fad74a2017-12-20 13:28:55 -05002139 GrShape tempShape;
Chris Dalton09e56892019-03-13 00:22:01 -06002140 auto aaTypeFlags = choose_path_aa_type_flags(aa, this->fsaaType(), *this->caps());
2141
robertphillips68737822015-10-29 12:12:21 -07002142 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04002143 canDrawArgs.fCaps = this->caps();
robertphillips68737822015-10-29 12:12:21 -07002144 canDrawArgs.fViewMatrix = &viewMatrix;
Brian Salomon2fad74a2017-12-20 13:28:55 -05002145 canDrawArgs.fShape = &originalShape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06002146 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Greg Danielbe7fc462019-01-03 16:40:42 -05002147 canDrawArgs.fTargetIsWrappedVkSecondaryCB = this->wrapsVkSecondaryCB();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05002148 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07002149
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05002150 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05002151 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon2fad74a2017-12-20 13:28:55 -05002152 if (originalShape.isEmpty() && !originalShape.inverseFilled()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05002153 return;
2154 }
2155
Chris Dalton09e56892019-03-13 00:22:01 -06002156 canDrawArgs.fAATypeFlags = aaTypeFlags;
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05002157
2158 // Try a 1st time without applying any of the style to the geometry (and barring sw)
2159 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
2160 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
2161
Brian Salomon2fad74a2017-12-20 13:28:55 -05002162 if (!pr && originalShape.style().pathEffect()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05002163 // It didn't work above, so try again with the path effect applied.
Brian Salomon2fad74a2017-12-20 13:28:55 -05002164 tempShape = originalShape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
2165 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07002166 return;
2167 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05002168 canDrawArgs.fShape = &tempShape;
Robert Phillips72152832017-01-25 17:31:35 -05002169 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05002170 }
2171 if (!pr) {
Brian Salomon2fad74a2017-12-20 13:28:55 -05002172 if (canDrawArgs.fShape->style().applies()) {
2173 tempShape = canDrawArgs.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
2174 styleScale);
2175 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07002176 return;
2177 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05002178 canDrawArgs.fShape = &tempShape;
Brian Salomone7df0bb2018-05-07 14:44:57 -04002179 // This time, allow SW renderer
2180 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
2181 } else {
2182 pr = this->drawingManager()->getSoftwarePathRenderer();
bsalomon6663acf2016-05-10 09:14:17 -07002183 }
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05002184 }
robertphillipsea461502015-05-26 11:38:03 -07002185
bsalomon8acedde2016-06-24 10:42:16 -07002186 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07002187#ifdef SK_DEBUG
2188 SkDebugf("Unable to find path renderer compatible with path.\n");
2189#endif
2190 return;
2191 }
2192
Robert Phillips256c37b2017-03-01 14:32:46 -05002193 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05002194 std::move(paint),
2195 &GrUserStencilSettings::kUnused,
2196 this,
2197 &clip,
Chris Daltondb91c6e2017-09-08 16:25:08 -06002198 &clipConservativeBounds,
Brian Salomon82f44312017-01-11 13:42:54 -05002199 &viewMatrix,
Brian Salomon2fad74a2017-12-20 13:28:55 -05002200 canDrawArgs.fShape,
Chris Dalton09e56892019-03-13 00:22:01 -06002201 aaTypeFlags,
Brian Osman34ec3742018-07-03 10:40:57 -04002202 this->colorSpaceInfo().isLinearlyBlended()};
bsalomon0aff2fa2015-07-31 06:48:27 -07002203 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07002204}
2205
Brian Salomon467921e2017-03-06 16:17:12 -05002206static void op_bounds(SkRect* bounds, const GrOp* op) {
2207 *bounds = op->bounds();
2208 if (op->hasZeroArea()) {
2209 if (op->hasAABloat()) {
2210 bounds->outset(0.5f, 0.5f);
2211 } else {
2212 // We don't know which way the particular GPU will snap lines or points at integer
2213 // coords. So we ensure that the bounds is large enough for either snap.
2214 SkRect before = *bounds;
2215 bounds->roundOut(bounds);
2216 if (bounds->fLeft == before.fLeft) {
2217 bounds->fLeft -= 1;
2218 }
2219 if (bounds->fTop == before.fTop) {
2220 bounds->fTop -= 1;
2221 }
2222 if (bounds->fRight == before.fRight) {
2223 bounds->fRight += 1;
2224 }
2225 if (bounds->fBottom == before.fBottom) {
2226 bounds->fBottom += 1;
2227 }
2228 }
2229 }
2230}
2231
Brian Salomon348a0372018-10-31 10:42:18 -04002232void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
2233 const std::function<WillAddOpFn>& willAddFn) {
joshualitt1de610a2016-01-06 08:26:09 -08002234 ASSERT_SINGLE_OWNER
Robert Phillips69893702019-02-22 11:16:30 -05002235 if (fContext->priv().abandoned()) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002236 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002237 return;
Robert Phillipsc0138922017-03-08 11:50:55 -05002238 }
robertphillips2e1e51f2015-10-15 08:01:48 -07002239 SkDEBUGCODE(this->validate();)
Ethan Nicholas029b22c2018-10-18 16:49:56 -04002240 SkDEBUGCODE(op->fAddDrawOpCalled = true;)
Brian Salomondcbb9d92017-07-19 10:53:20 -04002241 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -07002242
Brian Salomon467921e2017-03-06 16:17:12 -05002243 // Setup clip
2244 SkRect bounds;
2245 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04002246 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04002247 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
2248 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
2249 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
2250 &bounds)) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002251 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002252 return;
Brian Salomon54d212e2017-03-21 14:22:38 -04002253 }
2254
Michael Ludwig6e17f1d2019-05-15 14:00:20 +00002255 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
2256 appliedClip.hasStencilClip()) {
2257 if (this->caps()->performStencilClearsAsDraws()) {
2258 // Must use an op to perform the clear of the stencil buffer before this op, but only
2259 // have to clear the first time any draw needs it (this also ensures we don't loop
2260 // forever when the internal stencil clear adds a draw op that has stencil settings).
2261 if (!fRenderTargetProxy->needsStencil()) {
2262 // Send false so that the stencil buffer is fully cleared to 0
Michael Ludwigc39d0c82019-01-15 10:03:43 -05002263 this->internalStencilClear(GrFixedClip::Disabled(), /* inside mask */ false);
2264 }
Michael Ludwig6e17f1d2019-05-15 14:00:20 +00002265 } else {
2266 // Just make sure the stencil buffer is cleared before the draw op, easy to do it as
2267 // a load at the start
2268 this->getRTOpList()->setStencilLoadOp(GrLoadOp::kClear);
Michael Ludwigc39d0c82019-01-15 10:03:43 -05002269 }
Robert Phillips95214472017-08-08 18:00:03 -04002270
Robert Phillips65048132017-08-10 08:44:49 -04002271 this->setNeedsStencil();
Brian Salomon54d212e2017-03-21 14:22:38 -04002272 }
2273
Brian Osman5ced0bf2019-03-15 10:15:29 -04002274 GrClampType clampType = GrPixelConfigClampType(this->colorSpaceInfo().config());
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002275 GrXferProcessor::DstProxy dstProxy;
Brian Osman5ced0bf2019-03-15 10:15:29 -04002276 GrProcessorSet::Analysis analysis = op->finalize(
2277 *this->caps(), &appliedClip, this->fsaaType(), clampType);
Chris Dalton945ee652019-01-23 09:10:36 -07002278 if (analysis.requiresDstTexture()) {
Brian Salomon09181ef2018-11-14 13:39:51 -05002279 if (!this->setupDstProxy(this->asRenderTargetProxy(), clip, *op, &dstProxy)) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002280 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002281 return;
Brian Salomon54d212e2017-03-21 14:22:38 -04002282 }
2283 }
2284
2285 op->setClippedBounds(bounds);
Brian Salomon348a0372018-10-31 10:42:18 -04002286 auto opList = this->getRTOpList();
2287 if (willAddFn) {
2288 willAddFn(op.get(), opList->uniqueID());
2289 }
Chris Dalton945ee652019-01-23 09:10:36 -07002290 opList->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxy, *this->caps());
Brian Salomon54d212e2017-03-21 14:22:38 -04002291}
2292
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002293bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
Brian Salomon09181ef2018-11-14 13:39:51 -05002294 const GrOp& op,
Robert Phillips16d8ec62017-07-27 16:16:25 -04002295 GrXferProcessor::DstProxy* dstProxy) {
Greg Danielbe7fc462019-01-03 16:40:42 -05002296 // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
2297 // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
2298 // start and stop the render pass in order to make the copy.
2299 if (rtProxy->wrapsVkSecondaryCB()) {
2300 return false;
2301 }
2302
Brian Salomon467921e2017-03-06 16:17:12 -05002303 if (this->caps()->textureBarrierSupport()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04002304 if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
Brian Salomon467921e2017-03-06 16:17:12 -05002305 // The render target is a texture, so we can read from it directly in the shader. The XP
2306 // will be responsible to detect this situation and request a texture barrier.
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002307 dstProxy->setProxy(sk_ref_sp(texProxy));
2308 dstProxy->setOffset(0, 0);
Robert Phillipsbf25d432017-04-07 10:08:53 -04002309 return true;
Brian Salomon467921e2017-03-06 16:17:12 -05002310 }
2311 }
2312
Robert Phillipsbf25d432017-04-07 10:08:53 -04002313 SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
Brian Salomon467921e2017-03-06 16:17:12 -05002314
Eric Karl74480882017-04-03 14:49:05 -07002315 SkIRect clippedRect;
Robert Phillipsbf25d432017-04-07 10:08:53 -04002316 clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
Brian Salomon09181ef2018-11-14 13:39:51 -05002317 SkRect opBounds = op.bounds();
2318 // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by
2319 // 0.5 pixels.
2320 if (op.hasAABloat() || op.hasZeroArea()) {
2321 opBounds.outset(0.5f, 0.5f);
2322 // An antialiased/hairline draw can sometimes bleed outside of the clips bounds. For
2323 // performance we may ignore the clip when the draw is entirely inside the clip is float
2324 // space but will hit pixels just outside the clip when actually rasterizing.
2325 clippedRect.outset(1, 1);
2326 clippedRect.intersect(SkIRect::MakeWH(rtProxy->width(), rtProxy->height()));
2327 }
2328 SkIRect opIBounds;
2329 opBounds.roundOut(&opIBounds);
2330 if (!clippedRect.intersect(opIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05002331#ifdef SK_DEBUG
Robert Phillipsbf25d432017-04-07 10:08:53 -04002332 GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
Brian Salomon467921e2017-03-06 16:17:12 -05002333#endif
Robert Phillipsbf25d432017-04-07 10:08:53 -04002334 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05002335 }
2336
2337 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
2338 // have per-sample dst values by making the copy multisampled.
2339 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07002340 bool rectsMustMatch = false;
2341 bool disallowSubrect = false;
Brian Salomon2a4f9832018-03-03 22:43:43 -05002342 GrSurfaceOrigin origin;
2343 if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &origin, &rectsMustMatch,
2344 &disallowSubrect)) {
Brian Salomon467921e2017-03-06 16:17:12 -05002345 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillipsbf25d432017-04-07 10:08:53 -04002346 desc.fConfig = rtProxy->config();
Greg Daniel1efe3222018-04-04 14:02:51 -04002347 origin = rtProxy->origin();
Brian Salomon467921e2017-03-06 16:17:12 -05002348 }
2349
Eric Karl74480882017-04-03 14:49:05 -07002350 if (!disallowSubrect) {
2351 copyRect = clippedRect;
2352 }
Brian Salomon467921e2017-03-06 16:17:12 -05002353
Robert Phillipsbf25d432017-04-07 10:08:53 -04002354 SkIPoint dstPoint, dstOffset;
2355 SkBackingFit fit;
Eric Karl74480882017-04-03 14:49:05 -07002356 if (rectsMustMatch) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04002357 desc.fWidth = rtProxy->width();
2358 desc.fHeight = rtProxy->height();
Eric Karl74480882017-04-03 14:49:05 -07002359 dstPoint = {copyRect.fLeft, copyRect.fTop};
2360 dstOffset = {0, 0};
Robert Phillipsbf25d432017-04-07 10:08:53 -04002361 fit = SkBackingFit::kExact;
Eric Karl74480882017-04-03 14:49:05 -07002362 } else {
2363 desc.fWidth = copyRect.width();
2364 desc.fHeight = copyRect.height();
2365 dstPoint = {0, 0};
2366 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillipsbf25d432017-04-07 10:08:53 -04002367 fit = SkBackingFit::kApprox;
Eric Karl74480882017-04-03 14:49:05 -07002368 }
Brian Salomon467921e2017-03-06 16:17:12 -05002369
Greg Daniel4065d452018-11-16 15:43:41 -05002370 SkASSERT(rtProxy->backendFormat().textureType() == GrTextureType::k2D);
2371 const GrBackendFormat& format = rtProxy->backendFormat();
Robert Phillips9da87e02019-02-04 13:26:26 -05002372 sk_sp<GrSurfaceContext> sContext = fContext->priv().makeDeferredSurfaceContext(
Greg Daniel4065d452018-11-16 15:43:41 -05002373 format, desc, origin, GrMipMapped::kNo, fit, SkBudgeted::kYes,
Brian Salomonf802e752018-02-13 17:13:31 -05002374 sk_ref_sp(this->colorSpaceInfo().colorSpace()));
Robert Phillipsbf25d432017-04-07 10:08:53 -04002375 if (!sContext) {
2376 SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
2377 return false;
2378 }
2379
2380 if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
2381 SkDebugf("setupDstTexture: copy failed.\n");
2382 return false;
2383 }
2384
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002385 dstProxy->setProxy(sContext->asTextureProxyRef());
2386 dstProxy->setOffset(dstOffset);
Robert Phillipsbf25d432017-04-07 10:08:53 -04002387 return true;
robertphillips2334fb62015-06-17 05:43:33 -07002388}