blob: 05241d613da0a9e6e3aa4a357555bd5d027269ed [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
Brian Osman11052242016-10-27 14:47:55 -04008#include "GrRenderTargetContext.h"
Brian Salomon6d4b65e2017-05-03 17:06:09 -04009#include "../private/GrAuditTrail.h"
Jim Van Verth3af1af92017-05-18 15:06:54 -040010#include "../private/SkShadowFlags.h"
Brian Salomon467921e2017-03-06 16:17:12 -050011#include "GrAppliedClip.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040012#include "GrBackendSemaphore.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040013#include "GrBlurUtils.h"
Robert Phillips69893702019-02-22 11:16:30 -050014#include "GrCaps.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050015#include "GrColor.h"
Robert Phillipse78b7252017-04-06 07:59:41 -040016#include "GrContextPriv.h"
robertphillips77a2e522015-10-17 07:43:27 -070017#include "GrDrawingManager.h"
csmartdalton02fa32c2016-08-19 13:29:27 -070018#include "GrFixedClip.h"
robertphillips714712b2016-08-04 06:20:45 -070019#include "GrGpuResourcePriv.h"
Robert Phillipsb6e9d3c2019-02-11 14:29:34 -050020#include "GrMemoryPool.h"
Robert Phillips9d6c64f2017-09-14 10:56:45 -040021#include "GrOpList.h"
robertphillipsea461502015-05-26 11:38:03 -070022#include "GrPathRenderer.h"
Brian Salomon57caa662017-10-18 12:21:05 +000023#include "GrQuad.h"
Robert Phillips69893702019-02-22 11:16:30 -050024#include "GrRecordingContext.h"
25#include "GrRecordingContextPriv.h"
robertphillips2334fb62015-06-17 05:43:33 -070026#include "GrRenderTarget.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050027#include "GrRenderTargetContextPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070028#include "GrResourceProvider.h"
Brian Salomon653f42f2018-07-10 10:07:31 -040029#include "GrShape.h"
Brian Salomon467921e2017-03-06 16:17:12 -050030#include "GrStencilAttachment.h"
Brian Salomon653f42f2018-07-10 10:07:31 -040031#include "GrStyle.h"
Brian Salomondcbb9d92017-07-19 10:53:20 -040032#include "GrTracing.h"
Greg Daniel64cc9aa2018-10-19 13:54:56 -040033#include "SkDrawable.h"
Jim Van Verth1af03d42017-07-31 09:34:58 -040034#include "SkDrawShadowInfo.h"
Herb Derby8378dfb2018-08-30 14:50:04 -040035#include "SkGlyphRunPainter.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040036#include "SkGr.h"
Brian Salomon467921e2017-03-06 16:17:12 -050037#include "SkLatticeIter.h"
38#include "SkMatrixPriv.h"
Mike Reed242135a2018-02-22 13:41:39 -050039#include "SkRRectPriv.h"
Jim Van Verth34d6e4b2017-06-09 11:09:03 -040040#include "SkShadowUtils.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070041#include "SkSurfacePriv.h"
Brian Salomon467921e2017-03-06 16:17:12 -050042#include "effects/GrRRectEffect.h"
Michael Ludwigd54ca8f2019-02-13 13:25:21 -050043#include "effects/GrTextureDomain.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040044#include "ops/GrAtlasTextOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050045#include "ops/GrClearOp.h"
Robert Phillipsb9a02a12017-04-06 11:08:40 -040046#include "ops/GrClearStencilClipOp.h"
Robert Phillips65a88fa2017-08-08 08:36:22 -040047#include "ops/GrDebugMarkerOp.h"
Greg Daniel64cc9aa2018-10-19 13:54:56 -040048#include "ops/GrDrawableOp.h"
Brian Osman4d92b892019-03-24 00:53:23 +000049#include "ops/GrDrawAtlasOp.h"
Brian Salomon6d4b65e2017-05-03 17:06:09 -040050#include "ops/GrDrawOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050051#include "ops/GrDrawVerticesOp.h"
Michael Ludwig69858532018-11-28 15:34:34 -050052#include "ops/GrFillRectOp.h"
Chris Dalton82eb9e72019-03-21 14:26:39 -060053#include "ops/GrFillRRectOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050054#include "ops/GrLatticeOp.h"
55#include "ops/GrOp.h"
56#include "ops/GrOvalOpFactory.h"
Brian Salomon89527432016-12-16 09:52:16 -050057#include "ops/GrRegionOp.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040058#include "ops/GrSemaphoreOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050059#include "ops/GrShadowRRectOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050060#include "ops/GrStencilPathOp.h"
Michael Ludwig72ab3462018-12-10 12:43:36 -050061#include "ops/GrStrokeRectOp.h"
Brian Salomon34169692017-08-28 15:32:01 -040062#include "ops/GrTextureOp.h"
Herb Derby26cbe512018-05-24 14:39:01 -040063#include "text/GrTextContext.h"
Herb Derbyc1b482c2018-08-09 15:02:27 -040064#include "text/GrTextTarget.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040065
Herb Derbyc1b482c2018-08-09 15:02:27 -040066class GrRenderTargetContext::TextTarget : public GrTextTarget {
Brian Salomonf18b1d82017-10-27 11:30:49 -040067public:
68 TextTarget(GrRenderTargetContext* renderTargetContext)
Herb Derbyc1b482c2018-08-09 15:02:27 -040069 : GrTextTarget(renderTargetContext->width(), renderTargetContext->height(),
Robert Phillips7e90be92019-02-15 12:22:59 -050070 renderTargetContext->colorSpaceInfo())
Herb Derby74c6ed32018-07-28 18:07:54 -040071 , fRenderTargetContext(renderTargetContext)
Herb Derby65956872018-08-21 16:55:04 -040072 , fGlyphPainter{*renderTargetContext}{}
Brian Salomonf18b1d82017-10-27 11:30:49 -040073
Robert Phillips7c525e62018-06-12 10:11:12 -040074 void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
Brian Salomonf18b1d82017-10-27 11:30:49 -040075 fRenderTargetContext->addDrawOp(clip, std::move(op));
76 }
77
Robert Phillips46a13382018-08-23 13:53:01 -040078 void drawShape(const GrClip& clip, const SkPaint& paint,
79 const SkMatrix& viewMatrix, const GrShape& shape) override {
Robert Phillips27927a52018-08-20 13:18:12 -040080 GrBlurUtils::drawShapeWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
81 clip, paint, viewMatrix, shape);
Brian Salomonf18b1d82017-10-27 11:30:49 -040082 }
83
84 void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
Robert Phillips7c525e62018-06-12 10:11:12 -040085 GrPaint* grPaint) override {
Robert Phillips69893702019-02-22 11:16:30 -050086 auto context = fRenderTargetContext->fContext;
Brian Salomonf18b1d82017-10-27 11:30:49 -040087 const GrColorSpaceInfo& colorSpaceInfo = fRenderTargetContext->colorSpaceInfo();
88 if (kARGB_GrMaskFormat == maskFormat) {
89 SkPaintToGrPaintWithPrimitiveColor(context, colorSpaceInfo, skPaint, grPaint);
90 } else {
91 SkPaintToGrPaint(context, colorSpaceInfo, skPaint, viewMatrix, grPaint);
92 }
93 }
94
Robert Phillips69893702019-02-22 11:16:30 -050095 GrRecordingContext* getContext() override {
Robert Phillips7c525e62018-06-12 10:11:12 -040096 return fRenderTargetContext->fContext;
97 }
98
Herb Derby65956872018-08-21 16:55:04 -040099 SkGlyphRunListPainter* glyphPainter() override {
100 return &fGlyphPainter;
Herb Derby74c6ed32018-07-28 18:07:54 -0400101 }
102
Brian Salomonf18b1d82017-10-27 11:30:49 -0400103private:
104 GrRenderTargetContext* fRenderTargetContext;
Herb Derby65956872018-08-21 16:55:04 -0400105 SkGlyphRunListPainter fGlyphPainter;
Herb Derby74c6ed32018-07-28 18:07:54 -0400106
Brian Salomonf18b1d82017-10-27 11:30:49 -0400107};
joshualittbc907352016-01-13 06:45:40 -0800108
Robert Phillips72152832017-01-25 17:31:35 -0500109#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -0800110#define ASSERT_SINGLE_OWNER \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -0400111 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
robertphillips391395d2016-03-02 09:26:36 -0800112#define ASSERT_SINGLE_OWNER_PRIV \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -0400113 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
Robert Phillips69893702019-02-22 11:16:30 -0500114#define RETURN_IF_ABANDONED if (fContext->priv().abandoned()) { return; }
115#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->priv().abandoned()) { return; }
116#define RETURN_FALSE_IF_ABANDONED if (fContext->priv().abandoned()) { return false; }
117#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->fContext->priv().abandoned()) { return false; }
118#define RETURN_NULL_IF_ABANDONED if (fContext->priv().abandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -0700119
Brian Salomone225b562017-06-14 13:00:03 -0400120//////////////////////////////////////////////////////////////////////////////
121
robertphillipsea461502015-05-26 11:38:03 -0700122class AutoCheckFlush {
123public:
halcanary9d524f22016-03-29 09:03:52 -0700124 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -0700125 SkASSERT(fDrawingManager);
126 }
bsalomonb77a9072016-09-07 10:02:04 -0700127 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -0700128
129private:
robertphillips77a2e522015-10-17 07:43:27 -0700130 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -0700131};
132
Robert Phillipsf2361d22016-10-25 14:20:06 -0400133// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -0400134// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -0400135// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -0400136// when the renderTargetContext attempts to use it (via getOpList).
Robert Phillips69893702019-02-22 11:16:30 -0500137GrRenderTargetContext::GrRenderTargetContext(GrRecordingContext* context,
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400138 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -0400139 sk_sp<SkColorSpace> colorSpace,
140 const SkSurfaceProps* surfaceProps,
Robert Phillips941d1442017-06-14 16:37:02 -0400141 bool managedOpList)
Robert Phillips0d075de2019-03-04 11:08:13 -0500142 : GrSurfaceContext(context, rtp->config(), std::move(colorSpace))
Brian Salomonf3569f02017-10-24 12:52:33 -0400143 , fRenderTargetProxy(std::move(rtp))
144 , fOpList(sk_ref_sp(fRenderTargetProxy->getLastRenderTargetOpList()))
Brian Salomonf3569f02017-10-24 12:52:33 -0400145 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
146 , fManagedOpList(managedOpList) {
Robert Phillips7e90be92019-02-15 12:22:59 -0500147 if (!context->priv().explicitlyAllocateGPUResources()) {
Robert Phillips4150eea2018-02-07 17:08:21 -0500148 // MDB TODO: to ensure all resources still get allocated in the correct order in the hybrid
149 // world we need to get the correct opList here so that it, in turn, can grab and hold
150 // its rendertarget.
151 this->getRTOpList();
152 }
153
Brian Salomonf18b1d82017-10-27 11:30:49 -0400154 fTextTarget.reset(new TextTarget(this));
robertphillips2e1e51f2015-10-15 08:01:48 -0700155 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700156}
157
robertphillips2e1e51f2015-10-15 08:01:48 -0700158#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -0400159void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400160 SkASSERT(fRenderTargetProxy);
161 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -0700162
Robert Phillipsf2361d22016-10-25 14:20:06 -0400163 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsdc83b892017-04-13 12:23:54 -0400164 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList.get());
robertphillipsa106c622015-10-16 09:07:06 -0700165 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700166}
167#endif
168
Brian Osman11052242016-10-27 14:47:55 -0400169GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800170 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700171}
172
Chris Dalton7d6748e2019-03-13 00:34:52 -0600173inline GrAAType GrRenderTargetContext::chooseAAType(GrAA aa) {
174 auto fsaaType = this->fsaaType();
175 if (GrAA::kNo == aa) {
176 // On some devices we cannot disable MSAA if it is enabled so we make the AA type reflect
177 // that.
178 if (fsaaType == GrFSAAType::kUnifiedMSAA && !this->caps()->multisampleDisableSupport()) {
179 return GrAAType::kMSAA;
180 }
181 return GrAAType::kNone;
182 }
183 switch (fsaaType) {
184 case GrFSAAType::kNone:
185 case GrFSAAType::kMixedSamples:
186 return GrAAType::kCoverage;
187 case GrFSAAType::kUnifiedMSAA:
188 return GrAAType::kMSAA;
189 }
190 SK_ABORT("Unexpected fsaa type");
191 return GrAAType::kNone;
192}
193
194static inline GrPathRenderer::AATypeFlags choose_path_aa_type_flags(
195 GrAA aa, GrFSAAType fsaaType, const GrCaps& caps) {
196 using AATypeFlags = GrPathRenderer::AATypeFlags;
197 if (GrAA::kNo == aa) {
198 // On some devices we cannot disable MSAA if it is enabled so we make the AA type flags
199 // reflect that.
200 if (fsaaType == GrFSAAType::kUnifiedMSAA && !caps.multisampleDisableSupport()) {
201 return AATypeFlags::kMSAA;
202 }
203 return AATypeFlags::kNone;
204 }
205 switch (fsaaType) {
206 case GrFSAAType::kNone:
207 return AATypeFlags::kCoverage;
208 case GrFSAAType::kMixedSamples:
209 return AATypeFlags::kCoverage | AATypeFlags::kMixedSampledStencilThenCover;
210 case GrFSAAType::kUnifiedMSAA:
211 return AATypeFlags::kMSAA;
212 }
213 SK_ABORT("Invalid GrFSAAType.");
214 return AATypeFlags::kNone;
215}
216
Robert Phillipsf200a902017-01-30 13:27:37 -0500217GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000218 return fRenderTargetProxy->asTextureProxy();
219}
220
Greg Daniele252f082017-10-23 16:05:23 -0400221const GrTextureProxy* GrRenderTargetContext::asTextureProxy() const {
222 return fRenderTargetProxy->asTextureProxy();
223}
224
Robert Phillipsf200a902017-01-30 13:27:37 -0500225sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
226 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
227}
228
Greg Daniele252f082017-10-23 16:05:23 -0400229GrMipMapped GrRenderTargetContext::mipMapped() const {
230 if (const GrTextureProxy* proxy = this->asTextureProxy()) {
231 return proxy->mipMapped();
232 }
233 return GrMipMapped::kNo;
234}
235
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400236GrRenderTargetOpList* GrRenderTargetContext::getRTOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800237 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700238 SkDEBUGCODE(this->validate();)
239
Robert Phillipsf2361d22016-10-25 14:20:06 -0400240 if (!fOpList || fOpList->isClosed()) {
Robert Phillips941d1442017-06-14 16:37:02 -0400241 fOpList = this->drawingManager()->newRTOpList(fRenderTargetProxy.get(), fManagedOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700242 }
243
Robert Phillipsdc83b892017-04-13 12:23:54 -0400244 return fOpList.get();
robertphillipsa106c622015-10-16 09:07:06 -0700245}
246
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400247GrOpList* GrRenderTargetContext::getOpList() {
248 return this->getRTOpList();
robertphillipsea461502015-05-26 11:38:03 -0700249}
250
Herb Derbycddab252018-07-16 11:19:04 -0400251void GrRenderTargetContext::drawGlyphRunList(
252 const GrClip& clip, const SkMatrix& viewMatrix,
Robert Phillipse4643cc2018-08-14 13:01:29 -0400253 const SkGlyphRunList& blob) {
joshualitt1de610a2016-01-06 08:26:09 -0800254 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700255 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700256 SkDEBUGCODE(this->validate();)
Herb Derbycddab252018-07-16 11:19:04 -0400257 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -0700258
Greg Danielbe7fc462019-01-03 16:40:42 -0500259 // Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan
260 // secondary command buffers because it would require stopping and starting a render pass which
261 // we don't have access to.
262 if (this->wrapsVkSecondaryCB()) {
263 return;
264 }
265
Herb Derby26cbe512018-05-24 14:39:01 -0400266 GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
Herb Derbycddab252018-07-16 11:19:04 -0400267 atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
Robert Phillipse4643cc2018-08-14 13:01:29 -0400268 fSurfaceProps, blob);
robertphillipsea461502015-05-26 11:38:03 -0700269}
270
Brian Osman11052242016-10-27 14:47:55 -0400271void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800272 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700273 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700274 SkDEBUGCODE(this->validate();)
Robert Phillips6b47c7d2017-08-29 07:24:09 -0400275 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700276
Robert Phillips72152832017-01-25 17:31:35 -0500277 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400278
Robert Phillips380b90c2017-08-30 07:41:07 -0400279 this->getRTOpList()->discard();
robertphillipsea461502015-05-26 11:38:03 -0700280}
281
Brian Osman11052242016-10-27 14:47:55 -0400282void GrRenderTargetContext::clear(const SkIRect* rect,
Brian Osman9a9baae2018-11-05 15:06:26 -0500283 const SkPMColor4f& color,
Chris Dalton344e9032017-12-11 15:42:09 -0700284 CanClearFullscreen canClearFullscreen) {
joshualitt1de610a2016-01-06 08:26:09 -0800285 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700286 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700287 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400288 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
robertphillipsea461502015-05-26 11:38:03 -0700289
Robert Phillips72152832017-01-25 17:31:35 -0500290 AutoCheckFlush acf(this->drawingManager());
Chris Dalton344e9032017-12-11 15:42:09 -0700291 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color,
292 canClearFullscreen);
csmartdalton29df7602016-08-31 11:55:52 -0700293}
robertphillips9199a9f2016-07-13 07:48:43 -0700294
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500295void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
296 const SkPMColor4f& color,
297 CanClearFullscreen canClearFullscreen) {
298 ASSERT_SINGLE_OWNER_PRIV
299 RETURN_IF_ABANDONED_PRIV
300 SkDEBUGCODE(fRenderTargetContext->validate();)
301 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
302 fRenderTargetContext->fContext);
303
304 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
305 fRenderTargetContext->internalClear(clip, color, canClearFullscreen);
306}
307
308static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) {
309 paint->setColor4f(color);
310 if (color.isOpaque()) {
311 // Can just rely on the src-over blend mode to do the right thing
312 paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
313 } else {
314 // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
315 // were src blended
316 paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
317 }
318}
319
320void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
321 const SkPMColor4f& color,
322 CanClearFullscreen canClearFullscreen) {
323 bool isFull = false;
324 if (!clip.hasWindowRectangles()) {
Robert Phillips0e35ce22019-04-05 10:57:28 -0400325 // TODO: wrt the shouldInitializeTextures path, it would be more performant to
326 // only clear the entire target if we knew it had not been cleared before. As
327 // is this could end up doing a lot of redundant clears.
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500328 isFull = !clip.scissorEnabled() ||
329 (CanClearFullscreen::kYes == canClearFullscreen &&
Robert Phillips0e35ce22019-04-05 10:57:28 -0400330 (this->caps()->preferFullscreenClears() || this->caps()->shouldInitializeTextures())) ||
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500331 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
332 }
333
334 if (isFull) {
335 if (this->getRTOpList()->resetForFullscreenClear() &&
336 !this->caps()->performColorClearsAsDraws()) {
337 // The op list was emptied and native clears are allowed, so just use the load op
338 this->getRTOpList()->setColorLoadOp(GrLoadOp::kClear, color);
339 return;
340 } else {
341 // Will use an op for the clear, reset the load op to discard since the op will
342 // blow away the color buffer contents
343 this->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
344 }
345
346 // Must add an op to the list (either because we couldn't use a load op, or because the
347 // clear load op isn't supported)
348 if (this->caps()->performColorClearsAsDraws()) {
349 SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
350 GrPaint paint;
351 clear_to_grpaint(color, &paint);
352 this->addDrawOp(GrFixedClip::Disabled(),
353 GrFillRectOp::Make(fContext, std::move(paint),
354 GrAAType::kNone, SkMatrix::I(), rtRect));
355 } else {
356 this->getRTOpList()->addOp(GrClearOp::Make(fContext, SkIRect::MakeEmpty(), color,
357 /* fullscreen */ true), *this->caps());
358 }
359 } else {
360 if (this->caps()->performPartialClearsAsDraws()) {
361 // performPartialClearsAsDraws() also returns true if any clear has to be a draw.
362 SkRect scissor = SkRect::Make(clip.scissorRect());
363 GrPaint paint;
364 clear_to_grpaint(color, &paint);
365
366 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), GrAAType::kNone,
367 SkMatrix::I(), scissor));
368 } else {
369 std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
370 this->asSurfaceProxy()));
371 // This version of the clear op factory can return null if the clip doesn't intersect
372 // with the surface proxy's boundary
373 if (!op) {
374 return;
375 }
376 this->getRTOpList()->addOp(std::move(op), *this->caps());
377 }
378 }
379}
380
Brian Osman9a9baae2018-11-05 15:06:26 -0500381void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const SkPMColor4f& color) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500382 ASSERT_SINGLE_OWNER_PRIV
383 RETURN_IF_ABANDONED_PRIV
384 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400385 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "absClear",
386 fRenderTargetContext->fContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500387
Robert Phillips72152832017-01-25 17:31:35 -0500388 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500389
Brian Salomonbb5711a2017-05-17 13:49:59 -0400390 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(),
391 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500392
393 if (clearRect) {
394 if (clearRect->contains(rtRect)) {
395 clearRect = nullptr; // full screen
396 } else {
397 if (!rtRect.intersect(*clearRect)) {
398 return;
399 }
400 }
401 }
402
403 // TODO: in a post-MDB world this should be handled at the OpList level.
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500404 // This makes sure to always add an op to the list, instead of marking the clear as a load op.
405 // This code follows very similar logic to internalClear() below, but critical differences are
406 // highlighted in line related to absClear()'s unique behavior.
407 if (clearRect) {
408 if (fRenderTargetContext->caps()->performPartialClearsAsDraws()) {
Ethan Nicholas56d19a52018-10-15 11:26:20 -0400409 GrPaint paint;
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500410 clear_to_grpaint(color, &paint);
411
412 // Use the disabled clip; the rect geometry already matches the clear rectangle and
413 // if it were added to a scissor, that would be intersected with the logical surface
414 // bounds and not the worst case dimensions required here.
415 fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
416 GrFillRectOp::Make(fRenderTargetContext->fContext,
417 std::move(paint),
418 GrAAType::kNone,
419 SkMatrix::I(),
420 SkRect::Make(rtRect)));
421 } else {
422 // Must use the ClearOp factory that takes a boolean (false) instead of a surface
423 // proxy. The surface proxy variant would intersect the clip rect with its logical
424 // bounds, which is not desired in this special case.
425 fRenderTargetContext->getRTOpList()->addOp(
426 GrClearOp::Make(fRenderTargetContext->fContext, rtRect, color,
427 /* fullscreen */ false),
428 *fRenderTargetContext->caps());
csmartdalton29df7602016-08-31 11:55:52 -0700429 }
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500430 } else {
431 // Reset the oplist like in internalClear(), but do not rely on a load op for the clear
432 fRenderTargetContext->getRTOpList()->resetForFullscreenClear();
433 fRenderTargetContext->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
434
435 if (fRenderTargetContext->caps()->performColorClearsAsDraws()) {
436 // This draws a quad covering the worst case dimensions instead of just the logical
437 // width and height like in internalClear().
438 GrPaint paint;
439 clear_to_grpaint(color, &paint);
440 fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
441 GrFillRectOp::Make(fRenderTargetContext->fContext,
442 std::move(paint),
443 GrAAType::kNone,
444 SkMatrix::I(),
445 SkRect::Make(rtRect)));
446 } else {
447 // Nothing special about this path in absClear compared to internalClear()
448 fRenderTargetContext->getRTOpList()->addOp(
449 GrClearOp::Make(fRenderTargetContext->fContext, SkIRect::MakeEmpty(), color,
450 /* fullscreen */ true),
451 *fRenderTargetContext->caps());
Ethan Nicholas56d19a52018-10-15 11:26:20 -0400452 }
robertphillips9199a9f2016-07-13 07:48:43 -0700453 }
robertphillipsea461502015-05-26 11:38:03 -0700454}
455
Brian Osman11052242016-10-27 14:47:55 -0400456void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500457 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400458 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800459 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700460 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700461 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400462 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPaint", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700463
robertphillipsea461502015-05-26 11:38:03 -0700464 // set rect to be big enough to fill the space, but not super-huge, so we
465 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700466
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400467 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700468
Michael Ludwig61a16512019-01-15 11:15:13 -0500469 // Check if we can optimize a clipped drawPaint(). We only do the transformation when there are
470 // no fragment processors because they may depend on having correct local coords and this path
471 // draws in device space without a local matrix. It currently handles converting clipRRect()
472 // to drawRRect() and solid colors to screen-filling drawRects() (which are then converted into
473 // clears if possible in drawRect).
Michael Ludwig3d6390e2018-10-09 11:45:16 -0400474 if (!paint.numTotalFragmentProcessors()) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500475 SkRRect rrect;
476 GrAA aa = GrAA::kNo;
477 if (clip.isRRect(r, &rrect, &aa)) {
478 if (rrect.isRect()) {
479 // Use drawFilledRect() with no clip and the reduced rectangle
480 this->drawFilledRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect.rect());
481 } else {
482 // Use drawRRect() with no clip
483 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
484 GrStyle::SimpleFill());
485 }
486 } else {
487 // Use drawFilledRect() with no view matrix to draw a fullscreen quad, but preserve
488 // the clip. Since the paint has no FPs we can drop the view matrix without worrying
489 // about local coordinates. If the clip is simple, drawFilledRect() will turn this into
490 // a clear or a scissored clear.
491 this->drawFilledRect(clip, std::move(paint), aa, SkMatrix::I(), r);
Michael Ludwig3d6390e2018-10-09 11:45:16 -0400492 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500493 return;
bsalomoncb31e512016-08-26 10:48:19 -0700494 }
495
Michael Ludwig61a16512019-01-15 11:15:13 -0500496 // Since the paint is not trivial, there's no way at this point drawRect() could have converted
497 // this drawPaint() into an optimized clear. drawRect() would then use GrFillRectOp without
498 // a local matrix, so we can simplify things and use the local matrix variant to draw a screen
499 // filling rect with the inverse view matrix for local coords, which works for all matrix
500 // conditions.
501 SkMatrix localMatrix;
502 if (!viewMatrix.invert(&localMatrix)) {
503 return;
robertphillipsea461502015-05-26 11:38:03 -0700504 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500505
506 AutoCheckFlush acf(this->drawingManager());
507 std::unique_ptr<GrDrawOp> op = GrFillRectOp::MakeWithLocalMatrix(
508 fContext, std::move(paint), GrAAType::kNone, SkMatrix::I(), localMatrix, r);
509 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700510}
511
robertphillipsea461502015-05-26 11:38:03 -0700512static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
513 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
514 point.fY >= rect.fTop && point.fY <= rect.fBottom;
515}
516
csmartdalton97f6cd52016-07-13 13:37:08 -0700517// Attempts to crop a rect and optional local rect to the clip boundaries.
518// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700519static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700520 const SkMatrix& viewMatrix, SkRect* rect,
521 SkRect* localRect = nullptr) {
522 if (!viewMatrix.rectStaysRect()) {
523 return true;
524 }
525
csmartdalton97f6cd52016-07-13 13:37:08 -0700526 SkIRect clipDevBounds;
527 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700528
robertphillips13a7eee2016-08-31 15:06:24 -0700529 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700530 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
531 return false;
532 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700533
534 if (localRect) {
535 if (!rect->intersects(clipBounds)) {
536 return false;
537 }
538 const SkScalar dx = localRect->width() / rect->width();
539 const SkScalar dy = localRect->height() / rect->height();
540 if (clipBounds.fLeft > rect->fLeft) {
541 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
542 rect->fLeft = clipBounds.fLeft;
543 }
544 if (clipBounds.fTop > rect->fTop) {
545 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
546 rect->fTop = clipBounds.fTop;
547 }
548 if (clipBounds.fRight < rect->fRight) {
549 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
550 rect->fRight = clipBounds.fRight;
551 }
552 if (clipBounds.fBottom < rect->fBottom) {
553 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
554 rect->fBottom = clipBounds.fBottom;
555 }
556 return true;
557 }
558
559 return rect->intersect(clipBounds);
560}
561
Michael Ludwig61a16512019-01-15 11:15:13 -0500562bool GrRenderTargetContext::drawFilledRectAsClear(const GrClip& clip, GrPaint&& paint, GrAA aa,
563 const SkMatrix& viewMatrix, const SkRect& rect) {
564 // Rules for a filled rect to become a clear [+scissor]:
565 // 1. The paint is a constant blend color with no other FPs
566 // 2. The view matrix maps rectangles to rectangles, or the transformed quad fully covers
567 // the render target (or clear region in #3).
568 // 3. The clip is an intersection of rectangles, so the clear region will be the
569 // intersection of the clip and the provided rect.
570 // 4. The clear region aligns with pixel bounds
571 // 5. There are no user stencil settings (and since the clip was IOR, the clip won't need
572 // to use the stencil either).
573 // If all conditions pass, the filled rect can either be a fullscreen clear (if it's big
574 // enough), or the rectangle geometry will be used as the scissor clip on the clear.
575 // If everything passes but rule #4, this submits a simplified fill rect op instead so that the
576 // rounding differences between clip and draws don't fight each other.
577 // NOTE: we route draws into clear() regardless of performColorClearsAsDraws() since the
578 // clear call is allowed to reset the oplist even when it also happens to use a GrFillRectOp.
579
580 SkPMColor4f clearColor;
581 if (paint.numCoverageFragmentProcessors() > 0 || !paint.isConstantBlendedColor(&clearColor)) {
582 return false;
583 }
584
585 const SkRect rtRect = fRenderTargetProxy->getBoundsRect();
586 // Will be the intersection of render target, clip, and quad
587 SkRect combinedRect = rtRect;
588
589 SkRRect clipRRect;
590 GrAA clipAA;
591 if (!clip.quickContains(rtRect)) {
592 // If the clip is an rrect with no rounding, then it can replace the full RT bounds as the
593 // limiting region, although we will have to worry about AA. If the clip is anything
594 // more complicated, just punt to the regular fill rect op.
595 if (!clip.isRRect(rtRect, &clipRRect, &clipAA) || !clipRRect.isRect()) {
596 return false;
597 }
598 combinedRect = clipRRect.rect();
599 } else {
600 // The clip is outside the render target, so the clip can be ignored
601 clipAA = GrAA::kNo;
602 }
603
604 if (viewMatrix.rectStaysRect()) {
605 // Skip the extra overhead of inverting the view matrix to see if rtRect is contained in the
606 // drawn rectangle, and instead just intersect rtRect with the transformed rect. It will be
607 // the new clear region.
608 if (!combinedRect.intersect(viewMatrix.mapRect(rect))) {
609 // No intersection means nothing should be drawn, so return true but don't add an op
610 return true;
611 }
612 } else {
613 // If the transformed rectangle does not contain the combined rt and clip, the draw is too
614 // complex to be implemented as a clear
615 SkMatrix invM;
616 if (!viewMatrix.invert(&invM)) {
617 return false;
618 }
619 // The clip region in the rect's local space, so the test becomes the local rect containing
620 // the quad's points.
Michael Ludwige9c57d32019-02-13 13:39:39 -0500621 GrQuad quad = GrQuad::MakeFromRect(rtRect, invM);
Michael Ludwig61a16512019-01-15 11:15:13 -0500622 if (!rect_contains_inclusive(rect, quad.point(0)) ||
623 !rect_contains_inclusive(rect, quad.point(1)) ||
624 !rect_contains_inclusive(rect, quad.point(2)) ||
625 !rect_contains_inclusive(rect, quad.point(3))) {
626 // No containment, so rtRect can't be filled by a solid color
627 return false;
628 }
629 // combinedRect can be filled by a solid color but doesn't need to be modified since it's
630 // inside the quad to be drawn.
631 }
632
633 // Almost every condition is met; now it requires that the combined rect align with pixel
634 // boundaries in order for it to become a scissor-clear. Ignore the AA status in this case
635 // since non-AA with partial-pixel coordinates can be rounded differently on the GPU,
636 // leading to unexpected differences between a scissor test and a rasterized quad.
637 // Also skip very small rectangles since the scissor+clear doesn't by us much then.
638 if (combinedRect.contains(rtRect)) {
639 // Full screen clear
640 this->clear(nullptr, clearColor, CanClearFullscreen::kYes);
641 return true;
642 } else if (GrClip::IsPixelAligned(combinedRect) &&
643 combinedRect.width() > 256 && combinedRect.height() > 256) {
644 // Scissor + clear (round shouldn't do anything since we are pixel aligned)
645 SkIRect scissorRect;
646 combinedRect.round(&scissorRect);
647 this->clear(&scissorRect, clearColor, CanClearFullscreen::kNo);
648 return true;
649 }
650
651 // If we got here, we can't use a scissor + clear, but combinedRect represents the correct
652 // geometry combination of quad + clip so we can perform a simplified fill rect op. We do this
653 // mostly to avoid mismatches in rounding logic on the CPU vs. the GPU, which frequently appears
654 // when drawing and clipping something to the same non-AA rect that never-the-less has
655 // non-integer coordinates.
656
657 // For AA, use non-AA only when both clip and draw are non-AA.
658 if (clipAA == GrAA::kYes) {
659 aa = GrAA::kYes;
660 }
Chris Dalton7d6748e2019-03-13 00:34:52 -0600661 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig61a16512019-01-15 11:15:13 -0500662 this->addDrawOp(GrFixedClip::Disabled(),
663 GrFillRectOp::Make(fContext, std::move(paint), aaType, SkMatrix::I(),
664 combinedRect));
665 return true;
666}
667
668void GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500669 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500670 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400671 const SkMatrix& viewMatrix,
672 const SkRect& rect,
673 const GrUserStencilSettings* ss) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500674
675 if (!ss) {
676 if (this->drawFilledRectAsClear(clip, std::move(paint), aa, viewMatrix, rect)) {
677 return;
678 }
679 // Fall through to fill rect op
680 assert_alive(paint);
681 }
682
csmartdalton97f6cd52016-07-13 13:37:08 -0700683 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500684 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500685 // The rectangle would not be drawn, so no need to add a draw op to the list
686 return;
csmartdalton97f6cd52016-07-13 13:37:08 -0700687 }
robertphillips44302392016-07-08 14:43:03 -0700688
Chris Dalton7d6748e2019-03-13 00:34:52 -0600689 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500690 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), aaType, viewMatrix,
691 croppedRect, ss));
robertphillips391395d2016-03-02 09:26:36 -0800692}
693
Brian Osman11052242016-10-27 14:47:55 -0400694void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500695 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500696 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400697 const SkMatrix& viewMatrix,
698 const SkRect& rect,
699 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700700 if (!style) {
701 style = &GrStyle::SimpleFill();
702 }
joshualitt1de610a2016-01-06 08:26:09 -0800703 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700704 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700705 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400706 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700707
bsalomon6663acf2016-05-10 09:14:17 -0700708 // Path effects should've been devolved to a path in SkGpuDevice
709 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700710
Robert Phillips72152832017-01-25 17:31:35 -0500711 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700712
bsalomon6663acf2016-05-10 09:14:17 -0700713 const SkStrokeRec& stroke = style->strokeRec();
Robert Phillips8c8b0462018-08-24 16:18:03 -0400714 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500715 this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect);
716 return;
bsalomona7d85ba2016-07-06 11:54:59 -0700717 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
718 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
719 if ((!rect.width() || !rect.height()) &&
720 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
721 SkScalar r = stroke.getWidth() / 2;
722 // TODO: Move these stroke->fill fallbacks to GrShape?
723 switch (stroke.getJoin()) {
724 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500725 this->drawRect(
726 clip, std::move(paint), aa, viewMatrix,
727 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
728 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700729 return;
730 case SkPaint::kRound_Join:
731 // Raster draws nothing when both dimensions are empty.
732 if (rect.width() || rect.height()){
733 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500734 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
735 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700736 return;
737 }
738 case SkPaint::kBevel_Join:
739 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500740 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700741 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
742 &GrStyle::SimpleFill());
743 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500744 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700745 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
746 &GrStyle::SimpleFill());
747 }
748 return;
749 }
750 }
robertphillips44302392016-07-08 14:43:03 -0700751
Brian Salomonbaaf4392017-06-15 09:59:23 -0400752 std::unique_ptr<GrDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700753
Chris Dalton7d6748e2019-03-13 00:34:52 -0600754 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500755 op = GrStrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
756 // op may be null if the stroke is not supported or if using coverage aa and the view matrix
757 // does not preserve rectangles.
Brian Salomon42521e82016-12-07 16:44:58 -0500758 if (op) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400759 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700760 return;
robertphillips4bc31812016-03-01 12:22:49 -0800761 }
robertphillips4bc31812016-03-01 12:22:49 -0800762 }
Mike Klein16885072018-12-11 09:54:31 -0500763 assert_alive(paint);
Brian Salomon2fad74a2017-12-20 13:28:55 -0500764 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(rect, *style));
robertphillipsea461502015-05-26 11:38:03 -0700765}
766
Michael Ludwig69858532018-11-28 15:34:34 -0500767void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa,
768 const SkMatrix& viewMatrix, const QuadSetEntry quads[],
769 int cnt) {
Chris Dalton7d6748e2019-03-13 00:34:52 -0600770 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig69858532018-11-28 15:34:34 -0500771 this->addDrawOp(clip, GrFillRectOp::MakeSet(fContext, std::move(paint), aaType, viewMatrix,
772 quads, cnt));
773}
774
Robert Phillipsec2249f2016-11-09 08:54:35 -0500775int GrRenderTargetContextPriv::maxWindowRectangles() const {
776 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400777 *fRenderTargetContext->caps());
Robert Phillipsec2249f2016-11-09 08:54:35 -0500778}
779
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000780void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700781 ASSERT_SINGLE_OWNER_PRIV
782 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400783 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400784 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
785 fRenderTargetContext->fContext);
robertphillips976f5f02016-06-03 10:59:20 -0700786
Robert Phillips72152832017-01-25 17:31:35 -0500787 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400788
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500789 fRenderTargetContext->internalStencilClear(clip, insideStencilMask);
790}
791
792void GrRenderTargetContext::internalStencilClear(const GrFixedClip& clip, bool insideStencilMask) {
793 if (this->caps()->performStencilClearsAsDraws()) {
794 const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);
795 SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
796
797 // Configure the paint to have no impact on the color buffer
798 GrPaint paint;
799 paint.setColor4f({0.f, 0.f, 0.f, 0.f});
800 paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
801
802 // Mark stencil usage here before addDrawOp() so that it doesn't try to re-call
803 // internalStencilClear() just because the op has stencil settings.
804 this->setNeedsStencil();
805 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint),
806 GrAAType::kNone, SkMatrix::I(), rtRect, ss));
807 } else {
808 std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask,
809 fRenderTargetProxy.get()));
810 if (!op) {
811 return;
812 }
813 this->getRTOpList()->addOp(std::move(op), *this->caps());
Robert Phillipse60ad622016-11-17 10:22:48 -0500814 }
robertphillips976f5f02016-06-03 10:59:20 -0700815}
816
Chris Daltonbbfd5162017-11-07 13:35:22 -0700817void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
Chris Dalton09e56892019-03-13 00:22:01 -0600818 GrAA doStencilMSAA,
Brian Osman11052242016-10-27 14:47:55 -0400819 const SkMatrix& viewMatrix,
820 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500821 ASSERT_SINGLE_OWNER_PRIV
822 RETURN_IF_ABANDONED_PRIV
823 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400824 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
825 fRenderTargetContext->fContext);
Brian Salomon467921e2017-03-06 16:17:12 -0500826
Brian Salomon467921e2017-03-06 16:17:12 -0500827 // TODO: extract portions of checkDraw that are relevant to path stenciling.
828 SkASSERT(path);
829 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
830
831 // FIXME: Use path bounds instead of this WAR once
832 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
833 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
834
835 // Setup clip
Chris Daltonbbfd5162017-11-07 13:35:22 -0700836 GrAppliedHardClip appliedClip;
837 if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
838 &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500839 return;
840 }
841
Robert Phillips65048132017-08-10 08:44:49 -0400842 fRenderTargetContext->setNeedsStencil();
Brian Salomon467921e2017-03-06 16:17:12 -0500843
Robert Phillips7c525e62018-06-12 10:11:12 -0400844 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
845 viewMatrix,
Chris Dalton09e56892019-03-13 00:22:01 -0600846 GrAA::kYes == doStencilMSAA,
Brian Salomon467921e2017-03-06 16:17:12 -0500847 path->getFillType(),
848 appliedClip.hasStencilClip(),
Brian Salomon467921e2017-03-06 16:17:12 -0500849 appliedClip.scissorState(),
Brian Salomon467921e2017-03-06 16:17:12 -0500850 path);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400851 if (!op) {
852 return;
853 }
Brian Salomon97180af2017-03-14 13:42:58 -0400854 op->setClippedBounds(bounds);
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400855 fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -0700856}
857
Chris Daltonbbfd5162017-11-07 13:35:22 -0700858void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400859 const GrUserStencilSettings* ss,
Chris Dalton09e56892019-03-13 00:22:01 -0600860 GrAA doStencilMSAA,
Brian Osman11052242016-10-27 14:47:55 -0400861 const SkMatrix& viewMatrix,
862 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700863 ASSERT_SINGLE_OWNER_PRIV
864 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400865 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400866 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilRect",
867 fRenderTargetContext->fContext);
868
Robert Phillips72152832017-01-25 17:31:35 -0500869 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700870
871 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500872 paint.setXPFactory(GrDisableColorXPFactory::Get());
Chris Dalton09e56892019-03-13 00:22:01 -0600873 auto aaType = (GrAA::kYes == doStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
Michael Ludwig72ab3462018-12-10 12:43:36 -0500874 std::unique_ptr<GrDrawOp> op = GrFillRectOp::Make(
875 fRenderTargetContext->fContext, std::move(paint), aaType, viewMatrix, rect, ss);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400876 fRenderTargetContext->addDrawOp(clip, std::move(op));
robertphillips976f5f02016-06-03 10:59:20 -0700877}
878
Chris Daltonbbfd5162017-11-07 13:35:22 -0700879bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400880 const GrUserStencilSettings* ss,
881 SkRegion::Op op,
882 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500883 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400884 const SkMatrix& viewMatrix,
885 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800886 ASSERT_SINGLE_OWNER_PRIV
887 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400888 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400889 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
890 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -0800891
Robert Phillips72152832017-01-25 17:31:35 -0500892 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800893
894 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800895 paint.setCoverageSetOpXPFactory(op, invert);
896
Michael Ludwig61a16512019-01-15 11:15:13 -0500897 // This will always succeed to draw a rectangle
898 fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss);
899 return true;
robertphillips391395d2016-03-02 09:26:36 -0800900}
901
Michael Ludwig136f45a2019-02-19 11:44:41 -0500902void GrRenderTargetContext::fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
Michael Ludwig75451902019-01-23 11:14:29 -0500903 GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
Michael Ludwig136f45a2019-02-19 11:44:41 -0500904 const SkRect& rect, const SkRect* localRect) {
Michael Ludwig75451902019-01-23 11:14:29 -0500905 ASSERT_SINGLE_OWNER
906 RETURN_IF_ABANDONED
907 SkDEBUGCODE(this->validate();)
908 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithEdgeAA", fContext);
909
Chris Dalton7d6748e2019-03-13 00:34:52 -0600910 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig136f45a2019-02-19 11:44:41 -0500911 std::unique_ptr<GrDrawOp> op;
Michael Ludwig75451902019-01-23 11:14:29 -0500912
Michael Ludwig136f45a2019-02-19 11:44:41 -0500913 if (localRect) {
914 // If local coordinates are provided, skip the optimization check to go through
915 // drawFilledRect, and also calculate clipped local coordinates
916 SkRect croppedRect = rect;
917 SkRect croppedLocalRect = *localRect;
918 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect,
919 &croppedLocalRect)) {
920 return;
921 }
922 op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType, edgeAA,
923 viewMatrix, croppedRect, croppedLocalRect);
924 } else {
925 // If aaType turns into MSAA, make sure to keep quads with no AA edges as MSAA. Sending
926 // those to drawFilledRect() would have it turn off MSAA in that case, which breaks seaming
927 // with any partial AA edges that kept MSAA.
928 if (aaType != GrAAType::kMSAA &&
929 (edgeAA == GrQuadAAFlags::kNone || edgeAA == GrQuadAAFlags::kAll)) {
930 // This is equivalent to a regular filled rect draw, so route through there to take
931 // advantage of draw->clear optimizations
932 this->drawFilledRect(clip, std::move(paint), GrAA(edgeAA == GrQuadAAFlags::kAll),
933 viewMatrix, rect);
934 return;
935 }
936
937 SkRect croppedRect = rect;
938 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
939 return;
940 }
941 op = GrFillRectOp::MakePerEdge(fContext, std::move(paint), aaType, edgeAA, viewMatrix,
942 croppedRect);
Michael Ludwig75451902019-01-23 11:14:29 -0500943 }
944
945 AutoCheckFlush acf(this->drawingManager());
Michael Ludwig136f45a2019-02-19 11:44:41 -0500946 this->addDrawOp(clip, std::move(op));
Michael Ludwig75451902019-01-23 11:14:29 -0500947}
948
Michael Ludwigce62dec2019-02-19 11:48:46 -0500949void GrRenderTargetContext::fillQuadWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
950 GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
951 const SkPoint quad[4], const SkPoint localQuad[4]) {
952 ASSERT_SINGLE_OWNER
953 RETURN_IF_ABANDONED
954 SkDEBUGCODE(this->validate();)
955 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillQuadWithEdgeAA", fContext);
956
Chris Dalton7d6748e2019-03-13 00:34:52 -0600957 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwigce62dec2019-02-19 11:48:46 -0500958
959 AutoCheckFlush acf(this->drawingManager());
960 // MakePerEdgeQuad automatically does the right thing if localQuad is null or not
961 this->addDrawOp(clip, GrFillRectOp::MakePerEdgeQuad(fContext, std::move(paint), aaType, edgeAA,
962 viewMatrix, quad, localQuad));
963}
964
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500965// Creates a paint for GrFillRectOp that matches behavior of GrTextureOp
966static void draw_texture_to_grpaint(sk_sp<GrTextureProxy> proxy, const SkRect* domain,
967 GrSamplerState::Filter filter, SkBlendMode mode,
968 const SkPMColor4f& color, sk_sp<GrColorSpaceXform> csXform,
969 GrPaint* paint) {
970 paint->setColor4f(color);
971 paint->setXPFactory(SkBlendMode_AsXPFactory(mode));
972
973 std::unique_ptr<GrFragmentProcessor> fp;
974 if (domain) {
Michael Ludwigce62dec2019-02-19 11:48:46 -0500975 SkRect correctedDomain = *domain;
976 if (filter == GrSamplerState::Filter::kBilerp) {
977 // Inset by 1/2 pixel, which GrTextureOp and GrTextureAdjuster handle automatically
978 correctedDomain.inset(0.5f, 0.5f);
979 }
980 fp = GrTextureDomainEffect::Make(std::move(proxy), SkMatrix::I(), correctedDomain,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500981 GrTextureDomain::kClamp_Mode, filter);
982 } else {
983 fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I(), filter);
984 }
985
986 fp = GrColorSpaceXformEffect::Make(std::move(fp), csXform);
987 paint->addColorFragmentProcessor(std::move(fp));
988}
989
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400990void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500991 GrSamplerState::Filter filter, SkBlendMode mode,
992 const SkPMColor4f& color, const SkRect& srcRect,
Michael Ludwig136f45a2019-02-19 11:44:41 -0500993 const SkRect& dstRect, GrAA aa, GrQuadAAFlags aaFlags,
Brian Salomonb80ffee2018-05-23 16:39:39 -0400994 SkCanvas::SrcRectConstraint constraint,
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400995 const SkMatrix& viewMatrix,
Brian Osman3d139a42018-11-19 10:42:10 -0500996 sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
Brian Salomon34169692017-08-28 15:32:01 -0400997 ASSERT_SINGLE_OWNER
998 RETURN_IF_ABANDONED
999 SkDEBUGCODE(this->validate();)
Brian Salomonbe3c1d22018-05-21 12:54:39 -04001000 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexture", fContext);
Brian Salomonf1709042018-10-03 11:57:00 -04001001 if (constraint == SkCanvas::kStrict_SrcRectConstraint &&
1002 srcRect.contains(proxy->getWorstCaseBoundsRect())) {
1003 constraint = SkCanvas::kFast_SrcRectConstraint;
Brian Salomon34169692017-08-28 15:32:01 -04001004 }
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001005
Chris Dalton7d6748e2019-03-13 00:34:52 -06001006 GrAAType aaType = this->chooseAAType(aa);
Brian Salomonff9d6d32017-08-30 10:27:49 -04001007 SkRect clippedDstRect = dstRect;
1008 SkRect clippedSrcRect = srcRect;
1009 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &clippedDstRect,
1010 &clippedSrcRect)) {
1011 return;
1012 }
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001013
1014 AutoCheckFlush acf(this->drawingManager());
1015
1016 std::unique_ptr<GrDrawOp> op;
1017 if (mode != SkBlendMode::kSrcOver) {
1018 // Emulation mode with GrPaint and GrFillRectOp
1019 if (filter != GrSamplerState::Filter::kNearest &&
1020 !GrTextureOp::GetFilterHasEffect(viewMatrix, clippedSrcRect, clippedDstRect)) {
1021 filter = GrSamplerState::Filter::kNearest;
1022 }
1023
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001024 GrPaint paint;
1025 draw_texture_to_grpaint(std::move(proxy),
Michael Ludwigce62dec2019-02-19 11:48:46 -05001026 constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001027 filter, mode, color, std::move(textureColorSpaceXform), &paint);
1028 op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType, aaFlags,
1029 viewMatrix, clippedDstRect, clippedSrcRect);
1030 } else {
1031 // Can use a lighter weight op that can chain across proxies
1032 op = GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect,
1033 clippedDstRect, aaType, aaFlags, constraint, viewMatrix,
1034 std::move(textureColorSpaceXform));
1035 }
1036
Brian Salomon2213ee92018-10-02 10:44:21 -04001037 this->addDrawOp(clip, std::move(op));
Brian Salomon34169692017-08-28 15:32:01 -04001038}
1039
Michael Ludwigce62dec2019-02-19 11:48:46 -05001040void GrRenderTargetContext::drawTextureQuad(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
1041 GrSamplerState::Filter filter, SkBlendMode mode,
1042 const SkPMColor4f& color, const SkPoint srcQuad[4],
1043 const SkPoint dstQuad[4], GrAA aa,
1044 GrQuadAAFlags aaFlags, const SkRect* domain,
1045 const SkMatrix& viewMatrix,
1046 sk_sp<GrColorSpaceXform> texXform) {
1047 ASSERT_SINGLE_OWNER
1048 RETURN_IF_ABANDONED
1049 SkDEBUGCODE(this->validate();)
1050 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureQuad", fContext);
1051 if (domain && domain->contains(proxy->getWorstCaseBoundsRect())) {
1052 domain = nullptr;
1053 }
1054
Chris Dalton7d6748e2019-03-13 00:34:52 -06001055 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001056
1057 // Unlike drawTexture(), don't bother cropping or optimizing the filter type since we're
1058 // sampling an arbitrary quad of the texture.
1059 AutoCheckFlush acf(this->drawingManager());
1060 std::unique_ptr<GrDrawOp> op;
1061 if (mode != SkBlendMode::kSrcOver) {
1062 // Emulation mode, but don't bother converting to kNearest filter since it's an arbitrary
1063 // quad that is being drawn, which makes the tests too expensive here
1064 GrPaint paint;
1065 draw_texture_to_grpaint(
1066 std::move(proxy), domain, filter, mode, color, std::move(texXform), &paint);
1067 op = GrFillRectOp::MakePerEdgeQuad(fContext, std::move(paint), aaType, aaFlags, viewMatrix,
1068 dstQuad, srcQuad);
1069 } else {
1070 // Use lighter weight GrTextureOp
1071 op = GrTextureOp::MakeQuad(fContext, std::move(proxy), filter, color, srcQuad, dstQuad,
1072 aaType, aaFlags, domain, viewMatrix, std::move(texXform));
1073 }
1074
1075 this->addDrawOp(clip, std::move(op));
1076}
1077
Brian Salomond7065e72018-10-12 11:42:02 -04001078void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetEntry set[], int cnt,
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001079 GrSamplerState::Filter filter, SkBlendMode mode,
Michael Ludwig31ba7182019-04-03 10:38:06 -04001080 GrAA aa, SkCanvas::SrcRectConstraint constraint,
1081 const SkMatrix& viewMatrix,
Brian Osman3d139a42018-11-19 10:42:10 -05001082 sk_sp<GrColorSpaceXform> texXform) {
Brian Salomond7065e72018-10-12 11:42:02 -04001083 ASSERT_SINGLE_OWNER
1084 RETURN_IF_ABANDONED
1085 SkDEBUGCODE(this->validate();)
1086 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureSet", fContext);
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001087
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001088 if (mode != SkBlendMode::kSrcOver ||
Robert Phillips9da87e02019-02-04 13:26:26 -05001089 !fContext->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001090 // Draw one at a time with GrFillRectOp and a GrPaint that emulates what GrTextureOp does
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001091 SkMatrix ctm;
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001092 for (int i = 0; i < cnt; ++i) {
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001093 float alpha = set[i].fAlpha;
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001094 ctm = viewMatrix;
1095 if (set[i].fPreViewMatrix) {
1096 ctm.preConcat(*set[i].fPreViewMatrix);
1097 }
1098
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001099 if (set[i].fDstClipQuad == nullptr) {
Michael Ludwigce62dec2019-02-19 11:48:46 -05001100 // Stick with original rectangles, which allows the ops to know more about what's
1101 // being drawn.
1102 this->drawTexture(clip, set[i].fProxy, filter, mode, {alpha, alpha, alpha, alpha},
1103 set[i].fSrcRect, set[i].fDstRect, aa, set[i].fAAFlags,
Michael Ludwig31ba7182019-04-03 10:38:06 -04001104 constraint, ctm, texXform);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001105 } else {
1106 // Generate interpolated texture coordinates to match the dst clip
1107 SkPoint srcQuad[4];
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001108 GrMapRectPoints(set[i].fDstRect, set[i].fSrcRect, set[i].fDstClipQuad, srcQuad, 4);
Michael Ludwig31ba7182019-04-03 10:38:06 -04001109 const SkRect* domain = constraint == SkCanvas::kStrict_SrcRectConstraint
1110 ? &set[i].fSrcRect : nullptr;
Michael Ludwigce62dec2019-02-19 11:48:46 -05001111 this->drawTextureQuad(clip, set[i].fProxy, filter, mode,
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001112 {alpha, alpha, alpha, alpha}, srcQuad, set[i].fDstClipQuad,
Michael Ludwig31ba7182019-04-03 10:38:06 -04001113 aa, set[i].fAAFlags, domain, ctm, texXform);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001114 }
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001115 }
1116 } else {
1117 // Can use a single op, avoiding GrPaint creation, and can batch across proxies
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001118 AutoCheckFlush acf(this->drawingManager());
Chris Dalton7d6748e2019-03-13 00:34:52 -06001119 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig31ba7182019-04-03 10:38:06 -04001120 auto op = GrTextureOp::MakeSet(fContext, set, cnt, filter, aaType, constraint, viewMatrix,
Michael Ludwig009b92e2019-02-15 16:03:53 -05001121 std::move(texXform));
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001122 this->addDrawOp(clip, std::move(op));
1123 }
Brian Salomond7065e72018-10-12 11:42:02 -04001124}
1125
Brian Osman11052242016-10-27 14:47:55 -04001126void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001127 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001128 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001129 const SkMatrix& viewMatrix,
1130 const SkRect& rectToDraw,
1131 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -08001132 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -07001133 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001134 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001135 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithLocalMatrix", fContext);
joshualittb6b513b2015-08-21 10:25:18 -07001136
csmartdalton97f6cd52016-07-13 13:37:08 -07001137 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -07001138 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -07001139 return;
1140 }
1141
Robert Phillips72152832017-01-25 17:31:35 -05001142 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001143
Chris Dalton7d6748e2019-03-13 00:34:52 -06001144 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -05001145 this->addDrawOp(clip, GrFillRectOp::MakeWithLocalMatrix(fContext, std::move(paint), aaType,
1146 viewMatrix, localMatrix, croppedRect));
robertphillipsea461502015-05-26 11:38:03 -07001147}
1148
Brian Osman11052242016-10-27 14:47:55 -04001149void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001150 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001151 const SkMatrix& viewMatrix,
Brian Osmanae0c50c2017-05-25 16:56:34 -04001152 sk_sp<SkVertices> vertices,
Ruiqi Maoc97a3392018-08-15 10:44:19 -04001153 const SkVertices::Bone bones[],
Ruiqi Mao4ec72f72018-07-10 17:21:07 -04001154 int boneCount,
Brian Osmanae0c50c2017-05-25 16:56:34 -04001155 GrPrimitiveType* overridePrimType) {
Brian Salomon199fb872017-02-06 09:41:10 -05001156 ASSERT_SINGLE_OWNER
1157 RETURN_IF_ABANDONED
1158 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001159 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
Brian Salomon199fb872017-02-06 09:41:10 -05001160
1161 AutoCheckFlush acf(this->drawingManager());
1162
1163 SkASSERT(vertices);
Chris Dalton7d6748e2019-03-13 00:34:52 -06001164 GrAAType aaType = this->chooseAAType(GrAA::kNo);
Brian Salomonf3569f02017-10-24 12:52:33 -04001165 std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
Ruiqi Mao4ec72f72018-07-10 17:21:07 -04001166 fContext, std::move(paint), std::move(vertices), bones, boneCount, viewMatrix, aaType,
Brian Salomonf3569f02017-10-24 12:52:33 -04001167 this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
Brian Salomonc2f42542017-07-12 14:11:22 -04001168 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001169}
1170
1171///////////////////////////////////////////////////////////////////////////////
1172
Brian Osman4d92b892019-03-24 00:53:23 +00001173void GrRenderTargetContext::drawAtlas(const GrClip& clip,
1174 GrPaint&& paint,
1175 const SkMatrix& viewMatrix,
1176 int spriteCount,
1177 const SkRSXform xform[],
1178 const SkRect texRect[],
1179 const SkColor colors[]) {
1180 ASSERT_SINGLE_OWNER
1181 RETURN_IF_ABANDONED
1182 SkDEBUGCODE(this->validate();)
1183 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
1184
1185 AutoCheckFlush acf(this->drawingManager());
1186
1187 GrAAType aaType = this->chooseAAType(GrAA::kNo);
1188 std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
1189 aaType, spriteCount, xform, texRect, colors);
1190 this->addDrawOp(clip, std::move(op));
1191}
1192
1193///////////////////////////////////////////////////////////////////////////////
1194
Brian Osman11052242016-10-27 14:47:55 -04001195void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -05001196 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001197 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001198 const SkMatrix& viewMatrix,
1199 const SkRRect& rrect,
1200 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001201 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001202 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001203 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001204 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
Robert Phillips85290802018-07-02 13:14:28 -04001205
1206 const SkStrokeRec& stroke = style.strokeRec();
1207 if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001208 return;
1209 }
1210
bsalomon7f0d9f32016-08-15 14:49:10 -07001211 GrNoClip noclip;
1212 const GrClip* clip = &origClip;
1213#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1214 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -05001215 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -07001216 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
1217 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
Michael Ludwig28398842019-03-25 10:24:24 -04001218 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls. This
1219 // only works for filled rrects since the stroke width outsets beyond the rrect itself.
bsalomon7f0d9f32016-08-15 14:49:10 -07001220 SkRRect devRRect;
Michael Ludwig28398842019-03-25 10:24:24 -04001221 if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.transform(viewMatrix, &devRRect) &&
1222 clip->quickContains(devRRect)) {
bsalomon7f0d9f32016-08-15 14:49:10 -07001223 clip = &noclip;
1224 }
1225#endif
bsalomon6663acf2016-05-10 09:14:17 -07001226 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -07001227
Robert Phillips72152832017-01-25 17:31:35 -05001228 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001229
Chris Dalton7d6748e2019-03-13 00:34:52 -06001230 GrAAType aaType = this->chooseAAType(aa);
Chris Dalton133944a2018-11-16 23:30:29 -05001231
Chris Dalton0dffbab2019-03-27 13:08:50 -06001232 std::unique_ptr<GrDrawOp> op;
1233 if (style.isSimpleFill()) {
1234 assert_alive(paint);
1235 op = GrFillRRectOp::Make(
1236 fContext, aaType, viewMatrix, rrect, *this->caps(), std::move(paint));
1237 }
Greg Daniel2655ede2019-04-10 00:49:28 +00001238 if (!op && GrAAType::kCoverage == aaType) {
Chris Dalton0dffbab2019-03-27 13:08:50 -06001239 assert_alive(paint);
1240 op = GrOvalOpFactory::MakeRRectOp(
Greg Daniel2655ede2019-04-10 00:49:28 +00001241 fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
1242
Chris Dalton0dffbab2019-03-27 13:08:50 -06001243 }
1244 if (op) {
1245 this->addDrawOp(*clip, std::move(op));
1246 return;
robertphillipsea461502015-05-26 11:38:03 -07001247 }
robertphillipsb56f9272016-02-25 11:03:52 -08001248
Mike Klein16885072018-12-11 09:54:31 -05001249 assert_alive(paint);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001250 this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
1251 GrShape(rrect, style));
robertphillipsea461502015-05-26 11:38:03 -07001252}
1253
Jim Van Verthc5903412016-11-17 15:27:09 -05001254///////////////////////////////////////////////////////////////////////////////
1255
Jim Van Verth3af1af92017-05-18 15:06:54 -04001256static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
1257 SkPoint3 result;
1258 m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
1259 result.fZ = pt.fZ;
1260 return result;
1261}
1262
1263bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
Jim Van Verth3af1af92017-05-18 15:06:54 -04001264 const SkMatrix& viewMatrix,
1265 const SkPath& path,
1266 const SkDrawShadowRec& rec) {
Jim Van Verthc5903412016-11-17 15:27:09 -05001267 ASSERT_SINGLE_OWNER
Robert Phillips6a6de562019-02-15 15:19:15 -05001268 if (fContext->priv().abandoned()) {
Jim Van Verth3af1af92017-05-18 15:06:54 -04001269 return true;
1270 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001271 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001272 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001273
1274 // check z plane
1275 bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
1276 !SkScalarNearlyZero(rec.fZPlaneParams.fY));
1277 bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1278 if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
1279 return false;
1280 }
1281
1282 SkRRect rrect;
1283 SkRect rect;
1284 // we can only handle rects, circles, and rrects with circular corners
Mike Reed242135a2018-02-22 13:41:39 -05001285 bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsSimpleCircular(rrect) &&
Jim Van Verth3af1af92017-05-18 15:06:54 -04001286 rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
1287 if (!isRRect &&
1288 path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
1289 rect.width() > SK_ScalarNearlyZero) {
1290 rrect.setOval(rect);
1291 isRRect = true;
1292 }
1293 if (!isRRect && path.isRect(&rect)) {
1294 rrect.setRect(rect);
1295 isRRect = true;
1296 }
1297
1298 if (!isRRect) {
1299 return false;
1300 }
1301
Jim Van Verthc5903412016-11-17 15:27:09 -05001302 if (rrect.isEmpty()) {
Jim Van Verth3af1af92017-05-18 15:06:54 -04001303 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -05001304 }
1305
Robert Phillips72152832017-01-25 17:31:35 -05001306 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001307
Jim Van Verth3af1af92017-05-18 15:06:54 -04001308 // transform light
1309 SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
1310
1311 // 1/scale
1312 SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
1313 SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) :
1314 sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
1315 viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
1316
1317 SkScalar occluderHeight = rec.fZPlaneParams.fZ;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001318 bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1319
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001320 if (SkColorGetA(rec.fAmbientColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001321 SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1322 const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1323 const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001324
1325 // Outset the shadow rrect to the border of the penumbra
1326 SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1327 SkRRect ambientRRect;
1328 SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1329 // If the rrect was an oval then its outset will also be one.
1330 // We set it explicitly to avoid errors.
1331 if (rrect.isOval()) {
1332 ambientRRect = SkRRect::MakeOval(outsetRect);
1333 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001334 SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001335 ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1336 }
1337
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001338 GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001339 if (transparent) {
1340 // set a large inset to force a fill
1341 devSpaceInsetWidth = ambientRRect.width();
1342 }
Jim Van Verth39e71652018-04-23 18:08:45 +00001343
Robert Phillips7c525e62018-06-12 10:11:12 -04001344 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1345 ambientColor,
1346 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001347 ambientRRect,
1348 devSpaceAmbientBlur,
Jim Van Verthfb186392018-09-11 11:37:46 -04001349 devSpaceInsetWidth);
Brian Salomon05969092017-07-13 11:20:51 -04001350 SkASSERT(op);
1351 this->addDrawOp(clip, std::move(op));
Jim Van Verthc5903412016-11-17 15:27:09 -05001352 }
Jim Van Verth3af1af92017-05-18 15:06:54 -04001353
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001354 if (SkColorGetA(rec.fSpotColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001355 SkScalar devSpaceSpotBlur;
1356 SkScalar spotScale;
1357 SkVector spotOffset;
1358 SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1359 devLightPos.fZ, rec.fLightRadius,
1360 &devSpaceSpotBlur, &spotScale, &spotOffset);
1361 // handle scale of radius due to CTM
Jim Van Verth3af1af92017-05-18 15:06:54 -04001362 const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1363
Jim Van Verth3af1af92017-05-18 15:06:54 -04001364 // Adjust translate for the effect of the scale.
1365 spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1366 spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1367 // This offset is in dev space, need to transform it into source space.
1368 SkMatrix ctmInverse;
1369 if (viewMatrix.invert(&ctmInverse)) {
1370 ctmInverse.mapPoints(&spotOffset, 1);
1371 } else {
1372 // Since the matrix is a similarity, this should never happen, but just in case...
1373 SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1374 SkASSERT(false);
1375 }
1376
1377 // Compute the transformed shadow rrect
1378 SkRRect spotShadowRRect;
1379 SkMatrix shadowTransform;
1380 shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1381 rrect.transform(shadowTransform, &spotShadowRRect);
Mike Reed242135a2018-02-22 13:41:39 -05001382 SkScalar spotRadius = SkRRectPriv::GetSimpleRadii(spotShadowRRect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001383
1384 // Compute the insetWidth
Jim Van Verth1af03d42017-07-31 09:34:58 -04001385 SkScalar blurOutset = srcSpaceSpotBlur;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001386 SkScalar insetWidth = blurOutset;
1387 if (transparent) {
1388 // If transparent, just do a fill
1389 insetWidth += spotShadowRRect.width();
1390 } else {
1391 // For shadows, instead of using a stroke we specify an inset from the penumbra
1392 // border. We want to extend this inset area so that it meets up with the caster
1393 // geometry. The inset geometry will by default already be inset by the blur width.
1394 //
1395 // We compare the min and max corners inset by the radius between the original
1396 // rrect and the shadow rrect. The distance between the two plus the difference
1397 // between the scaled radius and the original radius gives the distance from the
1398 // transformed shadow shape to the original shape in that corner. The max
1399 // of these gives the maximum distance we need to cover.
1400 //
1401 // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1402 // that to get the full insetWidth.
1403 SkScalar maxOffset;
1404 if (rrect.isRect()) {
1405 // Manhattan distance works better for rects
1406 maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft -
1407 rrect.rect().fLeft),
1408 SkTAbs(spotShadowRRect.rect().fTop -
1409 rrect.rect().fTop)),
1410 SkTMax(SkTAbs(spotShadowRRect.rect().fRight -
1411 rrect.rect().fRight),
1412 SkTAbs(spotShadowRRect.rect().fBottom -
1413 rrect.rect().fBottom)));
1414 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001415 SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001416 SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1417 rrect.rect().fLeft + dr,
1418 spotShadowRRect.rect().fTop -
1419 rrect.rect().fTop + dr);
1420 SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1421 rrect.rect().fRight - dr,
1422 spotShadowRRect.rect().fBottom -
1423 rrect.rect().fBottom - dr);
Cary Clarkdf429f32017-11-08 11:44:31 -05001424 maxOffset = SkScalarSqrt(SkTMax(SkPointPriv::LengthSqd(upperLeftOffset),
1425 SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001426 }
Jim Van Verth4c8c1e82018-04-23 17:14:48 -04001427 insetWidth += SkTMax(blurOutset, maxOffset);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001428 }
1429
1430 // Outset the shadow rrect to the border of the penumbra
1431 SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1432 if (spotShadowRRect.isOval()) {
1433 spotShadowRRect = SkRRect::MakeOval(outsetRect);
1434 } else {
1435 SkScalar outsetRad = spotRadius + blurOutset;
1436 spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1437 }
1438
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001439 GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
Jim Van Verth34d6e4b2017-06-09 11:09:03 -04001440
Robert Phillips7c525e62018-06-12 10:11:12 -04001441 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1442 spotColor,
1443 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001444 spotShadowRRect,
Jim Van Verth1af03d42017-07-31 09:34:58 -04001445 2.0f * devSpaceSpotBlur,
Brian Salomon05969092017-07-13 11:20:51 -04001446 insetWidth);
1447 SkASSERT(op);
1448 this->addDrawOp(clip, std::move(op));
Jim Van Verth3af1af92017-05-18 15:06:54 -04001449 }
1450
1451 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -05001452}
1453
1454///////////////////////////////////////////////////////////////////////////////
1455
Brian Osman11052242016-10-27 14:47:55 -04001456bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001457 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001458 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001459 const SkMatrix& viewMatrix,
1460 const SkRRect& origOuter,
1461 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001462 SkASSERT(!origInner.isEmpty());
1463 SkASSERT(!origOuter.isEmpty());
1464
Brian Salomon65749212017-12-01 16:01:47 -05001465 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1466
Chris Dalton7d6748e2019-03-13 00:34:52 -06001467 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon45839f92017-12-04 09:02:35 -05001468
1469 if (GrAAType::kMSAA == aaType) {
1470 return false;
1471 }
1472
Greg Daniel2655ede2019-04-10 00:49:28 +00001473 if (GrAAType::kCoverage == aaType && SkRRectPriv::IsCircle(*inner)
1474 && SkRRectPriv::IsCircle(*outer)) {
Brian Salomon65749212017-12-01 16:01:47 -05001475 auto outerR = outer->width() / 2.f;
1476 auto innerR = inner->width() / 2.f;
1477 auto cx = outer->getBounds().fLeft + outerR;
1478 auto cy = outer->getBounds().fTop + outerR;
1479 if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
1480 SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
1481 auto avgR = (innerR + outerR) / 2.f;
1482 auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
1483 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
1484 stroke.setStrokeStyle(outerR - innerR);
Greg Daniel2655ede2019-04-10 00:49:28 +00001485 auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix,
Robert Phillips7c525e62018-06-12 10:11:12 -04001486 circleBounds, GrStyle(stroke, nullptr),
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001487 this->caps()->shaderCaps());
Brian Salomon65749212017-12-01 16:01:47 -05001488 if (op) {
1489 this->addDrawOp(clip, std::move(op));
1490 return true;
1491 }
Mike Klein16885072018-12-11 09:54:31 -05001492 assert_alive(paint);
Brian Salomon65749212017-12-01 16:01:47 -05001493 }
1494 }
1495
Ethan Nicholas0f3c7322017-11-09 14:51:17 -05001496 GrClipEdgeType innerEdgeType, outerEdgeType;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001497 if (GrAAType::kCoverage == aaType) {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001498 innerEdgeType = GrClipEdgeType::kInverseFillAA;
1499 outerEdgeType = GrClipEdgeType::kFillAA;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001500 } else {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001501 innerEdgeType = GrClipEdgeType::kInverseFillBW;
1502 outerEdgeType = GrClipEdgeType::kFillBW;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001503 }
robertphillips00095892016-02-29 13:50:40 -08001504
robertphillips00095892016-02-29 13:50:40 -08001505 SkMatrix inverseVM;
1506 if (!viewMatrix.isIdentity()) {
1507 if (!origInner.transform(viewMatrix, inner.writable())) {
1508 return false;
1509 }
1510 if (!origOuter.transform(viewMatrix, outer.writable())) {
1511 return false;
1512 }
1513 if (!viewMatrix.invert(&inverseVM)) {
1514 return false;
1515 }
1516 } else {
1517 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001518 }
robertphillips00095892016-02-29 13:50:40 -08001519
Ethan Nicholaseace9352018-10-15 20:09:54 +00001520 const auto& caps = *this->caps()->shaderCaps();
robertphillips00095892016-02-29 13:50:40 -08001521 // TODO these need to be a geometry processors
Ethan Nicholaseace9352018-10-15 20:09:54 +00001522 auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
robertphillips00095892016-02-29 13:50:40 -08001523 if (!innerEffect) {
1524 return false;
1525 }
1526
Ethan Nicholaseace9352018-10-15 20:09:54 +00001527 auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
robertphillips00095892016-02-29 13:50:40 -08001528 if (!outerEffect) {
1529 return false;
1530 }
1531
Brian Salomon82f44312017-01-11 13:42:54 -05001532 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1533 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001534
1535 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001536 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001537 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1538 }
halcanary9d524f22016-03-29 09:03:52 -07001539
Brian Salomon82f44312017-01-11 13:42:54 -05001540 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1541 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001542 return true;
1543}
1544
Brian Osman11052242016-10-27 14:47:55 -04001545void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001546 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001547 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001548 const SkMatrix& viewMatrix,
1549 const SkRRect& outer,
1550 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001551 ASSERT_SINGLE_OWNER
1552 RETURN_IF_ABANDONED
1553 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001554 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
robertphillips00095892016-02-29 13:50:40 -08001555
1556 SkASSERT(!outer.isEmpty());
1557 SkASSERT(!inner.isEmpty());
1558
Robert Phillips72152832017-01-25 17:31:35 -05001559 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001560
Brian Salomon82f44312017-01-11 13:42:54 -05001561 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001562 return;
1563 }
Mike Klein16885072018-12-11 09:54:31 -05001564 assert_alive(paint);
robertphillips00095892016-02-29 13:50:40 -08001565
1566 SkPath path;
1567 path.setIsVolatile(true);
1568 path.addRRect(inner);
1569 path.addRRect(outer);
1570 path.setFillType(SkPath::kEvenOdd_FillType);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001571 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path));
robertphillips00095892016-02-29 13:50:40 -08001572}
1573
robertphillipsea461502015-05-26 11:38:03 -07001574///////////////////////////////////////////////////////////////////////////////
1575
Brian Osman11052242016-10-27 14:47:55 -04001576void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001577 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001578 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001579 const SkMatrix& viewMatrix,
1580 const SkRegion& region,
Stan Iliev73d8fd92017-08-02 15:36:24 -04001581 const GrStyle& style,
1582 const GrUserStencilSettings* ss) {
msarettcc319b92016-08-25 18:07:18 -07001583 ASSERT_SINGLE_OWNER
1584 RETURN_IF_ABANDONED
1585 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001586 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
msarettcc319b92016-08-25 18:07:18 -07001587
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001588 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001589 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001590 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001591 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
Brian Salomon34169692017-08-28 15:32:01 -04001592 SkScalarIsInt(viewMatrix.getTranslateX()) &&
1593 SkScalarIsInt(viewMatrix.getTranslateY())) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001594 aa = GrAA::kNo;
1595 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001596 }
msarettcc319b92016-08-25 18:07:18 -07001597 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001598 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001599 SkPath path;
1600 region.getBoundaryPath(&path);
Robert Phillips46a13382018-08-23 13:53:01 -04001601 path.setIsVolatile(true);
1602
Brian Salomon82f44312017-01-11 13:42:54 -05001603 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001604 }
1605
Chris Dalton7d6748e2019-03-13 00:34:52 -06001606 GrAAType aaType = this->chooseAAType(GrAA::kNo);
Robert Phillips7c525e62018-06-12 10:11:12 -04001607 std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
1608 aaType, ss);
Brian Salomonf0366322017-07-11 15:53:05 -04001609 this->addDrawOp(clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001610}
1611
Brian Osman11052242016-10-27 14:47:55 -04001612void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001613 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001614 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001615 const SkMatrix& viewMatrix,
1616 const SkRect& oval,
1617 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001618 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001619 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001620 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001621 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -07001622
Robert Phillips7484d202018-07-03 09:09:08 -04001623 const SkStrokeRec& stroke = style.strokeRec();
1624
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001625 if (oval.isEmpty() && !style.pathEffect()) {
Robert Phillips7484d202018-07-03 09:09:08 -04001626 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
1627 return;
1628 }
1629
1630 this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001631 return;
robertphillipsea461502015-05-26 11:38:03 -07001632 }
1633
Robert Phillips72152832017-01-25 17:31:35 -05001634 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001635
Chris Dalton7d6748e2019-03-13 00:34:52 -06001636 GrAAType aaType = this->chooseAAType(aa);
Chris Dalton0dffbab2019-03-27 13:08:50 -06001637
1638 std::unique_ptr<GrDrawOp> op;
1639 if (style.isSimpleFill()) {
Chris Dalton82eb9e72019-03-21 14:26:39 -06001640 // GrFillRRectOp has special geometry and a fragment-shader branch to conditionally evaluate
1641 // the arc equation. This same special geometry and fragment branch also turn out to be a
1642 // substantial optimization for drawing ovals (namely, by not evaluating the arc equation
1643 // inside the oval's inner diamond). Given these optimizations, it's a clear win to draw
1644 // ovals the exact same way we do round rects.
Chris Daltonebc38c92018-11-28 16:58:09 -07001645 //
Greg Daniel2655ede2019-04-10 00:49:28 +00001646 // However, we still don't draw true circles as round rects in coverage mode, because it can
1647 // cause perf regressions on some platforms as compared to the dedicated circle Op.
1648 if (GrAAType::kCoverage != aaType || oval.height() != oval.width()) {
Chris Daltonbf341ae2019-03-27 00:28:22 +00001649 assert_alive(paint);
Chris Dalton0dffbab2019-03-27 13:08:50 -06001650 op = GrFillRRectOp::Make(fContext, aaType, viewMatrix, SkRRect::MakeOval(oval),
1651 *this->caps(), std::move(paint));
Chris Daltonbf341ae2019-03-27 00:28:22 +00001652 }
Chris Dalton0dffbab2019-03-27 13:08:50 -06001653 }
Greg Daniel2655ede2019-04-10 00:49:28 +00001654 if (!op && GrAAType::kCoverage == aaType) {
Chris Dalton0dffbab2019-03-27 13:08:50 -06001655 assert_alive(paint);
Greg Daniel2655ede2019-04-10 00:49:28 +00001656 op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
1657 this->caps()->shaderCaps());
Chris Dalton0dffbab2019-03-27 13:08:50 -06001658 }
1659 if (op) {
1660 this->addDrawOp(clip, std::move(op));
1661 return;
robertphillipsea461502015-05-26 11:38:03 -07001662 }
robertphillipsb56f9272016-02-25 11:03:52 -08001663
Mike Klein16885072018-12-11 09:54:31 -05001664 assert_alive(paint);
Brian Salomon5209d7f2018-04-20 16:52:42 -04001665 this->drawShapeUsingPathRenderer(
1666 clip, std::move(paint), aa, viewMatrix,
1667 GrShape(SkRRect::MakeOval(oval), SkPath::kCW_Direction, 2, false, style));
robertphillipsea461502015-05-26 11:38:03 -07001668}
1669
Brian Osman11052242016-10-27 14:47:55 -04001670void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001671 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001672 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001673 const SkMatrix& viewMatrix,
1674 const SkRect& oval,
1675 SkScalar startAngle,
1676 SkScalar sweepAngle,
1677 bool useCenter,
1678 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001679 ASSERT_SINGLE_OWNER
1680 RETURN_IF_ABANDONED
1681 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001682 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001683
1684 AutoCheckFlush acf(this->drawingManager());
1685
Chris Dalton7d6748e2019-03-13 00:34:52 -06001686 GrAAType aaType = this->chooseAAType(aa);
Greg Daniel2655ede2019-04-10 00:49:28 +00001687 if (GrAAType::kCoverage == aaType) {
1688 const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
1689 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
1690 std::move(paint),
1691 viewMatrix,
1692 oval,
1693 startAngle,
1694 sweepAngle,
1695 useCenter,
1696 style,
1697 shaderCaps);
1698 if (op) {
1699 this->addDrawOp(clip, std::move(op));
1700 return;
1701 }
1702 assert_alive(paint);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001703 }
Brian Salomone4949402018-04-26 15:22:04 -04001704 this->drawShapeUsingPathRenderer(
1705 clip, std::move(paint), aa, viewMatrix,
1706 GrShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001707}
1708
Brian Osman11052242016-10-27 14:47:55 -04001709void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001710 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001711 const SkMatrix& viewMatrix,
Brian Salomon2a943df2018-05-04 13:43:19 -04001712 sk_sp<GrTextureProxy> image,
1713 sk_sp<GrColorSpaceXform> csxf,
1714 GrSamplerState::Filter filter,
Brian Osman11052242016-10-27 14:47:55 -04001715 std::unique_ptr<SkLatticeIter> iter,
1716 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001717 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001718 RETURN_IF_ABANDONED
1719 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001720 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
joshualitt33a5fce2015-11-18 13:28:51 -08001721
Robert Phillips72152832017-01-25 17:31:35 -05001722 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001723
Brian Salomon2a943df2018-05-04 13:43:19 -04001724 std::unique_ptr<GrDrawOp> op =
Robert Phillips7c525e62018-06-12 10:11:12 -04001725 GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(image),
1726 std::move(csxf), filter, std::move(iter), dst);
Brian Salomon815486c2017-07-11 08:52:13 -04001727 this->addDrawOp(clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001728}
1729
Greg Daniel64cc9aa2018-10-19 13:54:56 -04001730void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
1731 const SkRect& bounds) {
1732 std::unique_ptr<GrOp> op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
1733 SkASSERT(op);
1734 this->getRTOpList()->addOp(std::move(op), *this->caps());
1735}
1736
Greg Daniel51316782017-08-02 15:10:09 +00001737GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO(
Greg Danielb9990e42019-04-10 16:28:52 -04001738 SkSurface::BackendSurfaceAccess access, GrFlushFlags flags, int numSemaphores,
Greg Danielbae71212019-03-01 15:24:35 -05001739 GrBackendSemaphore backendSemaphores[]) {
robertphillips8c523e02016-07-26 07:41:00 -07001740 ASSERT_SINGLE_OWNER
Robert Phillips6a6de562019-02-15 15:19:15 -05001741 if (fContext->priv().abandoned()) {
Robert Phillipsa9162df2019-02-11 14:12:03 -05001742 return GrSemaphoresSubmitted::kNo;
1743 }
robertphillips8c523e02016-07-26 07:41:00 -07001744 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001745 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext);
robertphillips8c523e02016-07-26 07:41:00 -07001746
Greg Daniel51316782017-08-02 15:10:09 +00001747 return this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get(),
Greg Danielbae71212019-03-01 15:24:35 -05001748 access, flags,
Greg Daniel51316782017-08-02 15:10:09 +00001749 numSemaphores,
1750 backendSemaphores);
Greg Daniela5cb7812017-06-16 09:45:32 -04001751}
1752
Greg Danielc64ee462017-06-15 16:59:49 -04001753bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001754 const GrBackendSemaphore waitSemaphores[]) {
Greg Daniela5cb7812017-06-16 09:45:32 -04001755 ASSERT_SINGLE_OWNER
Greg Danielc64ee462017-06-15 16:59:49 -04001756 RETURN_FALSE_IF_ABANDONED
Greg Daniela5cb7812017-06-16 09:45:32 -04001757 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001758 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
Greg Daniela5cb7812017-06-16 09:45:32 -04001759
1760 AutoCheckFlush acf(this->drawingManager());
1761
Greg Danielc64ee462017-06-15 16:59:49 -04001762 if (numSemaphores && !this->caps()->fenceSyncSupport()) {
1763 return false;
1764 }
1765
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001766 auto direct = fContext->priv().asDirectContext();
1767 if (!direct) {
1768 return false;
1769 }
1770
1771 auto resourceProvider = direct->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -05001772
Greg Daniela5cb7812017-06-16 09:45:32 -04001773 SkTArray<sk_sp<GrSemaphore>> semaphores(numSemaphores);
1774 for (int i = 0; i < numSemaphores; ++i) {
Robert Phillips6be756b2018-01-16 15:07:54 -05001775 sk_sp<GrSemaphore> sema = resourceProvider->wrapBackendSemaphore(
Greg Daniel17b7c052018-01-09 13:55:33 -05001776 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
1777 kAdopt_GrWrapOwnership);
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001778 std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(fContext, std::move(sema),
Robert Phillips7c525e62018-06-12 10:11:12 -04001779 fRenderTargetProxy.get()));
Greg Danielcb324152019-02-25 11:36:53 -05001780 this->getRTOpList()->addWaitOp(std::move(waitOp), *this->caps());
Greg Daniela5cb7812017-06-16 09:45:32 -04001781 }
Greg Danielc64ee462017-06-15 16:59:49 -04001782 return true;
robertphillips8c523e02016-07-26 07:41:00 -07001783}
joshualitt33a5fce2015-11-18 13:28:51 -08001784
Robert Phillips65a88fa2017-08-08 08:36:22 -04001785void GrRenderTargetContext::insertEventMarker(const SkString& str) {
Robert Phillips88a32ef2018-06-07 11:05:56 -04001786 std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fContext, fRenderTargetProxy.get(), str));
Robert Phillips65a88fa2017-08-08 08:36:22 -04001787 this->getRTOpList()->addOp(std::move(op), *this->caps());
1788}
1789
Robert Phillipsbe9aff22019-02-15 11:33:22 -05001790const GrCaps* GrRenderTargetContext::caps() const {
1791 return fContext->priv().caps();
1792}
1793
Brian Osman11052242016-10-27 14:47:55 -04001794void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001795 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001796 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001797 const SkMatrix& viewMatrix,
Brian Salomon40b77a62017-12-22 11:25:52 -05001798 const SkPath& path,
Brian Osman11052242016-10-27 14:47:55 -04001799 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001800 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001801 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001802 SkDEBUGCODE(this->validate();)
Robert Phillips20390c32018-08-17 11:01:03 -04001803 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPath", fContext);
1804
Brian Salomon40b77a62017-12-22 11:25:52 -05001805 GrShape shape(path, style);
Robert Phillips20390c32018-08-17 11:01:03 -04001806
Robert Phillips27927a52018-08-20 13:18:12 -04001807 this->drawShape(clip, std::move(paint), aa, viewMatrix, shape);
Robert Phillips20390c32018-08-17 11:01:03 -04001808}
1809
1810void GrRenderTargetContext::drawShape(const GrClip& clip,
1811 GrPaint&& paint,
1812 GrAA aa,
1813 const SkMatrix& viewMatrix,
1814 const GrShape& shape) {
1815 ASSERT_SINGLE_OWNER
1816 RETURN_IF_ABANDONED
1817 SkDEBUGCODE(this->validate();)
1818 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawShape", fContext);
1819
Brian Salomon2fad74a2017-12-20 13:28:55 -05001820 if (shape.isEmpty()) {
1821 if (shape.inverseFilled()) {
1822 this->drawPaint(clip, std::move(paint), viewMatrix);
1823 }
1824 return;
robertphillipsea461502015-05-26 11:38:03 -07001825 }
1826
Robert Phillips72152832017-01-25 17:31:35 -05001827 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001828
Brian Salomon2fad74a2017-12-20 13:28:55 -05001829 if (!shape.style().hasPathEffect()) {
Chris Dalton7d6748e2019-03-13 00:34:52 -06001830 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001831 SkRRect rrect;
1832 // We can ignore the starting point and direction since there is no path effect.
1833 bool inverted;
1834 if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
1835 if (rrect.isRect()) {
1836 this->drawRect(clip, std::move(paint), aa, viewMatrix, rrect.rect(),
1837 &shape.style());
1838 return;
1839 } else if (rrect.isOval()) {
1840 this->drawOval(clip, std::move(paint), aa, viewMatrix, rrect.rect(), shape.style());
robertphillipsea461502015-05-26 11:38:03 -07001841 return;
1842 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001843 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect, shape.style());
1844 return;
Robert Phillips73653b42018-08-22 12:42:42 -04001845 } else if (GrAAType::kCoverage == aaType && shape.style().isSimpleFill() &&
1846 viewMatrix.rectStaysRect()) {
1847 // TODO: the rectStaysRect restriction could be lifted if we were willing to apply
1848 // the matrix to all the points individually rather than just to the rect
1849 SkRect rects[2];
1850 if (shape.asNestedRects(rects)) {
1851 // Concave AA paths are expensive - try to avoid them for special cases
Michael Ludwig72ab3462018-12-10 12:43:36 -05001852 std::unique_ptr<GrDrawOp> op = GrStrokeRectOp::MakeNested(
Robert Phillips73653b42018-08-22 12:42:42 -04001853 fContext, std::move(paint), viewMatrix, rects);
1854 if (op) {
1855 this->addDrawOp(clip, std::move(op));
1856 }
1857 // Returning here indicates that there is nothing to draw in this case.
1858 return;
1859 }
robertphillipsea461502015-05-26 11:38:03 -07001860 }
1861 }
robertphillips4bc31812016-03-01 12:22:49 -08001862
Brian Salomon2fad74a2017-12-20 13:28:55 -05001863 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, shape);
robertphillipsea461502015-05-26 11:38:03 -07001864}
1865
Chris Daltonbbfd5162017-11-07 13:35:22 -07001866bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -04001867 const GrUserStencilSettings* ss,
1868 SkRegion::Op op,
1869 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001870 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001871 const SkMatrix& viewMatrix,
1872 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001873 ASSERT_SINGLE_OWNER_PRIV
1874 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001875 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001876 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
1877 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -08001878
1879 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001880 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001881 SkRect::MakeIWH(fRenderTargetContext->width(),
1882 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001883 return true;
1884 }
1885
Robert Phillips72152832017-01-25 17:31:35 -05001886 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001887
1888 // An Assumption here is that path renderer would use some form of tweaking
1889 // the src color (either the input alpha or in the frag shader) to implement
1890 // aa. If we have some future driver-mojo path AA that can do the right
1891 // thing WRT to the blend then we'll need some query on the PR.
Chris Dalton09e56892019-03-13 00:22:01 -06001892 auto aaTypeFlags = choose_path_aa_type_flags(
1893 aa, fRenderTargetContext->fsaaType(), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -07001894 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001895
Chris Daltondb91c6e2017-09-08 16:25:08 -06001896 SkIRect clipConservativeBounds;
1897 clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(),
1898 &clipConservativeBounds, nullptr);
1899
bsalomon8acedde2016-06-24 10:42:16 -07001900 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001901 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001902 canDrawArgs.fCaps = fRenderTargetContext->caps();
robertphillips391395d2016-03-02 09:26:36 -08001903 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001904 canDrawArgs.fShape = &shape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06001905 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Chris Dalton09e56892019-03-13 00:22:01 -06001906 canDrawArgs.fAATypeFlags = aaTypeFlags;
Greg Danielbe7fc462019-01-03 16:40:42 -05001907 SkASSERT(!fRenderTargetContext->wrapsVkSecondaryCB());
1908 canDrawArgs.fTargetIsWrappedVkSecondaryCB = false;
cdalton93a379b2016-05-11 13:58:08 -07001909 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001910
1911 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001912 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001913 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001914 if (!pr) {
1915 return false;
1916 }
1917
1918 GrPaint paint;
1919 paint.setCoverageSetOpXPFactory(op, invert);
1920
Brian Salomonf3569f02017-10-24 12:52:33 -04001921 GrPathRenderer::DrawPathArgs args{fRenderTargetContext->drawingManager()->getContext(),
1922 std::move(paint),
1923 ss,
1924 fRenderTargetContext,
1925 &clip,
1926 &clipConservativeBounds,
1927 &viewMatrix,
1928 &shape,
Chris Dalton09e56892019-03-13 00:22:01 -06001929 aaTypeFlags,
Brian Osman34ec3742018-07-03 10:40:57 -04001930 fRenderTargetContext->colorSpaceInfo().isLinearlyBlended()};
robertphillips391395d2016-03-02 09:26:36 -08001931 pr->drawPath(args);
1932 return true;
1933}
1934
Brian Osman11052242016-10-27 14:47:55 -04001935SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001936 ASSERT_SINGLE_OWNER_PRIV
1937
Robert Phillips6a6de562019-02-15 15:19:15 -05001938 if (fRenderTargetContext->fContext->priv().abandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001939 return SkBudgeted::kNo;
1940 }
1941
Brian Osman11052242016-10-27 14:47:55 -04001942 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001943
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001944 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001945}
1946
Brian Salomon2fad74a2017-12-20 13:28:55 -05001947void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
1948 GrPaint&& paint,
1949 GrAA aa,
1950 const SkMatrix& viewMatrix,
1951 const GrShape& originalShape) {
joshualitt1de610a2016-01-06 08:26:09 -08001952 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001953 RETURN_IF_ABANDONED
Brian Salomondcbb9d92017-07-19 10:53:20 -04001954 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
1955
Jim Van Verthf86073a2018-10-02 13:05:38 -04001956 if (!viewMatrix.isFinite() || !originalShape.bounds().isFinite()) {
1957 return;
1958 }
1959
Chris Daltondb91c6e2017-09-08 16:25:08 -06001960 SkIRect clipConservativeBounds;
1961 clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr);
1962
Brian Salomon2fad74a2017-12-20 13:28:55 -05001963 GrShape tempShape;
Chris Dalton09e56892019-03-13 00:22:01 -06001964 auto aaTypeFlags = choose_path_aa_type_flags(aa, this->fsaaType(), *this->caps());
1965
robertphillips68737822015-10-29 12:12:21 -07001966 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001967 canDrawArgs.fCaps = this->caps();
robertphillips68737822015-10-29 12:12:21 -07001968 canDrawArgs.fViewMatrix = &viewMatrix;
Brian Salomon2fad74a2017-12-20 13:28:55 -05001969 canDrawArgs.fShape = &originalShape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06001970 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Greg Danielbe7fc462019-01-03 16:40:42 -05001971 canDrawArgs.fTargetIsWrappedVkSecondaryCB = this->wrapsVkSecondaryCB();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001972 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001973
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001974 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001975 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon2fad74a2017-12-20 13:28:55 -05001976 if (originalShape.isEmpty() && !originalShape.inverseFilled()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001977 return;
1978 }
1979
Chris Dalton09e56892019-03-13 00:22:01 -06001980 canDrawArgs.fAATypeFlags = aaTypeFlags;
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001981
1982 // Try a 1st time without applying any of the style to the geometry (and barring sw)
1983 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
1984 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1985
Brian Salomon2fad74a2017-12-20 13:28:55 -05001986 if (!pr && originalShape.style().pathEffect()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001987 // It didn't work above, so try again with the path effect applied.
Brian Salomon2fad74a2017-12-20 13:28:55 -05001988 tempShape = originalShape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1989 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001990 return;
1991 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001992 canDrawArgs.fShape = &tempShape;
Robert Phillips72152832017-01-25 17:31:35 -05001993 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001994 }
1995 if (!pr) {
Brian Salomon2fad74a2017-12-20 13:28:55 -05001996 if (canDrawArgs.fShape->style().applies()) {
1997 tempShape = canDrawArgs.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
1998 styleScale);
1999 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07002000 return;
2001 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05002002 canDrawArgs.fShape = &tempShape;
Brian Salomone7df0bb2018-05-07 14:44:57 -04002003 // This time, allow SW renderer
2004 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
2005 } else {
2006 pr = this->drawingManager()->getSoftwarePathRenderer();
bsalomon6663acf2016-05-10 09:14:17 -07002007 }
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05002008 }
robertphillipsea461502015-05-26 11:38:03 -07002009
bsalomon8acedde2016-06-24 10:42:16 -07002010 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07002011#ifdef SK_DEBUG
2012 SkDebugf("Unable to find path renderer compatible with path.\n");
2013#endif
2014 return;
2015 }
2016
Robert Phillips256c37b2017-03-01 14:32:46 -05002017 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05002018 std::move(paint),
2019 &GrUserStencilSettings::kUnused,
2020 this,
2021 &clip,
Chris Daltondb91c6e2017-09-08 16:25:08 -06002022 &clipConservativeBounds,
Brian Salomon82f44312017-01-11 13:42:54 -05002023 &viewMatrix,
Brian Salomon2fad74a2017-12-20 13:28:55 -05002024 canDrawArgs.fShape,
Chris Dalton09e56892019-03-13 00:22:01 -06002025 aaTypeFlags,
Brian Osman34ec3742018-07-03 10:40:57 -04002026 this->colorSpaceInfo().isLinearlyBlended()};
bsalomon0aff2fa2015-07-31 06:48:27 -07002027 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07002028}
2029
Brian Salomon467921e2017-03-06 16:17:12 -05002030static void op_bounds(SkRect* bounds, const GrOp* op) {
2031 *bounds = op->bounds();
2032 if (op->hasZeroArea()) {
2033 if (op->hasAABloat()) {
2034 bounds->outset(0.5f, 0.5f);
2035 } else {
2036 // We don't know which way the particular GPU will snap lines or points at integer
2037 // coords. So we ensure that the bounds is large enough for either snap.
2038 SkRect before = *bounds;
2039 bounds->roundOut(bounds);
2040 if (bounds->fLeft == before.fLeft) {
2041 bounds->fLeft -= 1;
2042 }
2043 if (bounds->fTop == before.fTop) {
2044 bounds->fTop -= 1;
2045 }
2046 if (bounds->fRight == before.fRight) {
2047 bounds->fRight += 1;
2048 }
2049 if (bounds->fBottom == before.fBottom) {
2050 bounds->fBottom += 1;
2051 }
2052 }
2053 }
2054}
2055
Brian Salomon348a0372018-10-31 10:42:18 -04002056void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
2057 const std::function<WillAddOpFn>& willAddFn) {
joshualitt1de610a2016-01-06 08:26:09 -08002058 ASSERT_SINGLE_OWNER
Robert Phillips69893702019-02-22 11:16:30 -05002059 if (fContext->priv().abandoned()) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002060 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002061 return;
Robert Phillipsc0138922017-03-08 11:50:55 -05002062 }
robertphillips2e1e51f2015-10-15 08:01:48 -07002063 SkDEBUGCODE(this->validate();)
Ethan Nicholas029b22c2018-10-18 16:49:56 -04002064 SkDEBUGCODE(op->fAddDrawOpCalled = true;)
Brian Salomondcbb9d92017-07-19 10:53:20 -04002065 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -07002066
Brian Salomon467921e2017-03-06 16:17:12 -05002067 // Setup clip
2068 SkRect bounds;
2069 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04002070 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04002071 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
2072 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
2073 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
2074 &bounds)) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002075 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002076 return;
Brian Salomon54d212e2017-03-21 14:22:38 -04002077 }
2078
Brian Salomon54d212e2017-03-21 14:22:38 -04002079 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
2080 appliedClip.hasStencilClip()) {
Michael Ludwigc39d0c82019-01-15 10:03:43 -05002081 if (this->caps()->performStencilClearsAsDraws()) {
2082 // Must use an op to perform the clear of the stencil buffer before this op, but only
2083 // have to clear the first time any draw needs it (this also ensures we don't loop
2084 // forever when the internal stencil clear adds a draw op that has stencil settings).
2085 if (!fRenderTargetProxy->needsStencil()) {
2086 // Send false so that the stencil buffer is fully cleared to 0
2087 this->internalStencilClear(GrFixedClip::Disabled(), /* inside mask */ false);
2088 }
2089 } else {
2090 // Just make sure the stencil buffer is cleared before the draw op, easy to do it as
2091 // a load at the start
2092 this->getRTOpList()->setStencilLoadOp(GrLoadOp::kClear);
2093 }
Robert Phillips95214472017-08-08 18:00:03 -04002094
Robert Phillips65048132017-08-10 08:44:49 -04002095 this->setNeedsStencil();
Brian Salomon54d212e2017-03-21 14:22:38 -04002096 }
2097
Brian Osman5ced0bf2019-03-15 10:15:29 -04002098 GrClampType clampType = GrPixelConfigClampType(this->colorSpaceInfo().config());
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002099 GrXferProcessor::DstProxy dstProxy;
Brian Osman5ced0bf2019-03-15 10:15:29 -04002100 GrProcessorSet::Analysis analysis = op->finalize(
2101 *this->caps(), &appliedClip, this->fsaaType(), clampType);
Chris Dalton945ee652019-01-23 09:10:36 -07002102 if (analysis.requiresDstTexture()) {
Brian Salomon09181ef2018-11-14 13:39:51 -05002103 if (!this->setupDstProxy(this->asRenderTargetProxy(), clip, *op, &dstProxy)) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002104 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002105 return;
Brian Salomon54d212e2017-03-21 14:22:38 -04002106 }
2107 }
2108
2109 op->setClippedBounds(bounds);
Brian Salomon348a0372018-10-31 10:42:18 -04002110 auto opList = this->getRTOpList();
2111 if (willAddFn) {
2112 willAddFn(op.get(), opList->uniqueID());
2113 }
Chris Dalton945ee652019-01-23 09:10:36 -07002114 opList->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxy, *this->caps());
Brian Salomon54d212e2017-03-21 14:22:38 -04002115}
2116
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002117bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
Brian Salomon09181ef2018-11-14 13:39:51 -05002118 const GrOp& op,
Robert Phillips16d8ec62017-07-27 16:16:25 -04002119 GrXferProcessor::DstProxy* dstProxy) {
Greg Danielbe7fc462019-01-03 16:40:42 -05002120 // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
2121 // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
2122 // start and stop the render pass in order to make the copy.
2123 if (rtProxy->wrapsVkSecondaryCB()) {
2124 return false;
2125 }
2126
Brian Salomon467921e2017-03-06 16:17:12 -05002127 if (this->caps()->textureBarrierSupport()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04002128 if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
Brian Salomon467921e2017-03-06 16:17:12 -05002129 // The render target is a texture, so we can read from it directly in the shader. The XP
2130 // will be responsible to detect this situation and request a texture barrier.
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002131 dstProxy->setProxy(sk_ref_sp(texProxy));
2132 dstProxy->setOffset(0, 0);
Robert Phillipsbf25d432017-04-07 10:08:53 -04002133 return true;
Brian Salomon467921e2017-03-06 16:17:12 -05002134 }
2135 }
2136
Robert Phillipsbf25d432017-04-07 10:08:53 -04002137 SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
Brian Salomon467921e2017-03-06 16:17:12 -05002138
Eric Karl74480882017-04-03 14:49:05 -07002139 SkIRect clippedRect;
Robert Phillipsbf25d432017-04-07 10:08:53 -04002140 clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
Brian Salomon09181ef2018-11-14 13:39:51 -05002141 SkRect opBounds = op.bounds();
2142 // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by
2143 // 0.5 pixels.
2144 if (op.hasAABloat() || op.hasZeroArea()) {
2145 opBounds.outset(0.5f, 0.5f);
2146 // An antialiased/hairline draw can sometimes bleed outside of the clips bounds. For
2147 // performance we may ignore the clip when the draw is entirely inside the clip is float
2148 // space but will hit pixels just outside the clip when actually rasterizing.
2149 clippedRect.outset(1, 1);
2150 clippedRect.intersect(SkIRect::MakeWH(rtProxy->width(), rtProxy->height()));
2151 }
2152 SkIRect opIBounds;
2153 opBounds.roundOut(&opIBounds);
2154 if (!clippedRect.intersect(opIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05002155#ifdef SK_DEBUG
Robert Phillipsbf25d432017-04-07 10:08:53 -04002156 GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
Brian Salomon467921e2017-03-06 16:17:12 -05002157#endif
Robert Phillipsbf25d432017-04-07 10:08:53 -04002158 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05002159 }
2160
2161 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
2162 // have per-sample dst values by making the copy multisampled.
2163 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07002164 bool rectsMustMatch = false;
2165 bool disallowSubrect = false;
Brian Salomon2a4f9832018-03-03 22:43:43 -05002166 GrSurfaceOrigin origin;
2167 if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &origin, &rectsMustMatch,
2168 &disallowSubrect)) {
Brian Salomon467921e2017-03-06 16:17:12 -05002169 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillipsbf25d432017-04-07 10:08:53 -04002170 desc.fConfig = rtProxy->config();
Greg Daniel1efe3222018-04-04 14:02:51 -04002171 origin = rtProxy->origin();
Brian Salomon467921e2017-03-06 16:17:12 -05002172 }
2173
Eric Karl74480882017-04-03 14:49:05 -07002174 if (!disallowSubrect) {
2175 copyRect = clippedRect;
2176 }
Brian Salomon467921e2017-03-06 16:17:12 -05002177
Robert Phillipsbf25d432017-04-07 10:08:53 -04002178 SkIPoint dstPoint, dstOffset;
2179 SkBackingFit fit;
Eric Karl74480882017-04-03 14:49:05 -07002180 if (rectsMustMatch) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04002181 desc.fWidth = rtProxy->width();
2182 desc.fHeight = rtProxy->height();
Eric Karl74480882017-04-03 14:49:05 -07002183 dstPoint = {copyRect.fLeft, copyRect.fTop};
2184 dstOffset = {0, 0};
Robert Phillipsbf25d432017-04-07 10:08:53 -04002185 fit = SkBackingFit::kExact;
Eric Karl74480882017-04-03 14:49:05 -07002186 } else {
2187 desc.fWidth = copyRect.width();
2188 desc.fHeight = copyRect.height();
2189 dstPoint = {0, 0};
2190 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillipsbf25d432017-04-07 10:08:53 -04002191 fit = SkBackingFit::kApprox;
Eric Karl74480882017-04-03 14:49:05 -07002192 }
Brian Salomon467921e2017-03-06 16:17:12 -05002193
Greg Daniel4065d452018-11-16 15:43:41 -05002194 SkASSERT(rtProxy->backendFormat().textureType() == GrTextureType::k2D);
2195 const GrBackendFormat& format = rtProxy->backendFormat();
Robert Phillips9da87e02019-02-04 13:26:26 -05002196 sk_sp<GrSurfaceContext> sContext = fContext->priv().makeDeferredSurfaceContext(
Greg Daniel4065d452018-11-16 15:43:41 -05002197 format, desc, origin, GrMipMapped::kNo, fit, SkBudgeted::kYes,
Brian Salomonf802e752018-02-13 17:13:31 -05002198 sk_ref_sp(this->colorSpaceInfo().colorSpace()));
Robert Phillipsbf25d432017-04-07 10:08:53 -04002199 if (!sContext) {
2200 SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
2201 return false;
2202 }
2203
2204 if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
2205 SkDebugf("setupDstTexture: copy failed.\n");
2206 return false;
2207 }
2208
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002209 dstProxy->setProxy(sContext->asTextureProxyRef());
2210 dstProxy->setOffset(dstOffset);
Robert Phillipsbf25d432017-04-07 10:08:53 -04002211 return true;
robertphillips2334fb62015-06-17 05:43:33 -07002212}