blob: 918d8d41a9117ca0401609fd43881f4f0ae472ba [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 Salomon5ec9def2016-12-20 15:34:05 -05009#include "GrColor.h"
10#include "GrDrawOpTest.h"
robertphillips77a2e522015-10-17 07:43:27 -070011#include "GrDrawingManager.h"
csmartdalton02fa32c2016-08-19 13:29:27 -070012#include "GrFixedClip.h"
robertphillips714712b2016-08-04 06:20:45 -070013#include "GrGpuResourcePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070014#include "GrPathRenderer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070015#include "GrPipelineBuilder.h"
robertphillips2334fb62015-06-17 05:43:33 -070016#include "GrRenderTarget.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050017#include "GrRenderTargetContextPriv.h"
robertphillips2334fb62015-06-17 05:43:33 -070018#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070019#include "GrResourceProvider.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070020#include "SkSurfacePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070021
Brian Salomon89527432016-12-16 09:52:16 -050022#include "ops/GrClearOp.h"
23#include "ops/GrDrawAtlasOp.h"
24#include "ops/GrDrawVerticesOp.h"
25#include "ops/GrLatticeOp.h"
26#include "ops/GrOp.h"
27#include "ops/GrOvalOpFactory.h"
28#include "ops/GrRectOpFactory.h"
29#include "ops/GrRegionOp.h"
30#include "ops/GrShadowRRectOp.h"
joshualitt74417822015-08-07 11:42:16 -070031
robertphillips00095892016-02-29 13:50:40 -080032#include "effects/GrRRectEffect.h"
33
csmartdaltona7f29642016-07-07 08:49:11 -070034#include "instanced/InstancedRendering.h"
35
joshualitte8042922015-12-11 06:11:21 -080036#include "text/GrAtlasTextContext.h"
37#include "text/GrStencilAndCoverTextContext.h"
38
joshualittbc907352016-01-13 06:45:40 -080039#include "../private/GrAuditTrail.h"
40
robertphillips1da3ecd2016-08-31 14:54:15 -070041#include "SkGr.h"
msarett10e3d9b2016-08-18 15:46:03 -070042#include "SkLatticeIter.h"
reeda39667c2016-08-22 06:39:49 -070043#include "SkMatrixPriv.h"
msarett10e3d9b2016-08-18 15:46:03 -070044
Robert Phillips72152832017-01-25 17:31:35 -050045#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080046#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080047 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080048#define ASSERT_SINGLE_OWNER_PRIV \
Brian Osman11052242016-10-27 14:47:55 -040049 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->fSingleOwner);)
Robert Phillips72152832017-01-25 17:31:35 -050050#define RETURN_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return; }
51#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
52#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
53#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
54#define RETURN_NULL_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070055
csmartdaltona7f29642016-07-07 08:49:11 -070056using gr_instanced::InstancedRendering;
57
robertphillipsea461502015-05-26 11:38:03 -070058class AutoCheckFlush {
59public:
halcanary9d524f22016-03-29 09:03:52 -070060 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070061 SkASSERT(fDrawingManager);
62 }
bsalomonb77a9072016-09-07 10:02:04 -070063 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070064
65private:
robertphillips77a2e522015-10-17 07:43:27 -070066 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070067};
68
Brian Osman11052242016-10-27 14:47:55 -040069bool GrRenderTargetContext::wasAbandoned() const {
Robert Phillips72152832017-01-25 17:31:35 -050070 return this->drawingManager()->wasAbandoned();
robertphillips7761d612016-05-16 09:14:53 -070071}
72
Robert Phillipsf2361d22016-10-25 14:20:06 -040073// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -040074// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -040075// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -040076// when the renderTargetContext attempts to use it (via getOpList).
77GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
78 GrDrawingManager* drawingMgr,
Robert Phillipsc7635fa2016-10-28 13:25:24 -040079 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -040080 sk_sp<SkColorSpace> colorSpace,
81 const SkSurfaceProps* surfaceProps,
82 GrAuditTrail* auditTrail,
83 GrSingleOwner* singleOwner)
Robert Phillips72152832017-01-25 17:31:35 -050084 : GrSurfaceContext(context, drawingMgr, std::move(colorSpace), auditTrail, singleOwner)
Robert Phillipsc7635fa2016-10-28 13:25:24 -040085 , fRenderTargetProxy(std::move(rtp))
86 , fOpList(SkSafeRef(fRenderTargetProxy->getLastRenderTargetOpList()))
Robert Phillipsc7635fa2016-10-28 13:25:24 -040087 , fInstancedPipelineInfo(fRenderTargetProxy.get())
brianosman5a7ae7e2016-09-12 12:07:25 -070088 , fColorXformFromSRGB(nullptr)
Robert Phillips2c862492017-01-18 10:08:39 -050089 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) {
brianosman5a7ae7e2016-09-12 12:07:25 -070090 if (fColorSpace) {
91 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
Matt Sarett77a7a1b2017-02-07 13:56:11 -050092 auto srgbColorSpace = SkColorSpace::MakeSRGB();
msarettc71a9b72016-09-16 11:01:27 -070093 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
brianosman5a7ae7e2016-09-12 12:07:25 -070094 }
robertphillips2e1e51f2015-10-15 08:01:48 -070095 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070096}
97
robertphillips2e1e51f2015-10-15 08:01:48 -070098#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -040099void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400100 SkASSERT(fRenderTargetProxy);
101 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -0700102
Robert Phillipsf2361d22016-10-25 14:20:06 -0400103 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400104 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700105 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700106}
107#endif
108
Brian Osman11052242016-10-27 14:47:55 -0400109GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800110 ASSERT_SINGLE_OWNER
Robert Phillipsf2361d22016-10-25 14:20:06 -0400111 SkSafeUnref(fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700112}
113
Robert Phillipseaa86252016-11-08 13:49:39 +0000114GrRenderTarget* GrRenderTargetContext::instantiate() {
115 return fRenderTargetProxy->instantiate(fContext->textureProvider());
116}
117
Robert Phillipsf200a902017-01-30 13:27:37 -0500118GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000119 return fRenderTargetProxy->asTextureProxy();
120}
121
Robert Phillipsf200a902017-01-30 13:27:37 -0500122sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
123 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
124}
125
Brian Osman11052242016-10-27 14:47:55 -0400126GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800127 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700128 SkDEBUGCODE(this->validate();)
129
Robert Phillipsf2361d22016-10-25 14:20:06 -0400130 if (!fOpList || fOpList->isClosed()) {
Robert Phillips72152832017-01-25 17:31:35 -0500131 fOpList = this->drawingManager()->newOpList(fRenderTargetProxy.get());
robertphillipsa106c622015-10-16 09:07:06 -0700132 }
133
Robert Phillipsf2361d22016-10-25 14:20:06 -0400134 return fOpList;
robertphillipsa106c622015-10-16 09:07:06 -0700135}
136
Robert Phillipse2f7d182016-12-15 09:23:05 -0500137// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
138bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
139 const SkIRect& srcRect,
140 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800141 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800142 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700143 SkDEBUGCODE(this->validate();)
Robert Phillipse2f7d182016-12-15 09:23:05 -0500144 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
145
146 // TODO: defer instantiation until flush time
147 sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->textureProvider())));
148 if (!src) {
149 return false;
150 }
robertphillips2d70dcb2015-10-06 07:38:23 -0700151
Brian Salomon69868af2016-12-22 15:42:51 -0500152 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400153 sk_sp<GrRenderTarget> rt(
154 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500155 if (!rt) {
156 return false;
157 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400158
Robert Phillipse2f7d182016-12-15 09:23:05 -0500159 return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700160}
161
Robert Phillips2c862492017-01-18 10:08:39 -0500162// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
163bool GrRenderTargetContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer,
164 size_t dstRowBytes, int x, int y) {
165 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
166 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
167 if (kUnknown_GrPixelConfig == config) {
168 return false;
169 }
170
171 uint32_t flags = 0;
172 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
173 flags = GrContext::kUnpremul_PixelOpsFlag;
174 }
175
176 // Deferral of the VRAM resources must end in this instance anyway
177 sk_sp<GrRenderTarget> rt(
178 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
179 if (!rt) {
180 return false;
181 }
182
183 return rt->readPixels(this->getColorSpace(), x, y, dstInfo.width(), dstInfo.height(),
184 config, dstInfo.colorSpace(), dstBuffer, dstRowBytes, flags);
185}
186
187// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
188bool GrRenderTargetContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
189 size_t srcRowBytes, int x, int y) {
190 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
191 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
192 if (kUnknown_GrPixelConfig == config) {
193 return false;
194 }
195 uint32_t flags = 0;
196 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
197 flags = GrContext::kUnpremul_PixelOpsFlag;
198 }
199
200 // Deferral of the VRAM resources must end in this instance anyway
201 sk_sp<GrRenderTarget> rt(
202 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
203 if (!rt) {
204 return false;
205 }
206
207 return rt->writePixels(this->getColorSpace(), x, y, srcInfo.width(), srcInfo.height(),
208 config, srcInfo.colorSpace(), srcBuffer, srcRowBytes, flags);
209}
210
211
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500212void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint,
Brian Salomon82f44312017-01-11 13:42:54 -0500213 const SkMatrix& viewMatrix, const char text[],
214 size_t byteLength, SkScalar x, SkScalar y,
215 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800216 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700217 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700218 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400219 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700220
Robert Phillips72152832017-01-25 17:31:35 -0500221 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500222 atlasTextContext->drawText(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, text,
223 byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700224}
robertphillipscaef3452015-11-11 13:18:11 -0800225
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 Osman11052242016-10-27 14:47:55 -0400234 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700235
Robert Phillips72152832017-01-25 17:31:35 -0500236 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500237 atlasTextContext->drawPosText(fContext, this, clip, paint, viewMatrix, fSurfaceProps, text,
238 byteLength, pos, scalarsPerPosition, offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700239}
robertphillipscaef3452015-11-11 13:18:11 -0800240
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500241void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
Brian Osman11052242016-10-27 14:47:55 -0400242 const SkMatrix& viewMatrix, const SkTextBlob* blob,
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500243 SkScalar x, SkScalar y, SkDrawFilter* filter,
244 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800245 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700246 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700247 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400248 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700249
Robert Phillips72152832017-01-25 17:31:35 -0500250 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500251 atlasTextContext->drawTextBlob(fContext, this, clip, paint, viewMatrix, fSurfaceProps, blob, x,
252 y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700253}
254
Brian Osman11052242016-10-27 14:47:55 -0400255void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800256 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700257 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700258 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400259 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700260
Robert Phillips72152832017-01-25 17:31:35 -0500261 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400262
Brian Salomon69868af2016-12-22 15:42:51 -0500263 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400264 sk_sp<GrRenderTarget> rt(
265 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500266 if (!rt) {
267 return;
268 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400269
Brian Salomon69868af2016-12-22 15:42:51 -0500270 this->getOpList()->discard(this);
robertphillipsea461502015-05-26 11:38:03 -0700271}
272
Brian Osman11052242016-10-27 14:47:55 -0400273void GrRenderTargetContext::clear(const SkIRect* rect,
274 const GrColor color,
275 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800276 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700277 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700278 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400279 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700280
Robert Phillips72152832017-01-25 17:31:35 -0500281 AutoCheckFlush acf(this->drawingManager());
csmartdalton29df7602016-08-31 11:55:52 -0700282 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
283}
robertphillips9199a9f2016-07-13 07:48:43 -0700284
Robert Phillips784b7bf2016-12-09 13:35:02 -0500285void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
286 ASSERT_SINGLE_OWNER_PRIV
287 RETURN_IF_ABANDONED_PRIV
288 SkDEBUGCODE(fRenderTargetContext->validate();)
289 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
290 "GrRenderTargetContext::absClear");
291
Robert Phillips72152832017-01-25 17:31:35 -0500292 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500293
294 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(
295 *fRenderTargetContext->caps()),
296 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight(
297 *fRenderTargetContext->caps()));
298
299 if (clearRect) {
300 if (clearRect->contains(rtRect)) {
301 clearRect = nullptr; // full screen
302 } else {
303 if (!rtRect.intersect(*clearRect)) {
304 return;
305 }
306 }
307 }
308
309 // TODO: in a post-MDB world this should be handled at the OpList level.
310 // An op-list that is initially cleared and has no other ops should receive an
311 // extra draw.
312 if (fRenderTargetContext->fContext->caps()->useDrawInsteadOfClear()) {
313 // This works around a driver bug with clear by drawing a rect instead.
314 // The driver will ignore a clear if it is the only thing rendered to a
315 // target before the target is read.
316 GrPaint paint;
317 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500318 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
Robert Phillips784b7bf2016-12-09 13:35:02 -0500319
320 // We don't call drawRect() here to avoid the cropping to the, possibly smaller,
321 // RenderTargetProxy bounds
Brian Salomon82f44312017-01-11 13:42:54 -0500322 fRenderTargetContext->drawNonAAFilledRect(GrNoClip(), std::move(paint), SkMatrix::I(),
323 SkRect::Make(rtRect), nullptr, nullptr, nullptr,
324 GrAAType::kNone);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500325
326 } else {
327 if (!fRenderTargetContext->accessRenderTarget()) {
328 return;
329 }
330
331 // This path doesn't handle coalescing of full screen clears b.c. it
332 // has to clear the entire render target - not just the content area.
333 // It could be done but will take more finagling.
Brian Salomonf8334782017-01-03 09:42:58 -0500334 std::unique_ptr<GrOp> op(GrClearOp::Make(
335 rtRect, color, fRenderTargetContext->accessRenderTarget(), !clearRect));
Brian Salomonfc527d22016-12-14 21:07:01 -0500336 if (!op) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500337 return;
338 }
Brian Salomon69868af2016-12-22 15:42:51 -0500339 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500340 }
341}
342
Brian Osman11052242016-10-27 14:47:55 -0400343void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
344 const GrColor color,
345 bool canIgnoreClip) {
csmartdalton29df7602016-08-31 11:55:52 -0700346 ASSERT_SINGLE_OWNER_PRIV
347 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400348 SkDEBUGCODE(fRenderTargetContext->validate();)
349 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
350 "GrRenderTargetContextPriv::clear");
csmartdalton29df7602016-08-31 11:55:52 -0700351
Robert Phillips72152832017-01-25 17:31:35 -0500352 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Osman11052242016-10-27 14:47:55 -0400353 fRenderTargetContext->internalClear(clip, color, canIgnoreClip);
csmartdalton29df7602016-08-31 11:55:52 -0700354}
355
Brian Osman11052242016-10-27 14:47:55 -0400356void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
357 const GrColor color,
358 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700359 bool isFull = false;
360 if (!clip.hasWindowRectangles()) {
361 isFull = !clip.scissorEnabled() ||
362 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
363 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
364 }
robertphillips9199a9f2016-07-13 07:48:43 -0700365
366 if (fContext->caps()->useDrawInsteadOfClear()) {
367 // This works around a driver bug with clear by drawing a rect instead.
368 // The driver will ignore a clear if it is the only thing rendered to a
369 // target before the target is read.
Robert Phillips784b7bf2016-12-09 13:35:02 -0500370 SkIRect clearRect = SkIRect::MakeWH(this->width(), this->height());
csmartdalton29df7602016-08-31 11:55:52 -0700371 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700372 this->discard();
Robert Phillips93f16332016-11-23 19:37:13 -0500373 } else if (!clearRect.intersect(clip.scissorRect())) {
csmartdalton29df7602016-08-31 11:55:52 -0700374 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700375 }
376
377 GrPaint paint;
378 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500379 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips9199a9f2016-07-13 07:48:43 -0700380
Brian Salomon82f44312017-01-11 13:42:54 -0500381 this->drawRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect));
bsalomon9f129de2016-08-10 16:31:05 -0700382 } else if (isFull) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500383 if (this->accessRenderTarget()) {
Brian Salomon69868af2016-12-22 15:42:51 -0500384 this->getOpList()->fullClear(this, color);
Robert Phillipse60ad622016-11-17 10:22:48 -0500385 }
robertphillips9199a9f2016-07-13 07:48:43 -0700386 } else {
Robert Phillipse60ad622016-11-17 10:22:48 -0500387 if (!this->accessRenderTarget()) {
388 return;
389 }
Brian Salomonf8334782017-01-03 09:42:58 -0500390 std::unique_ptr<GrOp> op(GrClearOp::Make(clip, color, this->accessRenderTarget()));
Brian Salomon42521e82016-12-07 16:44:58 -0500391 if (!op) {
csmartdalton29df7602016-08-31 11:55:52 -0700392 return;
393 }
Brian Salomon69868af2016-12-22 15:42:51 -0500394 this->getOpList()->addOp(std::move(op), this);
robertphillips9199a9f2016-07-13 07:48:43 -0700395 }
robertphillipsea461502015-05-26 11:38:03 -0700396}
397
Brian Osman11052242016-10-27 14:47:55 -0400398void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500399 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400400 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800401 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700402 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700403 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400404 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700405
robertphillipsea461502015-05-26 11:38:03 -0700406 // set rect to be big enough to fill the space, but not super-huge, so we
407 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700408
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400409 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700410
bsalomoncb31e512016-08-26 10:48:19 -0700411 SkRRect rrect;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500412 GrAA aa;
bsalomoncb31e512016-08-26 10:48:19 -0700413 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
414 // transformation for non-rect rrects. Rects caused a performance regression on an Android
415 // test that needs investigation. We also skip cases where there are fragment processors
416 // because they may depend on having correct local coords and this path draws in device space
417 // without a local matrix.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500418 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500419 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
420 GrStyle::SimpleFill());
bsalomoncb31e512016-08-26 10:48:19 -0700421 return;
422 }
423
robertphillipsea461502015-05-26 11:38:03 -0700424
425 bool isPerspective = viewMatrix.hasPerspective();
426
427 // We attempt to map r by the inverse matrix and draw that. mapRect will
428 // map the four corners and bound them with a new rect. This will not
429 // produce a correct result for some perspective matrices.
430 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700431 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700432 SkDebugf("Could not invert matrix\n");
433 return;
434 }
Brian Salomon82f44312017-01-11 13:42:54 -0500435 this->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700436 } else {
437 SkMatrix localMatrix;
438 if (!viewMatrix.invert(&localMatrix)) {
439 SkDebugf("Could not invert matrix\n");
440 return;
441 }
442
Robert Phillips72152832017-01-25 17:31:35 -0500443 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700444
Brian Salomon82f44312017-01-11 13:42:54 -0500445 this->drawNonAAFilledRect(clip, std::move(paint), SkMatrix::I(), r, nullptr, &localMatrix,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500446 nullptr, GrAAType::kNone);
robertphillipsea461502015-05-26 11:38:03 -0700447 }
448}
449
robertphillipsea461502015-05-26 11:38:03 -0700450static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
451 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
452 point.fY >= rect.fTop && point.fY <= rect.fBottom;
453}
454
bsalomonc55271f2015-11-09 11:55:57 -0800455static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
456 return viewMatrix.preservesRightAngles();
457}
458
csmartdalton97f6cd52016-07-13 13:37:08 -0700459// Attempts to crop a rect and optional local rect to the clip boundaries.
460// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700461static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700462 const SkMatrix& viewMatrix, SkRect* rect,
463 SkRect* localRect = nullptr) {
464 if (!viewMatrix.rectStaysRect()) {
465 return true;
466 }
467
csmartdalton97f6cd52016-07-13 13:37:08 -0700468 SkIRect clipDevBounds;
469 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700470
robertphillips13a7eee2016-08-31 15:06:24 -0700471 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700472 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
473 return false;
474 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700475
476 if (localRect) {
477 if (!rect->intersects(clipBounds)) {
478 return false;
479 }
480 const SkScalar dx = localRect->width() / rect->width();
481 const SkScalar dy = localRect->height() / rect->height();
482 if (clipBounds.fLeft > rect->fLeft) {
483 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
484 rect->fLeft = clipBounds.fLeft;
485 }
486 if (clipBounds.fTop > rect->fTop) {
487 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
488 rect->fTop = clipBounds.fTop;
489 }
490 if (clipBounds.fRight < rect->fRight) {
491 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
492 rect->fRight = clipBounds.fRight;
493 }
494 if (clipBounds.fBottom < rect->fBottom) {
495 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
496 rect->fBottom = clipBounds.fBottom;
497 }
498 return true;
499 }
500
501 return rect->intersect(clipBounds);
502}
503
Brian Osman11052242016-10-27 14:47:55 -0400504bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500505 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500506 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400507 const SkMatrix& viewMatrix,
508 const SkRect& rect,
509 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700510 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500511 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700512 return true;
513 }
robertphillips44302392016-07-08 14:43:03 -0700514
Brian Salomonf8334782017-01-03 09:42:58 -0500515 std::unique_ptr<GrDrawOp> op;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500516 GrAAType aaType;
robertphillips44302392016-07-08 14:43:03 -0700517
csmartdaltone0d36292016-07-29 08:14:20 -0700518 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400519 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon99ad1642016-12-16 09:50:45 -0500520 op = ir->recordRect(croppedRect, viewMatrix, paint.getColor(), aa, fInstancedPipelineInfo,
521 &aaType);
Brian Salomon42521e82016-12-07 16:44:58 -0500522 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500523 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
robertphillips44302392016-07-08 14:43:03 -0700524 if (ss) {
525 pipelineBuilder.setUserStencil(ss);
526 }
Brian Salomon21aa35f2016-12-09 16:01:53 -0500527 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700528 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700529 }
530 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500531 aaType = this->decideAAType(aa);
532 if (GrAAType::kCoverage == aaType) {
robertphillips391395d2016-03-02 09:26:36 -0800533 // The fill path can handle rotation but not skew.
534 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
535 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700536 viewMatrix.mapRect(&devBoundRect, croppedRect);
robertphillips44302392016-07-08 14:43:03 -0700537
Brian Salomon6a639042016-12-14 11:08:17 -0500538 op = GrRectOpFactory::MakeAAFill(paint, viewMatrix, rect, croppedRect, devBoundRect);
Brian Salomon42521e82016-12-07 16:44:58 -0500539 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500540 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
robertphillips44302392016-07-08 14:43:03 -0700541 if (ss) {
542 pipelineBuilder.setUserStencil(ss);
543 }
Brian Salomon21aa35f2016-12-09 16:01:53 -0500544 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700545 return true;
546 }
robertphillips391395d2016-03-02 09:26:36 -0800547 }
548 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500549 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr, nullptr,
550 ss, aaType);
robertphillips44302392016-07-08 14:43:03 -0700551 return true;
robertphillips391395d2016-03-02 09:26:36 -0800552 }
553
robertphillips44302392016-07-08 14:43:03 -0700554 return false;
robertphillips391395d2016-03-02 09:26:36 -0800555}
556
Brian Osman11052242016-10-27 14:47:55 -0400557void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500558 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500559 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400560 const SkMatrix& viewMatrix,
561 const SkRect& rect,
562 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700563 if (!style) {
564 style = &GrStyle::SimpleFill();
565 }
joshualitt1de610a2016-01-06 08:26:09 -0800566 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700567 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700568 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400569 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700570
bsalomon6663acf2016-05-10 09:14:17 -0700571 // Path effects should've been devolved to a path in SkGpuDevice
572 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700573
Robert Phillips72152832017-01-25 17:31:35 -0500574 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700575
bsalomon6663acf2016-05-10 09:14:17 -0700576 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700577 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
578
579 if (!fContext->caps()->useDrawInsteadOfClear()) {
580 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
581 // checking cases where the RT is fully inside a stroke.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400582 SkRect rtRect = fRenderTargetProxy->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700583 // Does the clip contain the entire RT?
584 if (clip.quickContains(rtRect)) {
585 SkMatrix invM;
586 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700587 return;
588 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700589 // Does the rect bound the RT?
590 SkPoint srcSpaceRTQuad[4];
591 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
592 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
593 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
594 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
595 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
596 // Will it blend?
597 GrColor clearColor;
598 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700599 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700600 return;
601 }
602 }
robertphillipsea461502015-05-26 11:38:03 -0700603 }
604 }
robertphillips44302392016-07-08 14:43:03 -0700605
Brian Salomon82f44312017-01-11 13:42:54 -0500606 if (this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, nullptr)) {
robertphillips44302392016-07-08 14:43:03 -0700607 return;
608 }
bsalomona7d85ba2016-07-06 11:54:59 -0700609 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
610 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
611 if ((!rect.width() || !rect.height()) &&
612 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
613 SkScalar r = stroke.getWidth() / 2;
614 // TODO: Move these stroke->fill fallbacks to GrShape?
615 switch (stroke.getJoin()) {
616 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500617 this->drawRect(
618 clip, std::move(paint), aa, viewMatrix,
619 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
620 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700621 return;
622 case SkPaint::kRound_Join:
623 // Raster draws nothing when both dimensions are empty.
624 if (rect.width() || rect.height()){
625 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500626 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
627 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700628 return;
629 }
630 case SkPaint::kBevel_Join:
631 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500632 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700633 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
634 &GrStyle::SimpleFill());
635 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500636 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700637 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
638 &GrStyle::SimpleFill());
639 }
640 return;
641 }
642 }
robertphillips44302392016-07-08 14:43:03 -0700643
robertphillips44302392016-07-08 14:43:03 -0700644 bool snapToPixelCenters = false;
Brian Salomonf8334782017-01-03 09:42:58 -0500645 std::unique_ptr<GrDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700646
robertphillips391395d2016-03-02 09:26:36 -0800647 GrColor color = paint.getColor();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500648 GrAAType aaType = this->decideAAType(aa);
649 if (GrAAType::kCoverage == aaType) {
cdaltonbb539482016-01-04 09:48:25 -0800650 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
651 if (viewMatrix.rectStaysRect()) {
Brian Salomon6a639042016-12-14 11:08:17 -0500652 op = GrRectOpFactory::MakeAAStroke(color, viewMatrix, rect, stroke);
cdaltonbb539482016-01-04 09:48:25 -0800653 }
robertphillipsea461502015-05-26 11:38:03 -0700654 } else {
robertphillips391395d2016-03-02 09:26:36 -0800655 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700656 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800657 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700658 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400659 !fRenderTargetProxy->isUnifiedMultisampled();
Brian Salomon6a639042016-12-14 11:08:17 -0500660 op = GrRectOpFactory::MakeNonAAStroke(color, viewMatrix, rect, stroke,
661 snapToPixelCenters);
robertphillips391395d2016-03-02 09:26:36 -0800662 }
robertphillips4bc31812016-03-01 12:22:49 -0800663
Brian Salomon42521e82016-12-07 16:44:58 -0500664 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500665 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon189098e72017-01-19 09:55:19 -0500666 pipelineBuilder.setSnapVerticesToPixelCenters(snapToPixelCenters);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500667 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700668 return;
robertphillips4bc31812016-03-01 12:22:49 -0800669 }
robertphillips4bc31812016-03-01 12:22:49 -0800670 }
halcanary9d524f22016-03-29 09:03:52 -0700671
robertphillips4bc31812016-03-01 12:22:49 -0800672 SkPath path;
673 path.setIsVolatile(true);
674 path.addRect(rect);
Brian Salomon82f44312017-01-11 13:42:54 -0500675 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700676}
677
Robert Phillipsec2249f2016-11-09 08:54:35 -0500678int GrRenderTargetContextPriv::maxWindowRectangles() const {
679 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
680 *fRenderTargetContext->fContext->caps());
681}
682
Brian Osman11052242016-10-27 14:47:55 -0400683void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700684 ASSERT_SINGLE_OWNER_PRIV
685 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400686 SkDEBUGCODE(fRenderTargetContext->validate();)
687 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
688 "GrRenderTargetContextPriv::clearStencilClip");
robertphillips976f5f02016-06-03 10:59:20 -0700689
Robert Phillips72152832017-01-25 17:31:35 -0500690 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Salomon69868af2016-12-22 15:42:51 -0500691 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipse60ad622016-11-17 10:22:48 -0500692 if (!fRenderTargetContext->accessRenderTarget()) {
693 return;
694 }
Brian Osman11052242016-10-27 14:47:55 -0400695 fRenderTargetContext->getOpList()->clearStencilClip(clip, insideStencilMask,
Brian Salomon69868af2016-12-22 15:42:51 -0500696 fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700697}
698
Brian Osman11052242016-10-27 14:47:55 -0400699void GrRenderTargetContextPriv::stencilPath(const GrClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500700 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400701 const SkMatrix& viewMatrix,
702 const GrPath* path) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500703 SkASSERT(aaType != GrAAType::kCoverage);
704 fRenderTargetContext->getOpList()->stencilPath(fRenderTargetContext, clip, aaType, viewMatrix,
Brian Osman11052242016-10-27 14:47:55 -0400705 path);
robertphillips976f5f02016-06-03 10:59:20 -0700706}
707
Brian Osman11052242016-10-27 14:47:55 -0400708void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
709 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500710 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400711 const SkMatrix& viewMatrix,
712 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700713 ASSERT_SINGLE_OWNER_PRIV
714 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400715 SkDEBUGCODE(fRenderTargetContext->validate();)
716 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
717 "GrRenderTargetContext::stencilRect");
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500718 SkASSERT(GrAAType::kCoverage != aaType);
Robert Phillips72152832017-01-25 17:31:35 -0500719 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700720
721 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500722 paint.setXPFactory(GrDisableColorXPFactory::Get());
robertphillips976f5f02016-06-03 10:59:20 -0700723
Brian Salomon82f44312017-01-11 13:42:54 -0500724 fRenderTargetContext->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, rect, nullptr,
725 nullptr, ss, aaType);
robertphillips976f5f02016-06-03 10:59:20 -0700726}
727
Brian Osman11052242016-10-27 14:47:55 -0400728bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip,
729 const GrUserStencilSettings* ss,
730 SkRegion::Op op,
731 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500732 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400733 const SkMatrix& viewMatrix,
734 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800735 ASSERT_SINGLE_OWNER_PRIV
736 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400737 SkDEBUGCODE(fRenderTargetContext->validate();)
738 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
739 "GrRenderTargetContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800740
Robert Phillips72152832017-01-25 17:31:35 -0500741 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800742
743 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800744 paint.setCoverageSetOpXPFactory(op, invert);
745
Brian Salomon82f44312017-01-11 13:42:54 -0500746 if (fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800747 return true;
748 }
robertphillips391395d2016-03-02 09:26:36 -0800749 SkPath path;
750 path.setIsVolatile(true);
751 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500752 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800753}
754
Brian Osman11052242016-10-27 14:47:55 -0400755void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500756 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500757 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400758 const SkMatrix& viewMatrix,
759 const SkRect& rectToDraw,
760 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800761 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700762 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700763 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400764 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700765
csmartdalton97f6cd52016-07-13 13:37:08 -0700766 SkRect croppedRect = rectToDraw;
767 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700768 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
769 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700770 return;
771 }
772
Robert Phillips72152832017-01-25 17:31:35 -0500773 AutoCheckFlush acf(this->drawingManager());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500774 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -0700775
csmartdaltone0d36292016-07-29 08:14:20 -0700776 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400777 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomonf8334782017-01-03 09:42:58 -0500778 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
779 croppedLocalRect, aa, fInstancedPipelineInfo,
780 &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -0500781 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500782 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500783 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700784 return;
785 }
786 }
787
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500788 aaType = this->decideAAType(aa);
789 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500790 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect,
791 &croppedLocalRect, nullptr, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700792 return;
joshualitt04194f32016-01-13 10:08:27 -0800793 }
bsalomonbb243832016-07-22 07:10:19 -0700794
csmartdaltonfc49d562016-07-26 17:05:47 -0700795 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomonf8334782017-01-03 09:42:58 -0500796 std::unique_ptr<GrDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(
797 paint.getColor(), viewMatrix, croppedRect, croppedLocalRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500798 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon24f19782016-12-13 15:10:11 -0500799 this->addDrawOp(pipelineBuilder, clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700800 return;
801 }
802
803 SkMatrix viewAndUnLocalMatrix;
804 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
805 SkDebugf("fillRectToRect called with empty local matrix.\n");
806 return;
807 }
808 viewAndUnLocalMatrix.postConcat(viewMatrix);
809
810 SkPath path;
811 path.setIsVolatile(true);
812 path.addRect(localRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500813 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700814}
815
Brian Osman11052242016-10-27 14:47:55 -0400816void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500817 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500818 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400819 const SkMatrix& viewMatrix,
820 const SkRect& rectToDraw,
821 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800822 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700823 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700824 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400825 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700826
csmartdalton97f6cd52016-07-13 13:37:08 -0700827 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700828 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700829 return;
830 }
831
Robert Phillips72152832017-01-25 17:31:35 -0500832 AutoCheckFlush acf(this->drawingManager());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500833 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -0700834
csmartdaltone0d36292016-07-29 08:14:20 -0700835 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400836 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomonf8334782017-01-03 09:42:58 -0500837 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
838 localMatrix, aa, fInstancedPipelineInfo,
839 &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -0500840 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500841 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500842 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700843 return;
844 }
845 }
846
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500847 aaType = this->decideAAType(aa);
848 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500849 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr,
850 &localMatrix, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700851 return;
bsalomonc55271f2015-11-09 11:55:57 -0800852 }
robertphillips4bc31812016-03-01 12:22:49 -0800853
csmartdaltonfc49d562016-07-26 17:05:47 -0700854 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomonf8334782017-01-03 09:42:58 -0500855 std::unique_ptr<GrDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -0500856 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500857 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500858 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700859 return;
860 }
861
862 SkMatrix viewAndUnLocalMatrix;
863 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
864 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
865 return;
866 }
867 viewAndUnLocalMatrix.postConcat(viewMatrix);
868
869 SkPath path;
870 path.setIsVolatile(true);
871 path.addRect(rectToDraw);
872 path.transform(localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -0500873 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700874}
875
Brian Osman11052242016-10-27 14:47:55 -0400876void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500877 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400878 const SkMatrix& viewMatrix,
879 GrPrimitiveType primitiveType,
880 int vertexCount,
881 const SkPoint positions[],
882 const SkPoint texCoords[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500883 const uint32_t colors[],
Brian Osman11052242016-10-27 14:47:55 -0400884 const uint16_t indices[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500885 int indexCount,
886 ColorArrayType colorArrayType) {
joshualitt1de610a2016-01-06 08:26:09 -0800887 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700888 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700889 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400890 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700891
Robert Phillips72152832017-01-25 17:31:35 -0500892 AutoCheckFlush acf(this->drawingManager());
robertphillips2e1e51f2015-10-15 08:01:48 -0700893
robertphillipsea461502015-05-26 11:38:03 -0700894 // TODO clients should give us bounds
895 SkRect bounds;
896 if (!bounds.setBoundsCheck(positions, vertexCount)) {
897 SkDebugf("drawVertices call empty bounds\n");
898 return;
899 }
900
Brian Salomon3de0aee2017-01-29 09:34:17 -0500901 std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
902 paint.getColor(), primitiveType, viewMatrix, positions, vertexCount, indices,
903 indexCount, colors, texCoords, bounds, colorArrayType);
Brian Salomon199fb872017-02-06 09:41:10 -0500904 if (!op) {
905 return;
906 }
907 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
908 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
909}
robertphillipsea461502015-05-26 11:38:03 -0700910
Brian Salomon199fb872017-02-06 09:41:10 -0500911void GrRenderTargetContext::drawVertices(const GrClip& clip,
912 GrPaint&& paint,
913 const SkMatrix& viewMatrix,
914 sk_sp<SkVertices> vertices,
915 uint32_t flags) {
916 ASSERT_SINGLE_OWNER
917 RETURN_IF_ABANDONED
918 SkDEBUGCODE(this->validate();)
919 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
920
921 AutoCheckFlush acf(this->drawingManager());
922
923 SkASSERT(vertices);
924 std::unique_ptr<GrDrawOp> op =
925 GrDrawVerticesOp::Make(paint.getColor(), std::move(vertices), viewMatrix, flags);
926 if (!op) {
927 return;
928 }
Brian Salomon82f44312017-01-11 13:42:54 -0500929 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500930 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700931}
932
933///////////////////////////////////////////////////////////////////////////////
934
Brian Osman11052242016-10-27 14:47:55 -0400935void GrRenderTargetContext::drawAtlas(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500936 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400937 const SkMatrix& viewMatrix,
938 int spriteCount,
939 const SkRSXform xform[],
940 const SkRect texRect[],
941 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800942 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700943 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700944 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400945 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700946
Robert Phillips72152832017-01-25 17:31:35 -0500947 AutoCheckFlush acf(this->drawingManager());
halcanary9d524f22016-03-29 09:03:52 -0700948
Brian Salomonf8334782017-01-03 09:42:58 -0500949 std::unique_ptr<GrDrawOp> op =
Brian Salomonfc527d22016-12-14 21:07:01 -0500950 GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
Brian Salomon82f44312017-01-11 13:42:54 -0500951 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500952 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -0700953}
954
955///////////////////////////////////////////////////////////////////////////////
956
Brian Osman11052242016-10-27 14:47:55 -0400957void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500958 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500959 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400960 const SkMatrix& viewMatrix,
961 const SkRRect& rrect,
962 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800963 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700964 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700965 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400966 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700967 if (rrect.isEmpty()) {
968 return;
969 }
970
bsalomon7f0d9f32016-08-15 14:49:10 -0700971 GrNoClip noclip;
972 const GrClip* clip = &origClip;
973#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
974 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -0500975 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -0700976 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
977 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
978 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
979 SkRRect devRRect;
980 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
981 clip = &noclip;
982 }
983#endif
bsalomon6663acf2016-05-10 09:14:17 -0700984 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700985
Robert Phillips72152832017-01-25 17:31:35 -0500986 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700987 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500988 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -0700989
csmartdaltone0d36292016-07-29 08:14:20 -0700990 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
991 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400992 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomonf8334782017-01-03 09:42:58 -0500993 std::unique_ptr<GrDrawOp> op(ir->recordRRect(rrect, viewMatrix, paint.getColor(), aa,
994 fInstancedPipelineInfo, &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -0500995 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500996 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500997 this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700998 return;
999 }
1000 }
1001
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001002 aaType = this->decideAAType(aa);
1003 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001004 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomonf8334782017-01-03 09:42:58 -05001005 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeRRectOp(paint.getColor(),
1006 paint.usesDistanceVectorField(),
1007 viewMatrix,
1008 rrect,
1009 stroke,
1010 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001011 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001012 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001013 this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001014 return;
1015 }
robertphillipsea461502015-05-26 11:38:03 -07001016 }
robertphillipsb56f9272016-02-25 11:03:52 -08001017
1018 SkPath path;
1019 path.setIsVolatile(true);
1020 path.addRRect(rrect);
Brian Salomon82f44312017-01-11 13:42:54 -05001021 this->internalDrawPath(*clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001022}
1023
Jim Van Verthc5903412016-11-17 15:27:09 -05001024///////////////////////////////////////////////////////////////////////////////
1025
1026void GrRenderTargetContext::drawShadowRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001027 GrPaint&& paint,
Jim Van Verthc5903412016-11-17 15:27:09 -05001028 const SkMatrix& viewMatrix,
1029 const SkRRect& rrect,
1030 SkScalar blurRadius,
1031 const GrStyle& style) {
1032 ASSERT_SINGLE_OWNER
1033 RETURN_IF_ABANDONED
1034 SkDEBUGCODE(this->validate();)
1035 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect");
1036 if (rrect.isEmpty()) {
1037 return;
1038 }
1039
1040 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1041
Robert Phillips72152832017-01-25 17:31:35 -05001042 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001043 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001044 // TODO: add instancing support?
Jim Van Verthc5903412016-11-17 15:27:09 -05001045
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001046 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomonf8334782017-01-03 09:42:58 -05001047 std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(paint.getColor(), viewMatrix, rrect,
1048 blurRadius, stroke, shaderCaps);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001049 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001050 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001051 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001052 return;
Jim Van Verthc5903412016-11-17 15:27:09 -05001053 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001054}
1055
1056///////////////////////////////////////////////////////////////////////////////
1057
Brian Osman11052242016-10-27 14:47:55 -04001058bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001059 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001060 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001061 const SkMatrix& viewMatrix,
1062 const SkRRect& origOuter,
1063 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001064 SkASSERT(!origInner.isEmpty());
1065 SkASSERT(!origOuter.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001066 GrAAType aaType;
robertphillips00095892016-02-29 13:50:40 -08001067
csmartdaltone0d36292016-07-29 08:14:20 -07001068 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001069 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomonf8334782017-01-03 09:42:58 -05001070 std::unique_ptr<GrDrawOp> op(ir->recordDRRect(origOuter, origInner, viewMatrix,
Brian Salomon82f44312017-01-11 13:42:54 -05001071 paint.getColor(), aa, fInstancedPipelineInfo,
1072 &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -05001073 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001074 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001075 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001076 return true;
1077 }
1078 }
1079
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001080 aaType = this->decideAAType(aa);
robertphillips00095892016-02-29 13:50:40 -08001081
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001082 GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
1083 if (GrAAType::kCoverage == aaType) {
1084 innerEdgeType = kInverseFillAA_GrProcessorEdgeType;
1085 outerEdgeType = kFillAA_GrProcessorEdgeType;
1086 } else {
1087 innerEdgeType = kInverseFillBW_GrProcessorEdgeType;
1088 outerEdgeType = kFillBW_GrProcessorEdgeType;
1089 }
robertphillips00095892016-02-29 13:50:40 -08001090
1091 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1092 SkMatrix inverseVM;
1093 if (!viewMatrix.isIdentity()) {
1094 if (!origInner.transform(viewMatrix, inner.writable())) {
1095 return false;
1096 }
1097 if (!origOuter.transform(viewMatrix, outer.writable())) {
1098 return false;
1099 }
1100 if (!viewMatrix.invert(&inverseVM)) {
1101 return false;
1102 }
1103 } else {
1104 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001105 }
robertphillips00095892016-02-29 13:50:40 -08001106
robertphillips00095892016-02-29 13:50:40 -08001107 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -07001108 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -08001109 if (!innerEffect) {
1110 return false;
1111 }
1112
bungeman06ca8ec2016-06-09 08:01:03 -07001113 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -08001114 if (!outerEffect) {
1115 return false;
1116 }
1117
Brian Salomon82f44312017-01-11 13:42:54 -05001118 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1119 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001120
1121 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001122 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001123 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1124 }
halcanary9d524f22016-03-29 09:03:52 -07001125
Brian Salomon82f44312017-01-11 13:42:54 -05001126 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1127 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001128 return true;
1129}
1130
Brian Osman11052242016-10-27 14:47:55 -04001131void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001132 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001133 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001134 const SkMatrix& viewMatrix,
1135 const SkRRect& outer,
1136 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001137 ASSERT_SINGLE_OWNER
1138 RETURN_IF_ABANDONED
1139 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001140 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
robertphillips00095892016-02-29 13:50:40 -08001141
1142 SkASSERT(!outer.isEmpty());
1143 SkASSERT(!inner.isEmpty());
1144
Robert Phillips72152832017-01-25 17:31:35 -05001145 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001146
Brian Salomon82f44312017-01-11 13:42:54 -05001147 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001148 return;
1149 }
1150
1151 SkPath path;
1152 path.setIsVolatile(true);
1153 path.addRRect(inner);
1154 path.addRRect(outer);
1155 path.setFillType(SkPath::kEvenOdd_FillType);
1156
Brian Salomon82f44312017-01-11 13:42:54 -05001157 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -08001158}
1159
robertphillipsea461502015-05-26 11:38:03 -07001160///////////////////////////////////////////////////////////////////////////////
1161
msarettcc319b92016-08-25 18:07:18 -07001162static inline bool is_int(float x) {
1163 return x == (float) sk_float_round2int(x);
1164}
1165
Brian Osman11052242016-10-27 14:47:55 -04001166void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001167 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001168 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001169 const SkMatrix& viewMatrix,
1170 const SkRegion& region,
1171 const GrStyle& style) {
msarettcc319b92016-08-25 18:07:18 -07001172 ASSERT_SINGLE_OWNER
1173 RETURN_IF_ABANDONED
1174 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001175 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
msarettcc319b92016-08-25 18:07:18 -07001176
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001177 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001178 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001179 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001180 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1181 is_int(viewMatrix.getTranslateX()) &&
1182 is_int(viewMatrix.getTranslateY())) {
1183 aa = GrAA::kNo;
1184 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001185 }
msarettcc319b92016-08-25 18:07:18 -07001186 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001187 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001188 SkPath path;
1189 region.getBoundaryPath(&path);
Brian Salomon82f44312017-01-11 13:42:54 -05001190 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001191 }
1192
Brian Salomonf8334782017-01-03 09:42:58 -05001193 std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
Brian Salomon82f44312017-01-11 13:42:54 -05001194 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001195 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001196}
1197
Brian Osman11052242016-10-27 14:47:55 -04001198void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001199 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001200 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001201 const SkMatrix& viewMatrix,
1202 const SkRect& oval,
1203 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001204 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001205 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001206 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001207 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001208
robertphillipsea461502015-05-26 11:38:03 -07001209 if (oval.isEmpty()) {
1210 return;
1211 }
1212
bsalomon6663acf2016-05-10 09:14:17 -07001213 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001214
Robert Phillips72152832017-01-25 17:31:35 -05001215 AutoCheckFlush acf(this->drawingManager());
bsalomon6663acf2016-05-10 09:14:17 -07001216 const SkStrokeRec& stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001217 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -07001218
csmartdaltone0d36292016-07-29 08:14:20 -07001219 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1220 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001221 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomonf8334782017-01-03 09:42:58 -05001222 std::unique_ptr<GrDrawOp> op(ir->recordOval(oval, viewMatrix, paint.getColor(), aa,
1223 fInstancedPipelineInfo, &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -05001224 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001225 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001226 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001227 return;
1228 }
1229 }
1230
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001231 aaType = this->decideAAType(aa);
1232 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001233 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomonf8334782017-01-03 09:42:58 -05001234 std::unique_ptr<GrDrawOp> op =
Brian Salomon289e3d82016-12-14 15:52:56 -05001235 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001236 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001237 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001238 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001239 return;
1240 }
robertphillipsea461502015-05-26 11:38:03 -07001241 }
robertphillipsb56f9272016-02-25 11:03:52 -08001242
1243 SkPath path;
1244 path.setIsVolatile(true);
1245 path.addOval(oval);
Brian Salomon82f44312017-01-11 13:42:54 -05001246 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001247}
1248
Brian Osman11052242016-10-27 14:47:55 -04001249void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001250 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001251 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001252 const SkMatrix& viewMatrix,
1253 const SkRect& oval,
1254 SkScalar startAngle,
1255 SkScalar sweepAngle,
1256 bool useCenter,
1257 const GrStyle& style) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001258 GrAAType aaType = this->decideAAType(aa);
1259 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001260 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomonf8334782017-01-03 09:42:58 -05001261 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
1262 viewMatrix,
1263 oval,
1264 startAngle,
1265 sweepAngle,
1266 useCenter,
1267 style,
1268 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001269 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001270 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001271 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001272 return;
1273 }
1274 }
1275 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001276 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1277 style.isSimpleFill());
Brian Salomon82f44312017-01-11 13:42:54 -05001278 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001279}
1280
Brian Osman11052242016-10-27 14:47:55 -04001281void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001282 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001283 const SkMatrix& viewMatrix,
1284 int imageWidth,
1285 int imageHeight,
1286 std::unique_ptr<SkLatticeIter> iter,
1287 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001288 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001289 RETURN_IF_ABANDONED
1290 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001291 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001292
Robert Phillips72152832017-01-25 17:31:35 -05001293 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001294
Brian Salomonf8334782017-01-03 09:42:58 -05001295 std::unique_ptr<GrDrawOp> op = GrLatticeOp::MakeNonAA(paint.getColor(), viewMatrix, imageWidth,
1296 imageHeight, std::move(iter), dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001297
Brian Salomon82f44312017-01-11 13:42:54 -05001298 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001299 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001300}
1301
Brian Osman11052242016-10-27 14:47:55 -04001302void GrRenderTargetContext::prepareForExternalIO() {
robertphillips8c523e02016-07-26 07:41:00 -07001303 ASSERT_SINGLE_OWNER
1304 RETURN_IF_ABANDONED
1305 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001306 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
robertphillips8c523e02016-07-26 07:41:00 -07001307
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001308 // Deferral of the VRAM resources must end in this instance anyway
1309 sk_sp<GrRenderTarget> rt(
1310 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -05001311 if (!rt) {
1312 return;
1313 }
robertphillips8c523e02016-07-26 07:41:00 -07001314
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001315 ASSERT_OWNED_RESOURCE(rt);
1316
Robert Phillips72152832017-01-25 17:31:35 -05001317 this->drawingManager()->prepareSurfaceForExternalIO(rt.get());
robertphillips8c523e02016-07-26 07:41:00 -07001318}
joshualitt33a5fce2015-11-18 13:28:51 -08001319
Brian Osman11052242016-10-27 14:47:55 -04001320void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001321 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001322 const SkMatrix& viewMatrix,
1323 const SkRect& rect,
1324 const SkRect* localRect,
1325 const SkMatrix* localMatrix,
1326 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001327 GrAAType hwOrNoneAAType) {
1328 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
1329 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
Brian Salomonf8334782017-01-03 09:42:58 -05001330 std::unique_ptr<GrDrawOp> op = GrRectOpFactory::MakeNonAAFill(paint.getColor(), viewMatrix,
1331 rect, localRect, localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -05001332 GrPipelineBuilder pipelineBuilder(std::move(paint), hwOrNoneAAType);
robertphillips44302392016-07-08 14:43:03 -07001333 if (ss) {
1334 pipelineBuilder.setUserStencil(ss);
1335 }
Brian Salomon21aa35f2016-12-09 16:01:53 -05001336 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -07001337}
1338
robertphillipsea461502015-05-26 11:38:03 -07001339// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001340static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001341
1342 if (path.isInverseFillType()) {
1343 return false;
1344 }
1345
1346 // TODO: this restriction could be lifted if we were willing to apply
1347 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001348 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001349 return false;
1350 }
1351
1352 SkPath::Direction dirs[2];
1353 if (!path.isNestedFillRects(rects, dirs)) {
1354 return false;
1355 }
1356
1357 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1358 // The two rects need to be wound opposite to each other
1359 return false;
1360 }
1361
1362 // Right now, nested rects where the margin is not the same width
1363 // all around do not render correctly
1364 const SkScalar* outer = rects[0].asScalars();
1365 const SkScalar* inner = rects[1].asScalars();
1366
1367 bool allEq = true;
1368
1369 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1370 bool allGoE1 = margin >= SK_Scalar1;
1371
1372 for (int i = 1; i < 4; ++i) {
1373 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1374 if (temp < SK_Scalar1) {
1375 allGoE1 = false;
1376 }
1377 if (!SkScalarNearlyEqual(margin, temp)) {
1378 allEq = false;
1379 }
1380 }
1381
1382 return allEq || allGoE1;
1383}
1384
Brian Osman11052242016-10-27 14:47:55 -04001385void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001386 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001387 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001388 const SkMatrix& viewMatrix,
1389 const SkPath& path,
1390 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001391 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001392 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001393 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001394 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001395
robertphillipsea461502015-05-26 11:38:03 -07001396 if (path.isEmpty()) {
1397 if (path.isInverseFillType()) {
Brian Salomon82f44312017-01-11 13:42:54 -05001398 this->drawPaint(clip, std::move(paint), viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001399 }
1400 return;
1401 }
1402
Robert Phillips72152832017-01-25 17:31:35 -05001403 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001404
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001405 GrAAType aaType = this->decideAAType(aa);
1406 if (GrAAType::kCoverage == aaType && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001407 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001408 // Concave AA paths are expensive - try to avoid them for special cases
1409 SkRect rects[2];
1410
bsalomon6663acf2016-05-10 09:14:17 -07001411 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Brian Salomonf8334782017-01-03 09:42:58 -05001412 std::unique_ptr<GrDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -05001413 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001414 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001415 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001416 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
bsalomon40ef4852016-05-02 13:22:13 -07001417 }
robertphillipsea461502015-05-26 11:38:03 -07001418 return;
1419 }
1420 }
1421 SkRect ovalRect;
1422 bool isOval = path.isOval(&ovalRect);
1423
1424 if (isOval && !path.isInverseFillType()) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001425 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomonf8334782017-01-03 09:42:58 -05001426 std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeOvalOp(
Brian Salomon289e3d82016-12-14 15:52:56 -05001427 paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001428 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001429 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001430 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001431 return;
1432 }
1433 }
1434 }
robertphillips4bc31812016-03-01 12:22:49 -08001435
1436 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1437 // Scratch textures can be recycled after they are returned to the texture
1438 // cache. This presents a potential hazard for buffered drawing. However,
1439 // the writePixels that uploads to the scratch will perform a flush so we're
1440 // OK.
Brian Salomon82f44312017-01-11 13:42:54 -05001441 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001442}
1443
Brian Osman11052242016-10-27 14:47:55 -04001444bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip,
1445 const GrUserStencilSettings* ss,
1446 SkRegion::Op op,
1447 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001448 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001449 const SkMatrix& viewMatrix,
1450 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001451 ASSERT_SINGLE_OWNER_PRIV
1452 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001453 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001454 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
1455 "GrRenderTargetContextPriv::drawAndStencilPath");
robertphillips391395d2016-03-02 09:26:36 -08001456
1457 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001458 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001459 SkRect::MakeIWH(fRenderTargetContext->width(),
1460 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001461 return true;
1462 }
1463
Robert Phillips72152832017-01-25 17:31:35 -05001464 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001465
1466 // An Assumption here is that path renderer would use some form of tweaking
1467 // the src color (either the input alpha or in the frag shader) to implement
1468 // aa. If we have some future driver-mojo path AA that can do the right
1469 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001470 GrAAType aaType = fRenderTargetContext->decideAAType(aa);
robertphillips976f5f02016-06-03 10:59:20 -07001471 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001472
bsalomon8acedde2016-06-24 10:42:16 -07001473 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001474 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Osman11052242016-10-27 14:47:55 -04001475 canDrawArgs.fShaderCaps =
Robert Phillips72152832017-01-25 17:31:35 -05001476 fRenderTargetContext->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips391395d2016-03-02 09:26:36 -08001477 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001478 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001479 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001480 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001481
1482 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001483 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001484 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001485 if (!pr) {
1486 return false;
1487 }
1488
1489 GrPaint paint;
1490 paint.setCoverageSetOpXPFactory(op, invert);
1491
Brian Salomon82f44312017-01-11 13:42:54 -05001492 GrPathRenderer::DrawPathArgs args{
Robert Phillips72152832017-01-25 17:31:35 -05001493 fRenderTargetContext->drawingManager()->getContext()->resourceProvider(),
Brian Salomon82f44312017-01-11 13:42:54 -05001494 std::move(paint),
1495 ss,
1496 fRenderTargetContext,
1497 &clip,
1498 &viewMatrix,
1499 &shape,
1500 aaType,
1501 fRenderTargetContext->isGammaCorrect()};
robertphillips391395d2016-03-02 09:26:36 -08001502 pr->drawPath(args);
1503 return true;
1504}
1505
Brian Osman11052242016-10-27 14:47:55 -04001506SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001507 ASSERT_SINGLE_OWNER_PRIV
1508
Brian Osman11052242016-10-27 14:47:55 -04001509 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001510 return SkBudgeted::kNo;
1511 }
1512
Brian Osman11052242016-10-27 14:47:55 -04001513 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001514
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001515 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001516}
1517
Brian Osman11052242016-10-27 14:47:55 -04001518void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001519 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001520 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001521 const SkMatrix& viewMatrix,
1522 const SkPath& path,
1523 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001524 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001525 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001526 SkASSERT(!path.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001527 GrShape shape;
robertphillipsea461502015-05-26 11:38:03 -07001528
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001529 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true);
1530 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) {
1531 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and
1532 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1533 // smoother hairlines than MSAA.
1534 aaType = GrAAType::kCoverage;
bsalomon0a0f67e2016-06-28 11:56:42 -07001535 }
robertphillips68737822015-10-29 12:12:21 -07001536 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Robert Phillips72152832017-01-25 17:31:35 -05001537 canDrawArgs.fShaderCaps = this->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips68737822015-10-29 12:12:21 -07001538 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001539 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001540 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001541
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001542 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001543 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001544 do {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001545 shape = GrShape(path, style);
bsalomon8acedde2016-06-24 10:42:16 -07001546 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001547 return;
1548 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001549
1550 canDrawArgs.fAAType = aaType;
1551
1552 // Try a 1st time without applying any of the style to the geometry (and barring sw)
Robert Phillips72152832017-01-25 17:31:35 -05001553 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001554 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1555
1556 if (!pr && shape.style().pathEffect()) {
1557 // It didn't work above, so try again with the path effect applied.
1558 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
bsalomon8acedde2016-06-24 10:42:16 -07001559 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001560 return;
1561 }
Robert Phillips72152832017-01-25 17:31:35 -05001562 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
bsalomon6663acf2016-05-10 09:14:17 -07001563 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001564 if (!pr) {
1565 if (shape.style().applies()) {
1566 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1567 if (shape.isEmpty()) {
1568 return;
1569 }
1570 }
1571 // This time, allow SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001572 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001573 }
Brian Salomon0abc8b42016-12-13 10:22:54 -05001574 if (!pr && GrAATypeIsHW(aaType)) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001575 // There are exceptional cases where we may wind up falling back to coverage based AA
1576 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions).
1577 aaType = GrAAType::kCoverage;
1578 } else {
1579 break;
1580 }
1581 } while(true);
robertphillipsea461502015-05-26 11:38:03 -07001582
bsalomon8acedde2016-06-24 10:42:16 -07001583 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001584#ifdef SK_DEBUG
1585 SkDebugf("Unable to find path renderer compatible with path.\n");
1586#endif
1587 return;
1588 }
1589
Robert Phillips72152832017-01-25 17:31:35 -05001590 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext()->resourceProvider(),
Brian Salomon82f44312017-01-11 13:42:54 -05001591 std::move(paint),
1592 &GrUserStencilSettings::kUnused,
1593 this,
1594 &clip,
1595 &viewMatrix,
1596 &shape,
1597 aaType,
1598 this->isGammaCorrect()};
bsalomon0aff2fa2015-07-31 06:48:27 -07001599 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001600}
1601
Brian Salomon42521e82016-12-07 16:44:58 -05001602void GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
Brian Salomonf8334782017-01-03 09:42:58 -05001603 std::unique_ptr<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001604 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001605 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001606 SkDEBUGCODE(this->validate();)
Brian Salomon42521e82016-12-07 16:44:58 -05001607 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
robertphillips2d70dcb2015-10-06 07:38:23 -07001608
Brian Salomon24f19782016-12-13 15:10:11 -05001609 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips2334fb62015-06-17 05:43:33 -07001610}