blob: e225bc9e5e45fd9b825c81eb6586acc3ebdfeec9 [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 Salomon467921e2017-03-06 16:17:12 -05009#include "GrAppliedClip.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050010#include "GrColor.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"
Brian Salomon467921e2017-03-06 16:17:12 -050020#include "GrStencilAttachment.h"
21#include "SkLatticeIter.h"
22#include "SkMatrixPriv.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070023#include "SkSurfacePriv.h"
Brian Salomon467921e2017-03-06 16:17:12 -050024#include "effects/GrRRectEffect.h"
25#include "instanced/InstancedRendering.h"
Brian Salomon89527432016-12-16 09:52:16 -050026#include "ops/GrClearOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050027#include "ops/GrDrawOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050028#include "ops/GrDrawAtlasOp.h"
29#include "ops/GrDrawVerticesOp.h"
30#include "ops/GrLatticeOp.h"
31#include "ops/GrOp.h"
32#include "ops/GrOvalOpFactory.h"
33#include "ops/GrRectOpFactory.h"
34#include "ops/GrRegionOp.h"
35#include "ops/GrShadowRRectOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050036#include "ops/GrStencilPathOp.h"
joshualitte8042922015-12-11 06:11:21 -080037#include "text/GrAtlasTextContext.h"
38#include "text/GrStencilAndCoverTextContext.h"
joshualittbc907352016-01-13 06:45:40 -080039#include "../private/GrAuditTrail.h"
40
Robert Phillips72152832017-01-25 17:31:35 -050041#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080042#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080043 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080044#define ASSERT_SINGLE_OWNER_PRIV \
Brian Osman11052242016-10-27 14:47:55 -040045 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->fSingleOwner);)
Robert Phillips72152832017-01-25 17:31:35 -050046#define RETURN_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return; }
47#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
48#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
49#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
50#define RETURN_NULL_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070051
csmartdaltona7f29642016-07-07 08:49:11 -070052using gr_instanced::InstancedRendering;
53
robertphillipsea461502015-05-26 11:38:03 -070054class AutoCheckFlush {
55public:
halcanary9d524f22016-03-29 09:03:52 -070056 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070057 SkASSERT(fDrawingManager);
58 }
bsalomonb77a9072016-09-07 10:02:04 -070059 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070060
61private:
robertphillips77a2e522015-10-17 07:43:27 -070062 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070063};
64
Brian Osman11052242016-10-27 14:47:55 -040065bool GrRenderTargetContext::wasAbandoned() const {
Robert Phillips72152832017-01-25 17:31:35 -050066 return this->drawingManager()->wasAbandoned();
robertphillips7761d612016-05-16 09:14:53 -070067}
68
Robert Phillipsf2361d22016-10-25 14:20:06 -040069// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -040070// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -040071// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -040072// when the renderTargetContext attempts to use it (via getOpList).
73GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
74 GrDrawingManager* drawingMgr,
Robert Phillipsc7635fa2016-10-28 13:25:24 -040075 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -040076 sk_sp<SkColorSpace> colorSpace,
77 const SkSurfaceProps* surfaceProps,
78 GrAuditTrail* auditTrail,
79 GrSingleOwner* singleOwner)
Robert Phillips72152832017-01-25 17:31:35 -050080 : GrSurfaceContext(context, drawingMgr, std::move(colorSpace), auditTrail, singleOwner)
Robert Phillipsc7635fa2016-10-28 13:25:24 -040081 , fRenderTargetProxy(std::move(rtp))
82 , fOpList(SkSafeRef(fRenderTargetProxy->getLastRenderTargetOpList()))
Robert Phillipsc7635fa2016-10-28 13:25:24 -040083 , fInstancedPipelineInfo(fRenderTargetProxy.get())
brianosman5a7ae7e2016-09-12 12:07:25 -070084 , fColorXformFromSRGB(nullptr)
Robert Phillips2c862492017-01-18 10:08:39 -050085 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) {
brianosman5a7ae7e2016-09-12 12:07:25 -070086 if (fColorSpace) {
87 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
Matt Sarett77a7a1b2017-02-07 13:56:11 -050088 auto srgbColorSpace = SkColorSpace::MakeSRGB();
msarettc71a9b72016-09-16 11:01:27 -070089 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
brianosman5a7ae7e2016-09-12 12:07:25 -070090 }
robertphillips2e1e51f2015-10-15 08:01:48 -070091 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070092}
93
robertphillips2e1e51f2015-10-15 08:01:48 -070094#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -040095void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -040096 SkASSERT(fRenderTargetProxy);
97 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -070098
Robert Phillipsf2361d22016-10-25 14:20:06 -040099 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400100 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700101 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700102}
103#endif
104
Brian Osman11052242016-10-27 14:47:55 -0400105GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800106 ASSERT_SINGLE_OWNER
Robert Phillipsf2361d22016-10-25 14:20:06 -0400107 SkSafeUnref(fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700108}
109
Robert Phillipsf200a902017-01-30 13:27:37 -0500110GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000111 return fRenderTargetProxy->asTextureProxy();
112}
113
Robert Phillipsf200a902017-01-30 13:27:37 -0500114sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
115 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
116}
117
Brian Osman11052242016-10-27 14:47:55 -0400118GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800119 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700120 SkDEBUGCODE(this->validate();)
121
Robert Phillipsf2361d22016-10-25 14:20:06 -0400122 if (!fOpList || fOpList->isClosed()) {
Robert Phillips72152832017-01-25 17:31:35 -0500123 fOpList = this->drawingManager()->newOpList(fRenderTargetProxy.get());
robertphillipsa106c622015-10-16 09:07:06 -0700124 }
125
Robert Phillipsf2361d22016-10-25 14:20:06 -0400126 return fOpList;
robertphillipsa106c622015-10-16 09:07:06 -0700127}
128
Robert Phillipse2f7d182016-12-15 09:23:05 -0500129// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
130bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
131 const SkIRect& srcRect,
132 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800133 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800134 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700135 SkDEBUGCODE(this->validate();)
Robert Phillipse2f7d182016-12-15 09:23:05 -0500136 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
137
138 // TODO: defer instantiation until flush time
Brian Osman32342f02017-03-04 08:12:46 -0500139 sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
Robert Phillipse2f7d182016-12-15 09:23:05 -0500140 if (!src) {
141 return false;
142 }
robertphillips2d70dcb2015-10-06 07:38:23 -0700143
Brian Salomon69868af2016-12-22 15:42:51 -0500144 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400145 sk_sp<GrRenderTarget> rt(
Brian Osman32342f02017-03-04 08:12:46 -0500146 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500147 if (!rt) {
148 return false;
149 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400150
Robert Phillipse2f7d182016-12-15 09:23:05 -0500151 return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700152}
153
Robert Phillips2c862492017-01-18 10:08:39 -0500154// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
155bool GrRenderTargetContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer,
Robert Phillipsb726d582017-03-09 16:36:32 -0500156 size_t dstRowBytes, int x, int y, uint32_t flags) {
Robert Phillips2c862492017-01-18 10:08:39 -0500157 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
158 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
159 if (kUnknown_GrPixelConfig == config) {
160 return false;
161 }
162
Robert Phillipsb726d582017-03-09 16:36:32 -0500163 // TODO: this seems to duplicate code in SkImage_Gpu::onReadPixels
Robert Phillips2c862492017-01-18 10:08:39 -0500164 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
Robert Phillipsb726d582017-03-09 16:36:32 -0500165 flags |= GrContext::kUnpremul_PixelOpsFlag;
Robert Phillips2c862492017-01-18 10:08:39 -0500166 }
167
168 // Deferral of the VRAM resources must end in this instance anyway
169 sk_sp<GrRenderTarget> rt(
Brian Osman32342f02017-03-04 08:12:46 -0500170 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
Robert Phillips2c862492017-01-18 10:08:39 -0500171 if (!rt) {
172 return false;
173 }
174
175 return rt->readPixels(this->getColorSpace(), x, y, dstInfo.width(), dstInfo.height(),
176 config, dstInfo.colorSpace(), dstBuffer, dstRowBytes, flags);
177}
178
179// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
180bool GrRenderTargetContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
Robert Phillips30f9bc62017-02-22 15:28:38 -0500181 size_t srcRowBytes, int x, int y, uint32_t flags) {
Robert Phillips2c862492017-01-18 10:08:39 -0500182 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
183 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
184 if (kUnknown_GrPixelConfig == config) {
185 return false;
186 }
Robert Phillips2c862492017-01-18 10:08:39 -0500187 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
Robert Phillips30f9bc62017-02-22 15:28:38 -0500188 flags |= GrContext::kUnpremul_PixelOpsFlag;
Robert Phillips2c862492017-01-18 10:08:39 -0500189 }
190
191 // Deferral of the VRAM resources must end in this instance anyway
192 sk_sp<GrRenderTarget> rt(
Brian Osman32342f02017-03-04 08:12:46 -0500193 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
Robert Phillips2c862492017-01-18 10:08:39 -0500194 if (!rt) {
195 return false;
196 }
197
198 return rt->writePixels(this->getColorSpace(), x, y, srcInfo.width(), srcInfo.height(),
199 config, srcInfo.colorSpace(), srcBuffer, srcRowBytes, flags);
200}
201
202
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500203void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint,
Brian Salomon82f44312017-01-11 13:42:54 -0500204 const SkMatrix& viewMatrix, const char text[],
205 size_t byteLength, SkScalar x, SkScalar y,
206 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800207 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700208 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700209 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400210 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700211
Robert Phillips72152832017-01-25 17:31:35 -0500212 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500213 atlasTextContext->drawText(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, text,
214 byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700215}
robertphillipscaef3452015-11-11 13:18:11 -0800216
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500217void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
218 const SkMatrix& viewMatrix, const char text[],
219 size_t byteLength, const SkScalar pos[],
Brian Salomon82f44312017-01-11 13:42:54 -0500220 int scalarsPerPosition, const SkPoint& offset,
221 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800222 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700223 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700224 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400225 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700226
Robert Phillips72152832017-01-25 17:31:35 -0500227 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500228 atlasTextContext->drawPosText(fContext, this, clip, paint, viewMatrix, fSurfaceProps, text,
229 byteLength, pos, scalarsPerPosition, offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700230}
robertphillipscaef3452015-11-11 13:18:11 -0800231
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500232void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
Brian Osman11052242016-10-27 14:47:55 -0400233 const SkMatrix& viewMatrix, const SkTextBlob* blob,
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500234 SkScalar x, SkScalar y, SkDrawFilter* filter,
235 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800236 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700237 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700238 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400239 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700240
Robert Phillips72152832017-01-25 17:31:35 -0500241 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500242 atlasTextContext->drawTextBlob(fContext, this, clip, paint, viewMatrix, fSurfaceProps, blob, x,
243 y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700244}
245
Brian Osman11052242016-10-27 14:47:55 -0400246void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800247 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700248 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700249 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400250 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700251
Robert Phillips72152832017-01-25 17:31:35 -0500252 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400253
Brian Salomon69868af2016-12-22 15:42:51 -0500254 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400255 sk_sp<GrRenderTarget> rt(
Brian Osman32342f02017-03-04 08:12:46 -0500256 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500257 if (!rt) {
258 return;
259 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400260
Brian Salomon69868af2016-12-22 15:42:51 -0500261 this->getOpList()->discard(this);
robertphillipsea461502015-05-26 11:38:03 -0700262}
263
Brian Osman11052242016-10-27 14:47:55 -0400264void GrRenderTargetContext::clear(const SkIRect* rect,
265 const GrColor color,
266 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800267 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700268 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700269 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400270 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700271
Robert Phillips72152832017-01-25 17:31:35 -0500272 AutoCheckFlush acf(this->drawingManager());
csmartdalton29df7602016-08-31 11:55:52 -0700273 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
274}
robertphillips9199a9f2016-07-13 07:48:43 -0700275
Robert Phillips784b7bf2016-12-09 13:35:02 -0500276void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
277 ASSERT_SINGLE_OWNER_PRIV
278 RETURN_IF_ABANDONED_PRIV
279 SkDEBUGCODE(fRenderTargetContext->validate();)
280 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
281 "GrRenderTargetContext::absClear");
282
Robert Phillips72152832017-01-25 17:31:35 -0500283 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500284
285 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(
286 *fRenderTargetContext->caps()),
287 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight(
288 *fRenderTargetContext->caps()));
289
290 if (clearRect) {
291 if (clearRect->contains(rtRect)) {
292 clearRect = nullptr; // full screen
293 } else {
294 if (!rtRect.intersect(*clearRect)) {
295 return;
296 }
297 }
298 }
299
300 // TODO: in a post-MDB world this should be handled at the OpList level.
301 // An op-list that is initially cleared and has no other ops should receive an
302 // extra draw.
303 if (fRenderTargetContext->fContext->caps()->useDrawInsteadOfClear()) {
304 // This works around a driver bug with clear by drawing a rect instead.
305 // The driver will ignore a clear if it is the only thing rendered to a
306 // target before the target is read.
307 GrPaint paint;
308 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500309 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
Robert Phillips784b7bf2016-12-09 13:35:02 -0500310
311 // We don't call drawRect() here to avoid the cropping to the, possibly smaller,
312 // RenderTargetProxy bounds
Brian Salomon82f44312017-01-11 13:42:54 -0500313 fRenderTargetContext->drawNonAAFilledRect(GrNoClip(), std::move(paint), SkMatrix::I(),
314 SkRect::Make(rtRect), nullptr, nullptr, nullptr,
315 GrAAType::kNone);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500316
317 } else {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500318 // This path doesn't handle coalescing of full screen clears b.c. it
319 // has to clear the entire render target - not just the content area.
320 // It could be done but will take more finagling.
Robert Phillipsf7a72612017-03-31 10:03:45 -0400321 std::unique_ptr<GrOp> op(GrClearOp::Make(rtRect, color, fRenderTargetContext, !clearRect));
Brian Salomonfc527d22016-12-14 21:07:01 -0500322 if (!op) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500323 return;
324 }
Brian Salomon69868af2016-12-22 15:42:51 -0500325 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500326 }
327}
328
Brian Osman11052242016-10-27 14:47:55 -0400329void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
330 const GrColor color,
331 bool canIgnoreClip) {
csmartdalton29df7602016-08-31 11:55:52 -0700332 ASSERT_SINGLE_OWNER_PRIV
333 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400334 SkDEBUGCODE(fRenderTargetContext->validate();)
335 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
336 "GrRenderTargetContextPriv::clear");
csmartdalton29df7602016-08-31 11:55:52 -0700337
Robert Phillips72152832017-01-25 17:31:35 -0500338 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Osman11052242016-10-27 14:47:55 -0400339 fRenderTargetContext->internalClear(clip, color, canIgnoreClip);
csmartdalton29df7602016-08-31 11:55:52 -0700340}
341
Brian Osman11052242016-10-27 14:47:55 -0400342void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
343 const GrColor color,
344 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700345 bool isFull = false;
346 if (!clip.hasWindowRectangles()) {
347 isFull = !clip.scissorEnabled() ||
348 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
349 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
350 }
robertphillips9199a9f2016-07-13 07:48:43 -0700351
352 if (fContext->caps()->useDrawInsteadOfClear()) {
353 // This works around a driver bug with clear by drawing a rect instead.
354 // The driver will ignore a clear if it is the only thing rendered to a
355 // target before the target is read.
Robert Phillips784b7bf2016-12-09 13:35:02 -0500356 SkIRect clearRect = SkIRect::MakeWH(this->width(), this->height());
csmartdalton29df7602016-08-31 11:55:52 -0700357 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700358 this->discard();
Robert Phillips93f16332016-11-23 19:37:13 -0500359 } else if (!clearRect.intersect(clip.scissorRect())) {
csmartdalton29df7602016-08-31 11:55:52 -0700360 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700361 }
362
363 GrPaint paint;
364 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500365 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips9199a9f2016-07-13 07:48:43 -0700366
Brian Salomon82f44312017-01-11 13:42:54 -0500367 this->drawRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect));
bsalomon9f129de2016-08-10 16:31:05 -0700368 } else if (isFull) {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400369 this->getOpList()->fullClear(this, color);
robertphillips9199a9f2016-07-13 07:48:43 -0700370 } else {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400371 std::unique_ptr<GrOp> op(GrClearOp::Make(clip, color, this));
Brian Salomon42521e82016-12-07 16:44:58 -0500372 if (!op) {
csmartdalton29df7602016-08-31 11:55:52 -0700373 return;
374 }
Brian Salomon69868af2016-12-22 15:42:51 -0500375 this->getOpList()->addOp(std::move(op), this);
robertphillips9199a9f2016-07-13 07:48:43 -0700376 }
robertphillipsea461502015-05-26 11:38:03 -0700377}
378
Brian Osman11052242016-10-27 14:47:55 -0400379void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500380 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400381 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800382 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700383 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700384 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400385 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700386
robertphillipsea461502015-05-26 11:38:03 -0700387 // set rect to be big enough to fill the space, but not super-huge, so we
388 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700389
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400390 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700391
bsalomoncb31e512016-08-26 10:48:19 -0700392 SkRRect rrect;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500393 GrAA aa;
bsalomoncb31e512016-08-26 10:48:19 -0700394 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
395 // transformation for non-rect rrects. Rects caused a performance regression on an Android
396 // test that needs investigation. We also skip cases where there are fragment processors
397 // because they may depend on having correct local coords and this path draws in device space
398 // without a local matrix.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500399 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500400 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
401 GrStyle::SimpleFill());
bsalomoncb31e512016-08-26 10:48:19 -0700402 return;
403 }
404
robertphillipsea461502015-05-26 11:38:03 -0700405
406 bool isPerspective = viewMatrix.hasPerspective();
407
408 // We attempt to map r by the inverse matrix and draw that. mapRect will
409 // map the four corners and bound them with a new rect. This will not
410 // produce a correct result for some perspective matrices.
411 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700412 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700413 SkDebugf("Could not invert matrix\n");
414 return;
415 }
Brian Salomon82f44312017-01-11 13:42:54 -0500416 this->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700417 } else {
418 SkMatrix localMatrix;
419 if (!viewMatrix.invert(&localMatrix)) {
420 SkDebugf("Could not invert matrix\n");
421 return;
422 }
423
Robert Phillips72152832017-01-25 17:31:35 -0500424 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700425
Brian Salomon82f44312017-01-11 13:42:54 -0500426 this->drawNonAAFilledRect(clip, std::move(paint), SkMatrix::I(), r, nullptr, &localMatrix,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500427 nullptr, GrAAType::kNone);
robertphillipsea461502015-05-26 11:38:03 -0700428 }
429}
430
robertphillipsea461502015-05-26 11:38:03 -0700431static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
432 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
433 point.fY >= rect.fTop && point.fY <= rect.fBottom;
434}
435
bsalomonc55271f2015-11-09 11:55:57 -0800436static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
437 return viewMatrix.preservesRightAngles();
438}
439
csmartdalton97f6cd52016-07-13 13:37:08 -0700440// Attempts to crop a rect and optional local rect to the clip boundaries.
441// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700442static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700443 const SkMatrix& viewMatrix, SkRect* rect,
444 SkRect* localRect = nullptr) {
445 if (!viewMatrix.rectStaysRect()) {
446 return true;
447 }
448
csmartdalton97f6cd52016-07-13 13:37:08 -0700449 SkIRect clipDevBounds;
450 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700451
robertphillips13a7eee2016-08-31 15:06:24 -0700452 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700453 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
454 return false;
455 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700456
457 if (localRect) {
458 if (!rect->intersects(clipBounds)) {
459 return false;
460 }
461 const SkScalar dx = localRect->width() / rect->width();
462 const SkScalar dy = localRect->height() / rect->height();
463 if (clipBounds.fLeft > rect->fLeft) {
464 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
465 rect->fLeft = clipBounds.fLeft;
466 }
467 if (clipBounds.fTop > rect->fTop) {
468 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
469 rect->fTop = clipBounds.fTop;
470 }
471 if (clipBounds.fRight < rect->fRight) {
472 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
473 rect->fRight = clipBounds.fRight;
474 }
475 if (clipBounds.fBottom < rect->fBottom) {
476 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
477 rect->fBottom = clipBounds.fBottom;
478 }
479 return true;
480 }
481
482 return rect->intersect(clipBounds);
483}
484
Brian Osman11052242016-10-27 14:47:55 -0400485bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500486 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500487 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400488 const SkMatrix& viewMatrix,
489 const SkRect& rect,
490 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700491 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500492 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700493 return true;
494 }
robertphillips44302392016-07-08 14:43:03 -0700495
Brian Salomon54d212e2017-03-21 14:22:38 -0400496 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
497 (!ss || ss->isDisabled(false))) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400498 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400499 std::unique_ptr<GrDrawOp> op = ir->recordRect(croppedRect, viewMatrix, std::move(paint), aa,
500 fInstancedPipelineInfo);
Brian Salomon42521e82016-12-07 16:44:58 -0500501 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400502 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700503 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700504 }
505 }
Brian Salomon54d212e2017-03-21 14:22:38 -0400506 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500507 if (GrAAType::kCoverage == aaType) {
robertphillips391395d2016-03-02 09:26:36 -0800508 // The fill path can handle rotation but not skew.
509 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
510 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700511 viewMatrix.mapRect(&devBoundRect, croppedRect);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400512 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -0500513 GrRectOpFactory::MakeAAFill(paint, viewMatrix, rect, croppedRect, devBoundRect);
Brian Salomon42521e82016-12-07 16:44:58 -0500514 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500515 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
robertphillips44302392016-07-08 14:43:03 -0700516 if (ss) {
517 pipelineBuilder.setUserStencil(ss);
518 }
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400519 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700520 return true;
521 }
robertphillips391395d2016-03-02 09:26:36 -0800522 }
523 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500524 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr, nullptr,
525 ss, aaType);
robertphillips44302392016-07-08 14:43:03 -0700526 return true;
robertphillips391395d2016-03-02 09:26:36 -0800527 }
528
robertphillips44302392016-07-08 14:43:03 -0700529 return false;
robertphillips391395d2016-03-02 09:26:36 -0800530}
531
Brian Osman11052242016-10-27 14:47:55 -0400532void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500533 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500534 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400535 const SkMatrix& viewMatrix,
536 const SkRect& rect,
537 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700538 if (!style) {
539 style = &GrStyle::SimpleFill();
540 }
joshualitt1de610a2016-01-06 08:26:09 -0800541 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700542 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700543 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400544 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700545
bsalomon6663acf2016-05-10 09:14:17 -0700546 // Path effects should've been devolved to a path in SkGpuDevice
547 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700548
Robert Phillips72152832017-01-25 17:31:35 -0500549 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700550
bsalomon6663acf2016-05-10 09:14:17 -0700551 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700552 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
553
554 if (!fContext->caps()->useDrawInsteadOfClear()) {
555 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
556 // checking cases where the RT is fully inside a stroke.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400557 SkRect rtRect = fRenderTargetProxy->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700558 // Does the clip contain the entire RT?
559 if (clip.quickContains(rtRect)) {
560 SkMatrix invM;
561 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700562 return;
563 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700564 // Does the rect bound the RT?
565 SkPoint srcSpaceRTQuad[4];
566 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
567 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
568 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
569 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
570 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
571 // Will it blend?
572 GrColor clearColor;
573 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700574 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700575 return;
576 }
577 }
robertphillipsea461502015-05-26 11:38:03 -0700578 }
579 }
robertphillips44302392016-07-08 14:43:03 -0700580
Brian Salomon82f44312017-01-11 13:42:54 -0500581 if (this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, nullptr)) {
robertphillips44302392016-07-08 14:43:03 -0700582 return;
583 }
bsalomona7d85ba2016-07-06 11:54:59 -0700584 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
585 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
586 if ((!rect.width() || !rect.height()) &&
587 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
588 SkScalar r = stroke.getWidth() / 2;
589 // TODO: Move these stroke->fill fallbacks to GrShape?
590 switch (stroke.getJoin()) {
591 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500592 this->drawRect(
593 clip, std::move(paint), aa, viewMatrix,
594 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
595 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700596 return;
597 case SkPaint::kRound_Join:
598 // Raster draws nothing when both dimensions are empty.
599 if (rect.width() || rect.height()){
600 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500601 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
602 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700603 return;
604 }
605 case SkPaint::kBevel_Join:
606 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500607 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700608 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
609 &GrStyle::SimpleFill());
610 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500611 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700612 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
613 &GrStyle::SimpleFill());
614 }
615 return;
616 }
617 }
robertphillips44302392016-07-08 14:43:03 -0700618
robertphillips44302392016-07-08 14:43:03 -0700619 bool snapToPixelCenters = false;
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400620 std::unique_ptr<GrLegacyMeshDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700621
robertphillips391395d2016-03-02 09:26:36 -0800622 GrColor color = paint.getColor();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500623 GrAAType aaType = this->decideAAType(aa);
624 if (GrAAType::kCoverage == aaType) {
cdaltonbb539482016-01-04 09:48:25 -0800625 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
626 if (viewMatrix.rectStaysRect()) {
Brian Salomon6a639042016-12-14 11:08:17 -0500627 op = GrRectOpFactory::MakeAAStroke(color, viewMatrix, rect, stroke);
cdaltonbb539482016-01-04 09:48:25 -0800628 }
robertphillipsea461502015-05-26 11:38:03 -0700629 } else {
robertphillips391395d2016-03-02 09:26:36 -0800630 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700631 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800632 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700633 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400634 !fRenderTargetProxy->isUnifiedMultisampled();
Brian Salomon6a639042016-12-14 11:08:17 -0500635 op = GrRectOpFactory::MakeNonAAStroke(color, viewMatrix, rect, stroke,
636 snapToPixelCenters);
robertphillips391395d2016-03-02 09:26:36 -0800637 }
robertphillips4bc31812016-03-01 12:22:49 -0800638
Brian Salomon42521e82016-12-07 16:44:58 -0500639 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500640 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon189098e72017-01-19 09:55:19 -0500641 pipelineBuilder.setSnapVerticesToPixelCenters(snapToPixelCenters);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400642 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700643 return;
robertphillips4bc31812016-03-01 12:22:49 -0800644 }
robertphillips4bc31812016-03-01 12:22:49 -0800645 }
halcanary9d524f22016-03-29 09:03:52 -0700646
robertphillips4bc31812016-03-01 12:22:49 -0800647 SkPath path;
648 path.setIsVolatile(true);
649 path.addRect(rect);
Brian Salomon82f44312017-01-11 13:42:54 -0500650 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700651}
652
Robert Phillipsec2249f2016-11-09 08:54:35 -0500653int GrRenderTargetContextPriv::maxWindowRectangles() const {
654 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
655 *fRenderTargetContext->fContext->caps());
656}
657
Brian Osman11052242016-10-27 14:47:55 -0400658void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700659 ASSERT_SINGLE_OWNER_PRIV
660 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400661 SkDEBUGCODE(fRenderTargetContext->validate();)
662 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
663 "GrRenderTargetContextPriv::clearStencilClip");
robertphillips976f5f02016-06-03 10:59:20 -0700664
Robert Phillips72152832017-01-25 17:31:35 -0500665 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Salomon69868af2016-12-22 15:42:51 -0500666 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipse60ad622016-11-17 10:22:48 -0500667 if (!fRenderTargetContext->accessRenderTarget()) {
668 return;
669 }
Brian Osman11052242016-10-27 14:47:55 -0400670 fRenderTargetContext->getOpList()->clearStencilClip(clip, insideStencilMask,
Brian Salomon69868af2016-12-22 15:42:51 -0500671 fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700672}
673
Brian Osman11052242016-10-27 14:47:55 -0400674void GrRenderTargetContextPriv::stencilPath(const GrClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500675 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400676 const SkMatrix& viewMatrix,
677 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500678 ASSERT_SINGLE_OWNER_PRIV
679 RETURN_IF_ABANDONED_PRIV
680 SkDEBUGCODE(fRenderTargetContext->validate();)
681 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
682 "GrRenderTargetContext::stencilPath");
683
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500684 SkASSERT(aaType != GrAAType::kCoverage);
Brian Salomon467921e2017-03-06 16:17:12 -0500685
686 bool useHWAA = GrAATypeIsHW(aaType);
687 // TODO: extract portions of checkDraw that are relevant to path stenciling.
688 SkASSERT(path);
689 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
690
691 // FIXME: Use path bounds instead of this WAR once
692 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
693 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
694
695 // Setup clip
Brian Salomon97180af2017-03-14 13:42:58 -0400696 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -0500697 if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true,
Brian Salomon97180af2017-03-14 13:42:58 -0400698 &appliedClip, &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500699 return;
700 }
701
702 // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
703 // attempt this in a situation that would require coverage AA.
704 SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
705
706 GrRenderTarget* rt = fRenderTargetContext->accessRenderTarget();
707 if (!rt) {
708 return;
709 }
710 GrStencilAttachment* stencilAttachment =
711 fRenderTargetContext->fContext->resourceProvider()->attachStencilAttachment(rt);
712 if (!stencilAttachment) {
713 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
714 return;
715 }
716
717 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
718 useHWAA,
719 path->getFillType(),
720 appliedClip.hasStencilClip(),
721 stencilAttachment->bits(),
722 appliedClip.scissorState(),
723 fRenderTargetContext->accessRenderTarget(),
724 path);
Brian Salomon97180af2017-03-14 13:42:58 -0400725 op->setClippedBounds(bounds);
Brian Salomon467921e2017-03-06 16:17:12 -0500726 fRenderTargetContext->getOpList()->recordOp(std::move(op), fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700727}
728
Brian Osman11052242016-10-27 14:47:55 -0400729void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
730 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500731 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400732 const SkMatrix& viewMatrix,
733 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700734 ASSERT_SINGLE_OWNER_PRIV
735 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400736 SkDEBUGCODE(fRenderTargetContext->validate();)
737 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
738 "GrRenderTargetContext::stencilRect");
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500739 SkASSERT(GrAAType::kCoverage != aaType);
Robert Phillips72152832017-01-25 17:31:35 -0500740 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700741
742 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500743 paint.setXPFactory(GrDisableColorXPFactory::Get());
robertphillips976f5f02016-06-03 10:59:20 -0700744
Brian Salomon82f44312017-01-11 13:42:54 -0500745 fRenderTargetContext->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, rect, nullptr,
746 nullptr, ss, aaType);
robertphillips976f5f02016-06-03 10:59:20 -0700747}
748
Brian Osman11052242016-10-27 14:47:55 -0400749bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip,
750 const GrUserStencilSettings* ss,
751 SkRegion::Op op,
752 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500753 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400754 const SkMatrix& viewMatrix,
755 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800756 ASSERT_SINGLE_OWNER_PRIV
757 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400758 SkDEBUGCODE(fRenderTargetContext->validate();)
759 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
760 "GrRenderTargetContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800761
Robert Phillips72152832017-01-25 17:31:35 -0500762 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800763
764 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800765 paint.setCoverageSetOpXPFactory(op, invert);
766
Brian Salomon82f44312017-01-11 13:42:54 -0500767 if (fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800768 return true;
769 }
robertphillips391395d2016-03-02 09:26:36 -0800770 SkPath path;
771 path.setIsVolatile(true);
772 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500773 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800774}
775
Brian Osman11052242016-10-27 14:47:55 -0400776void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500777 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500778 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400779 const SkMatrix& viewMatrix,
780 const SkRect& rectToDraw,
781 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800782 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700783 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700784 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400785 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700786
csmartdalton97f6cd52016-07-13 13:37:08 -0700787 SkRect croppedRect = rectToDraw;
788 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700789 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
790 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700791 return;
792 }
793
Robert Phillips72152832017-01-25 17:31:35 -0500794 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700795
csmartdaltone0d36292016-07-29 08:14:20 -0700796 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400797 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400798 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
799 croppedLocalRect, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500800 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400801 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700802 return;
803 }
804 }
805
Brian Salomon54d212e2017-03-21 14:22:38 -0400806 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500807 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500808 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect,
809 &croppedLocalRect, nullptr, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700810 return;
joshualitt04194f32016-01-13 10:08:27 -0800811 }
bsalomonbb243832016-07-22 07:10:19 -0700812
csmartdaltonfc49d562016-07-26 17:05:47 -0700813 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400814 std::unique_ptr<GrLegacyMeshDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(
Brian Salomonf8334782017-01-03 09:42:58 -0500815 paint.getColor(), viewMatrix, croppedRect, croppedLocalRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500816 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400817 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700818 return;
819 }
820
821 SkMatrix viewAndUnLocalMatrix;
822 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
823 SkDebugf("fillRectToRect called with empty local matrix.\n");
824 return;
825 }
826 viewAndUnLocalMatrix.postConcat(viewMatrix);
827
828 SkPath path;
829 path.setIsVolatile(true);
830 path.addRect(localRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500831 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700832}
833
Brian Osman11052242016-10-27 14:47:55 -0400834void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500835 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500836 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400837 const SkMatrix& viewMatrix,
838 const SkRect& rectToDraw,
839 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800840 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700841 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700842 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400843 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700844
csmartdalton97f6cd52016-07-13 13:37:08 -0700845 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700846 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700847 return;
848 }
849
Robert Phillips72152832017-01-25 17:31:35 -0500850 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700851
csmartdaltone0d36292016-07-29 08:14:20 -0700852 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400853 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400854 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
855 localMatrix, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500856 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400857 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700858 return;
859 }
860 }
861
Brian Salomon54d212e2017-03-21 14:22:38 -0400862 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500863 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500864 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr,
865 &localMatrix, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700866 return;
bsalomonc55271f2015-11-09 11:55:57 -0800867 }
robertphillips4bc31812016-03-01 12:22:49 -0800868
csmartdaltonfc49d562016-07-26 17:05:47 -0700869 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400870 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -0500871 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500872 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400873 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700874 return;
875 }
876
877 SkMatrix viewAndUnLocalMatrix;
878 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
879 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
880 return;
881 }
882 viewAndUnLocalMatrix.postConcat(viewMatrix);
883
884 SkPath path;
885 path.setIsVolatile(true);
886 path.addRect(rectToDraw);
887 path.transform(localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -0500888 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700889}
890
Brian Osman11052242016-10-27 14:47:55 -0400891void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500892 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400893 const SkMatrix& viewMatrix,
894 GrPrimitiveType primitiveType,
895 int vertexCount,
896 const SkPoint positions[],
897 const SkPoint texCoords[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500898 const uint32_t colors[],
Brian Osman11052242016-10-27 14:47:55 -0400899 const uint16_t indices[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500900 int indexCount,
901 ColorArrayType colorArrayType) {
joshualitt1de610a2016-01-06 08:26:09 -0800902 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700903 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700904 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400905 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700906
Robert Phillips72152832017-01-25 17:31:35 -0500907 AutoCheckFlush acf(this->drawingManager());
robertphillips2e1e51f2015-10-15 08:01:48 -0700908
robertphillipsea461502015-05-26 11:38:03 -0700909 // TODO clients should give us bounds
910 SkRect bounds;
911 if (!bounds.setBoundsCheck(positions, vertexCount)) {
912 SkDebugf("drawVertices call empty bounds\n");
913 return;
914 }
915
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400916 std::unique_ptr<GrLegacyMeshDrawOp> op = GrDrawVerticesOp::Make(
Brian Salomon3de0aee2017-01-29 09:34:17 -0500917 paint.getColor(), primitiveType, viewMatrix, positions, vertexCount, indices,
918 indexCount, colors, texCoords, bounds, colorArrayType);
Brian Salomon199fb872017-02-06 09:41:10 -0500919 if (!op) {
920 return;
921 }
922 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400923 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
Brian Salomon199fb872017-02-06 09:41:10 -0500924}
robertphillipsea461502015-05-26 11:38:03 -0700925
Brian Salomon199fb872017-02-06 09:41:10 -0500926void GrRenderTargetContext::drawVertices(const GrClip& clip,
927 GrPaint&& paint,
928 const SkMatrix& viewMatrix,
Mike Reed5fa66452017-03-16 09:06:34 -0400929 sk_sp<SkVertices> vertices) {
Brian Salomon199fb872017-02-06 09:41:10 -0500930 ASSERT_SINGLE_OWNER
931 RETURN_IF_ABANDONED
932 SkDEBUGCODE(this->validate();)
933 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
934
935 AutoCheckFlush acf(this->drawingManager());
936
937 SkASSERT(vertices);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400938 std::unique_ptr<GrLegacyMeshDrawOp> op =
Mike Reed5fa66452017-03-16 09:06:34 -0400939 GrDrawVerticesOp::Make(paint.getColor(), std::move(vertices), viewMatrix);
Brian Salomon199fb872017-02-06 09:41:10 -0500940 if (!op) {
941 return;
942 }
Brian Salomon82f44312017-01-11 13:42:54 -0500943 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400944 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700945}
946
947///////////////////////////////////////////////////////////////////////////////
948
Brian Osman11052242016-10-27 14:47:55 -0400949void GrRenderTargetContext::drawAtlas(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500950 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400951 const SkMatrix& viewMatrix,
952 int spriteCount,
953 const SkRSXform xform[],
954 const SkRect texRect[],
955 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800956 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700957 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700958 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400959 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700960
Robert Phillips72152832017-01-25 17:31:35 -0500961 AutoCheckFlush acf(this->drawingManager());
halcanary9d524f22016-03-29 09:03:52 -0700962
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400963 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomonfc527d22016-12-14 21:07:01 -0500964 GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
Brian Salomon82f44312017-01-11 13:42:54 -0500965 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400966 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -0700967}
968
969///////////////////////////////////////////////////////////////////////////////
970
Brian Osman11052242016-10-27 14:47:55 -0400971void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500972 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500973 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400974 const SkMatrix& viewMatrix,
975 const SkRRect& rrect,
976 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800977 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700978 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700979 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400980 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700981 if (rrect.isEmpty()) {
982 return;
983 }
984
bsalomon7f0d9f32016-08-15 14:49:10 -0700985 GrNoClip noclip;
986 const GrClip* clip = &origClip;
987#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
988 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -0500989 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -0700990 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
991 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
992 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
993 SkRRect devRRect;
994 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
995 clip = &noclip;
996 }
997#endif
bsalomon6663acf2016-05-10 09:14:17 -0700998 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700999
Robert Phillips72152832017-01-25 17:31:35 -05001000 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -07001001 const SkStrokeRec stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -07001002
csmartdaltone0d36292016-07-29 08:14:20 -07001003 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1004 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001005 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001006 std::unique_ptr<GrDrawOp> op(
1007 ir->recordRRect(rrect, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001008 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001009 this->addDrawOp(*clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001010 return;
1011 }
1012 }
1013
Brian Salomon54d212e2017-03-21 14:22:38 -04001014 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001015 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001016 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001017 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -05001018 GrOvalOpFactory::MakeRRectOp(paint.getColor(),
1019 paint.usesDistanceVectorField(),
1020 viewMatrix,
1021 rrect,
1022 stroke,
1023 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001024 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001025 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001026 this->addLegacyMeshDrawOp(pipelineBuilder, *clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001027 return;
1028 }
robertphillipsea461502015-05-26 11:38:03 -07001029 }
robertphillipsb56f9272016-02-25 11:03:52 -08001030
1031 SkPath path;
1032 path.setIsVolatile(true);
1033 path.addRRect(rrect);
Brian Salomon82f44312017-01-11 13:42:54 -05001034 this->internalDrawPath(*clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001035}
1036
Jim Van Verthc5903412016-11-17 15:27:09 -05001037///////////////////////////////////////////////////////////////////////////////
1038
1039void GrRenderTargetContext::drawShadowRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001040 GrPaint&& paint,
Jim Van Verthc5903412016-11-17 15:27:09 -05001041 const SkMatrix& viewMatrix,
1042 const SkRRect& rrect,
1043 SkScalar blurRadius,
1044 const GrStyle& style) {
1045 ASSERT_SINGLE_OWNER
1046 RETURN_IF_ABANDONED
1047 SkDEBUGCODE(this->validate();)
1048 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect");
1049 if (rrect.isEmpty()) {
1050 return;
1051 }
1052
1053 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1054
Robert Phillips72152832017-01-25 17:31:35 -05001055 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001056 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001057 // TODO: add instancing support?
Jim Van Verthc5903412016-11-17 15:27:09 -05001058
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001059 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001060 std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(
1061 paint.getColor(), viewMatrix, rrect, blurRadius, stroke, shaderCaps);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001062 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001063 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001064 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001065 return;
Jim Van Verthc5903412016-11-17 15:27:09 -05001066 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001067}
1068
1069///////////////////////////////////////////////////////////////////////////////
1070
Brian Osman11052242016-10-27 14:47:55 -04001071bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001072 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001073 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001074 const SkMatrix& viewMatrix,
1075 const SkRRect& origOuter,
1076 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001077 SkASSERT(!origInner.isEmpty());
1078 SkASSERT(!origOuter.isEmpty());
1079
csmartdaltone0d36292016-07-29 08:14:20 -07001080 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001081 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001082 std::unique_ptr<GrDrawOp> op(ir->recordDRRect(
1083 origOuter, origInner, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001084 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001085 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001086 return true;
1087 }
1088 }
1089
Brian Salomon54d212e2017-03-21 14:22:38 -04001090 GrAAType aaType = this->decideAAType(aa);
robertphillips00095892016-02-29 13:50:40 -08001091
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001092 GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
1093 if (GrAAType::kCoverage == aaType) {
1094 innerEdgeType = kInverseFillAA_GrProcessorEdgeType;
1095 outerEdgeType = kFillAA_GrProcessorEdgeType;
1096 } else {
1097 innerEdgeType = kInverseFillBW_GrProcessorEdgeType;
1098 outerEdgeType = kFillBW_GrProcessorEdgeType;
1099 }
robertphillips00095892016-02-29 13:50:40 -08001100
1101 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1102 SkMatrix inverseVM;
1103 if (!viewMatrix.isIdentity()) {
1104 if (!origInner.transform(viewMatrix, inner.writable())) {
1105 return false;
1106 }
1107 if (!origOuter.transform(viewMatrix, outer.writable())) {
1108 return false;
1109 }
1110 if (!viewMatrix.invert(&inverseVM)) {
1111 return false;
1112 }
1113 } else {
1114 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001115 }
robertphillips00095892016-02-29 13:50:40 -08001116
robertphillips00095892016-02-29 13:50:40 -08001117 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -07001118 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -08001119 if (!innerEffect) {
1120 return false;
1121 }
1122
bungeman06ca8ec2016-06-09 08:01:03 -07001123 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -08001124 if (!outerEffect) {
1125 return false;
1126 }
1127
Brian Salomon82f44312017-01-11 13:42:54 -05001128 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1129 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001130
1131 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001132 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001133 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1134 }
halcanary9d524f22016-03-29 09:03:52 -07001135
Brian Salomon82f44312017-01-11 13:42:54 -05001136 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1137 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001138 return true;
1139}
1140
Brian Osman11052242016-10-27 14:47:55 -04001141void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001142 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001143 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001144 const SkMatrix& viewMatrix,
1145 const SkRRect& outer,
1146 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001147 ASSERT_SINGLE_OWNER
1148 RETURN_IF_ABANDONED
1149 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001150 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
robertphillips00095892016-02-29 13:50:40 -08001151
1152 SkASSERT(!outer.isEmpty());
1153 SkASSERT(!inner.isEmpty());
1154
Robert Phillips72152832017-01-25 17:31:35 -05001155 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001156
Brian Salomon82f44312017-01-11 13:42:54 -05001157 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001158 return;
1159 }
1160
1161 SkPath path;
1162 path.setIsVolatile(true);
1163 path.addRRect(inner);
1164 path.addRRect(outer);
1165 path.setFillType(SkPath::kEvenOdd_FillType);
1166
Brian Salomon82f44312017-01-11 13:42:54 -05001167 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -08001168}
1169
robertphillipsea461502015-05-26 11:38:03 -07001170///////////////////////////////////////////////////////////////////////////////
1171
msarettcc319b92016-08-25 18:07:18 -07001172static inline bool is_int(float x) {
1173 return x == (float) sk_float_round2int(x);
1174}
1175
Brian Osman11052242016-10-27 14:47:55 -04001176void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001177 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001178 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001179 const SkMatrix& viewMatrix,
1180 const SkRegion& region,
1181 const GrStyle& style) {
msarettcc319b92016-08-25 18:07:18 -07001182 ASSERT_SINGLE_OWNER
1183 RETURN_IF_ABANDONED
1184 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001185 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
msarettcc319b92016-08-25 18:07:18 -07001186
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001187 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001188 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001189 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001190 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1191 is_int(viewMatrix.getTranslateX()) &&
1192 is_int(viewMatrix.getTranslateY())) {
1193 aa = GrAA::kNo;
1194 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001195 }
msarettcc319b92016-08-25 18:07:18 -07001196 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001197 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001198 SkPath path;
1199 region.getBoundaryPath(&path);
Brian Salomon82f44312017-01-11 13:42:54 -05001200 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001201 }
1202
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001203 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
Brian Salomon82f44312017-01-11 13:42:54 -05001204 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001205 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001206}
1207
Brian Osman11052242016-10-27 14:47:55 -04001208void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001209 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001210 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001211 const SkMatrix& viewMatrix,
1212 const SkRect& oval,
1213 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001214 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001215 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001216 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001217 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001218
robertphillipsea461502015-05-26 11:38:03 -07001219 if (oval.isEmpty()) {
1220 return;
1221 }
1222
bsalomon6663acf2016-05-10 09:14:17 -07001223 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001224
Robert Phillips72152832017-01-25 17:31:35 -05001225 AutoCheckFlush acf(this->drawingManager());
bsalomon6663acf2016-05-10 09:14:17 -07001226 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -07001227
csmartdaltone0d36292016-07-29 08:14:20 -07001228 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1229 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001230 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001231 std::unique_ptr<GrDrawOp> op(
1232 ir->recordOval(oval, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001233 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001234 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001235 return;
1236 }
1237 }
1238
Brian Salomon54d212e2017-03-21 14:22:38 -04001239 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001240 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001241 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001242 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon289e3d82016-12-14 15:52:56 -05001243 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001244 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001245 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001246 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001247 return;
1248 }
robertphillipsea461502015-05-26 11:38:03 -07001249 }
robertphillipsb56f9272016-02-25 11:03:52 -08001250
1251 SkPath path;
1252 path.setIsVolatile(true);
1253 path.addOval(oval);
Brian Salomon82f44312017-01-11 13:42:54 -05001254 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001255}
1256
Brian Osman11052242016-10-27 14:47:55 -04001257void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001258 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001259 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001260 const SkMatrix& viewMatrix,
1261 const SkRect& oval,
1262 SkScalar startAngle,
1263 SkScalar sweepAngle,
1264 bool useCenter,
1265 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001266 ASSERT_SINGLE_OWNER
1267 RETURN_IF_ABANDONED
1268 SkDEBUGCODE(this->validate();)
1269 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawArc");
1270
1271 AutoCheckFlush acf(this->drawingManager());
1272
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001273 GrAAType aaType = this->decideAAType(aa);
1274 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001275 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001276 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
1277 viewMatrix,
1278 oval,
1279 startAngle,
1280 sweepAngle,
1281 useCenter,
1282 style,
1283 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001284 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001285 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001286 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001287 return;
1288 }
1289 }
1290 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001291 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1292 style.isSimpleFill());
Brian Salomon82f44312017-01-11 13:42:54 -05001293 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001294}
1295
Brian Osman11052242016-10-27 14:47:55 -04001296void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001297 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001298 const SkMatrix& viewMatrix,
1299 int imageWidth,
1300 int imageHeight,
1301 std::unique_ptr<SkLatticeIter> iter,
1302 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001303 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001304 RETURN_IF_ABANDONED
1305 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001306 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001307
Robert Phillips72152832017-01-25 17:31:35 -05001308 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001309
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001310 std::unique_ptr<GrLegacyMeshDrawOp> op = GrLatticeOp::MakeNonAA(
Brian Salomon649a3412017-03-09 13:50:43 -05001311 paint.getColor(), viewMatrix, imageWidth, imageHeight, std::move(iter), dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001312
Brian Salomon82f44312017-01-11 13:42:54 -05001313 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001314 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001315}
1316
Brian Osman11052242016-10-27 14:47:55 -04001317void GrRenderTargetContext::prepareForExternalIO() {
robertphillips8c523e02016-07-26 07:41:00 -07001318 ASSERT_SINGLE_OWNER
1319 RETURN_IF_ABANDONED
1320 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001321 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
robertphillips8c523e02016-07-26 07:41:00 -07001322
Robert Phillips7ee385e2017-03-30 08:02:11 -04001323 this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get());
robertphillips8c523e02016-07-26 07:41:00 -07001324}
joshualitt33a5fce2015-11-18 13:28:51 -08001325
Brian Osman11052242016-10-27 14:47:55 -04001326void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001327 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001328 const SkMatrix& viewMatrix,
1329 const SkRect& rect,
1330 const SkRect* localRect,
1331 const SkMatrix* localMatrix,
1332 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001333 GrAAType hwOrNoneAAType) {
1334 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
1335 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001336 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill(
1337 paint.getColor(), viewMatrix, rect, localRect, localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -05001338 GrPipelineBuilder pipelineBuilder(std::move(paint), hwOrNoneAAType);
robertphillips44302392016-07-08 14:43:03 -07001339 if (ss) {
1340 pipelineBuilder.setUserStencil(ss);
1341 }
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001342 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -07001343}
1344
robertphillipsea461502015-05-26 11:38:03 -07001345// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001346static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001347
1348 if (path.isInverseFillType()) {
1349 return false;
1350 }
1351
1352 // TODO: this restriction could be lifted if we were willing to apply
1353 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001354 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001355 return false;
1356 }
1357
1358 SkPath::Direction dirs[2];
1359 if (!path.isNestedFillRects(rects, dirs)) {
1360 return false;
1361 }
1362
1363 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1364 // The two rects need to be wound opposite to each other
1365 return false;
1366 }
1367
1368 // Right now, nested rects where the margin is not the same width
1369 // all around do not render correctly
1370 const SkScalar* outer = rects[0].asScalars();
1371 const SkScalar* inner = rects[1].asScalars();
1372
1373 bool allEq = true;
1374
1375 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1376 bool allGoE1 = margin >= SK_Scalar1;
1377
1378 for (int i = 1; i < 4; ++i) {
1379 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1380 if (temp < SK_Scalar1) {
1381 allGoE1 = false;
1382 }
1383 if (!SkScalarNearlyEqual(margin, temp)) {
1384 allEq = false;
1385 }
1386 }
1387
1388 return allEq || allGoE1;
1389}
1390
Brian Osman11052242016-10-27 14:47:55 -04001391void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001392 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001393 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001394 const SkMatrix& viewMatrix,
1395 const SkPath& path,
1396 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001397 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001398 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001399 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001400 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001401
robertphillipsea461502015-05-26 11:38:03 -07001402 if (path.isEmpty()) {
1403 if (path.isInverseFillType()) {
Brian Salomon82f44312017-01-11 13:42:54 -05001404 this->drawPaint(clip, std::move(paint), viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001405 }
1406 return;
1407 }
1408
Robert Phillips72152832017-01-25 17:31:35 -05001409 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001410
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001411 GrAAType aaType = this->decideAAType(aa);
1412 if (GrAAType::kCoverage == aaType && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001413 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001414 // Concave AA paths are expensive - try to avoid them for special cases
1415 SkRect rects[2];
1416
bsalomon6663acf2016-05-10 09:14:17 -07001417 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001418 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -05001419 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001420 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001421 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001422 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
bsalomon40ef4852016-05-02 13:22:13 -07001423 }
robertphillipsea461502015-05-26 11:38:03 -07001424 return;
1425 }
1426 }
1427 SkRect ovalRect;
1428 bool isOval = path.isOval(&ovalRect);
1429
1430 if (isOval && !path.isInverseFillType()) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001431 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001432 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeOvalOp(
Brian Salomon289e3d82016-12-14 15:52:56 -05001433 paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001434 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001435 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001436 this->addLegacyMeshDrawOp(pipelineBuilder, clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001437 return;
1438 }
1439 }
1440 }
robertphillips4bc31812016-03-01 12:22:49 -08001441
1442 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1443 // Scratch textures can be recycled after they are returned to the texture
1444 // cache. This presents a potential hazard for buffered drawing. However,
1445 // the writePixels that uploads to the scratch will perform a flush so we're
1446 // OK.
Brian Salomon82f44312017-01-11 13:42:54 -05001447 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001448}
1449
Brian Osman11052242016-10-27 14:47:55 -04001450bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip,
1451 const GrUserStencilSettings* ss,
1452 SkRegion::Op op,
1453 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001454 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001455 const SkMatrix& viewMatrix,
1456 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001457 ASSERT_SINGLE_OWNER_PRIV
1458 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001459 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001460 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
1461 "GrRenderTargetContextPriv::drawAndStencilPath");
robertphillips391395d2016-03-02 09:26:36 -08001462
1463 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001464 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001465 SkRect::MakeIWH(fRenderTargetContext->width(),
1466 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001467 return true;
1468 }
1469
Robert Phillips72152832017-01-25 17:31:35 -05001470 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001471
1472 // An Assumption here is that path renderer would use some form of tweaking
1473 // the src color (either the input alpha or in the frag shader) to implement
1474 // aa. If we have some future driver-mojo path AA that can do the right
1475 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001476 GrAAType aaType = fRenderTargetContext->decideAAType(aa);
robertphillips976f5f02016-06-03 10:59:20 -07001477 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001478
bsalomon8acedde2016-06-24 10:42:16 -07001479 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001480 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Osman11052242016-10-27 14:47:55 -04001481 canDrawArgs.fShaderCaps =
Robert Phillips72152832017-01-25 17:31:35 -05001482 fRenderTargetContext->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips391395d2016-03-02 09:26:36 -08001483 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001484 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001485 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001486 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001487
1488 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001489 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001490 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001491 if (!pr) {
1492 return false;
1493 }
1494
1495 GrPaint paint;
1496 paint.setCoverageSetOpXPFactory(op, invert);
1497
Brian Salomon82f44312017-01-11 13:42:54 -05001498 GrPathRenderer::DrawPathArgs args{
Robert Phillips256c37b2017-03-01 14:32:46 -05001499 fRenderTargetContext->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001500 std::move(paint),
1501 ss,
1502 fRenderTargetContext,
1503 &clip,
1504 &viewMatrix,
1505 &shape,
1506 aaType,
1507 fRenderTargetContext->isGammaCorrect()};
robertphillips391395d2016-03-02 09:26:36 -08001508 pr->drawPath(args);
1509 return true;
1510}
1511
Brian Osman11052242016-10-27 14:47:55 -04001512SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001513 ASSERT_SINGLE_OWNER_PRIV
1514
Brian Osman11052242016-10-27 14:47:55 -04001515 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001516 return SkBudgeted::kNo;
1517 }
1518
Brian Osman11052242016-10-27 14:47:55 -04001519 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001520
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001521 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001522}
1523
Brian Osman11052242016-10-27 14:47:55 -04001524void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001525 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001526 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001527 const SkMatrix& viewMatrix,
1528 const SkPath& path,
1529 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001530 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001531 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001532 SkASSERT(!path.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001533 GrShape shape;
robertphillipsea461502015-05-26 11:38:03 -07001534
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001535 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true);
1536 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) {
1537 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and
1538 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1539 // smoother hairlines than MSAA.
1540 aaType = GrAAType::kCoverage;
bsalomon0a0f67e2016-06-28 11:56:42 -07001541 }
robertphillips68737822015-10-29 12:12:21 -07001542 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Robert Phillips72152832017-01-25 17:31:35 -05001543 canDrawArgs.fShaderCaps = this->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips68737822015-10-29 12:12:21 -07001544 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001545 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001546 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001547
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001548 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001549 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001550 do {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001551 shape = GrShape(path, style);
bsalomon8acedde2016-06-24 10:42:16 -07001552 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001553 return;
1554 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001555
1556 canDrawArgs.fAAType = aaType;
1557
1558 // Try a 1st time without applying any of the style to the geometry (and barring sw)
Robert Phillips72152832017-01-25 17:31:35 -05001559 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001560 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1561
1562 if (!pr && shape.style().pathEffect()) {
1563 // It didn't work above, so try again with the path effect applied.
1564 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
bsalomon8acedde2016-06-24 10:42:16 -07001565 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001566 return;
1567 }
Robert Phillips72152832017-01-25 17:31:35 -05001568 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
bsalomon6663acf2016-05-10 09:14:17 -07001569 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001570 if (!pr) {
1571 if (shape.style().applies()) {
1572 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1573 if (shape.isEmpty()) {
1574 return;
1575 }
1576 }
1577 // This time, allow SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001578 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001579 }
Brian Salomon0abc8b42016-12-13 10:22:54 -05001580 if (!pr && GrAATypeIsHW(aaType)) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001581 // There are exceptional cases where we may wind up falling back to coverage based AA
1582 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions).
1583 aaType = GrAAType::kCoverage;
1584 } else {
1585 break;
1586 }
1587 } while(true);
robertphillipsea461502015-05-26 11:38:03 -07001588
bsalomon8acedde2016-06-24 10:42:16 -07001589 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001590#ifdef SK_DEBUG
1591 SkDebugf("Unable to find path renderer compatible with path.\n");
1592#endif
1593 return;
1594 }
1595
Robert Phillips256c37b2017-03-01 14:32:46 -05001596 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001597 std::move(paint),
1598 &GrUserStencilSettings::kUnused,
1599 this,
1600 &clip,
1601 &viewMatrix,
1602 &shape,
1603 aaType,
1604 this->isGammaCorrect()};
bsalomon0aff2fa2015-07-31 06:48:27 -07001605 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001606}
1607
Brian Salomon467921e2017-03-06 16:17:12 -05001608static void op_bounds(SkRect* bounds, const GrOp* op) {
1609 *bounds = op->bounds();
1610 if (op->hasZeroArea()) {
1611 if (op->hasAABloat()) {
1612 bounds->outset(0.5f, 0.5f);
1613 } else {
1614 // We don't know which way the particular GPU will snap lines or points at integer
1615 // coords. So we ensure that the bounds is large enough for either snap.
1616 SkRect before = *bounds;
1617 bounds->roundOut(bounds);
1618 if (bounds->fLeft == before.fLeft) {
1619 bounds->fLeft -= 1;
1620 }
1621 if (bounds->fTop == before.fTop) {
1622 bounds->fTop -= 1;
1623 }
1624 if (bounds->fRight == before.fRight) {
1625 bounds->fRight += 1;
1626 }
1627 if (bounds->fBottom == before.fBottom) {
1628 bounds->fBottom += 1;
1629 }
1630 }
1631 }
1632}
1633
Brian Salomon54d212e2017-03-21 14:22:38 -04001634uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001635 ASSERT_SINGLE_OWNER
Robert Phillipsc0138922017-03-08 11:50:55 -05001636 if (this->drawingManager()->wasAbandoned()) {
1637 return SK_InvalidUniqueID;
1638 }
robertphillips2e1e51f2015-10-15 08:01:48 -07001639 SkDEBUGCODE(this->validate();)
Brian Salomon42521e82016-12-07 16:44:58 -05001640 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
robertphillips2d70dcb2015-10-06 07:38:23 -07001641
Brian Salomon467921e2017-03-06 16:17:12 -05001642 // Setup clip
1643 SkRect bounds;
1644 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04001645 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04001646 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1647 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1648 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1649 &bounds)) {
1650 return SK_InvalidUniqueID;
1651 }
1652
1653 // This forces instantiation of the render target.
1654 GrRenderTarget* rt = this->accessRenderTarget();
1655 if (!rt) {
1656 return SK_InvalidUniqueID;
1657 }
1658
1659 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1660 appliedClip.hasStencilClip()) {
1661 if (!fContext->resourceProvider()->attachStencilAttachment(rt)) {
1662 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
1663 return SK_InvalidUniqueID;
1664 }
1665 }
1666
1667 GrXferProcessor::DstTexture dstTexture;
1668 if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
1669 this->setupDstTexture(rt, clip, op->bounds(), &dstTexture);
1670 if (!dstTexture.texture()) {
1671 return SK_InvalidUniqueID;
1672 }
1673 }
1674
1675 op->setClippedBounds(bounds);
1676 return this->getOpList()->addOp(std::move(op), this, std::move(appliedClip), dstTexture);
1677}
1678
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001679uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(const GrPipelineBuilder& pipelineBuilder,
1680 const GrClip& clip,
1681 std::unique_ptr<GrLegacyMeshDrawOp> op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001682 ASSERT_SINGLE_OWNER
1683 if (this->drawingManager()->wasAbandoned()) {
1684 return SK_InvalidUniqueID;
1685 }
1686 SkDEBUGCODE(this->validate();)
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001687 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addLegacyMeshDrawOp");
Brian Salomon54d212e2017-03-21 14:22:38 -04001688
1689 // Setup clip
1690 SkRect bounds;
1691 op_bounds(&bounds, op.get());
1692 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -05001693 if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
Brian Salomon97180af2017-03-14 13:42:58 -04001694 pipelineBuilder.hasUserStencilSettings(), &appliedClip, &bounds)) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001695 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001696 }
1697
1698 // This forces instantiation of the render target. Pipeline creation is moving to flush time
1699 // by which point instantiation must have occurred anyway.
1700 GrRenderTarget* rt = this->accessRenderTarget();
1701 if (!rt) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001702 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001703 }
1704
1705 GrResourceProvider* resourceProvider = fContext->resourceProvider();
1706 if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
1707 if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
1708 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
Robert Phillipsc0138922017-03-08 11:50:55 -05001709 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001710 }
1711 }
1712
Brian Salomona811b122017-03-30 08:21:32 -04001713 GrProcessorSet::Analysis analysis;
Brian Salomon8d2f90b2017-03-13 09:11:58 -04001714 op->analyzeProcessors(&analysis, pipelineBuilder.processors(), &appliedClip, *this->caps());
Brian Salomon467921e2017-03-06 16:17:12 -05001715
1716 GrPipeline::InitArgs args;
1717 pipelineBuilder.getPipelineInitArgs(&args);
1718 args.fAppliedClip = &appliedClip;
1719 args.fRenderTarget = rt;
1720 args.fCaps = this->caps();
1721 args.fAnalysis = &analysis;
Brian Salomon1c6025c2017-03-29 14:25:04 -04001722 args.fInputColor = analysis.outputColor();
1723 args.fInputCoverage = analysis.outputCoverage();
Brian Salomon467921e2017-03-06 16:17:12 -05001724
Brian Salomon31853842017-03-28 16:32:05 -04001725 if (analysis.requiresDstTexture()) {
Brian Salomon467921e2017-03-06 16:17:12 -05001726 this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
1727 if (!args.fDstTexture.texture()) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001728 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001729 }
1730 }
1731 op->initPipeline(args);
1732 // TODO: We need to add pipeline dependencies on textures, etc before recording this op.
Brian Salomon97180af2017-03-14 13:42:58 -04001733 op->setClippedBounds(bounds);
Robert Phillipsc0138922017-03-08 11:50:55 -05001734 return this->getOpList()->addOp(std::move(op), this);
Brian Salomon467921e2017-03-06 16:17:12 -05001735}
1736
1737void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& clip,
1738 const SkRect& opBounds,
1739 GrXferProcessor::DstTexture* dstTexture) {
1740 if (this->caps()->textureBarrierSupport()) {
1741 if (GrTexture* rtTex = rt->asTexture()) {
1742 // The render target is a texture, so we can read from it directly in the shader. The XP
1743 // will be responsible to detect this situation and request a texture barrier.
1744 dstTexture->setTexture(sk_ref_sp(rtTex));
1745 dstTexture->setOffset(0, 0);
1746 return;
1747 }
1748 }
1749
1750 SkIRect copyRect;
1751 clip.getConservativeBounds(rt->width(), rt->height(), &copyRect);
1752
1753 SkIRect drawIBounds;
1754 opBounds.roundOut(&drawIBounds);
Brian Salomon859621f2017-03-16 09:21:54 -04001755 // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
1756 drawIBounds.outset(1, 1);
Mike Kleinec617852017-04-01 01:53:59 +00001757 if (!copyRect.intersect(drawIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001758#ifdef SK_DEBUG
1759 GrCapsDebugf(this->caps(), "Missed an early reject. "
1760 "Bailing on draw from setupDstTexture.\n");
1761#endif
1762 return;
1763 }
1764
1765 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
1766 // have per-sample dst values by making the copy multisampled.
1767 GrSurfaceDesc desc;
Mike Kleinec617852017-04-01 01:53:59 +00001768 if (!this->caps()->initDescForDstCopy(rt, &desc)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001769 desc.fOrigin = kDefault_GrSurfaceOrigin;
1770 desc.fFlags = kRenderTarget_GrSurfaceFlag;
1771 desc.fConfig = rt->config();
1772 }
1773
Mike Kleinec617852017-04-01 01:53:59 +00001774 desc.fWidth = copyRect.width();
1775 desc.fHeight = copyRect.height();
Brian Salomon467921e2017-03-06 16:17:12 -05001776
1777 static const uint32_t kFlags = 0;
Mike Kleinec617852017-04-01 01:53:59 +00001778 sk_sp<GrTexture> copy(fContext->resourceProvider()->createApproxTexture(desc, kFlags));
Brian Salomon467921e2017-03-06 16:17:12 -05001779
1780 if (!copy) {
1781 SkDebugf("Failed to create temporary copy of destination texture.\n");
1782 return;
1783 }
Mike Kleinec617852017-04-01 01:53:59 +00001784 SkIPoint dstPoint = {0, 0};
Brian Salomon467921e2017-03-06 16:17:12 -05001785 this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint);
1786 dstTexture->setTexture(std::move(copy));
Mike Kleinec617852017-04-01 01:53:59 +00001787 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
robertphillips2334fb62015-06-17 05:43:33 -07001788}