blob: 497518f46f63b7f6ce16d5dcd235add4fba04384 [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"
Brian Salomon5ec9def2016-12-20 15:34:05 -050014#include "GrColor.h"
Robert Phillipse78b7252017-04-06 07:59:41 -040015#include "GrContextPriv.h"
robertphillips77a2e522015-10-17 07:43:27 -070016#include "GrDrawingManager.h"
csmartdalton02fa32c2016-08-19 13:29:27 -070017#include "GrFixedClip.h"
robertphillips714712b2016-08-04 06:20:45 -070018#include "GrGpuResourcePriv.h"
Robert Phillips9d6c64f2017-09-14 10:56:45 -040019#include "GrOpList.h"
robertphillipsea461502015-05-26 11:38:03 -070020#include "GrPathRenderer.h"
Brian Salomon57caa662017-10-18 12:21:05 +000021#include "GrQuad.h"
robertphillips2334fb62015-06-17 05:43:33 -070022#include "GrRenderTarget.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050023#include "GrRenderTargetContextPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070024#include "GrResourceProvider.h"
Brian Salomon653f42f2018-07-10 10:07:31 -040025#include "GrShape.h"
Brian Salomon467921e2017-03-06 16:17:12 -050026#include "GrStencilAttachment.h"
Brian Salomon653f42f2018-07-10 10:07:31 -040027#include "GrStyle.h"
Brian Salomondcbb9d92017-07-19 10:53:20 -040028#include "GrTracing.h"
Jim Van Verth1af03d42017-07-31 09:34:58 -040029#include "SkDrawShadowInfo.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040030#include "SkGr.h"
Brian Salomon467921e2017-03-06 16:17:12 -050031#include "SkLatticeIter.h"
32#include "SkMatrixPriv.h"
Mike Reed242135a2018-02-22 13:41:39 -050033#include "SkRRectPriv.h"
Jim Van Verth34d6e4b2017-06-09 11:09:03 -040034#include "SkShadowUtils.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070035#include "SkSurfacePriv.h"
Brian Salomon467921e2017-03-06 16:17:12 -050036#include "effects/GrRRectEffect.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040037#include "ops/GrAtlasTextOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050038#include "ops/GrClearOp.h"
Robert Phillipsb9a02a12017-04-06 11:08:40 -040039#include "ops/GrClearStencilClipOp.h"
Robert Phillips65a88fa2017-08-08 08:36:22 -040040#include "ops/GrDebugMarkerOp.h"
Brian Salomon0f353322017-05-03 20:58:59 +000041#include "ops/GrDrawAtlasOp.h"
Brian Salomon6d4b65e2017-05-03 17:06:09 -040042#include "ops/GrDrawOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050043#include "ops/GrDrawVerticesOp.h"
44#include "ops/GrLatticeOp.h"
45#include "ops/GrOp.h"
46#include "ops/GrOvalOpFactory.h"
47#include "ops/GrRectOpFactory.h"
48#include "ops/GrRegionOp.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040049#include "ops/GrSemaphoreOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050050#include "ops/GrShadowRRectOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050051#include "ops/GrStencilPathOp.h"
Brian Salomon34169692017-08-28 15:32:01 -040052#include "ops/GrTextureOp.h"
Herb Derby26cbe512018-05-24 14:39:01 -040053#include "text/GrTextContext.h"
Brian Salomonf18b1d82017-10-27 11:30:49 -040054#include "text/GrTextUtils.h"
55
56class GrRenderTargetContext::TextTarget : public GrTextUtils::Target {
57public:
58 TextTarget(GrRenderTargetContext* renderTargetContext)
59 : Target(renderTargetContext->width(), renderTargetContext->height(),
60 renderTargetContext->colorSpaceInfo())
61 , fRenderTargetContext(renderTargetContext) {}
62
Robert Phillips7c525e62018-06-12 10:11:12 -040063 void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
Brian Salomonf18b1d82017-10-27 11:30:49 -040064 fRenderTargetContext->addDrawOp(clip, std::move(op));
65 }
66
67 void drawPath(const GrClip& clip, const SkPath& path, const SkPaint& paint,
68 const SkMatrix& viewMatrix, const SkMatrix* pathMatrix,
Robert Phillips7c525e62018-06-12 10:11:12 -040069 const SkIRect& clipBounds) override {
Brian Salomonf18b1d82017-10-27 11:30:49 -040070 GrBlurUtils::drawPathWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
71 clip, path, paint, viewMatrix, pathMatrix, clipBounds,
72 false);
73 }
74
75 void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
Robert Phillips7c525e62018-06-12 10:11:12 -040076 GrPaint* grPaint) override {
Brian Salomonf18b1d82017-10-27 11:30:49 -040077 GrContext* context = fRenderTargetContext->fContext;
78 const GrColorSpaceInfo& colorSpaceInfo = fRenderTargetContext->colorSpaceInfo();
79 if (kARGB_GrMaskFormat == maskFormat) {
80 SkPaintToGrPaintWithPrimitiveColor(context, colorSpaceInfo, skPaint, grPaint);
81 } else {
82 SkPaintToGrPaint(context, colorSpaceInfo, skPaint, viewMatrix, grPaint);
83 }
84 }
85
Robert Phillips7c525e62018-06-12 10:11:12 -040086 GrContext* getContext() override {
87 return fRenderTargetContext->fContext;
88 }
89
Brian Salomonf18b1d82017-10-27 11:30:49 -040090private:
91 GrRenderTargetContext* fRenderTargetContext;
92};
joshualittbc907352016-01-13 06:45:40 -080093
Robert Phillips72152832017-01-25 17:31:35 -050094#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080095#define ASSERT_SINGLE_OWNER \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -040096 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
robertphillips391395d2016-03-02 09:26:36 -080097#define ASSERT_SINGLE_OWNER_PRIV \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -040098 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
Robert Phillips72152832017-01-25 17:31:35 -050099#define RETURN_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return; }
100#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
101#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
102#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
103#define RETURN_NULL_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -0700104
Brian Salomone225b562017-06-14 13:00:03 -0400105//////////////////////////////////////////////////////////////////////////////
106
107GrAAType GrChooseAAType(GrAA aa, GrFSAAType fsaaType, GrAllowMixedSamples allowMixedSamples,
108 const GrCaps& caps) {
109 if (GrAA::kNo == aa) {
110 // On some devices we cannot disable MSAA if it is enabled so we make the AA type reflect
111 // that.
112 if (fsaaType == GrFSAAType::kUnifiedMSAA && !caps.multisampleDisableSupport()) {
113 return GrAAType::kMSAA;
114 }
115 return GrAAType::kNone;
116 }
117 switch (fsaaType) {
118 case GrFSAAType::kNone:
119 return GrAAType::kCoverage;
120 case GrFSAAType::kUnifiedMSAA:
121 return GrAAType::kMSAA;
122 case GrFSAAType::kMixedSamples:
123 return GrAllowMixedSamples::kYes == allowMixedSamples ? GrAAType::kMixedSamples
124 : GrAAType::kCoverage;
125 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400126 SK_ABORT("Unexpected fsaa type");
Brian Salomone225b562017-06-14 13:00:03 -0400127 return GrAAType::kNone;
128}
129
130//////////////////////////////////////////////////////////////////////////////
131
robertphillipsea461502015-05-26 11:38:03 -0700132class AutoCheckFlush {
133public:
halcanary9d524f22016-03-29 09:03:52 -0700134 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -0700135 SkASSERT(fDrawingManager);
136 }
bsalomonb77a9072016-09-07 10:02:04 -0700137 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -0700138
139private:
robertphillips77a2e522015-10-17 07:43:27 -0700140 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -0700141};
142
Brian Osman11052242016-10-27 14:47:55 -0400143bool GrRenderTargetContext::wasAbandoned() const {
Robert Phillips72152832017-01-25 17:31:35 -0500144 return this->drawingManager()->wasAbandoned();
robertphillips7761d612016-05-16 09:14:53 -0700145}
146
Robert Phillipsf2361d22016-10-25 14:20:06 -0400147// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -0400148// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -0400149// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -0400150// when the renderTargetContext attempts to use it (via getOpList).
151GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
152 GrDrawingManager* drawingMgr,
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400153 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -0400154 sk_sp<SkColorSpace> colorSpace,
155 const SkSurfaceProps* surfaceProps,
156 GrAuditTrail* auditTrail,
Robert Phillips941d1442017-06-14 16:37:02 -0400157 GrSingleOwner* singleOwner,
158 bool managedOpList)
Brian Salomonf3569f02017-10-24 12:52:33 -0400159 : GrSurfaceContext(context, drawingMgr, rtp->config(), std::move(colorSpace), auditTrail,
160 singleOwner)
161 , fRenderTargetProxy(std::move(rtp))
162 , fOpList(sk_ref_sp(fRenderTargetProxy->getLastRenderTargetOpList()))
Brian Salomonf3569f02017-10-24 12:52:33 -0400163 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
164 , fManagedOpList(managedOpList) {
Robert Phillips4150eea2018-02-07 17:08:21 -0500165 GrResourceProvider* resourceProvider = context->contextPriv().resourceProvider();
166 if (resourceProvider && !resourceProvider->explicitlyAllocateGPUResources()) {
167 // MDB TODO: to ensure all resources still get allocated in the correct order in the hybrid
168 // world we need to get the correct opList here so that it, in turn, can grab and hold
169 // its rendertarget.
170 this->getRTOpList();
171 }
172
Brian Salomonf18b1d82017-10-27 11:30:49 -0400173 fTextTarget.reset(new TextTarget(this));
robertphillips2e1e51f2015-10-15 08:01:48 -0700174 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700175}
176
robertphillips2e1e51f2015-10-15 08:01:48 -0700177#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -0400178void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400179 SkASSERT(fRenderTargetProxy);
180 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -0700181
Robert Phillipsf2361d22016-10-25 14:20:06 -0400182 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsdc83b892017-04-13 12:23:54 -0400183 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList.get());
robertphillipsa106c622015-10-16 09:07:06 -0700184 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700185}
186#endif
187
Brian Osman11052242016-10-27 14:47:55 -0400188GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800189 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700190}
191
Robert Phillipsf200a902017-01-30 13:27:37 -0500192GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000193 return fRenderTargetProxy->asTextureProxy();
194}
195
Greg Daniele252f082017-10-23 16:05:23 -0400196const GrTextureProxy* GrRenderTargetContext::asTextureProxy() const {
197 return fRenderTargetProxy->asTextureProxy();
198}
199
Robert Phillipsf200a902017-01-30 13:27:37 -0500200sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
201 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
202}
203
Greg Daniele252f082017-10-23 16:05:23 -0400204GrMipMapped GrRenderTargetContext::mipMapped() const {
205 if (const GrTextureProxy* proxy = this->asTextureProxy()) {
206 return proxy->mipMapped();
207 }
208 return GrMipMapped::kNo;
209}
210
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400211GrRenderTargetOpList* GrRenderTargetContext::getRTOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800212 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700213 SkDEBUGCODE(this->validate();)
214
Robert Phillipsf2361d22016-10-25 14:20:06 -0400215 if (!fOpList || fOpList->isClosed()) {
Robert Phillips941d1442017-06-14 16:37:02 -0400216 fOpList = this->drawingManager()->newRTOpList(fRenderTargetProxy.get(), fManagedOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700217 }
218
Robert Phillipsdc83b892017-04-13 12:23:54 -0400219 return fOpList.get();
robertphillipsa106c622015-10-16 09:07:06 -0700220}
221
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400222GrOpList* GrRenderTargetContext::getOpList() {
223 return this->getRTOpList();
robertphillipsea461502015-05-26 11:38:03 -0700224}
225
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500226void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
227 const SkMatrix& viewMatrix, const char text[],
228 size_t byteLength, const SkScalar pos[],
Brian Salomon82f44312017-01-11 13:42:54 -0500229 int scalarsPerPosition, const SkPoint& offset,
230 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800231 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700232 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700233 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400234 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPosText", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -0700235
Herb Derby26cbe512018-05-24 14:39:01 -0400236 GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
Brian Salomonf18b1d82017-10-27 11:30:49 -0400237 atlasTextContext->drawPosText(fContext, fTextTarget.get(), clip, paint, viewMatrix,
238 fSurfaceProps, text, byteLength, pos, scalarsPerPosition, offset,
239 clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700240}
robertphillipscaef3452015-11-11 13:18:11 -0800241
Robert Phillips38580452018-06-28 12:00:35 +0000242void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
243 const SkMatrix& viewMatrix, const SkTextBlob* blob,
244 SkScalar x, SkScalar y, SkDrawFilter* filter,
245 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800246 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700247 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700248 SkDEBUGCODE(this->validate();)
Robert Phillips38580452018-06-28 12:00:35 +0000249 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextBlob", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -0700250
Herb Derby26cbe512018-05-24 14:39:01 -0400251 GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
Robert Phillips38580452018-06-28 12:00:35 +0000252 atlasTextContext->drawTextBlob(fContext, fTextTarget.get(), clip, paint, viewMatrix,
253 fSurfaceProps, blob, x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700254}
255
Brian Osman11052242016-10-27 14:47:55 -0400256void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800257 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700258 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700259 SkDEBUGCODE(this->validate();)
Robert Phillips6b47c7d2017-08-29 07:24:09 -0400260 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700261
Robert Phillips72152832017-01-25 17:31:35 -0500262 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400263
Robert Phillips380b90c2017-08-30 07:41:07 -0400264 this->getRTOpList()->discard();
robertphillipsea461502015-05-26 11:38:03 -0700265}
266
Brian Osman11052242016-10-27 14:47:55 -0400267void GrRenderTargetContext::clear(const SkIRect* rect,
268 const GrColor color,
Chris Dalton344e9032017-12-11 15:42:09 -0700269 CanClearFullscreen canClearFullscreen) {
joshualitt1de610a2016-01-06 08:26:09 -0800270 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700271 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700272 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400273 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
robertphillipsea461502015-05-26 11:38:03 -0700274
Robert Phillips72152832017-01-25 17:31:35 -0500275 AutoCheckFlush acf(this->drawingManager());
Chris Dalton344e9032017-12-11 15:42:09 -0700276 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color,
277 canClearFullscreen);
csmartdalton29df7602016-08-31 11:55:52 -0700278}
robertphillips9199a9f2016-07-13 07:48:43 -0700279
Robert Phillips784b7bf2016-12-09 13:35:02 -0500280void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
281 ASSERT_SINGLE_OWNER_PRIV
282 RETURN_IF_ABANDONED_PRIV
283 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400284 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "absClear",
285 fRenderTargetContext->fContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500286
Robert Phillips72152832017-01-25 17:31:35 -0500287 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500288
Brian Salomonbb5711a2017-05-17 13:49:59 -0400289 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(),
290 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500291
292 if (clearRect) {
293 if (clearRect->contains(rtRect)) {
294 clearRect = nullptr; // full screen
295 } else {
296 if (!rtRect.intersect(*clearRect)) {
297 return;
298 }
299 }
300 }
301
302 // TODO: in a post-MDB world this should be handled at the OpList level.
303 // An op-list that is initially cleared and has no other ops should receive an
304 // extra draw.
Brian Salomon43f8bf02017-10-18 08:33:29 -0400305 // This path doesn't handle coalescing of full screen clears b.c. it
306 // has to clear the entire render target - not just the content area.
307 // It could be done but will take more finagling.
Robert Phillips7c525e62018-06-12 10:11:12 -0400308 std::unique_ptr<GrOp> op(GrClearOp::Make(fRenderTargetContext->fContext, rtRect,
309 color, !clearRect));
Brian Salomon43f8bf02017-10-18 08:33:29 -0400310 if (!op) {
311 return;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500312 }
Brian Salomon43f8bf02017-10-18 08:33:29 -0400313 fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500314}
315
Brian Osman11052242016-10-27 14:47:55 -0400316void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
317 const GrColor color,
Chris Dalton344e9032017-12-11 15:42:09 -0700318 CanClearFullscreen canClearFullscreen) {
csmartdalton29df7602016-08-31 11:55:52 -0700319 ASSERT_SINGLE_OWNER_PRIV
320 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400321 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400322 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
323 fRenderTargetContext->fContext);
csmartdalton29df7602016-08-31 11:55:52 -0700324
Robert Phillips72152832017-01-25 17:31:35 -0500325 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Chris Dalton344e9032017-12-11 15:42:09 -0700326 fRenderTargetContext->internalClear(clip, color, canClearFullscreen);
csmartdalton29df7602016-08-31 11:55:52 -0700327}
328
Brian Osman11052242016-10-27 14:47:55 -0400329void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
330 const GrColor color,
Chris Dalton344e9032017-12-11 15:42:09 -0700331 CanClearFullscreen canClearFullscreen) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700332 bool isFull = false;
333 if (!clip.hasWindowRectangles()) {
Brian Salomond818ebf2018-07-02 14:08:49 +0000334 isFull = !clip.scissorEnabled() ||
Chris Dalton344e9032017-12-11 15:42:09 -0700335 (CanClearFullscreen::kYes == canClearFullscreen &&
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400336 this->caps()->preferFullscreenClears()) ||
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700337 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
338 }
robertphillips9199a9f2016-07-13 07:48:43 -0700339
Brian Salomon43f8bf02017-10-18 08:33:29 -0400340 if (isFull) {
Robert Phillips7c525e62018-06-12 10:11:12 -0400341 this->getRTOpList()->fullClear(fContext, color);
robertphillips9199a9f2016-07-13 07:48:43 -0700342 } else {
Robert Phillips7c525e62018-06-12 10:11:12 -0400343 std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color, this->asSurfaceProxy()));
Brian Salomon42521e82016-12-07 16:44:58 -0500344 if (!op) {
csmartdalton29df7602016-08-31 11:55:52 -0700345 return;
346 }
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400347 this->getRTOpList()->addOp(std::move(op), *this->caps());
robertphillips9199a9f2016-07-13 07:48:43 -0700348 }
robertphillipsea461502015-05-26 11:38:03 -0700349}
350
Brian Osman11052242016-10-27 14:47:55 -0400351void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500352 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400353 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800354 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700355 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700356 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400357 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPaint", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700358
robertphillipsea461502015-05-26 11:38:03 -0700359 // set rect to be big enough to fill the space, but not super-huge, so we
360 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700361
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400362 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700363
bsalomoncb31e512016-08-26 10:48:19 -0700364 SkRRect rrect;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500365 GrAA aa;
bsalomoncb31e512016-08-26 10:48:19 -0700366 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
367 // transformation for non-rect rrects. Rects caused a performance regression on an Android
368 // test that needs investigation. We also skip cases where there are fragment processors
369 // because they may depend on having correct local coords and this path draws in device space
370 // without a local matrix.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500371 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500372 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
373 GrStyle::SimpleFill());
bsalomoncb31e512016-08-26 10:48:19 -0700374 return;
375 }
376
robertphillipsea461502015-05-26 11:38:03 -0700377
378 bool isPerspective = viewMatrix.hasPerspective();
379
380 // We attempt to map r by the inverse matrix and draw that. mapRect will
381 // map the four corners and bound them with a new rect. This will not
382 // produce a correct result for some perspective matrices.
383 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700384 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700385 return;
386 }
Brian Salomon82f44312017-01-11 13:42:54 -0500387 this->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700388 } else {
389 SkMatrix localMatrix;
390 if (!viewMatrix.invert(&localMatrix)) {
robertphillipsea461502015-05-26 11:38:03 -0700391 return;
392 }
393
Robert Phillips72152832017-01-25 17:31:35 -0500394 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700395
Brian Salomonbaaf4392017-06-15 09:59:23 -0400396 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
Robert Phillips7c525e62018-06-12 10:11:12 -0400397 fContext, std::move(paint), SkMatrix::I(), localMatrix, r, GrAAType::kNone);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400398 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700399 }
400}
401
robertphillipsea461502015-05-26 11:38:03 -0700402static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
403 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
404 point.fY >= rect.fTop && point.fY <= rect.fBottom;
405}
406
csmartdalton97f6cd52016-07-13 13:37:08 -0700407// Attempts to crop a rect and optional local rect to the clip boundaries.
408// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700409static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700410 const SkMatrix& viewMatrix, SkRect* rect,
411 SkRect* localRect = nullptr) {
412 if (!viewMatrix.rectStaysRect()) {
413 return true;
414 }
415
csmartdalton97f6cd52016-07-13 13:37:08 -0700416 SkIRect clipDevBounds;
417 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700418
robertphillips13a7eee2016-08-31 15:06:24 -0700419 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700420 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
421 return false;
422 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700423
424 if (localRect) {
425 if (!rect->intersects(clipBounds)) {
426 return false;
427 }
428 const SkScalar dx = localRect->width() / rect->width();
429 const SkScalar dy = localRect->height() / rect->height();
430 if (clipBounds.fLeft > rect->fLeft) {
431 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
432 rect->fLeft = clipBounds.fLeft;
433 }
434 if (clipBounds.fTop > rect->fTop) {
435 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
436 rect->fTop = clipBounds.fTop;
437 }
438 if (clipBounds.fRight < rect->fRight) {
439 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
440 rect->fRight = clipBounds.fRight;
441 }
442 if (clipBounds.fBottom < rect->fBottom) {
443 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
444 rect->fBottom = clipBounds.fBottom;
445 }
446 return true;
447 }
448
449 return rect->intersect(clipBounds);
450}
451
Brian Osman11052242016-10-27 14:47:55 -0400452bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500453 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500454 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400455 const SkMatrix& viewMatrix,
456 const SkRect& rect,
457 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700458 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500459 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700460 return true;
461 }
robertphillips44302392016-07-08 14:43:03 -0700462
Brian Salomon7c8460e2017-05-12 11:36:10 -0400463 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400464 std::unique_ptr<GrDrawOp> op;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500465 if (GrAAType::kCoverage == aaType) {
Robert Phillips7c525e62018-06-12 10:11:12 -0400466 op = GrRectOpFactory::MakeAAFill(fContext, std::move(paint), viewMatrix, croppedRect, ss);
robertphillips391395d2016-03-02 09:26:36 -0800467 } else {
Robert Phillips7c525e62018-06-12 10:11:12 -0400468 op = GrRectOpFactory::MakeNonAAFill(fContext, std::move(paint), viewMatrix, croppedRect,
469 aaType, ss);
robertphillips391395d2016-03-02 09:26:36 -0800470 }
Brian Salomonbaaf4392017-06-15 09:59:23 -0400471 if (!op) {
472 return false;
473 }
474 this->addDrawOp(clip, std::move(op));
475 return true;
robertphillips391395d2016-03-02 09:26:36 -0800476}
477
Brian Osman11052242016-10-27 14:47:55 -0400478void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500479 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500480 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400481 const SkMatrix& viewMatrix,
482 const SkRect& rect,
483 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700484 if (!style) {
485 style = &GrStyle::SimpleFill();
486 }
joshualitt1de610a2016-01-06 08:26:09 -0800487 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700488 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700489 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400490 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700491
bsalomon6663acf2016-05-10 09:14:17 -0700492 // Path effects should've been devolved to a path in SkGpuDevice
493 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700494
Robert Phillips72152832017-01-25 17:31:35 -0500495 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700496
bsalomon6663acf2016-05-10 09:14:17 -0700497 const SkStrokeRec& stroke = style->strokeRec();
Robert Phillipsc90b4db2018-04-23 15:12:00 +0000498 if (stroke.getStyle() == SkStrokeRec::kFill_Style && !paint.numCoverageFragmentProcessors()) {
Brian Salomon43f8bf02017-10-18 08:33:29 -0400499 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
500 // checking cases where the RT is fully inside a stroke.
501 SkRect rtRect = fRenderTargetProxy->getBoundsRect();
502 // Does the clip contain the entire RT?
503 if (clip.quickContains(rtRect)) {
504 SkMatrix invM;
505 if (!viewMatrix.invert(&invM)) {
506 return;
507 }
508 // Does the rect bound the RT?
Brian Salomona33b67c2018-05-17 10:42:14 -0400509 GrQuad quad(rtRect, invM);
Brian Salomon43f8bf02017-10-18 08:33:29 -0400510 if (rect_contains_inclusive(rect, quad.point(0)) &&
511 rect_contains_inclusive(rect, quad.point(1)) &&
512 rect_contains_inclusive(rect, quad.point(2)) &&
513 rect_contains_inclusive(rect, quad.point(3))) {
514 // Will it blend?
515 GrColor clearColor;
516 if (paint.isConstantBlendedColor(&clearColor)) {
Chris Dalton344e9032017-12-11 15:42:09 -0700517 this->clear(nullptr, clearColor,
518 GrRenderTargetContext::CanClearFullscreen::kYes);
robertphillipsea461502015-05-26 11:38:03 -0700519 return;
520 }
521 }
522 }
robertphillips44302392016-07-08 14:43:03 -0700523
Brian Salomon82f44312017-01-11 13:42:54 -0500524 if (this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, nullptr)) {
robertphillips44302392016-07-08 14:43:03 -0700525 return;
526 }
bsalomona7d85ba2016-07-06 11:54:59 -0700527 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
528 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
529 if ((!rect.width() || !rect.height()) &&
530 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
531 SkScalar r = stroke.getWidth() / 2;
532 // TODO: Move these stroke->fill fallbacks to GrShape?
533 switch (stroke.getJoin()) {
534 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500535 this->drawRect(
536 clip, std::move(paint), aa, viewMatrix,
537 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
538 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700539 return;
540 case SkPaint::kRound_Join:
541 // Raster draws nothing when both dimensions are empty.
542 if (rect.width() || rect.height()){
543 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500544 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
545 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700546 return;
547 }
548 case SkPaint::kBevel_Join:
549 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500550 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700551 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
552 &GrStyle::SimpleFill());
553 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500554 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700555 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
556 &GrStyle::SimpleFill());
557 }
558 return;
559 }
560 }
robertphillips44302392016-07-08 14:43:03 -0700561
Brian Salomonbaaf4392017-06-15 09:59:23 -0400562 std::unique_ptr<GrDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700563
Brian Salomon7c8460e2017-05-12 11:36:10 -0400564 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500565 if (GrAAType::kCoverage == aaType) {
cdaltonbb539482016-01-04 09:48:25 -0800566 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
567 if (viewMatrix.rectStaysRect()) {
Robert Phillips7c525e62018-06-12 10:11:12 -0400568 op = GrRectOpFactory::MakeAAStroke(fContext, std::move(paint), viewMatrix, rect,
569 stroke);
cdaltonbb539482016-01-04 09:48:25 -0800570 }
robertphillipsea461502015-05-26 11:38:03 -0700571 } else {
Robert Phillips7c525e62018-06-12 10:11:12 -0400572 op = GrRectOpFactory::MakeNonAAStroke(fContext, std::move(paint), viewMatrix, rect,
573 stroke, aaType);
robertphillips391395d2016-03-02 09:26:36 -0800574 }
robertphillips4bc31812016-03-01 12:22:49 -0800575
Brian Salomon42521e82016-12-07 16:44:58 -0500576 if (op) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400577 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700578 return;
robertphillips4bc31812016-03-01 12:22:49 -0800579 }
robertphillips4bc31812016-03-01 12:22:49 -0800580 }
Brian Salomon2fad74a2017-12-20 13:28:55 -0500581 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(rect, *style));
robertphillipsea461502015-05-26 11:38:03 -0700582}
583
Robert Phillipsec2249f2016-11-09 08:54:35 -0500584int GrRenderTargetContextPriv::maxWindowRectangles() const {
585 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400586 *fRenderTargetContext->caps());
Robert Phillipsec2249f2016-11-09 08:54:35 -0500587}
588
Jim Van Verth6a40abc2017-11-02 16:56:09 +0000589void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700590 ASSERT_SINGLE_OWNER_PRIV
591 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400592 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400593 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
594 fRenderTargetContext->fContext);
robertphillips976f5f02016-06-03 10:59:20 -0700595
Robert Phillips72152832017-01-25 17:31:35 -0500596 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400597
Robert Phillips7c525e62018-06-12 10:11:12 -0400598 GrRenderTargetProxy* rtProxy = fRenderTargetContext->fRenderTargetProxy.get();
599 std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fRenderTargetContext->fContext,
600 clip, insideStencilMask, rtProxy));
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400601 if (!op) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500602 return;
603 }
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400604 fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -0700605}
606
Chris Daltonbbfd5162017-11-07 13:35:22 -0700607void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500608 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400609 const SkMatrix& viewMatrix,
610 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500611 ASSERT_SINGLE_OWNER_PRIV
612 RETURN_IF_ABANDONED_PRIV
613 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400614 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
615 fRenderTargetContext->fContext);
Brian Salomon467921e2017-03-06 16:17:12 -0500616
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500617 SkASSERT(aaType != GrAAType::kCoverage);
Brian Salomon467921e2017-03-06 16:17:12 -0500618
619 bool useHWAA = GrAATypeIsHW(aaType);
620 // TODO: extract portions of checkDraw that are relevant to path stenciling.
621 SkASSERT(path);
622 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
623
624 // FIXME: Use path bounds instead of this WAR once
625 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
626 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
627
628 // Setup clip
Chris Daltonbbfd5162017-11-07 13:35:22 -0700629 GrAppliedHardClip appliedClip;
630 if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
631 &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500632 return;
633 }
634
Robert Phillips65048132017-08-10 08:44:49 -0400635 fRenderTargetContext->setNeedsStencil();
Brian Salomon467921e2017-03-06 16:17:12 -0500636
Robert Phillips7c525e62018-06-12 10:11:12 -0400637 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
638 viewMatrix,
Brian Salomon467921e2017-03-06 16:17:12 -0500639 useHWAA,
640 path->getFillType(),
641 appliedClip.hasStencilClip(),
Brian Salomon467921e2017-03-06 16:17:12 -0500642 appliedClip.scissorState(),
Brian Salomon467921e2017-03-06 16:17:12 -0500643 path);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400644 if (!op) {
645 return;
646 }
Brian Salomon97180af2017-03-14 13:42:58 -0400647 op->setClippedBounds(bounds);
Robert Phillips2de8cfa2017-06-28 10:33:41 -0400648 fRenderTargetContext->getRTOpList()->addOp(std::move(op), *fRenderTargetContext->caps());
robertphillips976f5f02016-06-03 10:59:20 -0700649}
650
Chris Daltonbbfd5162017-11-07 13:35:22 -0700651void GrRenderTargetContextPriv::stencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400652 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500653 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400654 const SkMatrix& viewMatrix,
655 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700656 ASSERT_SINGLE_OWNER_PRIV
657 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400658 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400659 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilRect",
660 fRenderTargetContext->fContext);
661
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500662 SkASSERT(GrAAType::kCoverage != aaType);
Robert Phillips72152832017-01-25 17:31:35 -0500663 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700664
665 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500666 paint.setXPFactory(GrDisableColorXPFactory::Get());
Robert Phillips7c525e62018-06-12 10:11:12 -0400667 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFill(fRenderTargetContext->fContext,
668 std::move(paint), viewMatrix,
669 rect, aaType, ss);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400670 fRenderTargetContext->addDrawOp(clip, std::move(op));
robertphillips976f5f02016-06-03 10:59:20 -0700671}
672
Chris Daltonbbfd5162017-11-07 13:35:22 -0700673bool GrRenderTargetContextPriv::drawAndStencilRect(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -0400674 const GrUserStencilSettings* ss,
675 SkRegion::Op op,
676 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500677 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400678 const SkMatrix& viewMatrix,
679 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800680 ASSERT_SINGLE_OWNER_PRIV
681 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400682 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400683 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilRect",
684 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -0800685
Robert Phillips72152832017-01-25 17:31:35 -0500686 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800687
688 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800689 paint.setCoverageSetOpXPFactory(op, invert);
690
Brian Salomon82f44312017-01-11 13:42:54 -0500691 if (fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800692 return true;
693 }
robertphillips391395d2016-03-02 09:26:36 -0800694 SkPath path;
695 path.setIsVolatile(true);
696 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500697 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800698}
699
Brian Osman11052242016-10-27 14:47:55 -0400700void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500701 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500702 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400703 const SkMatrix& viewMatrix,
704 const SkRect& rectToDraw,
705 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800706 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700707 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700708 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400709 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectToRect", fContext);
robertphillipsea461502015-05-26 11:38:03 -0700710
csmartdalton97f6cd52016-07-13 13:37:08 -0700711 SkRect croppedRect = rectToDraw;
712 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700713 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
714 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700715 return;
716 }
717
Robert Phillips72152832017-01-25 17:31:35 -0500718 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700719
Brian Salomon7c8460e2017-05-12 11:36:10 -0400720 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500721 if (GrAAType::kCoverage != aaType) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400722 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalRect(
Robert Phillips7c525e62018-06-12 10:11:12 -0400723 fContext, std::move(paint), viewMatrix, croppedRect, croppedLocalRect, aaType);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400724 this->addDrawOp(clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700725 return;
joshualitt04194f32016-01-13 10:08:27 -0800726 }
bsalomonbb243832016-07-22 07:10:19 -0700727
Brian Salomonbaaf4392017-06-15 09:59:23 -0400728 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillWithLocalRect(
Robert Phillips7c525e62018-06-12 10:11:12 -0400729 fContext, std::move(paint), viewMatrix, croppedRect, croppedLocalRect);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400730 if (op) {
731 this->addDrawOp(clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700732 return;
733 }
734
735 SkMatrix viewAndUnLocalMatrix;
736 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
737 SkDebugf("fillRectToRect called with empty local matrix.\n");
738 return;
739 }
740 viewAndUnLocalMatrix.postConcat(viewMatrix);
741
Brian Salomon2fad74a2017-12-20 13:28:55 -0500742 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewAndUnLocalMatrix,
743 GrShape(localRect));
joshualittb6b513b2015-08-21 10:25:18 -0700744}
745
Brian Salomon34169692017-08-28 15:32:01 -0400746static bool must_filter(const SkRect& src, const SkRect& dst, const SkMatrix& ctm) {
747 // We don't currently look for 90 degree rotations, mirroring, or downscales that sample at
748 // texel centers.
749 if (!ctm.isTranslate()) {
750 return true;
751 }
752 if (src.width() != dst.width() || src.height() != dst.height()) {
753 return true;
754 }
755 // Check that the device space rectangle's fractional offset is the same as the src rectangle,
756 // and that therefore integers in the src image fall on integers in device space.
757 SkScalar x = ctm.getTranslateX(), y = ctm.getTranslateY();
758 x += dst.fLeft; y += dst.fTop;
759 x -= src.fLeft; y -= src.fTop;
760 return !SkScalarIsInt(x) || !SkScalarIsInt(y);
761}
762
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400763void GrRenderTargetContext::drawTexture(const GrClip& clip, sk_sp<GrTextureProxy> proxy,
764 GrSamplerState::Filter filter, GrColor color,
765 const SkRect& srcRect, const SkRect& dstRect, GrAA aa,
Brian Salomonb80ffee2018-05-23 16:39:39 -0400766 SkCanvas::SrcRectConstraint constraint,
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400767 const SkMatrix& viewMatrix,
768 sk_sp<GrColorSpaceXform> colorSpaceXform) {
Brian Salomon34169692017-08-28 15:32:01 -0400769 ASSERT_SINGLE_OWNER
770 RETURN_IF_ABANDONED
771 SkDEBUGCODE(this->validate();)
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400772 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexture", fContext);
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400773 if (filter != GrSamplerState::Filter::kNearest && !must_filter(srcRect, dstRect, viewMatrix)) {
774 filter = GrSamplerState::Filter::kNearest;
Brian Salomon34169692017-08-28 15:32:01 -0400775 }
Brian Salomond8eb7b62018-05-25 10:08:05 -0400776 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
777 if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
778 // No need to use a texture domain with nearest filtering unless there is AA bloating.
779 // Also, no need if the srcRect contains the entire texture.
780 if (filter == GrSamplerState::Filter::kNearest && aaType != GrAAType::kCoverage) {
781 constraint = SkCanvas::kFast_SrcRectConstraint;
782 } else if (srcRect.contains(proxy->getWorstCaseBoundsRect())) {
783 constraint = SkCanvas::kFast_SrcRectConstraint;
784 }
785 }
Brian Salomonff9d6d32017-08-30 10:27:49 -0400786 SkRect clippedDstRect = dstRect;
787 SkRect clippedSrcRect = srcRect;
788 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &clippedDstRect,
789 &clippedSrcRect)) {
790 return;
791 }
Robert Phillips7c525e62018-06-12 10:11:12 -0400792 this->addDrawOp(clip, GrTextureOp::Make(fContext, std::move(proxy), filter, color,
793 clippedSrcRect, clippedDstRect, aaType, constraint,
794 viewMatrix, std::move(colorSpaceXform)));
Brian Salomon34169692017-08-28 15:32:01 -0400795}
796
Brian Osman11052242016-10-27 14:47:55 -0400797void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500798 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500799 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400800 const SkMatrix& viewMatrix,
801 const SkRect& rectToDraw,
802 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800803 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700804 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700805 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400806 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "fillRectWithLocalMatrix", fContext);
joshualittb6b513b2015-08-21 10:25:18 -0700807
csmartdalton97f6cd52016-07-13 13:37:08 -0700808 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700809 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700810 return;
811 }
812
Robert Phillips72152832017-01-25 17:31:35 -0500813 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700814
Brian Salomon7c8460e2017-05-12 11:36:10 -0400815 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500816 if (GrAAType::kCoverage != aaType) {
Brian Salomonbaaf4392017-06-15 09:59:23 -0400817 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFillWithLocalMatrix(
Robert Phillips7c525e62018-06-12 10:11:12 -0400818 fContext, std::move(paint), viewMatrix, localMatrix, croppedRect, aaType);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400819 this->addDrawOp(clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700820 return;
bsalomonc55271f2015-11-09 11:55:57 -0800821 }
robertphillips4bc31812016-03-01 12:22:49 -0800822
Brian Salomonbaaf4392017-06-15 09:59:23 -0400823 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillWithLocalMatrix(
Robert Phillips7c525e62018-06-12 10:11:12 -0400824 fContext, std::move(paint), viewMatrix, localMatrix, croppedRect);
Brian Salomonbaaf4392017-06-15 09:59:23 -0400825 if (op) {
826 this->addDrawOp(clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700827 return;
828 }
829
830 SkMatrix viewAndUnLocalMatrix;
831 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
832 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
833 return;
834 }
835 viewAndUnLocalMatrix.postConcat(viewMatrix);
836
837 SkPath path;
838 path.setIsVolatile(true);
839 path.addRect(rectToDraw);
840 path.transform(localMatrix);
Brian Salomon2fad74a2017-12-20 13:28:55 -0500841 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewAndUnLocalMatrix,
842 GrShape(path));
robertphillipsea461502015-05-26 11:38:03 -0700843}
844
Brian Osman11052242016-10-27 14:47:55 -0400845void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500846 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400847 const SkMatrix& viewMatrix,
Brian Osmanae0c50c2017-05-25 16:56:34 -0400848 sk_sp<SkVertices> vertices,
849 GrPrimitiveType* overridePrimType) {
Brian Salomon199fb872017-02-06 09:41:10 -0500850 ASSERT_SINGLE_OWNER
851 RETURN_IF_ABANDONED
852 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400853 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
Brian Salomon199fb872017-02-06 09:41:10 -0500854
855 AutoCheckFlush acf(this->drawingManager());
856
857 SkASSERT(vertices);
Brian Salomonc2f42542017-07-12 14:11:22 -0400858 GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
Brian Salomonf3569f02017-10-24 12:52:33 -0400859 std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
Ruiqi Maoc05aa7d2018-07-03 21:18:07 +0000860 fContext, std::move(paint), std::move(vertices), viewMatrix, aaType,
Brian Salomonf3569f02017-10-24 12:52:33 -0400861 this->colorSpaceInfo().refColorSpaceXformFromSRGB(), overridePrimType);
Brian Salomonc2f42542017-07-12 14:11:22 -0400862 this->addDrawOp(clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700863}
864
865///////////////////////////////////////////////////////////////////////////////
866
Brian Osman11052242016-10-27 14:47:55 -0400867void GrRenderTargetContext::drawAtlas(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500868 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400869 const SkMatrix& viewMatrix,
870 int spriteCount,
871 const SkRSXform xform[],
872 const SkRect texRect[],
873 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800874 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700875 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700876 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400877 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -0700878
Robert Phillips72152832017-01-25 17:31:35 -0500879 AutoCheckFlush acf(this->drawingManager());
halcanary9d524f22016-03-29 09:03:52 -0700880
Brian Salomon0088f942017-07-12 11:51:27 -0400881 GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
Robert Phillips7c525e62018-06-12 10:11:12 -0400882 std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
883 aaType, spriteCount, xform, texRect, colors);
Brian Salomon0088f942017-07-12 11:51:27 -0400884 this->addDrawOp(clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -0700885}
886
887///////////////////////////////////////////////////////////////////////////////
888
Brian Osman11052242016-10-27 14:47:55 -0400889void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500890 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500891 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400892 const SkMatrix& viewMatrix,
893 const SkRRect& rrect,
894 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800895 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700896 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700897 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400898 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
Robert Phillips85290802018-07-02 13:14:28 -0400899
900 const SkStrokeRec& stroke = style.strokeRec();
901 if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -0700902 return;
903 }
904
bsalomon7f0d9f32016-08-15 14:49:10 -0700905 GrNoClip noclip;
906 const GrClip* clip = &origClip;
907#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
908 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -0500909 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -0700910 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
911 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
912 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
913 SkRRect devRRect;
914 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
915 clip = &noclip;
916 }
917#endif
bsalomon6663acf2016-05-10 09:14:17 -0700918 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700919
Robert Phillips72152832017-01-25 17:31:35 -0500920 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700921
Brian Salomonea26d6b2018-01-23 20:33:21 +0000922 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500923 if (GrAAType::kCoverage == aaType) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400924 const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
Robert Phillips7c525e62018-06-12 10:11:12 -0400925 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeRRectOp(fContext,
926 std::move(paint),
Brian Salomonea26d6b2018-01-23 20:33:21 +0000927 viewMatrix,
928 rrect,
929 stroke,
930 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -0500931 if (op) {
Brian Salomon05441c42017-05-15 16:45:49 -0400932 this->addDrawOp(*clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -0800933 return;
934 }
robertphillipsea461502015-05-26 11:38:03 -0700935 }
robertphillipsb56f9272016-02-25 11:03:52 -0800936
Brian Salomon2fad74a2017-12-20 13:28:55 -0500937 this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
938 GrShape(rrect, style));
robertphillipsea461502015-05-26 11:38:03 -0700939}
940
Jim Van Verthc5903412016-11-17 15:27:09 -0500941///////////////////////////////////////////////////////////////////////////////
942
Jim Van Verth3af1af92017-05-18 15:06:54 -0400943static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
944 SkPoint3 result;
945 m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
946 result.fZ = pt.fZ;
947 return result;
948}
949
950bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
Jim Van Verth3af1af92017-05-18 15:06:54 -0400951 const SkMatrix& viewMatrix,
952 const SkPath& path,
953 const SkDrawShadowRec& rec) {
Jim Van Verthc5903412016-11-17 15:27:09 -0500954 ASSERT_SINGLE_OWNER
Jim Van Verth3af1af92017-05-18 15:06:54 -0400955 if (this->drawingManager()->wasAbandoned()) {
956 return true;
957 }
Jim Van Verthc5903412016-11-17 15:27:09 -0500958 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -0400959 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
Jim Van Verth3af1af92017-05-18 15:06:54 -0400960
961 // check z plane
962 bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
963 !SkScalarNearlyZero(rec.fZPlaneParams.fY));
964 bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
965 if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
966 return false;
967 }
968
969 SkRRect rrect;
970 SkRect rect;
971 // we can only handle rects, circles, and rrects with circular corners
Mike Reed242135a2018-02-22 13:41:39 -0500972 bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsSimpleCircular(rrect) &&
Jim Van Verth3af1af92017-05-18 15:06:54 -0400973 rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
974 if (!isRRect &&
975 path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
976 rect.width() > SK_ScalarNearlyZero) {
977 rrect.setOval(rect);
978 isRRect = true;
979 }
980 if (!isRRect && path.isRect(&rect)) {
981 rrect.setRect(rect);
982 isRRect = true;
983 }
984
985 if (!isRRect) {
986 return false;
987 }
988
Jim Van Verthc5903412016-11-17 15:27:09 -0500989 if (rrect.isEmpty()) {
Jim Van Verth3af1af92017-05-18 15:06:54 -0400990 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -0500991 }
992
Robert Phillips72152832017-01-25 17:31:35 -0500993 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -0500994
Jim Van Verth3af1af92017-05-18 15:06:54 -0400995 // transform light
996 SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
997
998 // 1/scale
999 SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
1000 SkScalarInvert(viewMatrix[SkMatrix::kMScaleX]) :
1001 sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
1002 viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
1003
1004 SkScalar occluderHeight = rec.fZPlaneParams.fZ;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001005 bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1006
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001007 if (SkColorGetA(rec.fAmbientColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001008 SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1009 const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1010 const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001011
1012 // Outset the shadow rrect to the border of the penumbra
1013 SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1014 SkRRect ambientRRect;
1015 SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1016 // If the rrect was an oval then its outset will also be one.
1017 // We set it explicitly to avoid errors.
1018 if (rrect.isOval()) {
1019 ambientRRect = SkRRect::MakeOval(outsetRect);
1020 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001021 SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001022 ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1023 }
1024
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001025 GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001026 if (transparent) {
1027 // set a large inset to force a fill
1028 devSpaceInsetWidth = ambientRRect.width();
1029 }
Jim Van Verth39e71652018-04-23 18:08:45 +00001030 // the fraction of the blur we want to apply is devSpaceInsetWidth/devSpaceAmbientBlur,
1031 // which is just 1/umbraRecipAlpha.
1032 SkScalar blurClamp = SkScalarInvert(umbraRecipAlpha);
1033
Robert Phillips7c525e62018-06-12 10:11:12 -04001034 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1035 ambientColor,
1036 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001037 ambientRRect,
1038 devSpaceAmbientBlur,
Jim Van Verth39e71652018-04-23 18:08:45 +00001039 devSpaceInsetWidth,
1040 blurClamp);
Brian Salomon05969092017-07-13 11:20:51 -04001041 SkASSERT(op);
1042 this->addDrawOp(clip, std::move(op));
Jim Van Verthc5903412016-11-17 15:27:09 -05001043 }
Jim Van Verth3af1af92017-05-18 15:06:54 -04001044
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001045 if (SkColorGetA(rec.fSpotColor) > 0) {
Jim Van Verth1af03d42017-07-31 09:34:58 -04001046 SkScalar devSpaceSpotBlur;
1047 SkScalar spotScale;
1048 SkVector spotOffset;
1049 SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1050 devLightPos.fZ, rec.fLightRadius,
1051 &devSpaceSpotBlur, &spotScale, &spotOffset);
1052 // handle scale of radius due to CTM
Jim Van Verth3af1af92017-05-18 15:06:54 -04001053 const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1054
Jim Van Verth3af1af92017-05-18 15:06:54 -04001055 // Adjust translate for the effect of the scale.
1056 spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1057 spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1058 // This offset is in dev space, need to transform it into source space.
1059 SkMatrix ctmInverse;
1060 if (viewMatrix.invert(&ctmInverse)) {
1061 ctmInverse.mapPoints(&spotOffset, 1);
1062 } else {
1063 // Since the matrix is a similarity, this should never happen, but just in case...
1064 SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1065 SkASSERT(false);
1066 }
1067
1068 // Compute the transformed shadow rrect
1069 SkRRect spotShadowRRect;
1070 SkMatrix shadowTransform;
1071 shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1072 rrect.transform(shadowTransform, &spotShadowRRect);
Mike Reed242135a2018-02-22 13:41:39 -05001073 SkScalar spotRadius = SkRRectPriv::GetSimpleRadii(spotShadowRRect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001074
1075 // Compute the insetWidth
Jim Van Verth1af03d42017-07-31 09:34:58 -04001076 SkScalar blurOutset = srcSpaceSpotBlur;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001077 SkScalar insetWidth = blurOutset;
1078 if (transparent) {
1079 // If transparent, just do a fill
1080 insetWidth += spotShadowRRect.width();
1081 } else {
1082 // For shadows, instead of using a stroke we specify an inset from the penumbra
1083 // border. We want to extend this inset area so that it meets up with the caster
1084 // geometry. The inset geometry will by default already be inset by the blur width.
1085 //
1086 // We compare the min and max corners inset by the radius between the original
1087 // rrect and the shadow rrect. The distance between the two plus the difference
1088 // between the scaled radius and the original radius gives the distance from the
1089 // transformed shadow shape to the original shape in that corner. The max
1090 // of these gives the maximum distance we need to cover.
1091 //
1092 // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1093 // that to get the full insetWidth.
1094 SkScalar maxOffset;
1095 if (rrect.isRect()) {
1096 // Manhattan distance works better for rects
1097 maxOffset = SkTMax(SkTMax(SkTAbs(spotShadowRRect.rect().fLeft -
1098 rrect.rect().fLeft),
1099 SkTAbs(spotShadowRRect.rect().fTop -
1100 rrect.rect().fTop)),
1101 SkTMax(SkTAbs(spotShadowRRect.rect().fRight -
1102 rrect.rect().fRight),
1103 SkTAbs(spotShadowRRect.rect().fBottom -
1104 rrect.rect().fBottom)));
1105 } else {
Mike Reed242135a2018-02-22 13:41:39 -05001106 SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001107 SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1108 rrect.rect().fLeft + dr,
1109 spotShadowRRect.rect().fTop -
1110 rrect.rect().fTop + dr);
1111 SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1112 rrect.rect().fRight - dr,
1113 spotShadowRRect.rect().fBottom -
1114 rrect.rect().fBottom - dr);
Cary Clarkdf429f32017-11-08 11:44:31 -05001115 maxOffset = SkScalarSqrt(SkTMax(SkPointPriv::LengthSqd(upperLeftOffset),
1116 SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
Jim Van Verth3af1af92017-05-18 15:06:54 -04001117 }
Jim Van Verth4c8c1e82018-04-23 17:14:48 -04001118 insetWidth += SkTMax(blurOutset, maxOffset);
Jim Van Verth3af1af92017-05-18 15:06:54 -04001119 }
1120
1121 // Outset the shadow rrect to the border of the penumbra
1122 SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1123 if (spotShadowRRect.isOval()) {
1124 spotShadowRRect = SkRRect::MakeOval(outsetRect);
1125 } else {
1126 SkScalar outsetRad = spotRadius + blurOutset;
1127 spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1128 }
1129
Jim Van Verthb1b80f72018-01-18 15:19:13 -05001130 GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
Jim Van Verth34d6e4b2017-06-09 11:09:03 -04001131
Robert Phillips7c525e62018-06-12 10:11:12 -04001132 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1133 spotColor,
1134 viewMatrix,
Brian Salomon05969092017-07-13 11:20:51 -04001135 spotShadowRRect,
Jim Van Verth1af03d42017-07-31 09:34:58 -04001136 2.0f * devSpaceSpotBlur,
Brian Salomon05969092017-07-13 11:20:51 -04001137 insetWidth);
1138 SkASSERT(op);
1139 this->addDrawOp(clip, std::move(op));
Jim Van Verth3af1af92017-05-18 15:06:54 -04001140 }
1141
1142 return true;
Jim Van Verthc5903412016-11-17 15:27:09 -05001143}
1144
1145///////////////////////////////////////////////////////////////////////////////
1146
Brian Osman11052242016-10-27 14:47:55 -04001147bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001148 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001149 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001150 const SkMatrix& viewMatrix,
1151 const SkRRect& origOuter,
1152 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001153 SkASSERT(!origInner.isEmpty());
1154 SkASSERT(!origOuter.isEmpty());
1155
Brian Salomon65749212017-12-01 16:01:47 -05001156 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1157
Brian Salomon45839f92017-12-04 09:02:35 -05001158 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1159
1160 if (GrAAType::kMSAA == aaType) {
1161 return false;
1162 }
1163
Mike Reed242135a2018-02-22 13:41:39 -05001164 if (GrAAType::kCoverage == aaType && SkRRectPriv::IsCircle(*inner)
1165 && SkRRectPriv::IsCircle(*outer)) {
Brian Salomon65749212017-12-01 16:01:47 -05001166 auto outerR = outer->width() / 2.f;
1167 auto innerR = inner->width() / 2.f;
1168 auto cx = outer->getBounds().fLeft + outerR;
1169 auto cy = outer->getBounds().fTop + outerR;
1170 if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
1171 SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
1172 auto avgR = (innerR + outerR) / 2.f;
1173 auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
1174 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
1175 stroke.setStrokeStyle(outerR - innerR);
Robert Phillips7c525e62018-06-12 10:11:12 -04001176 auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix,
1177 circleBounds, GrStyle(stroke, nullptr),
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001178 this->caps()->shaderCaps());
Brian Salomon65749212017-12-01 16:01:47 -05001179 if (op) {
1180 this->addDrawOp(clip, std::move(op));
1181 return true;
1182 }
1183 }
1184 }
1185
Ethan Nicholas0f3c7322017-11-09 14:51:17 -05001186 GrClipEdgeType innerEdgeType, outerEdgeType;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001187 if (GrAAType::kCoverage == aaType) {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001188 innerEdgeType = GrClipEdgeType::kInverseFillAA;
1189 outerEdgeType = GrClipEdgeType::kFillAA;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001190 } else {
Ethan Nicholas1706f842017-11-10 11:58:19 -05001191 innerEdgeType = GrClipEdgeType::kInverseFillBW;
1192 outerEdgeType = GrClipEdgeType::kFillBW;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001193 }
robertphillips00095892016-02-29 13:50:40 -08001194
robertphillips00095892016-02-29 13:50:40 -08001195 SkMatrix inverseVM;
1196 if (!viewMatrix.isIdentity()) {
1197 if (!origInner.transform(viewMatrix, inner.writable())) {
1198 return false;
1199 }
1200 if (!origOuter.transform(viewMatrix, outer.writable())) {
1201 return false;
1202 }
1203 if (!viewMatrix.invert(&inverseVM)) {
1204 return false;
1205 }
1206 } else {
1207 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001208 }
robertphillips00095892016-02-29 13:50:40 -08001209
Brian Salomon14471772017-12-05 10:35:15 -05001210 const auto& caps = *this->caps()->shaderCaps();
robertphillips00095892016-02-29 13:50:40 -08001211 // TODO these need to be a geometry processors
Brian Salomon14471772017-12-05 10:35:15 -05001212 auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
robertphillips00095892016-02-29 13:50:40 -08001213 if (!innerEffect) {
1214 return false;
1215 }
1216
Brian Salomon14471772017-12-05 10:35:15 -05001217 auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
robertphillips00095892016-02-29 13:50:40 -08001218 if (!outerEffect) {
1219 return false;
1220 }
1221
Brian Salomon82f44312017-01-11 13:42:54 -05001222 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1223 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001224
1225 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001226 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001227 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1228 }
halcanary9d524f22016-03-29 09:03:52 -07001229
Brian Salomon82f44312017-01-11 13:42:54 -05001230 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1231 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001232 return true;
1233}
1234
Brian Osman11052242016-10-27 14:47:55 -04001235void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001236 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001237 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001238 const SkMatrix& viewMatrix,
1239 const SkRRect& outer,
1240 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001241 ASSERT_SINGLE_OWNER
1242 RETURN_IF_ABANDONED
1243 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001244 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
robertphillips00095892016-02-29 13:50:40 -08001245
1246 SkASSERT(!outer.isEmpty());
1247 SkASSERT(!inner.isEmpty());
1248
Robert Phillips72152832017-01-25 17:31:35 -05001249 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001250
Brian Salomon82f44312017-01-11 13:42:54 -05001251 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001252 return;
1253 }
1254
1255 SkPath path;
1256 path.setIsVolatile(true);
1257 path.addRRect(inner);
1258 path.addRRect(outer);
1259 path.setFillType(SkPath::kEvenOdd_FillType);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001260 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path));
robertphillips00095892016-02-29 13:50:40 -08001261}
1262
robertphillipsea461502015-05-26 11:38:03 -07001263///////////////////////////////////////////////////////////////////////////////
1264
Brian Osman11052242016-10-27 14:47:55 -04001265void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001266 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001267 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001268 const SkMatrix& viewMatrix,
1269 const SkRegion& region,
Stan Iliev73d8fd92017-08-02 15:36:24 -04001270 const GrStyle& style,
1271 const GrUserStencilSettings* ss) {
msarettcc319b92016-08-25 18:07:18 -07001272 ASSERT_SINGLE_OWNER
1273 RETURN_IF_ABANDONED
1274 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001275 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
msarettcc319b92016-08-25 18:07:18 -07001276
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001277 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001278 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001279 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001280 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
Brian Salomon34169692017-08-28 15:32:01 -04001281 SkScalarIsInt(viewMatrix.getTranslateX()) &&
1282 SkScalarIsInt(viewMatrix.getTranslateY())) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001283 aa = GrAA::kNo;
1284 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001285 }
msarettcc319b92016-08-25 18:07:18 -07001286 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001287 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001288 SkPath path;
1289 region.getBoundaryPath(&path);
Brian Salomon82f44312017-01-11 13:42:54 -05001290 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001291 }
1292
Brian Salomonf0366322017-07-11 15:53:05 -04001293 GrAAType aaType = this->chooseAAType(GrAA::kNo, GrAllowMixedSamples::kNo);
Robert Phillips7c525e62018-06-12 10:11:12 -04001294 std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
1295 aaType, ss);
Brian Salomonf0366322017-07-11 15:53:05 -04001296 this->addDrawOp(clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001297}
1298
Brian Osman11052242016-10-27 14:47:55 -04001299void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001300 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001301 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001302 const SkMatrix& viewMatrix,
1303 const SkRect& oval,
1304 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001305 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001306 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001307 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001308 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
robertphillips2e1e51f2015-10-15 08:01:48 -07001309
Robert Phillips7484d202018-07-03 09:09:08 -04001310 const SkStrokeRec& stroke = style.strokeRec();
1311
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001312 if (oval.isEmpty() && !style.pathEffect()) {
Robert Phillips7484d202018-07-03 09:09:08 -04001313 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
1314 return;
1315 }
1316
1317 this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
Brian Salomon62e4f3d2018-04-20 13:54:11 -04001318 return;
robertphillipsea461502015-05-26 11:38:03 -07001319 }
1320
Robert Phillips72152832017-01-25 17:31:35 -05001321 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001322
Brian Salomonea26d6b2018-01-23 20:33:21 +00001323 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001324 if (GrAAType::kCoverage == aaType) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001325 const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
Robert Phillips7c525e62018-06-12 10:11:12 -04001326 if (auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval,
1327 style, shaderCaps)) {
Brian Salomon05441c42017-05-15 16:45:49 -04001328 this->addDrawOp(clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001329 return;
1330 }
robertphillipsea461502015-05-26 11:38:03 -07001331 }
robertphillipsb56f9272016-02-25 11:03:52 -08001332
Brian Salomon5209d7f2018-04-20 16:52:42 -04001333 this->drawShapeUsingPathRenderer(
1334 clip, std::move(paint), aa, viewMatrix,
1335 GrShape(SkRRect::MakeOval(oval), SkPath::kCW_Direction, 2, false, style));
robertphillipsea461502015-05-26 11:38:03 -07001336}
1337
Brian Osman11052242016-10-27 14:47:55 -04001338void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001339 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001340 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001341 const SkMatrix& viewMatrix,
1342 const SkRect& oval,
1343 SkScalar startAngle,
1344 SkScalar sweepAngle,
1345 bool useCenter,
1346 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001347 ASSERT_SINGLE_OWNER
1348 RETURN_IF_ABANDONED
1349 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001350 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001351
1352 AutoCheckFlush acf(this->drawingManager());
1353
Brian Salomonea26d6b2018-01-23 20:33:21 +00001354 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001355 if (GrAAType::kCoverage == aaType) {
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001356 const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
Robert Phillips7c525e62018-06-12 10:11:12 -04001357 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
1358 std::move(paint),
Brian Salomonea26d6b2018-01-23 20:33:21 +00001359 viewMatrix,
1360 oval,
1361 startAngle,
1362 sweepAngle,
1363 useCenter,
1364 style,
1365 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001366 if (op) {
Brian Salomon05441c42017-05-15 16:45:49 -04001367 this->addDrawOp(clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001368 return;
1369 }
1370 }
Brian Salomone4949402018-04-26 15:22:04 -04001371 this->drawShapeUsingPathRenderer(
1372 clip, std::move(paint), aa, viewMatrix,
1373 GrShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001374}
1375
Brian Osman11052242016-10-27 14:47:55 -04001376void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001377 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001378 const SkMatrix& viewMatrix,
Brian Salomon2a943df2018-05-04 13:43:19 -04001379 sk_sp<GrTextureProxy> image,
1380 sk_sp<GrColorSpaceXform> csxf,
1381 GrSamplerState::Filter filter,
Brian Osman11052242016-10-27 14:47:55 -04001382 std::unique_ptr<SkLatticeIter> iter,
1383 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001384 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001385 RETURN_IF_ABANDONED
1386 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001387 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
joshualitt33a5fce2015-11-18 13:28:51 -08001388
Robert Phillips72152832017-01-25 17:31:35 -05001389 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001390
Brian Salomon2a943df2018-05-04 13:43:19 -04001391 std::unique_ptr<GrDrawOp> op =
Robert Phillips7c525e62018-06-12 10:11:12 -04001392 GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(image),
1393 std::move(csxf), filter, std::move(iter), dst);
Brian Salomon815486c2017-07-11 08:52:13 -04001394 this->addDrawOp(clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001395}
1396
Greg Daniel51316782017-08-02 15:10:09 +00001397GrSemaphoresSubmitted GrRenderTargetContext::prepareForExternalIO(
1398 int numSemaphores, GrBackendSemaphore backendSemaphores[]) {
robertphillips8c523e02016-07-26 07:41:00 -07001399 ASSERT_SINGLE_OWNER
Greg Daniel51316782017-08-02 15:10:09 +00001400 if (this->drawingManager()->wasAbandoned()) { return GrSemaphoresSubmitted::kNo; }
robertphillips8c523e02016-07-26 07:41:00 -07001401 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001402 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "prepareForExternalIO", fContext);
robertphillips8c523e02016-07-26 07:41:00 -07001403
Greg Daniel51316782017-08-02 15:10:09 +00001404 return this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get(),
1405 numSemaphores,
1406 backendSemaphores);
Greg Daniela5cb7812017-06-16 09:45:32 -04001407}
1408
Greg Danielc64ee462017-06-15 16:59:49 -04001409bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
Greg Daniela5cb7812017-06-16 09:45:32 -04001410 const GrBackendSemaphore* waitSemaphores) {
1411 ASSERT_SINGLE_OWNER
Greg Danielc64ee462017-06-15 16:59:49 -04001412 RETURN_FALSE_IF_ABANDONED
Greg Daniela5cb7812017-06-16 09:45:32 -04001413 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001414 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
Greg Daniela5cb7812017-06-16 09:45:32 -04001415
1416 AutoCheckFlush acf(this->drawingManager());
1417
Greg Danielc64ee462017-06-15 16:59:49 -04001418 if (numSemaphores && !this->caps()->fenceSyncSupport()) {
1419 return false;
1420 }
1421
Robert Phillips6be756b2018-01-16 15:07:54 -05001422 auto resourceProvider = fContext->contextPriv().resourceProvider();
1423
Greg Daniela5cb7812017-06-16 09:45:32 -04001424 SkTArray<sk_sp<GrSemaphore>> semaphores(numSemaphores);
1425 for (int i = 0; i < numSemaphores; ++i) {
Robert Phillips6be756b2018-01-16 15:07:54 -05001426 sk_sp<GrSemaphore> sema = resourceProvider->wrapBackendSemaphore(
Greg Daniel17b7c052018-01-09 13:55:33 -05001427 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
1428 kAdopt_GrWrapOwnership);
Robert Phillips7c525e62018-06-12 10:11:12 -04001429 std::unique_ptr<GrOp> waitOp(GrSemaphoreOp::MakeWait(fContext, sema,
1430 fRenderTargetProxy.get()));
Robert Phillips2de8cfa2017-06-28 10:33:41 -04001431 this->getRTOpList()->addOp(std::move(waitOp), *this->caps());
Greg Daniela5cb7812017-06-16 09:45:32 -04001432 }
Greg Danielc64ee462017-06-15 16:59:49 -04001433 return true;
robertphillips8c523e02016-07-26 07:41:00 -07001434}
joshualitt33a5fce2015-11-18 13:28:51 -08001435
Robert Phillips65a88fa2017-08-08 08:36:22 -04001436void GrRenderTargetContext::insertEventMarker(const SkString& str) {
Robert Phillips88a32ef2018-06-07 11:05:56 -04001437 std::unique_ptr<GrOp> op(GrDebugMarkerOp::Make(fContext, fRenderTargetProxy.get(), str));
Robert Phillips65a88fa2017-08-08 08:36:22 -04001438 this->getRTOpList()->addOp(std::move(op), *this->caps());
1439}
1440
1441
robertphillipsea461502015-05-26 11:38:03 -07001442// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001443static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001444
1445 if (path.isInverseFillType()) {
1446 return false;
1447 }
1448
1449 // TODO: this restriction could be lifted if we were willing to apply
1450 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001451 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001452 return false;
1453 }
1454
1455 SkPath::Direction dirs[2];
1456 if (!path.isNestedFillRects(rects, dirs)) {
1457 return false;
1458 }
1459
1460 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1461 // The two rects need to be wound opposite to each other
1462 return false;
1463 }
1464
1465 // Right now, nested rects where the margin is not the same width
1466 // all around do not render correctly
1467 const SkScalar* outer = rects[0].asScalars();
1468 const SkScalar* inner = rects[1].asScalars();
1469
1470 bool allEq = true;
1471
1472 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1473 bool allGoE1 = margin >= SK_Scalar1;
1474
1475 for (int i = 1; i < 4; ++i) {
1476 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1477 if (temp < SK_Scalar1) {
1478 allGoE1 = false;
1479 }
1480 if (!SkScalarNearlyEqual(margin, temp)) {
1481 allEq = false;
1482 }
1483 }
1484
1485 return allEq || allGoE1;
1486}
1487
Brian Osman11052242016-10-27 14:47:55 -04001488void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001489 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001490 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001491 const SkMatrix& viewMatrix,
Brian Salomon40b77a62017-12-22 11:25:52 -05001492 const SkPath& path,
Brian Osman11052242016-10-27 14:47:55 -04001493 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001494 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001495 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001496 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001497 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawPath", fContext);
Brian Salomon40b77a62017-12-22 11:25:52 -05001498
1499 GrShape shape(path, style);
Brian Salomon2fad74a2017-12-20 13:28:55 -05001500 if (shape.isEmpty()) {
1501 if (shape.inverseFilled()) {
1502 this->drawPaint(clip, std::move(paint), viewMatrix);
1503 }
1504 return;
robertphillipsea461502015-05-26 11:38:03 -07001505 }
1506
Robert Phillips72152832017-01-25 17:31:35 -05001507 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001508
Brian Salomon2fad74a2017-12-20 13:28:55 -05001509 if (!shape.style().hasPathEffect()) {
1510 SkRRect rrect;
1511 // We can ignore the starting point and direction since there is no path effect.
1512 bool inverted;
1513 if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
1514 if (rrect.isRect()) {
1515 this->drawRect(clip, std::move(paint), aa, viewMatrix, rrect.rect(),
1516 &shape.style());
1517 return;
1518 } else if (rrect.isOval()) {
1519 this->drawOval(clip, std::move(paint), aa, viewMatrix, rrect.rect(), shape.style());
robertphillipsea461502015-05-26 11:38:03 -07001520 return;
1521 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001522 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect, shape.style());
1523 return;
robertphillipsea461502015-05-26 11:38:03 -07001524 }
1525 }
robertphillips4bc31812016-03-01 12:22:49 -08001526
Brian Salomon40b77a62017-12-22 11:25:52 -05001527 GrAAType aaType = this->chooseAAType(aa, GrAllowMixedSamples::kNo);
1528 if (GrAAType::kCoverage == aaType) {
1529 // TODO: Make GrShape check for nested rects.
1530 SkRect rects[2];
1531 if (shape.style().isSimpleFill() && fills_as_nested_rects(viewMatrix, path, rects)) {
1532 // Concave AA paths are expensive - try to avoid them for special cases
1533 SkRect rects[2];
1534
1535 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Robert Phillips7c525e62018-06-12 10:11:12 -04001536 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeAAFillNestedRects(
1537 fContext, std::move(paint), viewMatrix, rects);
Brian Salomon40b77a62017-12-22 11:25:52 -05001538 if (op) {
1539 this->addDrawOp(clip, std::move(op));
1540 }
1541 // A null return indicates that there is nothing to draw in this case.
1542 return;
1543 }
1544 }
1545 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001546 this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, shape);
robertphillipsea461502015-05-26 11:38:03 -07001547}
1548
Chris Daltonbbfd5162017-11-07 13:35:22 -07001549bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
Brian Osman11052242016-10-27 14:47:55 -04001550 const GrUserStencilSettings* ss,
1551 SkRegion::Op op,
1552 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001553 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001554 const SkMatrix& viewMatrix,
1555 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001556 ASSERT_SINGLE_OWNER_PRIV
1557 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001558 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001559 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
1560 fRenderTargetContext->fContext);
robertphillips391395d2016-03-02 09:26:36 -08001561
1562 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001563 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001564 SkRect::MakeIWH(fRenderTargetContext->width(),
1565 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001566 return true;
1567 }
1568
Robert Phillips72152832017-01-25 17:31:35 -05001569 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001570
1571 // An Assumption here is that path renderer would use some form of tweaking
1572 // the src color (either the input alpha or in the frag shader) to implement
1573 // aa. If we have some future driver-mojo path AA that can do the right
1574 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon7c8460e2017-05-12 11:36:10 -04001575 GrAAType aaType = fRenderTargetContext->chooseAAType(aa, GrAllowMixedSamples::kNo);
robertphillips976f5f02016-06-03 10:59:20 -07001576 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001577
Chris Daltondb91c6e2017-09-08 16:25:08 -06001578 SkIRect clipConservativeBounds;
1579 clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(),
1580 &clipConservativeBounds, nullptr);
1581
bsalomon8acedde2016-06-24 10:42:16 -07001582 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001583 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001584 canDrawArgs.fCaps = fRenderTargetContext->caps();
robertphillips391395d2016-03-02 09:26:36 -08001585 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001586 canDrawArgs.fShape = &shape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06001587 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001588 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001589 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001590
1591 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001592 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001593 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001594 if (!pr) {
1595 return false;
1596 }
1597
1598 GrPaint paint;
1599 paint.setCoverageSetOpXPFactory(op, invert);
1600
Brian Salomonf3569f02017-10-24 12:52:33 -04001601 GrPathRenderer::DrawPathArgs args{fRenderTargetContext->drawingManager()->getContext(),
1602 std::move(paint),
1603 ss,
1604 fRenderTargetContext,
1605 &clip,
1606 &clipConservativeBounds,
1607 &viewMatrix,
1608 &shape,
1609 aaType,
Brian Osman34ec3742018-07-03 10:40:57 -04001610 fRenderTargetContext->colorSpaceInfo().isLinearlyBlended()};
robertphillips391395d2016-03-02 09:26:36 -08001611 pr->drawPath(args);
1612 return true;
1613}
1614
Brian Osman11052242016-10-27 14:47:55 -04001615SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001616 ASSERT_SINGLE_OWNER_PRIV
1617
Brian Osman11052242016-10-27 14:47:55 -04001618 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001619 return SkBudgeted::kNo;
1620 }
1621
Brian Osman11052242016-10-27 14:47:55 -04001622 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001623
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001624 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001625}
1626
Brian Salomon2fad74a2017-12-20 13:28:55 -05001627void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
1628 GrPaint&& paint,
1629 GrAA aa,
1630 const SkMatrix& viewMatrix,
1631 const GrShape& originalShape) {
joshualitt1de610a2016-01-06 08:26:09 -08001632 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001633 RETURN_IF_ABANDONED
Brian Salomondcbb9d92017-07-19 10:53:20 -04001634 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
1635
Chris Daltondb91c6e2017-09-08 16:25:08 -06001636 SkIRect clipConservativeBounds;
1637 clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr);
1638
Brian Salomon2fad74a2017-12-20 13:28:55 -05001639 GrShape tempShape;
Brian Salomon7c8460e2017-05-12 11:36:10 -04001640 // NVPR cannot handle hairlines, so this would get picked up by a different stencil and
1641 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1642 // smoother hairlines than MSAA.
Brian Salomon2fad74a2017-12-20 13:28:55 -05001643 GrAllowMixedSamples allowMixedSamples = originalShape.style().isSimpleHairline()
1644 ? GrAllowMixedSamples::kNo
1645 : GrAllowMixedSamples::kYes;
Brian Salomon7c8460e2017-05-12 11:36:10 -04001646 GrAAType aaType = this->chooseAAType(aa, allowMixedSamples);
robertphillips68737822015-10-29 12:12:21 -07001647 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Salomonc7fe0f72018-05-11 10:14:21 -04001648 canDrawArgs.fCaps = this->caps();
robertphillips68737822015-10-29 12:12:21 -07001649 canDrawArgs.fViewMatrix = &viewMatrix;
Brian Salomon2fad74a2017-12-20 13:28:55 -05001650 canDrawArgs.fShape = &originalShape;
Chris Daltondb91c6e2017-09-08 16:25:08 -06001651 canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001652 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001653
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001654 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001655 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon2fad74a2017-12-20 13:28:55 -05001656 if (originalShape.isEmpty() && !originalShape.inverseFilled()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001657 return;
1658 }
1659
1660 canDrawArgs.fAAType = aaType;
1661
1662 // Try a 1st time without applying any of the style to the geometry (and barring sw)
1663 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
1664 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1665
Brian Salomon2fad74a2017-12-20 13:28:55 -05001666 if (!pr && originalShape.style().pathEffect()) {
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001667 // It didn't work above, so try again with the path effect applied.
Brian Salomon2fad74a2017-12-20 13:28:55 -05001668 tempShape = originalShape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1669 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001670 return;
1671 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001672 canDrawArgs.fShape = &tempShape;
Robert Phillips72152832017-01-25 17:31:35 -05001673 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001674 }
1675 if (!pr) {
Brian Salomon2fad74a2017-12-20 13:28:55 -05001676 if (canDrawArgs.fShape->style().applies()) {
1677 tempShape = canDrawArgs.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
1678 styleScale);
1679 if (tempShape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001680 return;
1681 }
Brian Salomon2fad74a2017-12-20 13:28:55 -05001682 canDrawArgs.fShape = &tempShape;
Brian Salomone7df0bb2018-05-07 14:44:57 -04001683 // This time, allow SW renderer
1684 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
1685 } else {
1686 pr = this->drawingManager()->getSoftwarePathRenderer();
bsalomon6663acf2016-05-10 09:14:17 -07001687 }
Brian Salomon1e5d0ca2017-12-14 10:50:19 -05001688 }
robertphillipsea461502015-05-26 11:38:03 -07001689
bsalomon8acedde2016-06-24 10:42:16 -07001690 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001691#ifdef SK_DEBUG
1692 SkDebugf("Unable to find path renderer compatible with path.\n");
1693#endif
1694 return;
1695 }
1696
Robert Phillips256c37b2017-03-01 14:32:46 -05001697 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001698 std::move(paint),
1699 &GrUserStencilSettings::kUnused,
1700 this,
1701 &clip,
Chris Daltondb91c6e2017-09-08 16:25:08 -06001702 &clipConservativeBounds,
Brian Salomon82f44312017-01-11 13:42:54 -05001703 &viewMatrix,
Brian Salomon2fad74a2017-12-20 13:28:55 -05001704 canDrawArgs.fShape,
Brian Salomon82f44312017-01-11 13:42:54 -05001705 aaType,
Brian Osman34ec3742018-07-03 10:40:57 -04001706 this->colorSpaceInfo().isLinearlyBlended()};
bsalomon0aff2fa2015-07-31 06:48:27 -07001707 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001708}
1709
Brian Salomon467921e2017-03-06 16:17:12 -05001710static void op_bounds(SkRect* bounds, const GrOp* op) {
1711 *bounds = op->bounds();
1712 if (op->hasZeroArea()) {
1713 if (op->hasAABloat()) {
1714 bounds->outset(0.5f, 0.5f);
1715 } else {
1716 // We don't know which way the particular GPU will snap lines or points at integer
1717 // coords. So we ensure that the bounds is large enough for either snap.
1718 SkRect before = *bounds;
1719 bounds->roundOut(bounds);
1720 if (bounds->fLeft == before.fLeft) {
1721 bounds->fLeft -= 1;
1722 }
1723 if (bounds->fTop == before.fTop) {
1724 bounds->fTop -= 1;
1725 }
1726 if (bounds->fRight == before.fRight) {
1727 bounds->fRight += 1;
1728 }
1729 if (bounds->fBottom == before.fBottom) {
1730 bounds->fBottom += 1;
1731 }
1732 }
1733 }
1734}
1735
Brian Salomon54d212e2017-03-21 14:22:38 -04001736uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001737 ASSERT_SINGLE_OWNER
Robert Phillipsc0138922017-03-08 11:50:55 -05001738 if (this->drawingManager()->wasAbandoned()) {
Robert Phillipsc994a932018-06-19 13:09:54 -04001739 fContext->contextPriv().opMemoryPool()->release(std::move(op));
Robert Phillipsc0138922017-03-08 11:50:55 -05001740 return SK_InvalidUniqueID;
1741 }
robertphillips2e1e51f2015-10-15 08:01:48 -07001742 SkDEBUGCODE(this->validate();)
Brian Salomondcbb9d92017-07-19 10:53:20 -04001743 GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
robertphillips2d70dcb2015-10-06 07:38:23 -07001744
Brian Salomon467921e2017-03-06 16:17:12 -05001745 // Setup clip
1746 SkRect bounds;
1747 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04001748 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04001749 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1750 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1751 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1752 &bounds)) {
Robert Phillipsc994a932018-06-19 13:09:54 -04001753 fContext->contextPriv().opMemoryPool()->release(std::move(op));
Brian Salomon54d212e2017-03-21 14:22:38 -04001754 return SK_InvalidUniqueID;
1755 }
1756
Brian Salomon54d212e2017-03-21 14:22:38 -04001757 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1758 appliedClip.hasStencilClip()) {
Robert Phillips6b47c7d2017-08-29 07:24:09 -04001759 this->getOpList()->setStencilLoadOp(GrLoadOp::kClear);
Robert Phillips95214472017-08-08 18:00:03 -04001760
Robert Phillips65048132017-08-10 08:44:49 -04001761 this->setNeedsStencil();
Brian Salomon54d212e2017-03-21 14:22:38 -04001762 }
1763
Brian Salomonf3569f02017-10-24 12:52:33 -04001764 GrPixelConfigIsClamped dstIsClamped =
1765 GrGetPixelConfigIsClamped(this->colorSpaceInfo().config());
Robert Phillipsbb581ce2017-05-29 15:05:15 -04001766 GrXferProcessor::DstProxy dstProxy;
Brian Osman9a725dd2017-09-20 09:53:22 -04001767 if (GrDrawOp::RequiresDstTexture::kYes == op->finalize(*this->caps(), &appliedClip,
1768 dstIsClamped)) {
Robert Phillipsbb581ce2017-05-29 15:05:15 -04001769 if (!this->setupDstProxy(this->asRenderTargetProxy(), clip, op->bounds(), &dstProxy)) {
Robert Phillipsc994a932018-06-19 13:09:54 -04001770 fContext->contextPriv().opMemoryPool()->release(std::move(op));
Brian Salomon54d212e2017-03-21 14:22:38 -04001771 return SK_InvalidUniqueID;
1772 }
1773 }
1774
1775 op->setClippedBounds(bounds);
Robert Phillips2de8cfa2017-06-28 10:33:41 -04001776 return this->getRTOpList()->addOp(std::move(op), *this->caps(),
1777 std::move(appliedClip), dstProxy);
Brian Salomon54d212e2017-03-21 14:22:38 -04001778}
1779
Robert Phillipsbb581ce2017-05-29 15:05:15 -04001780bool GrRenderTargetContext::setupDstProxy(GrRenderTargetProxy* rtProxy, const GrClip& clip,
Robert Phillips16d8ec62017-07-27 16:16:25 -04001781 const SkRect& opBounds,
1782 GrXferProcessor::DstProxy* dstProxy) {
Brian Salomon467921e2017-03-06 16:17:12 -05001783 if (this->caps()->textureBarrierSupport()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001784 if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
Brian Salomon467921e2017-03-06 16:17:12 -05001785 // The render target is a texture, so we can read from it directly in the shader. The XP
1786 // will be responsible to detect this situation and request a texture barrier.
Robert Phillipsbb581ce2017-05-29 15:05:15 -04001787 dstProxy->setProxy(sk_ref_sp(texProxy));
1788 dstProxy->setOffset(0, 0);
Robert Phillipsbf25d432017-04-07 10:08:53 -04001789 return true;
Brian Salomon467921e2017-03-06 16:17:12 -05001790 }
1791 }
1792
Robert Phillipsbf25d432017-04-07 10:08:53 -04001793 SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
Brian Salomon467921e2017-03-06 16:17:12 -05001794
Eric Karl74480882017-04-03 14:49:05 -07001795 SkIRect clippedRect;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001796 clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
Eric Karl72e551e2017-04-04 13:42:10 -07001797 SkIRect drawIBounds;
Brian Salomon467921e2017-03-06 16:17:12 -05001798 opBounds.roundOut(&drawIBounds);
Brian Salomon859621f2017-03-16 09:21:54 -04001799 // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
1800 drawIBounds.outset(1, 1);
Eric Karl72e551e2017-04-04 13:42:10 -07001801 if (!clippedRect.intersect(drawIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001802#ifdef SK_DEBUG
Robert Phillipsbf25d432017-04-07 10:08:53 -04001803 GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
Brian Salomon467921e2017-03-06 16:17:12 -05001804#endif
Robert Phillipsbf25d432017-04-07 10:08:53 -04001805 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05001806 }
1807
1808 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
1809 // have per-sample dst values by making the copy multisampled.
1810 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07001811 bool rectsMustMatch = false;
1812 bool disallowSubrect = false;
Brian Salomon2a4f9832018-03-03 22:43:43 -05001813 GrSurfaceOrigin origin;
1814 if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &origin, &rectsMustMatch,
1815 &disallowSubrect)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001816 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001817 desc.fConfig = rtProxy->config();
Greg Daniel1efe3222018-04-04 14:02:51 -04001818 origin = rtProxy->origin();
Brian Salomon467921e2017-03-06 16:17:12 -05001819 }
1820
Eric Karl74480882017-04-03 14:49:05 -07001821 if (!disallowSubrect) {
1822 copyRect = clippedRect;
1823 }
Brian Salomon467921e2017-03-06 16:17:12 -05001824
Robert Phillipsbf25d432017-04-07 10:08:53 -04001825 SkIPoint dstPoint, dstOffset;
1826 SkBackingFit fit;
Eric Karl74480882017-04-03 14:49:05 -07001827 if (rectsMustMatch) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001828 desc.fWidth = rtProxy->width();
1829 desc.fHeight = rtProxy->height();
Eric Karl74480882017-04-03 14:49:05 -07001830 dstPoint = {copyRect.fLeft, copyRect.fTop};
1831 dstOffset = {0, 0};
Robert Phillipsbf25d432017-04-07 10:08:53 -04001832 fit = SkBackingFit::kExact;
Eric Karl74480882017-04-03 14:49:05 -07001833 } else {
1834 desc.fWidth = copyRect.width();
1835 desc.fHeight = copyRect.height();
1836 dstPoint = {0, 0};
1837 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillipsbf25d432017-04-07 10:08:53 -04001838 fit = SkBackingFit::kApprox;
Eric Karl74480882017-04-03 14:49:05 -07001839 }
Brian Salomon467921e2017-03-06 16:17:12 -05001840
Robert Phillipsbf25d432017-04-07 10:08:53 -04001841 sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeDeferredSurfaceContext(
Brian Salomon2a4f9832018-03-03 22:43:43 -05001842 desc, origin, GrMipMapped::kNo, fit, SkBudgeted::kYes,
Brian Salomonf802e752018-02-13 17:13:31 -05001843 sk_ref_sp(this->colorSpaceInfo().colorSpace()));
Robert Phillipsbf25d432017-04-07 10:08:53 -04001844 if (!sContext) {
1845 SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
1846 return false;
1847 }
1848
1849 if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
1850 SkDebugf("setupDstTexture: copy failed.\n");
1851 return false;
1852 }
1853
Robert Phillipsbb581ce2017-05-29 15:05:15 -04001854 dstProxy->setProxy(sContext->asTextureProxyRef());
1855 dstProxy->setOffset(dstOffset);
Robert Phillipsbf25d432017-04-07 10:08:53 -04001856 return true;
robertphillips2334fb62015-06-17 05:43:33 -07001857}