blob: 6c56750c8aab4348973631d8be14643e0e823a67 [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 Salomon0f353322017-05-03 20:58:59 +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 Dalton133944a2018-11-16 23:30:29 -050053#include "ops/GrAAFillRRectOp.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()) {
325 isFull = !clip.scissorEnabled() ||
326 (CanClearFullscreen::kYes == canClearFullscreen &&
327 this->caps()->preferFullscreenClears()) ||
328 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
329 }
330
331 if (isFull) {
332 if (this->getRTOpList()->resetForFullscreenClear() &&
333 !this->caps()->performColorClearsAsDraws()) {
334 // The op list was emptied and native clears are allowed, so just use the load op
335 this->getRTOpList()->setColorLoadOp(GrLoadOp::kClear, color);
336 return;
337 } else {
338 // Will use an op for the clear, reset the load op to discard since the op will
339 // blow away the color buffer contents
340 this->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
341 }
342
343 // Must add an op to the list (either because we couldn't use a load op, or because the
344 // clear load op isn't supported)
345 if (this->caps()->performColorClearsAsDraws()) {
346 SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
347 GrPaint paint;
348 clear_to_grpaint(color, &paint);
349 this->addDrawOp(GrFixedClip::Disabled(),
350 GrFillRectOp::Make(fContext, std::move(paint),
351 GrAAType::kNone, SkMatrix::I(), rtRect));
352 } else {
353 this->getRTOpList()->addOp(GrClearOp::Make(fContext, SkIRect::MakeEmpty(), color,
354 /* fullscreen */ true), *this->caps());
355 }
356 } else {
357 if (this->caps()->performPartialClearsAsDraws()) {
358 // performPartialClearsAsDraws() also returns true if any clear has to be a draw.
359 SkRect scissor = SkRect::Make(clip.scissorRect());
360 GrPaint paint;
361 clear_to_grpaint(color, &paint);
362
363 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), GrAAType::kNone,
364 SkMatrix::I(), scissor));
365 } else {
366 std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
367 this->asSurfaceProxy()));
368 // This version of the clear op factory can return null if the clip doesn't intersect
369 // with the surface proxy's boundary
370 if (!op) {
371 return;
372 }
373 this->getRTOpList()->addOp(std::move(op), *this->caps());
374 }
375 }
376}
377
Brian Osman9a9baae2018-11-05 15:06:26 -0500378void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const SkPMColor4f& color) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500379 ASSERT_SINGLE_OWNER_PRIV
380 RETURN_IF_ABANDONED_PRIV
381 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400382 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "absClear",
383 fRenderTargetContext->fContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500384
Robert Phillips72152832017-01-25 17:31:35 -0500385 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500386
Brian Salomonbb5711a2017-05-17 13:49:59 -0400387 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(),
388 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500389
390 if (clearRect) {
391 if (clearRect->contains(rtRect)) {
392 clearRect = nullptr; // full screen
393 } else {
394 if (!rtRect.intersect(*clearRect)) {
395 return;
396 }
397 }
398 }
399
400 // TODO: in a post-MDB world this should be handled at the OpList level.
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500401 // This makes sure to always add an op to the list, instead of marking the clear as a load op.
402 // This code follows very similar logic to internalClear() below, but critical differences are
403 // highlighted in line related to absClear()'s unique behavior.
404 if (clearRect) {
405 if (fRenderTargetContext->caps()->performPartialClearsAsDraws()) {
Ethan Nicholas56d19a52018-10-15 11:26:20 -0400406 GrPaint paint;
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500407 clear_to_grpaint(color, &paint);
408
409 // Use the disabled clip; the rect geometry already matches the clear rectangle and
410 // if it were added to a scissor, that would be intersected with the logical surface
411 // bounds and not the worst case dimensions required here.
412 fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
413 GrFillRectOp::Make(fRenderTargetContext->fContext,
414 std::move(paint),
415 GrAAType::kNone,
416 SkMatrix::I(),
417 SkRect::Make(rtRect)));
418 } else {
419 // Must use the ClearOp factory that takes a boolean (false) instead of a surface
420 // proxy. The surface proxy variant would intersect the clip rect with its logical
421 // bounds, which is not desired in this special case.
422 fRenderTargetContext->getRTOpList()->addOp(
423 GrClearOp::Make(fRenderTargetContext->fContext, rtRect, color,
424 /* fullscreen */ false),
425 *fRenderTargetContext->caps());
csmartdalton29df7602016-08-31 11:55:52 -0700426 }
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500427 } else {
428 // Reset the oplist like in internalClear(), but do not rely on a load op for the clear
429 fRenderTargetContext->getRTOpList()->resetForFullscreenClear();
430 fRenderTargetContext->getRTOpList()->setColorLoadOp(GrLoadOp::kDiscard);
431
432 if (fRenderTargetContext->caps()->performColorClearsAsDraws()) {
433 // This draws a quad covering the worst case dimensions instead of just the logical
434 // width and height like in internalClear().
435 GrPaint paint;
436 clear_to_grpaint(color, &paint);
437 fRenderTargetContext->addDrawOp(GrFixedClip::Disabled(),
438 GrFillRectOp::Make(fRenderTargetContext->fContext,
439 std::move(paint),
440 GrAAType::kNone,
441 SkMatrix::I(),
442 SkRect::Make(rtRect)));
443 } else {
444 // Nothing special about this path in absClear compared to internalClear()
445 fRenderTargetContext->getRTOpList()->addOp(
446 GrClearOp::Make(fRenderTargetContext->fContext, SkIRect::MakeEmpty(), color,
447 /* fullscreen */ true),
448 *fRenderTargetContext->caps());
Ethan Nicholas56d19a52018-10-15 11:26:20 -0400449 }
robertphillips9199a9f2016-07-13 07:48:43 -0700450 }
robertphillipsea461502015-05-26 11:38:03 -0700451}
452
Brian Osman11052242016-10-27 14:47:55 -0400453void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500454 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400455 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800456 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700457 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700458 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400459 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPaint", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700460
robertphillipsea461502015-05-26 11:38:03 -0700461 // set rect to be big enough to fill the space, but not super-huge, so we
462 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700463
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400464 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700465
Michael Ludwig61a16512019-01-15 11:15:13 -0500466 // Check if we can optimize a clipped drawPaint(). We only do the transformation when there are
467 // no fragment processors because they may depend on having correct local coords and this path
468 // draws in device space without a local matrix. It currently handles converting clipRRect()
469 // to drawRRect() and solid colors to screen-filling drawRects() (which are then converted into
470 // clears if possible in drawRect).
Michael Ludwig3d6390e2018-10-09 11:45:16 -0400471 if (!paint.numTotalFragmentProcessors()) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500472 SkRRect rrect;
473 GrAA aa = GrAA::kNo;
474 if (clip.isRRect(r, &rrect, &aa)) {
475 if (rrect.isRect()) {
476 // Use drawFilledRect() with no clip and the reduced rectangle
477 this->drawFilledRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect.rect());
478 } else {
479 // Use drawRRect() with no clip
480 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
481 GrStyle::SimpleFill());
482 }
483 } else {
484 // Use drawFilledRect() with no view matrix to draw a fullscreen quad, but preserve
485 // the clip. Since the paint has no FPs we can drop the view matrix without worrying
486 // about local coordinates. If the clip is simple, drawFilledRect() will turn this into
487 // a clear or a scissored clear.
488 this->drawFilledRect(clip, std::move(paint), aa, SkMatrix::I(), r);
Michael Ludwig3d6390e2018-10-09 11:45:16 -0400489 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500490 return;
bsalomoncb31e512016-08-26 10:48:19 -0700491 }
492
Michael Ludwig61a16512019-01-15 11:15:13 -0500493 // Since the paint is not trivial, there's no way at this point drawRect() could have converted
494 // this drawPaint() into an optimized clear. drawRect() would then use GrFillRectOp without
495 // a local matrix, so we can simplify things and use the local matrix variant to draw a screen
496 // filling rect with the inverse view matrix for local coords, which works for all matrix
497 // conditions.
498 SkMatrix localMatrix;
499 if (!viewMatrix.invert(&localMatrix)) {
500 return;
robertphillipsea461502015-05-26 11:38:03 -0700501 }
Michael Ludwig61a16512019-01-15 11:15:13 -0500502
503 AutoCheckFlush acf(this->drawingManager());
504 std::unique_ptr<GrDrawOp> op = GrFillRectOp::MakeWithLocalMatrix(
505 fContext, std::move(paint), GrAAType::kNone, SkMatrix::I(), localMatrix, r);
506 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700507}
508
robertphillipsea461502015-05-26 11:38:03 -0700509static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
510 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
511 point.fY >= rect.fTop && point.fY <= rect.fBottom;
512}
513
csmartdalton97f6cd52016-07-13 13:37:08 -0700514// Attempts to crop a rect and optional local rect to the clip boundaries.
515// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700516static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700517 const SkMatrix& viewMatrix, SkRect* rect,
518 SkRect* localRect = nullptr) {
519 if (!viewMatrix.rectStaysRect()) {
520 return true;
521 }
522
csmartdalton97f6cd52016-07-13 13:37:08 -0700523 SkIRect clipDevBounds;
524 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700525
robertphillips13a7eee2016-08-31 15:06:24 -0700526 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700527 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
528 return false;
529 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700530
531 if (localRect) {
532 if (!rect->intersects(clipBounds)) {
533 return false;
534 }
535 const SkScalar dx = localRect->width() / rect->width();
536 const SkScalar dy = localRect->height() / rect->height();
537 if (clipBounds.fLeft > rect->fLeft) {
538 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
539 rect->fLeft = clipBounds.fLeft;
540 }
541 if (clipBounds.fTop > rect->fTop) {
542 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
543 rect->fTop = clipBounds.fTop;
544 }
545 if (clipBounds.fRight < rect->fRight) {
546 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
547 rect->fRight = clipBounds.fRight;
548 }
549 if (clipBounds.fBottom < rect->fBottom) {
550 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
551 rect->fBottom = clipBounds.fBottom;
552 }
553 return true;
554 }
555
556 return rect->intersect(clipBounds);
557}
558
Michael Ludwig61a16512019-01-15 11:15:13 -0500559bool GrRenderTargetContext::drawFilledRectAsClear(const GrClip& clip, GrPaint&& paint, GrAA aa,
560 const SkMatrix& viewMatrix, const SkRect& rect) {
561 // Rules for a filled rect to become a clear [+scissor]:
562 // 1. The paint is a constant blend color with no other FPs
563 // 2. The view matrix maps rectangles to rectangles, or the transformed quad fully covers
564 // the render target (or clear region in #3).
565 // 3. The clip is an intersection of rectangles, so the clear region will be the
566 // intersection of the clip and the provided rect.
567 // 4. The clear region aligns with pixel bounds
568 // 5. There are no user stencil settings (and since the clip was IOR, the clip won't need
569 // to use the stencil either).
570 // If all conditions pass, the filled rect can either be a fullscreen clear (if it's big
571 // enough), or the rectangle geometry will be used as the scissor clip on the clear.
572 // If everything passes but rule #4, this submits a simplified fill rect op instead so that the
573 // rounding differences between clip and draws don't fight each other.
574 // NOTE: we route draws into clear() regardless of performColorClearsAsDraws() since the
575 // clear call is allowed to reset the oplist even when it also happens to use a GrFillRectOp.
576
577 SkPMColor4f clearColor;
578 if (paint.numCoverageFragmentProcessors() > 0 || !paint.isConstantBlendedColor(&clearColor)) {
579 return false;
580 }
581
582 const SkRect rtRect = fRenderTargetProxy->getBoundsRect();
583 // Will be the intersection of render target, clip, and quad
584 SkRect combinedRect = rtRect;
585
586 SkRRect clipRRect;
587 GrAA clipAA;
588 if (!clip.quickContains(rtRect)) {
589 // If the clip is an rrect with no rounding, then it can replace the full RT bounds as the
590 // limiting region, although we will have to worry about AA. If the clip is anything
591 // more complicated, just punt to the regular fill rect op.
592 if (!clip.isRRect(rtRect, &clipRRect, &clipAA) || !clipRRect.isRect()) {
593 return false;
594 }
595 combinedRect = clipRRect.rect();
596 } else {
597 // The clip is outside the render target, so the clip can be ignored
598 clipAA = GrAA::kNo;
599 }
600
601 if (viewMatrix.rectStaysRect()) {
602 // Skip the extra overhead of inverting the view matrix to see if rtRect is contained in the
603 // drawn rectangle, and instead just intersect rtRect with the transformed rect. It will be
604 // the new clear region.
605 if (!combinedRect.intersect(viewMatrix.mapRect(rect))) {
606 // No intersection means nothing should be drawn, so return true but don't add an op
607 return true;
608 }
609 } else {
610 // If the transformed rectangle does not contain the combined rt and clip, the draw is too
611 // complex to be implemented as a clear
612 SkMatrix invM;
613 if (!viewMatrix.invert(&invM)) {
614 return false;
615 }
616 // The clip region in the rect's local space, so the test becomes the local rect containing
617 // the quad's points.
Michael Ludwige9c57d32019-02-13 13:39:39 -0500618 GrQuad quad = GrQuad::MakeFromRect(rtRect, invM);
Michael Ludwig61a16512019-01-15 11:15:13 -0500619 if (!rect_contains_inclusive(rect, quad.point(0)) ||
620 !rect_contains_inclusive(rect, quad.point(1)) ||
621 !rect_contains_inclusive(rect, quad.point(2)) ||
622 !rect_contains_inclusive(rect, quad.point(3))) {
623 // No containment, so rtRect can't be filled by a solid color
624 return false;
625 }
626 // combinedRect can be filled by a solid color but doesn't need to be modified since it's
627 // inside the quad to be drawn.
628 }
629
630 // Almost every condition is met; now it requires that the combined rect align with pixel
631 // boundaries in order for it to become a scissor-clear. Ignore the AA status in this case
632 // since non-AA with partial-pixel coordinates can be rounded differently on the GPU,
633 // leading to unexpected differences between a scissor test and a rasterized quad.
634 // Also skip very small rectangles since the scissor+clear doesn't by us much then.
635 if (combinedRect.contains(rtRect)) {
636 // Full screen clear
637 this->clear(nullptr, clearColor, CanClearFullscreen::kYes);
638 return true;
639 } else if (GrClip::IsPixelAligned(combinedRect) &&
640 combinedRect.width() > 256 && combinedRect.height() > 256) {
641 // Scissor + clear (round shouldn't do anything since we are pixel aligned)
642 SkIRect scissorRect;
643 combinedRect.round(&scissorRect);
644 this->clear(&scissorRect, clearColor, CanClearFullscreen::kNo);
645 return true;
646 }
647
648 // If we got here, we can't use a scissor + clear, but combinedRect represents the correct
649 // geometry combination of quad + clip so we can perform a simplified fill rect op. We do this
650 // mostly to avoid mismatches in rounding logic on the CPU vs. the GPU, which frequently appears
651 // when drawing and clipping something to the same non-AA rect that never-the-less has
652 // non-integer coordinates.
653
654 // For AA, use non-AA only when both clip and draw are non-AA.
655 if (clipAA == GrAA::kYes) {
656 aa = GrAA::kYes;
657 }
Chris Dalton7d6748e2019-03-13 00:34:52 -0600658 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig61a16512019-01-15 11:15:13 -0500659 this->addDrawOp(GrFixedClip::Disabled(),
660 GrFillRectOp::Make(fContext, std::move(paint), aaType, SkMatrix::I(),
661 combinedRect));
662 return true;
663}
664
665void GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500666 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500667 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400668 const SkMatrix& viewMatrix,
669 const SkRect& rect,
670 const GrUserStencilSettings* ss) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500671
672 if (!ss) {
673 if (this->drawFilledRectAsClear(clip, std::move(paint), aa, viewMatrix, rect)) {
674 return;
675 }
676 // Fall through to fill rect op
677 assert_alive(paint);
678 }
679
csmartdalton97f6cd52016-07-13 13:37:08 -0700680 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500681 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500682 // The rectangle would not be drawn, so no need to add a draw op to the list
683 return;
csmartdalton97f6cd52016-07-13 13:37:08 -0700684 }
robertphillips44302392016-07-08 14:43:03 -0700685
Chris Dalton7d6748e2019-03-13 00:34:52 -0600686 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500687 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint), aaType, viewMatrix,
688 croppedRect, ss));
robertphillips391395d2016-03-02 09:26:36 -0800689}
690
Brian Osman11052242016-10-27 14:47:55 -0400691void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500692 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500693 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400694 const SkMatrix& viewMatrix,
695 const SkRect& rect,
696 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700697 if (!style) {
698 style = &GrStyle::SimpleFill();
699 }
joshualitt1de610a2016-01-06 08:26:09 -0800700 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700701 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700702 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400703 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700704
bsalomon6663acf2016-05-10 09:14:17 -0700705 // Path effects should've been devolved to a path in SkGpuDevice
706 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700707
Robert Phillips72152832017-01-25 17:31:35 -0500708 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700709
bsalomon6663acf2016-05-10 09:14:17 -0700710 const SkStrokeRec& stroke = style->strokeRec();
Robert Phillips8c8b0462018-08-24 16:18:03 -0400711 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
Michael Ludwig61a16512019-01-15 11:15:13 -0500712 this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect);
713 return;
bsalomona7d85ba2016-07-06 11:54:59 -0700714 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
715 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
716 if ((!rect.width() || !rect.height()) &&
717 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
718 SkScalar r = stroke.getWidth() / 2;
719 // TODO: Move these stroke->fill fallbacks to GrShape?
720 switch (stroke.getJoin()) {
721 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500722 this->drawRect(
723 clip, std::move(paint), aa, viewMatrix,
724 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
725 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700726 return;
727 case SkPaint::kRound_Join:
728 // Raster draws nothing when both dimensions are empty.
729 if (rect.width() || rect.height()){
730 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500731 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
732 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700733 return;
734 }
735 case SkPaint::kBevel_Join:
736 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500737 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700738 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
739 &GrStyle::SimpleFill());
740 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500741 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700742 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
743 &GrStyle::SimpleFill());
744 }
745 return;
746 }
747 }
robertphillips44302392016-07-08 14:43:03 -0700748
Brian Salomonbaaf4392017-06-15 09:59:23 -0400749 std::unique_ptr<GrDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700750
Chris Dalton7d6748e2019-03-13 00:34:52 -0600751 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -0500752 op = GrStrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
753 // op may be null if the stroke is not supported or if using coverage aa and the view matrix
754 // does not preserve rectangles.
Brian Salomon42521e82016-12-07 16:44:58 -0500755 if (op) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400756 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700757 return;
robertphillips4bc31812016-03-01 12:22:49 -0800758 }
robertphillips4bc31812016-03-01 12:22:49 -0800759 }
Mike Klein16885072018-12-11 09:54:31 -0500760 assert_alive(paint);
Brian Salomon2fad74a2017-12-20 13:28:55 -0500761 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(rect, *style));
robertphillipsea461502015-05-26 11:38:03 -0700762}
763
Michael Ludwig69858532018-11-28 15:34:34 -0500764void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa,
765 const SkMatrix& viewMatrix, const QuadSetEntry quads[],
766 int cnt) {
Chris Dalton7d6748e2019-03-13 00:34:52 -0600767 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig69858532018-11-28 15:34:34 -0500768 this->addDrawOp(clip, GrFillRectOp::MakeSet(fContext, std::move(paint), aaType, viewMatrix,
769 quads, cnt));
770}
771
Robert Phillipsec2249f2016-11-09 08:54:35 -0500772int GrRenderTargetContextPriv::maxWindowRectangles() const {
773 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400774 *fRenderTargetContext->caps());
Robert Phillipsec2249f2016-11-09 08:54:35 -0500775}
776
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000777void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700778 ASSERT_SINGLE_OWNER_PRIV
779 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400780 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400781 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
782 fRenderTargetContext->fContext);
robertphillips976f5f02016-06-03 10:59:20 -0700783
Robert Phillips72152832017-01-25 17:31:35 -0500784 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400785
Michael Ludwigc39d0c82019-01-15 10:03:43 -0500786 fRenderTargetContext->internalStencilClear(clip, insideStencilMask);
787}
788
789void GrRenderTargetContext::internalStencilClear(const GrFixedClip& clip, bool insideStencilMask) {
790 if (this->caps()->performStencilClearsAsDraws()) {
791 const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);
792 SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
793
794 // Configure the paint to have no impact on the color buffer
795 GrPaint paint;
796 paint.setColor4f({0.f, 0.f, 0.f, 0.f});
797 paint.setPorterDuffXPFactory(SkBlendMode::kSrcOver);
798
799 // Mark stencil usage here before addDrawOp() so that it doesn't try to re-call
800 // internalStencilClear() just because the op has stencil settings.
801 this->setNeedsStencil();
802 this->addDrawOp(clip, GrFillRectOp::Make(fContext, std::move(paint),
803 GrAAType::kNone, SkMatrix::I(), rtRect, ss));
804 } else {
805 std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask,
806 fRenderTargetProxy.get()));
807 if (!op) {
808 return;
809 }
810 this->getRTOpList()->addOp(std::move(op), *this->caps());
Robert Phillipse60ad622016-11-17 10:22:48 -0500811 }
robertphillips976f5f02016-06-03 10:59:20 -0700812}
813
Chris Daltonbbfd5162017-11-07 13:35:22 -0700814void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
Chris Dalton09e56892019-03-13 00:22:01 -0600815 GrAA doStencilMSAA,
Brian Osman11052242016-10-27 14:47:55 -0400816 const SkMatrix& viewMatrix,
817 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500818 ASSERT_SINGLE_OWNER_PRIV
819 RETURN_IF_ABANDONED_PRIV
820 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400821 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
822 fRenderTargetContext->fContext);
Brian Salomon467921e2017-03-06 16:17:12 -0500823
Brian Salomon467921e2017-03-06 16:17:12 -0500824 // TODO: extract portions of checkDraw that are relevant to path stenciling.
825 SkASSERT(path);
826 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
827
828 // FIXME: Use path bounds instead of this WAR once
829 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
830 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
831
832 // Setup clip
Chris Daltonbbfd5162017-11-07 13:35:22 -0700833 GrAppliedHardClip appliedClip;
834 if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
835 &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500836 return;
837 }
838
Robert Phillips65048132017-08-10 08:44:49 -0400839 fRenderTargetContext->setNeedsStencil();
Brian Salomon467921e2017-03-06 16:17:12 -0500840
Robert Phillips7c525e62018-06-12 10:11:12 -0400841 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
842 viewMatrix,
Chris Dalton09e56892019-03-13 00:22:01 -0600843 GrAA::kYes == doStencilMSAA,
Brian Salomon467921e2017-03-06 16:17:12 -0500844 path->getFillType(),
845 appliedClip.hasStencilClip(),
Brian Salomon467921e2017-03-06 16:17:12 -0500846 appliedClip.scissorState(),
Brian Salomon467921e2017-03-06 16:17:12 -0500847 path);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400848 if (!op) {
849 return;
850 }
Brian Salomon97180af2017-03-14 13:42:58 -0400851 op->setClippedBounds(bounds);
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400852 fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -0700853}
854
Chris Daltonbbfd5162017-11-07 13:35:22 -0700855void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400856 const GrUserStencilSettings* ss,
Chris Dalton09e56892019-03-13 00:22:01 -0600857 GrAA doStencilMSAA,
Brian Osman11052242016-10-27 14:47:55 -0400858 const SkMatrix& viewMatrix,
859 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700860 ASSERT_SINGLE_OWNER_PRIV
861 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400862 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400863 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilRect",
864 fRenderTargetContext->fContext);
865
Robert Phillips72152832017-01-25 17:31:35 -0500866 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700867
868 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500869 paint.setXPFactory(GrDisableColorXPFactory::Get());
Chris Dalton09e56892019-03-13 00:22:01 -0600870 auto aaType = (GrAA::kYes == doStencilMSAA) ? GrAAType::kMSAA : GrAAType::kNone;
Michael Ludwig72ab3462018-12-10 12:43:36 -0500871 std::unique_ptr<GrDrawOp> op = GrFillRectOp::Make(
872 fRenderTargetContext->fContext, std::move(paint), aaType, viewMatrix, rect, ss);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400873 fRenderTargetContext->addDrawOp(clip, std::move(op));
robertphillips976f5f02016-06-03 10:59:20 -0700874}
875
Chris Daltonbbfd5162017-11-07 13:35:22 -0700876bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400877 const GrUserStencilSettings* ss,
878 SkRegion::Op op,
879 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500880 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400881 const SkMatrix& viewMatrix,
882 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800883 ASSERT_SINGLE_OWNER_PRIV
884 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400885 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400886 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
887 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -0800888
Robert Phillips72152832017-01-25 17:31:35 -0500889 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800890
891 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800892 paint.setCoverageSetOpXPFactory(op, invert);
893
Michael Ludwig61a16512019-01-15 11:15:13 -0500894 // This will always succeed to draw a rectangle
895 fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss);
896 return true;
robertphillips391395d2016-03-02 09:26:36 -0800897}
898
Michael Ludwig136f45a2019-02-19 11:44:41 -0500899void GrRenderTargetContext::fillRectWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
Michael Ludwig75451902019-01-23 11:14:29 -0500900 GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
Michael Ludwig136f45a2019-02-19 11:44:41 -0500901 const SkRect& rect, const SkRect* localRect) {
Michael Ludwig75451902019-01-23 11:14:29 -0500902 ASSERT_SINGLE_OWNER
903 RETURN_IF_ABANDONED
904 SkDEBUGCODE(this->validate();)
905 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithEdgeAA", fContext);
906
Chris Dalton7d6748e2019-03-13 00:34:52 -0600907 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig136f45a2019-02-19 11:44:41 -0500908 std::unique_ptr<GrDrawOp> op;
Michael Ludwig75451902019-01-23 11:14:29 -0500909
Michael Ludwig136f45a2019-02-19 11:44:41 -0500910 if (localRect) {
911 // If local coordinates are provided, skip the optimization check to go through
912 // drawFilledRect, and also calculate clipped local coordinates
913 SkRect croppedRect = rect;
914 SkRect croppedLocalRect = *localRect;
915 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect,
916 &croppedLocalRect)) {
917 return;
918 }
919 op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType, edgeAA,
920 viewMatrix, croppedRect, croppedLocalRect);
921 } else {
922 // If aaType turns into MSAA, make sure to keep quads with no AA edges as MSAA. Sending
923 // those to drawFilledRect() would have it turn off MSAA in that case, which breaks seaming
924 // with any partial AA edges that kept MSAA.
925 if (aaType != GrAAType::kMSAA &&
926 (edgeAA == GrQuadAAFlags::kNone || edgeAA == GrQuadAAFlags::kAll)) {
927 // This is equivalent to a regular filled rect draw, so route through there to take
928 // advantage of draw->clear optimizations
929 this->drawFilledRect(clip, std::move(paint), GrAA(edgeAA == GrQuadAAFlags::kAll),
930 viewMatrix, rect);
931 return;
932 }
933
934 SkRect croppedRect = rect;
935 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
936 return;
937 }
938 op = GrFillRectOp::MakePerEdge(fContext, std::move(paint), aaType, edgeAA, viewMatrix,
939 croppedRect);
Michael Ludwig75451902019-01-23 11:14:29 -0500940 }
941
942 AutoCheckFlush acf(this->drawingManager());
Michael Ludwig136f45a2019-02-19 11:44:41 -0500943 this->addDrawOp(clip, std::move(op));
Michael Ludwig75451902019-01-23 11:14:29 -0500944}
945
Michael Ludwigce62dec2019-02-19 11:48:46 -0500946void GrRenderTargetContext::fillQuadWithEdgeAA(const GrClip& clip, GrPaint&& paint, GrAA aa,
947 GrQuadAAFlags edgeAA, const SkMatrix& viewMatrix,
948 const SkPoint quad[4], const SkPoint localQuad[4]) {
949 ASSERT_SINGLE_OWNER
950 RETURN_IF_ABANDONED
951 SkDEBUGCODE(this->validate();)
952 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillQuadWithEdgeAA", fContext);
953
Chris Dalton7d6748e2019-03-13 00:34:52 -0600954 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwigce62dec2019-02-19 11:48:46 -0500955
956 AutoCheckFlush acf(this->drawingManager());
957 // MakePerEdgeQuad automatically does the right thing if localQuad is null or not
958 this->addDrawOp(clip, GrFillRectOp::MakePerEdgeQuad(fContext, std::move(paint), aaType, edgeAA,
959 viewMatrix, quad, localQuad));
960}
961
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500962// Creates a paint for GrFillRectOp that matches behavior of GrTextureOp
963static void draw_texture_to_grpaint(sk_sp<GrTextureProxy> proxy, const SkRect* domain,
964 GrSamplerState::Filter filter, SkBlendMode mode,
965 const SkPMColor4f& color, sk_sp<GrColorSpaceXform> csXform,
966 GrPaint* paint) {
967 paint->setColor4f(color);
968 paint->setXPFactory(SkBlendMode_AsXPFactory(mode));
969
970 std::unique_ptr<GrFragmentProcessor> fp;
971 if (domain) {
Michael Ludwigce62dec2019-02-19 11:48:46 -0500972 SkRect correctedDomain = *domain;
973 if (filter == GrSamplerState::Filter::kBilerp) {
974 // Inset by 1/2 pixel, which GrTextureOp and GrTextureAdjuster handle automatically
975 correctedDomain.inset(0.5f, 0.5f);
976 }
977 fp = GrTextureDomainEffect::Make(std::move(proxy), SkMatrix::I(), correctedDomain,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500978 GrTextureDomain::kClamp_Mode, filter);
979 } else {
980 fp = GrSimpleTextureEffect::Make(std::move(proxy), SkMatrix::I(), filter);
981 }
982
983 fp = GrColorSpaceXformEffect::Make(std::move(fp), csXform);
984 paint->addColorFragmentProcessor(std::move(fp));
985}
986
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400987void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -0500988 GrSamplerState::Filter filter, SkBlendMode mode,
989 const SkPMColor4f& color, const SkRect& srcRect,
Michael Ludwig136f45a2019-02-19 11:44:41 -0500990 const SkRect& dstRect, GrAA aa, GrQuadAAFlags aaFlags,
Brian Salomonb80ffee2018-05-23 16:39:39 -0400991 SkCanvas::SrcRectConstraint constraint,
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400992 const SkMatrix& viewMatrix,
Brian Osman3d139a42018-11-19 10:42:10 -0500993 sk_sp<GrColorSpaceXform> textureColorSpaceXform) {
Brian Salomon34169692017-08-28 15:32:01 -0400994 ASSERT_SINGLE_OWNER
995 RETURN_IF_ABANDONED
996 SkDEBUGCODE(this->validate();)
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400997 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexture", fContext);
Brian Salomonf1709042018-10-03 11:57:00 -0400998 if (constraint == SkCanvas::kStrict_SrcRectConstraint &&
999 srcRect.contains(proxy->getWorstCaseBoundsRect())) {
1000 constraint = SkCanvas::kFast_SrcRectConstraint;
Brian Salomon34169692017-08-28 15:32:01 -04001001 }
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001002
Chris Dalton7d6748e2019-03-13 00:34:52 -06001003 GrAAType aaType = this->chooseAAType(aa);
Brian Salomonff9d6d32017-08-30 10:27:49 -04001004 SkRect clippedDstRect = dstRect;
1005 SkRect clippedSrcRect = srcRect;
1006 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &clippedDstRect,
1007 &clippedSrcRect)) {
1008 return;
1009 }
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001010
1011 AutoCheckFlush acf(this->drawingManager());
1012
1013 std::unique_ptr<GrDrawOp> op;
1014 if (mode != SkBlendMode::kSrcOver) {
1015 // Emulation mode with GrPaint and GrFillRectOp
1016 if (filter != GrSamplerState::Filter::kNearest &&
1017 !GrTextureOp::GetFilterHasEffect(viewMatrix, clippedSrcRect, clippedDstRect)) {
1018 filter = GrSamplerState::Filter::kNearest;
1019 }
1020
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001021 GrPaint paint;
1022 draw_texture_to_grpaint(std::move(proxy),
Michael Ludwigce62dec2019-02-19 11:48:46 -05001023 constraint == SkCanvas::kStrict_SrcRectConstraint ? &srcRect : nullptr,
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001024 filter, mode, color, std::move(textureColorSpaceXform), &paint);
1025 op = GrFillRectOp::MakePerEdgeWithLocalRect(fContext, std::move(paint), aaType, aaFlags,
1026 viewMatrix, clippedDstRect, clippedSrcRect);
1027 } else {
1028 // Can use a lighter weight op that can chain across proxies
1029 op = GrTextureOp::Make(fContext, std::move(proxy), filter, color, clippedSrcRect,
1030 clippedDstRect, aaType, aaFlags, constraint, viewMatrix,
1031 std::move(textureColorSpaceXform));
1032 }
1033
Brian Salomon2213ee92018-10-02 10:44:21 -04001034 this->addDrawOp(clip, std::move(op));
Brian Salomon34169692017-08-28 15:32:01 -04001035}
1036
Michael Ludwigce62dec2019-02-19 11:48:46 -05001037void GrRenderTargetContext::drawTextureQuad(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
1038 GrSamplerState::Filter filter, SkBlendMode mode,
1039 const SkPMColor4f& color, const SkPoint srcQuad[4],
1040 const SkPoint dstQuad[4], GrAA aa,
1041 GrQuadAAFlags aaFlags, const SkRect* domain,
1042 const SkMatrix& viewMatrix,
1043 sk_sp<GrColorSpaceXform> texXform) {
1044 ASSERT_SINGLE_OWNER
1045 RETURN_IF_ABANDONED
1046 SkDEBUGCODE(this->validate();)
1047 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureQuad", fContext);
1048 if (domain && domain->contains(proxy->getWorstCaseBoundsRect())) {
1049 domain = nullptr;
1050 }
1051
Chris Dalton7d6748e2019-03-13 00:34:52 -06001052 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001053
1054 // Unlike drawTexture(), don't bother cropping or optimizing the filter type since we're
1055 // sampling an arbitrary quad of the texture.
1056 AutoCheckFlush acf(this->drawingManager());
1057 std::unique_ptr<GrDrawOp> op;
1058 if (mode != SkBlendMode::kSrcOver) {
1059 // Emulation mode, but don't bother converting to kNearest filter since it's an arbitrary
1060 // quad that is being drawn, which makes the tests too expensive here
1061 GrPaint paint;
1062 draw_texture_to_grpaint(
1063 std::move(proxy), domain, filter, mode, color, std::move(texXform), &paint);
1064 op = GrFillRectOp::MakePerEdgeQuad(fContext, std::move(paint), aaType, aaFlags, viewMatrix,
1065 dstQuad, srcQuad);
1066 } else {
1067 // Use lighter weight GrTextureOp
1068 op = GrTextureOp::MakeQuad(fContext, std::move(proxy), filter, color, srcQuad, dstQuad,
1069 aaType, aaFlags, domain, viewMatrix, std::move(texXform));
1070 }
1071
1072 this->addDrawOp(clip, std::move(op));
1073}
1074
Brian Salomond7065e72018-10-12 11:42:02 -04001075void GrRenderTargetContext::drawTextureSet(const GrClip& clip, const TextureSetEntry set[], int cnt,
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001076 GrSamplerState::Filter filter, SkBlendMode mode,
Michael Ludwig136f45a2019-02-19 11:44:41 -05001077 GrAA aa, const SkMatrix& viewMatrix,
Brian Osman3d139a42018-11-19 10:42:10 -05001078 sk_sp<GrColorSpaceXform> texXform) {
Brian Salomond7065e72018-10-12 11:42:02 -04001079 ASSERT_SINGLE_OWNER
1080 RETURN_IF_ABANDONED
1081 SkDEBUGCODE(this->validate();)
1082 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureSet", fContext);
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001083
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001084 if (mode != SkBlendMode::kSrcOver ||
Robert Phillips9da87e02019-02-04 13:26:26 -05001085 !fContext->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001086 // Draw one at a time with GrFillRectOp and a GrPaint that emulates what GrTextureOp does
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001087 SkMatrix ctm;
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001088 for (int i = 0; i < cnt; ++i) {
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001089 float alpha = set[i].fAlpha;
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001090 ctm = viewMatrix;
1091 if (set[i].fPreViewMatrix) {
1092 ctm.preConcat(*set[i].fPreViewMatrix);
1093 }
1094
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001095 if (set[i].fDstClipQuad == nullptr) {
Michael Ludwigce62dec2019-02-19 11:48:46 -05001096 // Stick with original rectangles, which allows the ops to know more about what's
1097 // being drawn.
1098 this->drawTexture(clip, set[i].fProxy, filter, mode, {alpha, alpha, alpha, alpha},
1099 set[i].fSrcRect, set[i].fDstRect, aa, set[i].fAAFlags,
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001100 SkCanvas::kFast_SrcRectConstraint, ctm, texXform);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001101 } else {
1102 // Generate interpolated texture coordinates to match the dst clip
1103 SkPoint srcQuad[4];
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001104 GrMapRectPoints(set[i].fDstRect, set[i].fSrcRect, set[i].fDstClipQuad, srcQuad, 4);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001105 // Don't send srcRect as the domain, since the normal case doesn't use a constraint
1106 // with the entire srcRect, so sampling into dstRect outside of dstClip will just
1107 // keep seams look more correct.
1108 this->drawTextureQuad(clip, set[i].fProxy, filter, mode,
Michael Ludwig1433cfd2019-02-27 17:12:30 -05001109 {alpha, alpha, alpha, alpha}, srcQuad, set[i].fDstClipQuad,
Michael Ludwig7ae2ab52019-03-05 16:00:20 -05001110 aa, set[i].fAAFlags, nullptr, ctm, texXform);
Michael Ludwigce62dec2019-02-19 11:48:46 -05001111 }
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001112 }
1113 } else {
1114 // Can use a single op, avoiding GrPaint creation, and can batch across proxies
Michael Ludwigd54ca8f2019-02-13 13:25:21 -05001115 AutoCheckFlush acf(this->drawingManager());
Chris Dalton7d6748e2019-03-13 00:34:52 -06001116 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig009b92e2019-02-15 16:03:53 -05001117 auto op = GrTextureOp::MakeSet(fContext, set, cnt, filter, aaType, viewMatrix,
1118 std::move(texXform));
Michael Ludwiga3c45c72019-01-17 17:26:48 -05001119 this->addDrawOp(clip, std::move(op));
1120 }
Brian Salomond7065e72018-10-12 11:42:02 -04001121}
1122
Brian Osman11052242016-10-27 14:47:55 -04001123void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001124 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001125 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001126 const SkMatrix& viewMatrix,
1127 const SkRect& rectToDraw,
1128 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -08001129 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -07001130 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001131 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001132 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithLocalMatrix", fContext);
joshualittb6b513b2015-08-21 10:25:18 -07001133
csmartdalton97f6cd52016-07-13 13:37:08 -07001134 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -07001135 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -07001136 return;
1137 }
1138
Robert Phillips72152832017-01-25 17:31:35 -05001139 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001140
Chris Dalton7d6748e2019-03-13 00:34:52 -06001141 GrAAType aaType = this->chooseAAType(aa);
Michael Ludwig72ab3462018-12-10 12:43:36 -05001142 this->addDrawOp(clip, GrFillRectOp::MakeWithLocalMatrix(fContext, std::move(paint), aaType,
1143 viewMatrix, localMatrix, croppedRect));
robertphillipsea461502015-05-26 11:38:03 -07001144}
1145
Brian Osman11052242016-10-27 14:47:55 -04001146void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001147 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001148 const SkMatrix& viewMatrix,
Brian Osmanae0c50c2017-05-25 16:56:34 -04001149 sk_sp<SkVertices> vertices,
Ruiqi Maoc97a3392018-08-15 10:44:19 -04001150 const SkVertices::Bone bones[],
Ruiqi Mao4ec72f72018-07-10 17:21:07 -04001151 int boneCount,
Brian Osmanae0c50c2017-05-25 16:56:34 -04001152 GrPrimitiveType* overridePrimType) {
Brian Salomon199fb872017-02-06 09:41:10 -05001153 ASSERT_SINGLE_OWNER
1154 RETURN_IF_ABANDONED
1155 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001156 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
Brian Salomon199fb872017-02-06 09:41:10 -05001157
1158 AutoCheckFlush acf(this->drawingManager());
1159
1160 SkASSERT(vertices);
Chris Dalton7d6748e2019-03-13 00:34:52 -06001161 GrAAType aaType = this->chooseAAType(GrAA::kNo);
Brian Salomonf3569f02017-10-24 12:52:33 -04001162 std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
Ruiqi Mao4ec72f72018-07-10 17:21:07 -04001163 fContext, std::move(paint), std::move(vertices), bones, boneCount, viewMatrix, aaType,
Brian Salomonf3569f02017-10-24 12:52:33 -04001164 this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
Brian Salomonc2f42542017-07-12 14:11:22 -04001165 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001166}
1167
1168///////////////////////////////////////////////////////////////////////////////
1169
Brian Osman11052242016-10-27 14:47:55 -04001170void GrRenderTargetContext::drawAtlas(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001171 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001172 const SkMatrix& viewMatrix,
1173 int spriteCount,
1174 const SkRSXform xform[],
1175 const SkRect texRect[],
1176 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -08001177 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -07001178 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001179 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001180 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -07001181
Robert Phillips72152832017-01-25 17:31:35 -05001182 AutoCheckFlush acf(this->drawingManager());
halcanary9d524f22016-03-29 09:03:52 -07001183
Chris Dalton7d6748e2019-03-13 00:34:52 -06001184 GrAAType aaType = this->chooseAAType(GrAA::kNo);
Robert Phillips7c525e62018-06-12 10:11:12 -04001185 std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
1186 aaType, spriteCount, xform, texRect, colors);
Brian Salomon0088f942017-07-12 11:51:27 -04001187 this->addDrawOp(clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -07001188}
1189
1190///////////////////////////////////////////////////////////////////////////////
1191
Brian Osman11052242016-10-27 14:47:55 -04001192void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -05001193 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001194 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001195 const SkMatrix& viewMatrix,
1196 const SkRRect& rrect,
1197 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001198 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001199 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001200 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001201 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
Robert Phillips85290802018-07-02 13:14:28 -04001202
1203 const SkStrokeRec& stroke = style.strokeRec();
1204 if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001205 return;
1206 }
1207
bsalomon7f0d9f32016-08-15 14:49:10 -07001208 GrNoClip noclip;
1209 const GrClip* clip = &origClip;
1210#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1211 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -05001212 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -07001213 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
1214 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
1215 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
1216 SkRRect devRRect;
1217 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
1218 clip = &noclip;
1219 }
1220#endif
bsalomon6663acf2016-05-10 09:14:17 -07001221 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -07001222
Robert Phillips72152832017-01-25 17:31:35 -05001223 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001224
Chris Dalton7d6748e2019-03-13 00:34:52 -06001225 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001226 if (GrAAType::kCoverage == aaType) {
Chris Dalton133944a2018-11-16 23:30:29 -05001227 std::unique_ptr<GrDrawOp> op;
1228 if (style.isSimpleFill()) {
1229 op = GrAAFillRRectOp::Make(fContext, viewMatrix, rrect, *this->caps(),
1230 std::move(paint));
1231 }
1232 if (!op) {
Mike Klein16885072018-12-11 09:54:31 -05001233 assert_alive(paint);
Chris Dalton133944a2018-11-16 23:30:29 -05001234 op = GrOvalOpFactory::MakeRRectOp(fContext, std::move(paint), viewMatrix, rrect, stroke,
1235 this->caps()->shaderCaps());
1236 }
1237
Brian Salomon42521e82016-12-07 16:44:58 -05001238 if (op) {
Brian Salomon05441c42017-05-15 16:45:49 -04001239 this->addDrawOp(*clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001240 return;
1241 }
robertphillipsea461502015-05-26 11:38:03 -07001242 }
robertphillipsb56f9272016-02-25 11:03:52 -08001243
Mike Klein16885072018-12-11 09:54:31 -05001244 assert_alive(paint);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001245 this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
1246 GrShape(rrect, style));
robertphillipsea461502015-05-26 11:38:03 -07001247}
1248
Jim Van Verthc5903412016-11-17 15:27:09 -05001249///////////////////////////////////////////////////////////////////////////////
1250
Jim Van Verth3af1af92017-05-18 15:06:54 -04001251static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
1252 SkPoint3 result;
1253 m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
1254 result.fZ = pt.fZ;
1255 return result;
1256}
1257
1258bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
Jim Van Verth3af1af92017-05-18 15:06:54 -04001259 const SkMatrix& viewMatrix,
1260 const SkPath& path,
1261 const SkDrawShadowRec& rec) {
Jim Van Verthc5903412016-11-17 15:27:09 -05001262 ASSERT_SINGLE_OWNER
Robert Phillips6a6de562019-02-15 15:19:15 -05001263 if (fContext->priv().abandoned()) {
Jim Van Verth3af1af92017-05-18 15:06:54 -04001264 return true;
1265 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001266 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001267 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001268
1269 // check z plane
1270 bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
1271 !SkScalarNearlyZero(rec.fZPlaneParams.fY));
1272 bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1273 if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
1274 return false;
1275 }
1276
1277 SkRRect rrect;
1278 SkRect rect;
1279 // we can only handle rects, circles, and rrects with circular corners
Mike Reed242135a2018-02-22 13:41:39 -05001280 bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsSimpleCircular(rrect) &&
Jim Van Verth3af1af92017-05-18 15:06:54 -04001281 rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
1282 if (!isRRect &&
1283 path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
1284 rect.width() > SK_ScalarNearlyZero) {
1285 rrect.setOval(rect);
1286 isRRect = true;
1287 }
1288 if (!isRRect && path.isRect(&rect)) {
1289 rrect.setRect(rect);
1290 isRRect = true;
1291 }
1292
1293 if (!isRRect) {
1294 return false;
1295 }
1296
Jim Van Verthc5903412016-11-17 15:27:09 -05001297 if (rrect.isEmpty()) {
Jim Van Verth3af1af92017-05-18 15:06:54 -04001298 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -05001299 }
1300
Robert Phillips72152832017-01-25 17:31:35 -05001301 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001302
Jim Van Verth3af1af92017-05-18 15:06:54 -04001303 // transform light
1304 SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
1305
1306 // 1/scale
1307 SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
1308 SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) :
1309 sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
1310 viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
1311
1312 SkScalar occluderHeight = rec.fZPlaneParams.fZ;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001313 bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1314
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001315 if (SkColorGetA(rec.fAmbientColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001316 SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1317 const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1318 const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001319
1320 // Outset the shadow rrect to the border of the penumbra
1321 SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1322 SkRRect ambientRRect;
1323 SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1324 // If the rrect was an oval then its outset will also be one.
1325 // We set it explicitly to avoid errors.
1326 if (rrect.isOval()) {
1327 ambientRRect = SkRRect::MakeOval(outsetRect);
1328 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001329 SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001330 ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1331 }
1332
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001333 GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001334 if (transparent) {
1335 // set a large inset to force a fill
1336 devSpaceInsetWidth = ambientRRect.width();
1337 }
Jim Van Verth39e71652018-04-23 18:08:45 +00001338
Robert Phillips7c525e62018-06-12 10:11:12 -04001339 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1340 ambientColor,
1341 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001342 ambientRRect,
1343 devSpaceAmbientBlur,
Jim Van Verthfb186392018-09-11 11:37:46 -04001344 devSpaceInsetWidth);
Brian Salomon05969092017-07-13 11:20:51 -04001345 SkASSERT(op);
1346 this->addDrawOp(clip, std::move(op));
Jim Van Verthc5903412016-11-17 15:27:09 -05001347 }
Jim Van Verth3af1af92017-05-18 15:06:54 -04001348
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001349 if (SkColorGetA(rec.fSpotColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001350 SkScalar devSpaceSpotBlur;
1351 SkScalar spotScale;
1352 SkVector spotOffset;
1353 SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1354 devLightPos.fZ, rec.fLightRadius,
1355 &devSpaceSpotBlur, &spotScale, &spotOffset);
1356 // handle scale of radius due to CTM
Jim Van Verth3af1af92017-05-18 15:06:54 -04001357 const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1358
Jim Van Verth3af1af92017-05-18 15:06:54 -04001359 // Adjust translate for the effect of the scale.
1360 spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1361 spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1362 // This offset is in dev space, need to transform it into source space.
1363 SkMatrix ctmInverse;
1364 if (viewMatrix.invert(&ctmInverse)) {
1365 ctmInverse.mapPoints(&spotOffset, 1);
1366 } else {
1367 // Since the matrix is a similarity, this should never happen, but just in case...
1368 SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1369 SkASSERT(false);
1370 }
1371
1372 // Compute the transformed shadow rrect
1373 SkRRect spotShadowRRect;
1374 SkMatrix shadowTransform;
1375 shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1376 rrect.transform(shadowTransform, &spotShadowRRect);
Mike Reed242135a2018-02-22 13:41:39 -05001377 SkScalar spotRadius = SkRRectPriv::GetSimpleRadii(spotShadowRRect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001378
1379 // Compute the insetWidth
Jim Van Verth1af03d42017-07-31 09:34:58 -04001380 SkScalar blurOutset = srcSpaceSpotBlur;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001381 SkScalar insetWidth = blurOutset;
1382 if (transparent) {
1383 // If transparent, just do a fill
1384 insetWidth += spotShadowRRect.width();
1385 } else {
1386 // For shadows, instead of using a stroke we specify an inset from the penumbra
1387 // border. We want to extend this inset area so that it meets up with the caster
1388 // geometry. The inset geometry will by default already be inset by the blur width.
1389 //
1390 // We compare the min and max corners inset by the radius between the original
1391 // rrect and the shadow rrect. The distance between the two plus the difference
1392 // between the scaled radius and the original radius gives the distance from the
1393 // transformed shadow shape to the original shape in that corner. The max
1394 // of these gives the maximum distance we need to cover.
1395 //
1396 // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1397 // that to get the full insetWidth.
1398 SkScalar maxOffset;
1399 if (rrect.isRect()) {
1400 // Manhattan distance works better for rects
1401 maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft -
1402 rrect.rect().fLeft),
1403 SkTAbs(spotShadowRRect.rect().fTop -
1404 rrect.rect().fTop)),
1405 SkTMax(SkTAbs(spotShadowRRect.rect().fRight -
1406 rrect.rect().fRight),
1407 SkTAbs(spotShadowRRect.rect().fBottom -
1408 rrect.rect().fBottom)));
1409 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001410 SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001411 SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1412 rrect.rect().fLeft + dr,
1413 spotShadowRRect.rect().fTop -
1414 rrect.rect().fTop + dr);
1415 SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1416 rrect.rect().fRight - dr,
1417 spotShadowRRect.rect().fBottom -
1418 rrect.rect().fBottom - dr);
Cary Clarkdf429f32017-11-08 11:44:31 -05001419 maxOffset = SkScalarSqrt(SkTMax(SkPointPriv::LengthSqd(upperLeftOffset),
1420 SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001421 }
Jim Van Verth4c8c1e82018-04-23 17:14:48 -04001422 insetWidth += SkTMax(blurOutset, maxOffset);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001423 }
1424
1425 // Outset the shadow rrect to the border of the penumbra
1426 SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1427 if (spotShadowRRect.isOval()) {
1428 spotShadowRRect = SkRRect::MakeOval(outsetRect);
1429 } else {
1430 SkScalar outsetRad = spotRadius + blurOutset;
1431 spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1432 }
1433
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001434 GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
Jim Van Verth34d6e4b2017-06-09 11:09:03 -04001435
Robert Phillips7c525e62018-06-12 10:11:12 -04001436 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1437 spotColor,
1438 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001439 spotShadowRRect,
Jim Van Verth1af03d42017-07-31 09:34:58 -04001440 2.0f * devSpaceSpotBlur,
Brian Salomon05969092017-07-13 11:20:51 -04001441 insetWidth);
1442 SkASSERT(op);
1443 this->addDrawOp(clip, std::move(op));
Jim Van Verth3af1af92017-05-18 15:06:54 -04001444 }
1445
1446 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -05001447}
1448
1449///////////////////////////////////////////////////////////////////////////////
1450
Brian Osman11052242016-10-27 14:47:55 -04001451bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001452 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001453 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001454 const SkMatrix& viewMatrix,
1455 const SkRRect& origOuter,
1456 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001457 SkASSERT(!origInner.isEmpty());
1458 SkASSERT(!origOuter.isEmpty());
1459
Brian Salomon65749212017-12-01 16:01:47 -05001460 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1461
Chris Dalton7d6748e2019-03-13 00:34:52 -06001462 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon45839f92017-12-04 09:02:35 -05001463
1464 if (GrAAType::kMSAA == aaType) {
1465 return false;
1466 }
1467
Mike Reed242135a2018-02-22 13:41:39 -05001468 if (GrAAType::kCoverage == aaType && SkRRectPriv::IsCircle(*inner)
1469 && SkRRectPriv::IsCircle(*outer)) {
Brian Salomon65749212017-12-01 16:01:47 -05001470 auto outerR = outer->width() / 2.f;
1471 auto innerR = inner->width() / 2.f;
1472 auto cx = outer->getBounds().fLeft + outerR;
1473 auto cy = outer->getBounds().fTop + outerR;
1474 if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
1475 SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
1476 auto avgR = (innerR + outerR) / 2.f;
1477 auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
1478 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
1479 stroke.setStrokeStyle(outerR - innerR);
Robert Phillips7c525e62018-06-12 10:11:12 -04001480 auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix,
1481 circleBounds, GrStyle(stroke, nullptr),
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001482 this->caps()->shaderCaps());
Brian Salomon65749212017-12-01 16:01:47 -05001483 if (op) {
1484 this->addDrawOp(clip, std::move(op));
1485 return true;
1486 }
Mike Klein16885072018-12-11 09:54:31 -05001487 assert_alive(paint);
Brian Salomon65749212017-12-01 16:01:47 -05001488 }
1489 }
1490
Ethan Nicholas0f3c7322017-11-09 14:51:17 -05001491 GrClipEdgeType innerEdgeType, outerEdgeType;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001492 if (GrAAType::kCoverage == aaType) {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001493 innerEdgeType = GrClipEdgeType::kInverseFillAA;
1494 outerEdgeType = GrClipEdgeType::kFillAA;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001495 } else {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001496 innerEdgeType = GrClipEdgeType::kInverseFillBW;
1497 outerEdgeType = GrClipEdgeType::kFillBW;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001498 }
robertphillips00095892016-02-29 13:50:40 -08001499
robertphillips00095892016-02-29 13:50:40 -08001500 SkMatrix inverseVM;
1501 if (!viewMatrix.isIdentity()) {
1502 if (!origInner.transform(viewMatrix, inner.writable())) {
1503 return false;
1504 }
1505 if (!origOuter.transform(viewMatrix, outer.writable())) {
1506 return false;
1507 }
1508 if (!viewMatrix.invert(&inverseVM)) {
1509 return false;
1510 }
1511 } else {
1512 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001513 }
robertphillips00095892016-02-29 13:50:40 -08001514
Ethan Nicholaseace9352018-10-15 20:09:54 +00001515 const auto& caps = *this->caps()->shaderCaps();
robertphillips00095892016-02-29 13:50:40 -08001516 // TODO these need to be a geometry processors
Ethan Nicholaseace9352018-10-15 20:09:54 +00001517 auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
robertphillips00095892016-02-29 13:50:40 -08001518 if (!innerEffect) {
1519 return false;
1520 }
1521
Ethan Nicholaseace9352018-10-15 20:09:54 +00001522 auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
robertphillips00095892016-02-29 13:50:40 -08001523 if (!outerEffect) {
1524 return false;
1525 }
1526
Brian Salomon82f44312017-01-11 13:42:54 -05001527 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1528 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001529
1530 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001531 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001532 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1533 }
halcanary9d524f22016-03-29 09:03:52 -07001534
Brian Salomon82f44312017-01-11 13:42:54 -05001535 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1536 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001537 return true;
1538}
1539
Brian Osman11052242016-10-27 14:47:55 -04001540void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001541 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001542 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001543 const SkMatrix& viewMatrix,
1544 const SkRRect& outer,
1545 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001546 ASSERT_SINGLE_OWNER
1547 RETURN_IF_ABANDONED
1548 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001549 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
robertphillips00095892016-02-29 13:50:40 -08001550
1551 SkASSERT(!outer.isEmpty());
1552 SkASSERT(!inner.isEmpty());
1553
Robert Phillips72152832017-01-25 17:31:35 -05001554 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001555
Brian Salomon82f44312017-01-11 13:42:54 -05001556 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001557 return;
1558 }
Mike Klein16885072018-12-11 09:54:31 -05001559 assert_alive(paint);
robertphillips00095892016-02-29 13:50:40 -08001560
1561 SkPath path;
1562 path.setIsVolatile(true);
1563 path.addRRect(inner);
1564 path.addRRect(outer);
1565 path.setFillType(SkPath::kEvenOdd_FillType);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001566 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path));
robertphillips00095892016-02-29 13:50:40 -08001567}
1568
robertphillipsea461502015-05-26 11:38:03 -07001569///////////////////////////////////////////////////////////////////////////////
1570
Brian Osman11052242016-10-27 14:47:55 -04001571void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001572 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001573 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001574 const SkMatrix& viewMatrix,
1575 const SkRegion& region,
Stan Iliev73d8fd92017-08-02 15:36:24 -04001576 const GrStyle& style,
1577 const GrUserStencilSettings* ss) {
msarettcc319b92016-08-25 18:07:18 -07001578 ASSERT_SINGLE_OWNER
1579 RETURN_IF_ABANDONED
1580 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001581 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
msarettcc319b92016-08-25 18:07:18 -07001582
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001583 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001584 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001585 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001586 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
Brian Salomon34169692017-08-28 15:32:01 -04001587 SkScalarIsInt(viewMatrix.getTranslateX()) &&
1588 SkScalarIsInt(viewMatrix.getTranslateY())) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001589 aa = GrAA::kNo;
1590 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001591 }
msarettcc319b92016-08-25 18:07:18 -07001592 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001593 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001594 SkPath path;
1595 region.getBoundaryPath(&path);
Robert Phillips46a13382018-08-23 13:53:01 -04001596 path.setIsVolatile(true);
1597
Brian Salomon82f44312017-01-11 13:42:54 -05001598 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001599 }
1600
Chris Dalton7d6748e2019-03-13 00:34:52 -06001601 GrAAType aaType = this->chooseAAType(GrAA::kNo);
Robert Phillips7c525e62018-06-12 10:11:12 -04001602 std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
1603 aaType, ss);
Brian Salomonf0366322017-07-11 15:53:05 -04001604 this->addDrawOp(clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001605}
1606
Brian Osman11052242016-10-27 14:47:55 -04001607void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001608 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001609 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001610 const SkMatrix& viewMatrix,
1611 const SkRect& oval,
1612 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001613 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001614 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001615 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001616 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -07001617
Robert Phillips7484d202018-07-03 09:09:08 -04001618 const SkStrokeRec& stroke = style.strokeRec();
1619
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001620 if (oval.isEmpty() && !style.pathEffect()) {
Robert Phillips7484d202018-07-03 09:09:08 -04001621 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
1622 return;
1623 }
1624
1625 this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001626 return;
robertphillipsea461502015-05-26 11:38:03 -07001627 }
1628
Robert Phillips72152832017-01-25 17:31:35 -05001629 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001630
Chris Dalton7d6748e2019-03-13 00:34:52 -06001631 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001632 if (GrAAType::kCoverage == aaType) {
Chris Daltonebc38c92018-11-28 16:58:09 -07001633 std::unique_ptr<GrDrawOp> op;
1634 // GrAAFillRRectOp has special geometry and a fragment-shader branch to conditionally
1635 // evaluate the arc equation. This same special geometry and fragment branch also turn out
1636 // to be a substantial optimization for drawing ovals (namely, by not evaluating the arc
1637 // equation inside the oval's inner diamond). Given these optimizations, it's a clear win to
1638 // draw ovals the exact same way we do round rects.
1639 //
1640 // However, we still don't draw true circles as round rects, because it can cause perf
1641 // regressions on some platforms as compared to the dedicated circle Op.
1642 if (style.isSimpleFill() && oval.height() != oval.width()) {
1643 op = GrAAFillRRectOp::Make(fContext, viewMatrix, SkRRect::MakeOval(oval), *this->caps(),
1644 std::move(paint));
1645 }
1646 if (!op) {
Mike Klein16885072018-12-11 09:54:31 -05001647 assert_alive(paint);
Chris Daltonebc38c92018-11-28 16:58:09 -07001648 op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
1649 this->caps()->shaderCaps());
1650 }
1651 if (op) {
Brian Salomon05441c42017-05-15 16:45:49 -04001652 this->addDrawOp(clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001653 return;
1654 }
robertphillipsea461502015-05-26 11:38:03 -07001655 }
robertphillipsb56f9272016-02-25 11:03:52 -08001656
Mike Klein16885072018-12-11 09:54:31 -05001657 assert_alive(paint);
Brian Salomon5209d7f2018-04-20 16:52:42 -04001658 this->drawShapeUsingPathRenderer(
1659 clip, std::move(paint), aa, viewMatrix,
1660 GrShape(SkRRect::MakeOval(oval), SkPath::kCW_Direction, 2, false, style));
robertphillipsea461502015-05-26 11:38:03 -07001661}
1662
Brian Osman11052242016-10-27 14:47:55 -04001663void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001664 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001665 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001666 const SkMatrix& viewMatrix,
1667 const SkRect& oval,
1668 SkScalar startAngle,
1669 SkScalar sweepAngle,
1670 bool useCenter,
1671 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001672 ASSERT_SINGLE_OWNER
1673 RETURN_IF_ABANDONED
1674 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001675 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001676
1677 AutoCheckFlush acf(this->drawingManager());
1678
Chris Dalton7d6748e2019-03-13 00:34:52 -06001679 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001680 if (GrAAType::kCoverage == aaType) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001681 const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
Robert Phillips7c525e62018-06-12 10:11:12 -04001682 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
1683 std::move(paint),
Brian Salomonea26d6b2018-01-23 20:33:21 +00001684 viewMatrix,
1685 oval,
1686 startAngle,
1687 sweepAngle,
1688 useCenter,
1689 style,
1690 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001691 if (op) {
Brian Salomon05441c42017-05-15 16:45:49 -04001692 this->addDrawOp(clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001693 return;
1694 }
Mike Klein16885072018-12-11 09:54:31 -05001695 assert_alive(paint);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001696 }
Brian Salomone4949402018-04-26 15:22:04 -04001697 this->drawShapeUsingPathRenderer(
1698 clip, std::move(paint), aa, viewMatrix,
1699 GrShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001700}
1701
Brian Osman11052242016-10-27 14:47:55 -04001702void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001703 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001704 const SkMatrix& viewMatrix,
Brian Salomon2a943df2018-05-04 13:43:19 -04001705 sk_sp<GrTextureProxy> image,
1706 sk_sp<GrColorSpaceXform> csxf,
1707 GrSamplerState::Filter filter,
Brian Osman11052242016-10-27 14:47:55 -04001708 std::unique_ptr<SkLatticeIter> iter,
1709 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001710 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001711 RETURN_IF_ABANDONED
1712 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001713 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
joshualitt33a5fce2015-11-18 13:28:51 -08001714
Robert Phillips72152832017-01-25 17:31:35 -05001715 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001716
Brian Salomon2a943df2018-05-04 13:43:19 -04001717 std::unique_ptr<GrDrawOp> op =
Robert Phillips7c525e62018-06-12 10:11:12 -04001718 GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(image),
1719 std::move(csxf), filter, std::move(iter), dst);
Brian Salomon815486c2017-07-11 08:52:13 -04001720 this->addDrawOp(clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001721}
1722
Greg Daniel64cc9aa2018-10-19 13:54:56 -04001723void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
1724 const SkRect& bounds) {
1725 std::unique_ptr<GrOp> op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
1726 SkASSERT(op);
1727 this->getRTOpList()->addOp(std::move(op), *this->caps());
1728}
1729
Greg Daniel51316782017-08-02 15:10:09 +00001730GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO(
Greg Danielbae71212019-03-01 15:24:35 -05001731 SkSurface::BackendSurfaceAccess access, SkSurface::FlushFlags flags, int numSemaphores,
1732 GrBackendSemaphore backendSemaphores[]) {
robertphillips8c523e02016-07-26 07:41:00 -07001733 ASSERT_SINGLE_OWNER
Robert Phillips6a6de562019-02-15 15:19:15 -05001734 if (fContext->priv().abandoned()) {
Robert Phillipsa9162df2019-02-11 14:12:03 -05001735 return GrSemaphoresSubmitted::kNo;
1736 }
robertphillips8c523e02016-07-26 07:41:00 -07001737 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001738 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext);
robertphillips8c523e02016-07-26 07:41:00 -07001739
Greg Daniel51316782017-08-02 15:10:09 +00001740 return this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get(),
Greg Danielbae71212019-03-01 15:24:35 -05001741 access, flags,
Greg Daniel51316782017-08-02 15:10:09 +00001742 numSemaphores,
1743 backendSemaphores);
Greg Daniela5cb7812017-06-16 09:45:32 -04001744}
1745
Greg Danielc64ee462017-06-15 16:59:49 -04001746bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001747 const GrBackendSemaphore waitSemaphores[]) {
Greg Daniela5cb7812017-06-16 09:45:32 -04001748 ASSERT_SINGLE_OWNER
Greg Danielc64ee462017-06-15 16:59:49 -04001749 RETURN_FALSE_IF_ABANDONED
Greg Daniela5cb7812017-06-16 09:45:32 -04001750 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001751 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
Greg Daniela5cb7812017-06-16 09:45:32 -04001752
1753 AutoCheckFlush acf(this->drawingManager());
1754
Greg Danielc64ee462017-06-15 16:59:49 -04001755 if (numSemaphores && !this->caps()->fenceSyncSupport()) {
1756 return false;
1757 }
1758
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001759 auto direct = fContext->priv().asDirectContext();
1760 if (!direct) {
1761 return false;
1762 }
1763
1764 auto resourceProvider = direct->priv().resourceProvider();
Robert Phillips6be756b2018-01-16 15:07:54 -05001765
Greg Daniela5cb7812017-06-16 09:45:32 -04001766 SkTArray<sk_sp<GrSemaphore>> semaphores(numSemaphores);
1767 for (int i = 0; i < numSemaphores; ++i) {
Robert Phillips6be756b2018-01-16 15:07:54 -05001768 sk_sp<GrSemaphore> sema = resourceProvider->wrapBackendSemaphore(
Greg Daniel17b7c052018-01-09 13:55:33 -05001769 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
1770 kAdopt_GrWrapOwnership);
Robert Phillipsbc4994a2019-02-14 08:36:56 -05001771 std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(fContext, std::move(sema),
Robert Phillips7c525e62018-06-12 10:11:12 -04001772 fRenderTargetProxy.get()));
Greg Danielcb324152019-02-25 11:36:53 -05001773 this->getRTOpList()->addWaitOp(std::move(waitOp), *this->caps());
Greg Daniela5cb7812017-06-16 09:45:32 -04001774 }
Greg Danielc64ee462017-06-15 16:59:49 -04001775 return true;
robertphillips8c523e02016-07-26 07:41:00 -07001776}
joshualitt33a5fce2015-11-18 13:28:51 -08001777
Robert Phillips65a88fa2017-08-08 08:36:22 -04001778void GrRenderTargetContext::insertEventMarker(const SkString& str) {
Robert Phillips88a32ef2018-06-07 11:05:56 -04001779 std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fContext, fRenderTargetProxy.get(), str));
Robert Phillips65a88fa2017-08-08 08:36:22 -04001780 this->getRTOpList()->addOp(std::move(op), *this->caps());
1781}
1782
Robert Phillipsbe9aff22019-02-15 11:33:22 -05001783const GrCaps* GrRenderTargetContext::caps() const {
1784 return fContext->priv().caps();
1785}
1786
Brian Osman11052242016-10-27 14:47:55 -04001787void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001788 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001789 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001790 const SkMatrix& viewMatrix,
Brian Salomon40b77a62017-12-22 11:25:52 -05001791 const SkPath& path,
Brian Osman11052242016-10-27 14:47:55 -04001792 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001793 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001794 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001795 SkDEBUGCODE(this->validate();)
Robert Phillips20390c32018-08-17 11:01:03 -04001796 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPath", fContext);
1797
Brian Salomon40b77a62017-12-22 11:25:52 -05001798 GrShape shape(path, style);
Robert Phillips20390c32018-08-17 11:01:03 -04001799
Robert Phillips27927a52018-08-20 13:18:12 -04001800 this->drawShape(clip, std::move(paint), aa, viewMatrix, shape);
Robert Phillips20390c32018-08-17 11:01:03 -04001801}
1802
1803void GrRenderTargetContext::drawShape(const GrClip& clip,
1804 GrPaint&& paint,
1805 GrAA aa,
1806 const SkMatrix& viewMatrix,
1807 const GrShape& shape) {
1808 ASSERT_SINGLE_OWNER
1809 RETURN_IF_ABANDONED
1810 SkDEBUGCODE(this->validate();)
1811 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawShape", fContext);
1812
Brian Salomon2fad74a2017-12-20 13:28:55 -05001813 if (shape.isEmpty()) {
1814 if (shape.inverseFilled()) {
1815 this->drawPaint(clip, std::move(paint), viewMatrix);
1816 }
1817 return;
robertphillipsea461502015-05-26 11:38:03 -07001818 }
1819
Robert Phillips72152832017-01-25 17:31:35 -05001820 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001821
Brian Salomon2fad74a2017-12-20 13:28:55 -05001822 if (!shape.style().hasPathEffect()) {
Chris Dalton7d6748e2019-03-13 00:34:52 -06001823 GrAAType aaType = this->chooseAAType(aa);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001824 SkRRect rrect;
1825 // We can ignore the starting point and direction since there is no path effect.
1826 bool inverted;
1827 if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
1828 if (rrect.isRect()) {
1829 this->drawRect(clip, std::move(paint), aa, viewMatrix, rrect.rect(),
1830 &shape.style());
1831 return;
1832 } else if (rrect.isOval()) {
1833 this->drawOval(clip, std::move(paint), aa, viewMatrix, rrect.rect(), shape.style());
robertphillipsea461502015-05-26 11:38:03 -07001834 return;
1835 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001836 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect, shape.style());
1837 return;
Robert Phillips73653b42018-08-22 12:42:42 -04001838 } else if (GrAAType::kCoverage == aaType && shape.style().isSimpleFill() &&
1839 viewMatrix.rectStaysRect()) {
1840 // TODO: the rectStaysRect restriction could be lifted if we were willing to apply
1841 // the matrix to all the points individually rather than just to the rect
1842 SkRect rects[2];
1843 if (shape.asNestedRects(rects)) {
1844 // Concave AA paths are expensive - try to avoid them for special cases
Michael Ludwig72ab3462018-12-10 12:43:36 -05001845 std::unique_ptr<GrDrawOp> op = GrStrokeRectOp::MakeNested(
Robert Phillips73653b42018-08-22 12:42:42 -04001846 fContext, std::move(paint), viewMatrix, rects);
1847 if (op) {
1848 this->addDrawOp(clip, std::move(op));
1849 }
1850 // Returning here indicates that there is nothing to draw in this case.
1851 return;
1852 }
robertphillipsea461502015-05-26 11:38:03 -07001853 }
1854 }
robertphillips4bc31812016-03-01 12:22:49 -08001855
Brian Salomon2fad74a2017-12-20 13:28:55 -05001856 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, shape);
robertphillipsea461502015-05-26 11:38:03 -07001857}
1858
Chris Daltonbbfd5162017-11-07 13:35:22 -07001859bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -04001860 const GrUserStencilSettings* ss,
1861 SkRegion::Op op,
1862 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001863 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001864 const SkMatrix& viewMatrix,
1865 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001866 ASSERT_SINGLE_OWNER_PRIV
1867 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001868 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001869 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
1870 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -08001871
1872 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001873 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001874 SkRect::MakeIWH(fRenderTargetContext->width(),
1875 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001876 return true;
1877 }
1878
Robert Phillips72152832017-01-25 17:31:35 -05001879 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001880
1881 // An Assumption here is that path renderer would use some form of tweaking
1882 // the src color (either the input alpha or in the frag shader) to implement
1883 // aa. If we have some future driver-mojo path AA that can do the right
1884 // thing WRT to the blend then we'll need some query on the PR.
Chris Dalton09e56892019-03-13 00:22:01 -06001885 auto aaTypeFlags = choose_path_aa_type_flags(
1886 aa, fRenderTargetContext->fsaaType(), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -07001887 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001888
Chris Daltondb91c6e2017-09-08 16:25:08 -06001889 SkIRect clipConservativeBounds;
1890 clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(),
1891 &clipConservativeBounds, nullptr);
1892
bsalomon8acedde2016-06-24 10:42:16 -07001893 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001894 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001895 canDrawArgs.fCaps = fRenderTargetContext->caps();
robertphillips391395d2016-03-02 09:26:36 -08001896 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001897 canDrawArgs.fShape = &shape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06001898 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Chris Dalton09e56892019-03-13 00:22:01 -06001899 canDrawArgs.fAATypeFlags = aaTypeFlags;
Greg Danielbe7fc462019-01-03 16:40:42 -05001900 SkASSERT(!fRenderTargetContext->wrapsVkSecondaryCB());
1901 canDrawArgs.fTargetIsWrappedVkSecondaryCB = false;
cdalton93a379b2016-05-11 13:58:08 -07001902 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001903
1904 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001905 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001906 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001907 if (!pr) {
1908 return false;
1909 }
1910
1911 GrPaint paint;
1912 paint.setCoverageSetOpXPFactory(op, invert);
1913
Brian Salomonf3569f02017-10-24 12:52:33 -04001914 GrPathRenderer::DrawPathArgs args{fRenderTargetContext->drawingManager()->getContext(),
1915 std::move(paint),
1916 ss,
1917 fRenderTargetContext,
1918 &clip,
1919 &clipConservativeBounds,
1920 &viewMatrix,
1921 &shape,
Chris Dalton09e56892019-03-13 00:22:01 -06001922 aaTypeFlags,
Brian Osman34ec3742018-07-03 10:40:57 -04001923 fRenderTargetContext->colorSpaceInfo().isLinearlyBlended()};
robertphillips391395d2016-03-02 09:26:36 -08001924 pr->drawPath(args);
1925 return true;
1926}
1927
Brian Osman11052242016-10-27 14:47:55 -04001928SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001929 ASSERT_SINGLE_OWNER_PRIV
1930
Robert Phillips6a6de562019-02-15 15:19:15 -05001931 if (fRenderTargetContext->fContext->priv().abandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001932 return SkBudgeted::kNo;
1933 }
1934
Brian Osman11052242016-10-27 14:47:55 -04001935 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001936
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001937 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001938}
1939
Brian Salomon2fad74a2017-12-20 13:28:55 -05001940void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
1941 GrPaint&& paint,
1942 GrAA aa,
1943 const SkMatrix& viewMatrix,
1944 const GrShape& originalShape) {
joshualitt1de610a2016-01-06 08:26:09 -08001945 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001946 RETURN_IF_ABANDONED
Brian Salomondcbb9d92017-07-19 10:53:20 -04001947 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
1948
Jim Van Verthf86073a2018-10-02 13:05:38 -04001949 if (!viewMatrix.isFinite() || !originalShape.bounds().isFinite()) {
1950 return;
1951 }
1952
Chris Daltondb91c6e2017-09-08 16:25:08 -06001953 SkIRect clipConservativeBounds;
1954 clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr);
1955
Brian Salomon2fad74a2017-12-20 13:28:55 -05001956 GrShape tempShape;
Chris Dalton09e56892019-03-13 00:22:01 -06001957 auto aaTypeFlags = choose_path_aa_type_flags(aa, this->fsaaType(), *this->caps());
1958
robertphillips68737822015-10-29 12:12:21 -07001959 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001960 canDrawArgs.fCaps = this->caps();
robertphillips68737822015-10-29 12:12:21 -07001961 canDrawArgs.fViewMatrix = &viewMatrix;
Brian Salomon2fad74a2017-12-20 13:28:55 -05001962 canDrawArgs.fShape = &originalShape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06001963 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Greg Danielbe7fc462019-01-03 16:40:42 -05001964 canDrawArgs.fTargetIsWrappedVkSecondaryCB = this->wrapsVkSecondaryCB();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001965 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001966
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001967 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001968 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon2fad74a2017-12-20 13:28:55 -05001969 if (originalShape.isEmpty() && !originalShape.inverseFilled()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001970 return;
1971 }
1972
Chris Dalton09e56892019-03-13 00:22:01 -06001973 canDrawArgs.fAATypeFlags = aaTypeFlags;
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001974
1975 // Try a 1st time without applying any of the style to the geometry (and barring sw)
1976 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
1977 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1978
Brian Salomon2fad74a2017-12-20 13:28:55 -05001979 if (!pr && originalShape.style().pathEffect()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001980 // It didn't work above, so try again with the path effect applied.
Brian Salomon2fad74a2017-12-20 13:28:55 -05001981 tempShape = originalShape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1982 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001983 return;
1984 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001985 canDrawArgs.fShape = &tempShape;
Robert Phillips72152832017-01-25 17:31:35 -05001986 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001987 }
1988 if (!pr) {
Brian Salomon2fad74a2017-12-20 13:28:55 -05001989 if (canDrawArgs.fShape->style().applies()) {
1990 tempShape = canDrawArgs.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
1991 styleScale);
1992 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001993 return;
1994 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001995 canDrawArgs.fShape = &tempShape;
Brian Salomone7df0bb2018-05-07 14:44:57 -04001996 // This time, allow SW renderer
1997 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
1998 } else {
1999 pr = this->drawingManager()->getSoftwarePathRenderer();
bsalomon6663acf2016-05-10 09:14:17 -07002000 }
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05002001 }
robertphillipsea461502015-05-26 11:38:03 -07002002
bsalomon8acedde2016-06-24 10:42:16 -07002003 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07002004#ifdef SK_DEBUG
2005 SkDebugf("Unable to find path renderer compatible with path.\n");
2006#endif
2007 return;
2008 }
2009
Robert Phillips256c37b2017-03-01 14:32:46 -05002010 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05002011 std::move(paint),
2012 &GrUserStencilSettings::kUnused,
2013 this,
2014 &clip,
Chris Daltondb91c6e2017-09-08 16:25:08 -06002015 &clipConservativeBounds,
Brian Salomon82f44312017-01-11 13:42:54 -05002016 &viewMatrix,
Brian Salomon2fad74a2017-12-20 13:28:55 -05002017 canDrawArgs.fShape,
Chris Dalton09e56892019-03-13 00:22:01 -06002018 aaTypeFlags,
Brian Osman34ec3742018-07-03 10:40:57 -04002019 this->colorSpaceInfo().isLinearlyBlended()};
bsalomon0aff2fa2015-07-31 06:48:27 -07002020 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07002021}
2022
Brian Salomon467921e2017-03-06 16:17:12 -05002023static void op_bounds(SkRect* bounds, const GrOp* op) {
2024 *bounds = op->bounds();
2025 if (op->hasZeroArea()) {
2026 if (op->hasAABloat()) {
2027 bounds->outset(0.5f, 0.5f);
2028 } else {
2029 // We don't know which way the particular GPU will snap lines or points at integer
2030 // coords. So we ensure that the bounds is large enough for either snap.
2031 SkRect before = *bounds;
2032 bounds->roundOut(bounds);
2033 if (bounds->fLeft == before.fLeft) {
2034 bounds->fLeft -= 1;
2035 }
2036 if (bounds->fTop == before.fTop) {
2037 bounds->fTop -= 1;
2038 }
2039 if (bounds->fRight == before.fRight) {
2040 bounds->fRight += 1;
2041 }
2042 if (bounds->fBottom == before.fBottom) {
2043 bounds->fBottom += 1;
2044 }
2045 }
2046 }
2047}
2048
Brian Salomon348a0372018-10-31 10:42:18 -04002049void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
2050 const std::function<WillAddOpFn>& willAddFn) {
joshualitt1de610a2016-01-06 08:26:09 -08002051 ASSERT_SINGLE_OWNER
Robert Phillips69893702019-02-22 11:16:30 -05002052 if (fContext->priv().abandoned()) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002053 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002054 return;
Robert Phillipsc0138922017-03-08 11:50:55 -05002055 }
robertphillips2e1e51f2015-10-15 08:01:48 -07002056 SkDEBUGCODE(this->validate();)
Ethan Nicholas029b22c2018-10-18 16:49:56 -04002057 SkDEBUGCODE(op->fAddDrawOpCalled = true;)
Brian Salomondcbb9d92017-07-19 10:53:20 -04002058 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -07002059
Brian Salomon467921e2017-03-06 16:17:12 -05002060 // Setup clip
2061 SkRect bounds;
2062 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04002063 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04002064 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
2065 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
2066 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
2067 &bounds)) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002068 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002069 return;
Brian Salomon54d212e2017-03-21 14:22:38 -04002070 }
2071
Brian Salomon54d212e2017-03-21 14:22:38 -04002072 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
2073 appliedClip.hasStencilClip()) {
Michael Ludwigc39d0c82019-01-15 10:03:43 -05002074 if (this->caps()->performStencilClearsAsDraws()) {
2075 // Must use an op to perform the clear of the stencil buffer before this op, but only
2076 // have to clear the first time any draw needs it (this also ensures we don't loop
2077 // forever when the internal stencil clear adds a draw op that has stencil settings).
2078 if (!fRenderTargetProxy->needsStencil()) {
2079 // Send false so that the stencil buffer is fully cleared to 0
2080 this->internalStencilClear(GrFixedClip::Disabled(), /* inside mask */ false);
2081 }
2082 } else {
2083 // Just make sure the stencil buffer is cleared before the draw op, easy to do it as
2084 // a load at the start
2085 this->getRTOpList()->setStencilLoadOp(GrLoadOp::kClear);
2086 }
Robert Phillips95214472017-08-08 18:00:03 -04002087
Robert Phillips65048132017-08-10 08:44:49 -04002088 this->setNeedsStencil();
Brian Salomon54d212e2017-03-21 14:22:38 -04002089 }
2090
Brian Osman5ced0bf2019-03-15 10:15:29 -04002091 GrClampType clampType = GrPixelConfigClampType(this->colorSpaceInfo().config());
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002092 GrXferProcessor::DstProxy dstProxy;
Brian Osman5ced0bf2019-03-15 10:15:29 -04002093 GrProcessorSet::Analysis analysis = op->finalize(
2094 *this->caps(), &appliedClip, this->fsaaType(), clampType);
Chris Dalton945ee652019-01-23 09:10:36 -07002095 if (analysis.requiresDstTexture()) {
Brian Salomon09181ef2018-11-14 13:39:51 -05002096 if (!this->setupDstProxy(this->asRenderTargetProxy(), clip, *op, &dstProxy)) {
Robert Phillips9da87e02019-02-04 13:26:26 -05002097 fContext->priv().opMemoryPool()->release(std::move(op));
Brian Salomon348a0372018-10-31 10:42:18 -04002098 return;
Brian Salomon54d212e2017-03-21 14:22:38 -04002099 }
2100 }
2101
2102 op->setClippedBounds(bounds);
Brian Salomon348a0372018-10-31 10:42:18 -04002103 auto opList = this->getRTOpList();
2104 if (willAddFn) {
2105 willAddFn(op.get(), opList->uniqueID());
2106 }
Chris Dalton945ee652019-01-23 09:10:36 -07002107 opList->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxy, *this->caps());
Brian Salomon54d212e2017-03-21 14:22:38 -04002108}
2109
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002110bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
Brian Salomon09181ef2018-11-14 13:39:51 -05002111 const GrOp& op,
Robert Phillips16d8ec62017-07-27 16:16:25 -04002112 GrXferProcessor::DstProxy* dstProxy) {
Greg Danielbe7fc462019-01-03 16:40:42 -05002113 // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
2114 // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
2115 // start and stop the render pass in order to make the copy.
2116 if (rtProxy->wrapsVkSecondaryCB()) {
2117 return false;
2118 }
2119
Brian Salomon467921e2017-03-06 16:17:12 -05002120 if (this->caps()->textureBarrierSupport()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04002121 if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
Brian Salomon467921e2017-03-06 16:17:12 -05002122 // The render target is a texture, so we can read from it directly in the shader. The XP
2123 // will be responsible to detect this situation and request a texture barrier.
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002124 dstProxy->setProxy(sk_ref_sp(texProxy));
2125 dstProxy->setOffset(0, 0);
Robert Phillipsbf25d432017-04-07 10:08:53 -04002126 return true;
Brian Salomon467921e2017-03-06 16:17:12 -05002127 }
2128 }
2129
Robert Phillipsbf25d432017-04-07 10:08:53 -04002130 SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
Brian Salomon467921e2017-03-06 16:17:12 -05002131
Eric Karl74480882017-04-03 14:49:05 -07002132 SkIRect clippedRect;
Robert Phillipsbf25d432017-04-07 10:08:53 -04002133 clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
Brian Salomon09181ef2018-11-14 13:39:51 -05002134 SkRect opBounds = op.bounds();
2135 // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by
2136 // 0.5 pixels.
2137 if (op.hasAABloat() || op.hasZeroArea()) {
2138 opBounds.outset(0.5f, 0.5f);
2139 // An antialiased/hairline draw can sometimes bleed outside of the clips bounds. For
2140 // performance we may ignore the clip when the draw is entirely inside the clip is float
2141 // space but will hit pixels just outside the clip when actually rasterizing.
2142 clippedRect.outset(1, 1);
2143 clippedRect.intersect(SkIRect::MakeWH(rtProxy->width(), rtProxy->height()));
2144 }
2145 SkIRect opIBounds;
2146 opBounds.roundOut(&opIBounds);
2147 if (!clippedRect.intersect(opIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05002148#ifdef SK_DEBUG
Robert Phillipsbf25d432017-04-07 10:08:53 -04002149 GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
Brian Salomon467921e2017-03-06 16:17:12 -05002150#endif
Robert Phillipsbf25d432017-04-07 10:08:53 -04002151 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05002152 }
2153
2154 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
2155 // have per-sample dst values by making the copy multisampled.
2156 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07002157 bool rectsMustMatch = false;
2158 bool disallowSubrect = false;
Brian Salomon2a4f9832018-03-03 22:43:43 -05002159 GrSurfaceOrigin origin;
2160 if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &origin, &rectsMustMatch,
2161 &disallowSubrect)) {
Brian Salomon467921e2017-03-06 16:17:12 -05002162 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillipsbf25d432017-04-07 10:08:53 -04002163 desc.fConfig = rtProxy->config();
Greg Daniel1efe3222018-04-04 14:02:51 -04002164 origin = rtProxy->origin();
Brian Salomon467921e2017-03-06 16:17:12 -05002165 }
2166
Eric Karl74480882017-04-03 14:49:05 -07002167 if (!disallowSubrect) {
2168 copyRect = clippedRect;
2169 }
Brian Salomon467921e2017-03-06 16:17:12 -05002170
Robert Phillipsbf25d432017-04-07 10:08:53 -04002171 SkIPoint dstPoint, dstOffset;
2172 SkBackingFit fit;
Eric Karl74480882017-04-03 14:49:05 -07002173 if (rectsMustMatch) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04002174 desc.fWidth = rtProxy->width();
2175 desc.fHeight = rtProxy->height();
Eric Karl74480882017-04-03 14:49:05 -07002176 dstPoint = {copyRect.fLeft, copyRect.fTop};
2177 dstOffset = {0, 0};
Robert Phillipsbf25d432017-04-07 10:08:53 -04002178 fit = SkBackingFit::kExact;
Eric Karl74480882017-04-03 14:49:05 -07002179 } else {
2180 desc.fWidth = copyRect.width();
2181 desc.fHeight = copyRect.height();
2182 dstPoint = {0, 0};
2183 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillipsbf25d432017-04-07 10:08:53 -04002184 fit = SkBackingFit::kApprox;
Eric Karl74480882017-04-03 14:49:05 -07002185 }
Brian Salomon467921e2017-03-06 16:17:12 -05002186
Greg Daniel4065d452018-11-16 15:43:41 -05002187 SkASSERT(rtProxy->backendFormat().textureType() == GrTextureType::k2D);
2188 const GrBackendFormat& format = rtProxy->backendFormat();
Robert Phillips9da87e02019-02-04 13:26:26 -05002189 sk_sp<GrSurfaceContext> sContext = fContext->priv().makeDeferredSurfaceContext(
Greg Daniel4065d452018-11-16 15:43:41 -05002190 format, desc, origin, GrMipMapped::kNo, fit, SkBudgeted::kYes,
Brian Salomonf802e752018-02-13 17:13:31 -05002191 sk_ref_sp(this->colorSpaceInfo().colorSpace()));
Robert Phillipsbf25d432017-04-07 10:08:53 -04002192 if (!sContext) {
2193 SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
2194 return false;
2195 }
2196
2197 if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
2198 SkDebugf("setupDstTexture: copy failed.\n");
2199 return false;
2200 }
2201
Robert Phillipsbb581ce2017-05-29 15:05:15 -04002202 dstProxy->setProxy(sContext->asTextureProxyRef());
2203 dstProxy->setOffset(dstOffset);
Robert Phillipsbf25d432017-04-07 10:08:53 -04002204 return true;
robertphillips2334fb62015-06-17 05:43:33 -07002205}