blob: e7a9022c0c3b5ce65429ce80bb93a351b754e622 [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"
Robert Phillipse78b7252017-04-06 07:59:41 -040011#include "GrContextPriv.h"
robertphillips77a2e522015-10-17 07:43:27 -070012#include "GrDrawingManager.h"
csmartdalton02fa32c2016-08-19 13:29:27 -070013#include "GrFixedClip.h"
robertphillips714712b2016-08-04 06:20:45 -070014#include "GrGpuResourcePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070015#include "GrPathRenderer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070016#include "GrPipelineBuilder.h"
robertphillips2334fb62015-06-17 05:43:33 -070017#include "GrRenderTarget.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050018#include "GrRenderTargetContextPriv.h"
robertphillips2334fb62015-06-17 05:43:33 -070019#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070020#include "GrResourceProvider.h"
Brian Salomon467921e2017-03-06 16:17:12 -050021#include "GrStencilAttachment.h"
22#include "SkLatticeIter.h"
23#include "SkMatrixPriv.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070024#include "SkSurfacePriv.h"
Brian Salomon467921e2017-03-06 16:17:12 -050025#include "effects/GrRRectEffect.h"
26#include "instanced/InstancedRendering.h"
Brian Salomon89527432016-12-16 09:52:16 -050027#include "ops/GrClearOp.h"
Robert Phillipsb9a02a12017-04-06 11:08:40 -040028#include "ops/GrClearStencilClipOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050029#include "ops/GrDrawOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050030#include "ops/GrDrawAtlasOp.h"
31#include "ops/GrDrawVerticesOp.h"
32#include "ops/GrLatticeOp.h"
33#include "ops/GrOp.h"
34#include "ops/GrOvalOpFactory.h"
35#include "ops/GrRectOpFactory.h"
36#include "ops/GrRegionOp.h"
37#include "ops/GrShadowRRectOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050038#include "ops/GrStencilPathOp.h"
joshualitte8042922015-12-11 06:11:21 -080039#include "text/GrAtlasTextContext.h"
40#include "text/GrStencilAndCoverTextContext.h"
joshualittbc907352016-01-13 06:45:40 -080041#include "../private/GrAuditTrail.h"
42
Robert Phillips72152832017-01-25 17:31:35 -050043#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080044#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080045 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080046#define ASSERT_SINGLE_OWNER_PRIV \
Brian Osman11052242016-10-27 14:47:55 -040047 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->fSingleOwner);)
Robert Phillips72152832017-01-25 17:31:35 -050048#define RETURN_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return; }
49#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
50#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
51#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
52#define RETURN_NULL_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070053
csmartdaltona7f29642016-07-07 08:49:11 -070054using gr_instanced::InstancedRendering;
55
robertphillipsea461502015-05-26 11:38:03 -070056class AutoCheckFlush {
57public:
halcanary9d524f22016-03-29 09:03:52 -070058 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070059 SkASSERT(fDrawingManager);
60 }
bsalomonb77a9072016-09-07 10:02:04 -070061 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070062
63private:
robertphillips77a2e522015-10-17 07:43:27 -070064 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070065};
66
Brian Osman11052242016-10-27 14:47:55 -040067bool GrRenderTargetContext::wasAbandoned() const {
Robert Phillips72152832017-01-25 17:31:35 -050068 return this->drawingManager()->wasAbandoned();
robertphillips7761d612016-05-16 09:14:53 -070069}
70
Robert Phillipsf2361d22016-10-25 14:20:06 -040071// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -040072// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -040073// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -040074// when the renderTargetContext attempts to use it (via getOpList).
75GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
76 GrDrawingManager* drawingMgr,
Robert Phillipsc7635fa2016-10-28 13:25:24 -040077 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -040078 sk_sp<SkColorSpace> colorSpace,
79 const SkSurfaceProps* surfaceProps,
80 GrAuditTrail* auditTrail,
81 GrSingleOwner* singleOwner)
Robert Phillips72152832017-01-25 17:31:35 -050082 : GrSurfaceContext(context, drawingMgr, std::move(colorSpace), auditTrail, singleOwner)
Robert Phillipsc7635fa2016-10-28 13:25:24 -040083 , fRenderTargetProxy(std::move(rtp))
84 , fOpList(SkSafeRef(fRenderTargetProxy->getLastRenderTargetOpList()))
Robert Phillipsc7635fa2016-10-28 13:25:24 -040085 , fInstancedPipelineInfo(fRenderTargetProxy.get())
brianosman5a7ae7e2016-09-12 12:07:25 -070086 , fColorXformFromSRGB(nullptr)
Robert Phillips2c862492017-01-18 10:08:39 -050087 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) {
brianosman5a7ae7e2016-09-12 12:07:25 -070088 if (fColorSpace) {
89 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
Matt Sarett77a7a1b2017-02-07 13:56:11 -050090 auto srgbColorSpace = SkColorSpace::MakeSRGB();
msarettc71a9b72016-09-16 11:01:27 -070091 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
brianosman5a7ae7e2016-09-12 12:07:25 -070092 }
robertphillips2e1e51f2015-10-15 08:01:48 -070093 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070094}
95
robertphillips2e1e51f2015-10-15 08:01:48 -070096#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -040097void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -040098 SkASSERT(fRenderTargetProxy);
99 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -0700100
Robert Phillipsf2361d22016-10-25 14:20:06 -0400101 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400102 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700103 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700104}
105#endif
106
Brian Osman11052242016-10-27 14:47:55 -0400107GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800108 ASSERT_SINGLE_OWNER
Robert Phillipsf2361d22016-10-25 14:20:06 -0400109 SkSafeUnref(fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700110}
111
Robert Phillipsf200a902017-01-30 13:27:37 -0500112GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000113 return fRenderTargetProxy->asTextureProxy();
114}
115
Robert Phillipsf200a902017-01-30 13:27:37 -0500116sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
117 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
118}
119
Brian Osman11052242016-10-27 14:47:55 -0400120GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800121 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700122 SkDEBUGCODE(this->validate();)
123
Robert Phillipsf2361d22016-10-25 14:20:06 -0400124 if (!fOpList || fOpList->isClosed()) {
Robert Phillips72152832017-01-25 17:31:35 -0500125 fOpList = this->drawingManager()->newOpList(fRenderTargetProxy.get());
robertphillipsa106c622015-10-16 09:07:06 -0700126 }
127
Robert Phillipsf2361d22016-10-25 14:20:06 -0400128 return fOpList;
robertphillipsa106c622015-10-16 09:07:06 -0700129}
130
Robert Phillipse2f7d182016-12-15 09:23:05 -0500131// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
132bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
133 const SkIRect& srcRect,
134 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800135 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800136 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700137 SkDEBUGCODE(this->validate();)
Robert Phillips9a121cc2017-04-06 21:17:15 +0000138 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500139
Robert Phillips9a121cc2017-04-06 21:17:15 +0000140 // TODO: defer instantiation until flush time
141 sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
142 if (!src) {
143 return false;
144 }
145
146 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
147 sk_sp<GrRenderTarget> rt(
148 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
149 if (!rt) {
150 return false;
151 }
152
153 return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700154}
155
Robert Phillips2c862492017-01-18 10:08:39 -0500156// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
157bool GrRenderTargetContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer,
Robert Phillipsb726d582017-03-09 16:36:32 -0500158 size_t dstRowBytes, int x, int y, uint32_t flags) {
Robert Phillips2c862492017-01-18 10:08:39 -0500159 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
160 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
161 if (kUnknown_GrPixelConfig == config) {
162 return false;
163 }
164
Robert Phillipsb726d582017-03-09 16:36:32 -0500165 // TODO: this seems to duplicate code in SkImage_Gpu::onReadPixels
Robert Phillips2c862492017-01-18 10:08:39 -0500166 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400167 flags |= GrContextPriv::kUnpremul_PixelOpsFlag;
Robert Phillips2c862492017-01-18 10:08:39 -0500168 }
169
Robert Phillipse78b7252017-04-06 07:59:41 -0400170 return fContext->contextPriv().readSurfacePixels(fRenderTargetProxy.get(),
171 this->getColorSpace(), x, y,
172 dstInfo.width(), dstInfo.height(), config,
173 dstInfo.colorSpace(),
174 dstBuffer, dstRowBytes, flags);
Robert Phillips2c862492017-01-18 10:08:39 -0500175}
176
177// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
178bool GrRenderTargetContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
Robert Phillips30f9bc62017-02-22 15:28:38 -0500179 size_t srcRowBytes, int x, int y, uint32_t flags) {
Robert Phillips2c862492017-01-18 10:08:39 -0500180 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
181 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
182 if (kUnknown_GrPixelConfig == config) {
183 return false;
184 }
Robert Phillips2c862492017-01-18 10:08:39 -0500185 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400186 flags |= GrContextPriv::kUnpremul_PixelOpsFlag;
Robert Phillips2c862492017-01-18 10:08:39 -0500187 }
188
Robert Phillipse78b7252017-04-06 07:59:41 -0400189 return fContext->contextPriv().writeSurfacePixels(fRenderTargetProxy.get(),
190 this->getColorSpace(), x, y,
191 srcInfo.width(), srcInfo.height(),
192 config, srcInfo.colorSpace(),
193 srcBuffer, srcRowBytes, flags);
Robert Phillips2c862492017-01-18 10:08:39 -0500194}
195
196
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500197void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint,
Brian Salomon82f44312017-01-11 13:42:54 -0500198 const SkMatrix& viewMatrix, const char text[],
199 size_t byteLength, SkScalar x, SkScalar y,
200 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800201 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700202 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700203 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400204 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700205
Robert Phillips72152832017-01-25 17:31:35 -0500206 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500207 atlasTextContext->drawText(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, text,
208 byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700209}
robertphillipscaef3452015-11-11 13:18:11 -0800210
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500211void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
212 const SkMatrix& viewMatrix, const char text[],
213 size_t byteLength, const SkScalar pos[],
Brian Salomon82f44312017-01-11 13:42:54 -0500214 int scalarsPerPosition, const SkPoint& offset,
215 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800216 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700217 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700218 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400219 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700220
Robert Phillips72152832017-01-25 17:31:35 -0500221 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500222 atlasTextContext->drawPosText(fContext, this, clip, paint, viewMatrix, fSurfaceProps, text,
223 byteLength, pos, scalarsPerPosition, offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700224}
robertphillipscaef3452015-11-11 13:18:11 -0800225
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500226void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
Brian Osman11052242016-10-27 14:47:55 -0400227 const SkMatrix& viewMatrix, const SkTextBlob* blob,
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500228 SkScalar x, SkScalar y, SkDrawFilter* filter,
229 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800230 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700231 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700232 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400233 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700234
Robert Phillips72152832017-01-25 17:31:35 -0500235 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500236 atlasTextContext->drawTextBlob(fContext, this, clip, paint, viewMatrix, fSurfaceProps, blob, x,
237 y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700238}
239
Brian Osman11052242016-10-27 14:47:55 -0400240void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800241 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700242 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700243 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400244 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700245
Robert Phillips72152832017-01-25 17:31:35 -0500246 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400247
Brian Salomon69868af2016-12-22 15:42:51 -0500248 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400249 sk_sp<GrRenderTarget> rt(
Brian Osman32342f02017-03-04 08:12:46 -0500250 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500251 if (!rt) {
252 return;
253 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400254
Brian Salomon69868af2016-12-22 15:42:51 -0500255 this->getOpList()->discard(this);
robertphillipsea461502015-05-26 11:38:03 -0700256}
257
Brian Osman11052242016-10-27 14:47:55 -0400258void GrRenderTargetContext::clear(const SkIRect* rect,
259 const GrColor color,
260 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800261 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700262 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700263 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400264 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700265
Robert Phillips72152832017-01-25 17:31:35 -0500266 AutoCheckFlush acf(this->drawingManager());
csmartdalton29df7602016-08-31 11:55:52 -0700267 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
268}
robertphillips9199a9f2016-07-13 07:48:43 -0700269
Robert Phillips784b7bf2016-12-09 13:35:02 -0500270void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
271 ASSERT_SINGLE_OWNER_PRIV
272 RETURN_IF_ABANDONED_PRIV
273 SkDEBUGCODE(fRenderTargetContext->validate();)
274 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
275 "GrRenderTargetContext::absClear");
276
Robert Phillips72152832017-01-25 17:31:35 -0500277 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500278
279 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(
280 *fRenderTargetContext->caps()),
281 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight(
282 *fRenderTargetContext->caps()));
283
284 if (clearRect) {
285 if (clearRect->contains(rtRect)) {
286 clearRect = nullptr; // full screen
287 } else {
288 if (!rtRect.intersect(*clearRect)) {
289 return;
290 }
291 }
292 }
293
294 // TODO: in a post-MDB world this should be handled at the OpList level.
295 // An op-list that is initially cleared and has no other ops should receive an
296 // extra draw.
297 if (fRenderTargetContext->fContext->caps()->useDrawInsteadOfClear()) {
298 // This works around a driver bug with clear by drawing a rect instead.
299 // The driver will ignore a clear if it is the only thing rendered to a
300 // target before the target is read.
301 GrPaint paint;
302 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500303 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
Robert Phillips784b7bf2016-12-09 13:35:02 -0500304
305 // We don't call drawRect() here to avoid the cropping to the, possibly smaller,
306 // RenderTargetProxy bounds
Brian Salomon82f44312017-01-11 13:42:54 -0500307 fRenderTargetContext->drawNonAAFilledRect(GrNoClip(), std::move(paint), SkMatrix::I(),
308 SkRect::Make(rtRect), nullptr, nullptr, nullptr,
309 GrAAType::kNone);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500310
311 } else {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500312 // This path doesn't handle coalescing of full screen clears b.c. it
313 // has to clear the entire render target - not just the content area.
314 // It could be done but will take more finagling.
Robert Phillipsf7a72612017-03-31 10:03:45 -0400315 std::unique_ptr<GrOp> op(GrClearOp::Make(rtRect, color, fRenderTargetContext, !clearRect));
Brian Salomonfc527d22016-12-14 21:07:01 -0500316 if (!op) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500317 return;
318 }
Brian Salomon69868af2016-12-22 15:42:51 -0500319 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500320 }
321}
322
Brian Osman11052242016-10-27 14:47:55 -0400323void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
324 const GrColor color,
325 bool canIgnoreClip) {
csmartdalton29df7602016-08-31 11:55:52 -0700326 ASSERT_SINGLE_OWNER_PRIV
327 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400328 SkDEBUGCODE(fRenderTargetContext->validate();)
329 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
330 "GrRenderTargetContextPriv::clear");
csmartdalton29df7602016-08-31 11:55:52 -0700331
Robert Phillips72152832017-01-25 17:31:35 -0500332 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Osman11052242016-10-27 14:47:55 -0400333 fRenderTargetContext->internalClear(clip, color, canIgnoreClip);
csmartdalton29df7602016-08-31 11:55:52 -0700334}
335
Brian Osman11052242016-10-27 14:47:55 -0400336void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
337 const GrColor color,
338 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700339 bool isFull = false;
340 if (!clip.hasWindowRectangles()) {
341 isFull = !clip.scissorEnabled() ||
342 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
343 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
344 }
robertphillips9199a9f2016-07-13 07:48:43 -0700345
346 if (fContext->caps()->useDrawInsteadOfClear()) {
347 // This works around a driver bug with clear by drawing a rect instead.
348 // The driver will ignore a clear if it is the only thing rendered to a
349 // target before the target is read.
Robert Phillips784b7bf2016-12-09 13:35:02 -0500350 SkIRect clearRect = SkIRect::MakeWH(this->width(), this->height());
csmartdalton29df7602016-08-31 11:55:52 -0700351 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700352 this->discard();
Robert Phillips93f16332016-11-23 19:37:13 -0500353 } else if (!clearRect.intersect(clip.scissorRect())) {
csmartdalton29df7602016-08-31 11:55:52 -0700354 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700355 }
356
357 GrPaint paint;
358 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500359 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips9199a9f2016-07-13 07:48:43 -0700360
Brian Salomon82f44312017-01-11 13:42:54 -0500361 this->drawRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect));
bsalomon9f129de2016-08-10 16:31:05 -0700362 } else if (isFull) {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400363 this->getOpList()->fullClear(this, color);
robertphillips9199a9f2016-07-13 07:48:43 -0700364 } else {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400365 std::unique_ptr<GrOp> op(GrClearOp::Make(clip, color, this));
Brian Salomon42521e82016-12-07 16:44:58 -0500366 if (!op) {
csmartdalton29df7602016-08-31 11:55:52 -0700367 return;
368 }
Brian Salomon69868af2016-12-22 15:42:51 -0500369 this->getOpList()->addOp(std::move(op), this);
robertphillips9199a9f2016-07-13 07:48:43 -0700370 }
robertphillipsea461502015-05-26 11:38:03 -0700371}
372
Brian Osman11052242016-10-27 14:47:55 -0400373void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500374 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400375 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800376 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700377 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700378 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400379 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700380
robertphillipsea461502015-05-26 11:38:03 -0700381 // set rect to be big enough to fill the space, but not super-huge, so we
382 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700383
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400384 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700385
bsalomoncb31e512016-08-26 10:48:19 -0700386 SkRRect rrect;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500387 GrAA aa;
bsalomoncb31e512016-08-26 10:48:19 -0700388 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
389 // transformation for non-rect rrects. Rects caused a performance regression on an Android
390 // test that needs investigation. We also skip cases where there are fragment processors
391 // because they may depend on having correct local coords and this path draws in device space
392 // without a local matrix.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500393 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500394 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
395 GrStyle::SimpleFill());
bsalomoncb31e512016-08-26 10:48:19 -0700396 return;
397 }
398
robertphillipsea461502015-05-26 11:38:03 -0700399
400 bool isPerspective = viewMatrix.hasPerspective();
401
402 // We attempt to map r by the inverse matrix and draw that. mapRect will
403 // map the four corners and bound them with a new rect. This will not
404 // produce a correct result for some perspective matrices.
405 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700406 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700407 SkDebugf("Could not invert matrix\n");
408 return;
409 }
Brian Salomon82f44312017-01-11 13:42:54 -0500410 this->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700411 } else {
412 SkMatrix localMatrix;
413 if (!viewMatrix.invert(&localMatrix)) {
414 SkDebugf("Could not invert matrix\n");
415 return;
416 }
417
Robert Phillips72152832017-01-25 17:31:35 -0500418 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700419
Brian Salomon82f44312017-01-11 13:42:54 -0500420 this->drawNonAAFilledRect(clip, std::move(paint), SkMatrix::I(), r, nullptr, &localMatrix,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500421 nullptr, GrAAType::kNone);
robertphillipsea461502015-05-26 11:38:03 -0700422 }
423}
424
robertphillipsea461502015-05-26 11:38:03 -0700425static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
426 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
427 point.fY >= rect.fTop && point.fY <= rect.fBottom;
428}
429
bsalomonc55271f2015-11-09 11:55:57 -0800430static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
431 return viewMatrix.preservesRightAngles();
432}
433
csmartdalton97f6cd52016-07-13 13:37:08 -0700434// Attempts to crop a rect and optional local rect to the clip boundaries.
435// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700436static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700437 const SkMatrix& viewMatrix, SkRect* rect,
438 SkRect* localRect = nullptr) {
439 if (!viewMatrix.rectStaysRect()) {
440 return true;
441 }
442
csmartdalton97f6cd52016-07-13 13:37:08 -0700443 SkIRect clipDevBounds;
444 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700445
robertphillips13a7eee2016-08-31 15:06:24 -0700446 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700447 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
448 return false;
449 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700450
451 if (localRect) {
452 if (!rect->intersects(clipBounds)) {
453 return false;
454 }
455 const SkScalar dx = localRect->width() / rect->width();
456 const SkScalar dy = localRect->height() / rect->height();
457 if (clipBounds.fLeft > rect->fLeft) {
458 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
459 rect->fLeft = clipBounds.fLeft;
460 }
461 if (clipBounds.fTop > rect->fTop) {
462 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
463 rect->fTop = clipBounds.fTop;
464 }
465 if (clipBounds.fRight < rect->fRight) {
466 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
467 rect->fRight = clipBounds.fRight;
468 }
469 if (clipBounds.fBottom < rect->fBottom) {
470 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
471 rect->fBottom = clipBounds.fBottom;
472 }
473 return true;
474 }
475
476 return rect->intersect(clipBounds);
477}
478
Brian Osman11052242016-10-27 14:47:55 -0400479bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500480 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500481 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400482 const SkMatrix& viewMatrix,
483 const SkRect& rect,
484 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700485 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500486 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700487 return true;
488 }
robertphillips44302392016-07-08 14:43:03 -0700489
Brian Salomon54d212e2017-03-21 14:22:38 -0400490 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
491 (!ss || ss->isDisabled(false))) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400492 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400493 std::unique_ptr<GrDrawOp> op = ir->recordRect(croppedRect, viewMatrix, std::move(paint), aa,
494 fInstancedPipelineInfo);
Brian Salomon42521e82016-12-07 16:44:58 -0500495 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400496 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700497 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700498 }
499 }
Brian Salomon54d212e2017-03-21 14:22:38 -0400500 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500501 if (GrAAType::kCoverage == aaType) {
robertphillips391395d2016-03-02 09:26:36 -0800502 // The fill path can handle rotation but not skew.
503 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
504 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700505 viewMatrix.mapRect(&devBoundRect, croppedRect);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400506 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -0500507 GrRectOpFactory::MakeAAFill(paint, viewMatrix, rect, croppedRect, devBoundRect);
Brian Salomon42521e82016-12-07 16:44:58 -0500508 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500509 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
robertphillips44302392016-07-08 14:43:03 -0700510 if (ss) {
511 pipelineBuilder.setUserStencil(ss);
512 }
Brian Salomone14bd802017-04-04 15:13:25 -0400513 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700514 return true;
515 }
robertphillips391395d2016-03-02 09:26:36 -0800516 }
517 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500518 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr, nullptr,
519 ss, aaType);
robertphillips44302392016-07-08 14:43:03 -0700520 return true;
robertphillips391395d2016-03-02 09:26:36 -0800521 }
522
robertphillips44302392016-07-08 14:43:03 -0700523 return false;
robertphillips391395d2016-03-02 09:26:36 -0800524}
525
Brian Osman11052242016-10-27 14:47:55 -0400526void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500527 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500528 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400529 const SkMatrix& viewMatrix,
530 const SkRect& rect,
531 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700532 if (!style) {
533 style = &GrStyle::SimpleFill();
534 }
joshualitt1de610a2016-01-06 08:26:09 -0800535 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700536 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700537 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400538 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700539
bsalomon6663acf2016-05-10 09:14:17 -0700540 // Path effects should've been devolved to a path in SkGpuDevice
541 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700542
Robert Phillips72152832017-01-25 17:31:35 -0500543 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700544
bsalomon6663acf2016-05-10 09:14:17 -0700545 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700546 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
547
548 if (!fContext->caps()->useDrawInsteadOfClear()) {
549 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
550 // checking cases where the RT is fully inside a stroke.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400551 SkRect rtRect = fRenderTargetProxy->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700552 // Does the clip contain the entire RT?
553 if (clip.quickContains(rtRect)) {
554 SkMatrix invM;
555 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700556 return;
557 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700558 // Does the rect bound the RT?
559 SkPoint srcSpaceRTQuad[4];
560 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
561 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
562 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
563 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
564 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
565 // Will it blend?
566 GrColor clearColor;
567 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700568 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700569 return;
570 }
571 }
robertphillipsea461502015-05-26 11:38:03 -0700572 }
573 }
robertphillips44302392016-07-08 14:43:03 -0700574
Brian Salomon82f44312017-01-11 13:42:54 -0500575 if (this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, nullptr)) {
robertphillips44302392016-07-08 14:43:03 -0700576 return;
577 }
bsalomona7d85ba2016-07-06 11:54:59 -0700578 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
579 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
580 if ((!rect.width() || !rect.height()) &&
581 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
582 SkScalar r = stroke.getWidth() / 2;
583 // TODO: Move these stroke->fill fallbacks to GrShape?
584 switch (stroke.getJoin()) {
585 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500586 this->drawRect(
587 clip, std::move(paint), aa, viewMatrix,
588 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
589 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700590 return;
591 case SkPaint::kRound_Join:
592 // Raster draws nothing when both dimensions are empty.
593 if (rect.width() || rect.height()){
594 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500595 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
596 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700597 return;
598 }
599 case SkPaint::kBevel_Join:
600 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500601 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700602 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
603 &GrStyle::SimpleFill());
604 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500605 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700606 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
607 &GrStyle::SimpleFill());
608 }
609 return;
610 }
611 }
robertphillips44302392016-07-08 14:43:03 -0700612
robertphillips44302392016-07-08 14:43:03 -0700613 bool snapToPixelCenters = false;
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400614 std::unique_ptr<GrLegacyMeshDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700615
robertphillips391395d2016-03-02 09:26:36 -0800616 GrColor color = paint.getColor();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500617 GrAAType aaType = this->decideAAType(aa);
618 if (GrAAType::kCoverage == aaType) {
cdaltonbb539482016-01-04 09:48:25 -0800619 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
620 if (viewMatrix.rectStaysRect()) {
Brian Salomon6a639042016-12-14 11:08:17 -0500621 op = GrRectOpFactory::MakeAAStroke(color, viewMatrix, rect, stroke);
cdaltonbb539482016-01-04 09:48:25 -0800622 }
robertphillipsea461502015-05-26 11:38:03 -0700623 } else {
robertphillips391395d2016-03-02 09:26:36 -0800624 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700625 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800626 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700627 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400628 !fRenderTargetProxy->isUnifiedMultisampled();
Brian Salomon6a639042016-12-14 11:08:17 -0500629 op = GrRectOpFactory::MakeNonAAStroke(color, viewMatrix, rect, stroke,
630 snapToPixelCenters);
robertphillips391395d2016-03-02 09:26:36 -0800631 }
robertphillips4bc31812016-03-01 12:22:49 -0800632
Brian Salomon42521e82016-12-07 16:44:58 -0500633 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500634 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon189098e72017-01-19 09:55:19 -0500635 pipelineBuilder.setSnapVerticesToPixelCenters(snapToPixelCenters);
Brian Salomone14bd802017-04-04 15:13:25 -0400636 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700637 return;
robertphillips4bc31812016-03-01 12:22:49 -0800638 }
robertphillips4bc31812016-03-01 12:22:49 -0800639 }
halcanary9d524f22016-03-29 09:03:52 -0700640
robertphillips4bc31812016-03-01 12:22:49 -0800641 SkPath path;
642 path.setIsVolatile(true);
643 path.addRect(rect);
Brian Salomon82f44312017-01-11 13:42:54 -0500644 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700645}
646
Robert Phillipsec2249f2016-11-09 08:54:35 -0500647int GrRenderTargetContextPriv::maxWindowRectangles() const {
648 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
649 *fRenderTargetContext->fContext->caps());
650}
651
Brian Osman11052242016-10-27 14:47:55 -0400652void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700653 ASSERT_SINGLE_OWNER_PRIV
654 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400655 SkDEBUGCODE(fRenderTargetContext->validate();)
656 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
657 "GrRenderTargetContextPriv::clearStencilClip");
robertphillips976f5f02016-06-03 10:59:20 -0700658
Robert Phillips72152832017-01-25 17:31:35 -0500659 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400660
661 std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(clip, insideStencilMask,
662 fRenderTargetContext));
663 if (!op) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500664 return;
665 }
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400666 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700667}
668
Brian Osman11052242016-10-27 14:47:55 -0400669void GrRenderTargetContextPriv::stencilPath(const GrClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500670 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400671 const SkMatrix& viewMatrix,
672 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500673 ASSERT_SINGLE_OWNER_PRIV
674 RETURN_IF_ABANDONED_PRIV
675 SkDEBUGCODE(fRenderTargetContext->validate();)
676 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
677 "GrRenderTargetContext::stencilPath");
678
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500679 SkASSERT(aaType != GrAAType::kCoverage);
Brian Salomon467921e2017-03-06 16:17:12 -0500680
681 bool useHWAA = GrAATypeIsHW(aaType);
682 // TODO: extract portions of checkDraw that are relevant to path stenciling.
683 SkASSERT(path);
684 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
685
686 // FIXME: Use path bounds instead of this WAR once
687 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
688 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
689
690 // Setup clip
Brian Salomon97180af2017-03-14 13:42:58 -0400691 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -0500692 if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true,
Brian Salomon97180af2017-03-14 13:42:58 -0400693 &appliedClip, &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500694 return;
695 }
696
697 // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
698 // attempt this in a situation that would require coverage AA.
699 SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
700
701 GrRenderTarget* rt = fRenderTargetContext->accessRenderTarget();
702 if (!rt) {
703 return;
704 }
705 GrStencilAttachment* stencilAttachment =
706 fRenderTargetContext->fContext->resourceProvider()->attachStencilAttachment(rt);
707 if (!stencilAttachment) {
708 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
709 return;
710 }
711
712 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
713 useHWAA,
714 path->getFillType(),
715 appliedClip.hasStencilClip(),
716 stencilAttachment->bits(),
717 appliedClip.scissorState(),
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400718 fRenderTargetContext,
Brian Salomon467921e2017-03-06 16:17:12 -0500719 path);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400720 if (!op) {
721 return;
722 }
Brian Salomon97180af2017-03-14 13:42:58 -0400723 op->setClippedBounds(bounds);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400724 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700725}
726
Brian Osman11052242016-10-27 14:47:55 -0400727void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
728 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500729 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400730 const SkMatrix& viewMatrix,
731 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700732 ASSERT_SINGLE_OWNER_PRIV
733 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400734 SkDEBUGCODE(fRenderTargetContext->validate();)
735 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
736 "GrRenderTargetContext::stencilRect");
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500737 SkASSERT(GrAAType::kCoverage != aaType);
Robert Phillips72152832017-01-25 17:31:35 -0500738 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700739
740 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500741 paint.setXPFactory(GrDisableColorXPFactory::Get());
robertphillips976f5f02016-06-03 10:59:20 -0700742
Brian Salomon82f44312017-01-11 13:42:54 -0500743 fRenderTargetContext->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, rect, nullptr,
744 nullptr, ss, aaType);
robertphillips976f5f02016-06-03 10:59:20 -0700745}
746
Brian Osman11052242016-10-27 14:47:55 -0400747bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip,
748 const GrUserStencilSettings* ss,
749 SkRegion::Op op,
750 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500751 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400752 const SkMatrix& viewMatrix,
753 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800754 ASSERT_SINGLE_OWNER_PRIV
755 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400756 SkDEBUGCODE(fRenderTargetContext->validate();)
757 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
758 "GrRenderTargetContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800759
Robert Phillips72152832017-01-25 17:31:35 -0500760 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800761
762 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800763 paint.setCoverageSetOpXPFactory(op, invert);
764
Brian Salomon82f44312017-01-11 13:42:54 -0500765 if (fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800766 return true;
767 }
robertphillips391395d2016-03-02 09:26:36 -0800768 SkPath path;
769 path.setIsVolatile(true);
770 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500771 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800772}
773
Brian Osman11052242016-10-27 14:47:55 -0400774void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500775 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500776 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400777 const SkMatrix& viewMatrix,
778 const SkRect& rectToDraw,
779 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800780 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700781 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700782 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400783 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700784
csmartdalton97f6cd52016-07-13 13:37:08 -0700785 SkRect croppedRect = rectToDraw;
786 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700787 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
788 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700789 return;
790 }
791
Robert Phillips72152832017-01-25 17:31:35 -0500792 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700793
csmartdaltone0d36292016-07-29 08:14:20 -0700794 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400795 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400796 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
797 croppedLocalRect, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500798 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400799 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700800 return;
801 }
802 }
803
Brian Salomon54d212e2017-03-21 14:22:38 -0400804 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500805 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500806 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect,
807 &croppedLocalRect, nullptr, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700808 return;
joshualitt04194f32016-01-13 10:08:27 -0800809 }
bsalomonbb243832016-07-22 07:10:19 -0700810
csmartdaltonfc49d562016-07-26 17:05:47 -0700811 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400812 std::unique_ptr<GrLegacyMeshDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(
Brian Salomonf8334782017-01-03 09:42:58 -0500813 paint.getColor(), viewMatrix, croppedRect, croppedLocalRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500814 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -0400815 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700816 return;
817 }
818
819 SkMatrix viewAndUnLocalMatrix;
820 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
821 SkDebugf("fillRectToRect called with empty local matrix.\n");
822 return;
823 }
824 viewAndUnLocalMatrix.postConcat(viewMatrix);
825
826 SkPath path;
827 path.setIsVolatile(true);
828 path.addRect(localRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500829 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700830}
831
Brian Osman11052242016-10-27 14:47:55 -0400832void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500833 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500834 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400835 const SkMatrix& viewMatrix,
836 const SkRect& rectToDraw,
837 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800838 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700839 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700840 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400841 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700842
csmartdalton97f6cd52016-07-13 13:37:08 -0700843 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700844 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700845 return;
846 }
847
Robert Phillips72152832017-01-25 17:31:35 -0500848 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700849
csmartdaltone0d36292016-07-29 08:14:20 -0700850 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400851 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400852 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
853 localMatrix, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500854 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400855 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700856 return;
857 }
858 }
859
Brian Salomon54d212e2017-03-21 14:22:38 -0400860 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500861 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500862 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr,
863 &localMatrix, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700864 return;
bsalomonc55271f2015-11-09 11:55:57 -0800865 }
robertphillips4bc31812016-03-01 12:22:49 -0800866
csmartdaltonfc49d562016-07-26 17:05:47 -0700867 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400868 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -0500869 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500870 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -0400871 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700872 return;
873 }
874
875 SkMatrix viewAndUnLocalMatrix;
876 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
877 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
878 return;
879 }
880 viewAndUnLocalMatrix.postConcat(viewMatrix);
881
882 SkPath path;
883 path.setIsVolatile(true);
884 path.addRect(rectToDraw);
885 path.transform(localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -0500886 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700887}
888
Brian Osman11052242016-10-27 14:47:55 -0400889void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500890 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400891 const SkMatrix& viewMatrix,
892 GrPrimitiveType primitiveType,
893 int vertexCount,
894 const SkPoint positions[],
895 const SkPoint texCoords[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500896 const uint32_t colors[],
Brian Osman11052242016-10-27 14:47:55 -0400897 const uint16_t indices[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500898 int indexCount,
899 ColorArrayType colorArrayType) {
joshualitt1de610a2016-01-06 08:26:09 -0800900 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700901 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700902 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400903 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700904
Robert Phillips72152832017-01-25 17:31:35 -0500905 AutoCheckFlush acf(this->drawingManager());
robertphillips2e1e51f2015-10-15 08:01:48 -0700906
robertphillipsea461502015-05-26 11:38:03 -0700907 // TODO clients should give us bounds
908 SkRect bounds;
909 if (!bounds.setBoundsCheck(positions, vertexCount)) {
910 SkDebugf("drawVertices call empty bounds\n");
911 return;
912 }
913
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400914 std::unique_ptr<GrLegacyMeshDrawOp> op = GrDrawVerticesOp::Make(
Brian Salomon3de0aee2017-01-29 09:34:17 -0500915 paint.getColor(), primitiveType, viewMatrix, positions, vertexCount, indices,
916 indexCount, colors, texCoords, bounds, colorArrayType);
Brian Salomon199fb872017-02-06 09:41:10 -0500917 if (!op) {
918 return;
919 }
920 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400921 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
Brian Salomon199fb872017-02-06 09:41:10 -0500922}
robertphillipsea461502015-05-26 11:38:03 -0700923
Brian Salomon199fb872017-02-06 09:41:10 -0500924void GrRenderTargetContext::drawVertices(const GrClip& clip,
925 GrPaint&& paint,
926 const SkMatrix& viewMatrix,
Mike Reed5fa66452017-03-16 09:06:34 -0400927 sk_sp<SkVertices> vertices) {
Brian Salomon199fb872017-02-06 09:41:10 -0500928 ASSERT_SINGLE_OWNER
929 RETURN_IF_ABANDONED
930 SkDEBUGCODE(this->validate();)
931 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
932
933 AutoCheckFlush acf(this->drawingManager());
934
935 SkASSERT(vertices);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400936 std::unique_ptr<GrLegacyMeshDrawOp> op =
Mike Reed5fa66452017-03-16 09:06:34 -0400937 GrDrawVerticesOp::Make(paint.getColor(), std::move(vertices), viewMatrix);
Brian Salomon199fb872017-02-06 09:41:10 -0500938 if (!op) {
939 return;
940 }
Brian Salomon82f44312017-01-11 13:42:54 -0500941 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400942 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700943}
944
945///////////////////////////////////////////////////////////////////////////////
946
Brian Osman11052242016-10-27 14:47:55 -0400947void GrRenderTargetContext::drawAtlas(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500948 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400949 const SkMatrix& viewMatrix,
950 int spriteCount,
951 const SkRSXform xform[],
952 const SkRect texRect[],
953 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800954 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700955 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700956 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400957 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700958
Robert Phillips72152832017-01-25 17:31:35 -0500959 AutoCheckFlush acf(this->drawingManager());
halcanary9d524f22016-03-29 09:03:52 -0700960
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400961 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomonfc527d22016-12-14 21:07:01 -0500962 GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
Brian Salomon82f44312017-01-11 13:42:54 -0500963 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400964 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -0700965}
966
967///////////////////////////////////////////////////////////////////////////////
968
Brian Osman11052242016-10-27 14:47:55 -0400969void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500970 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500971 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400972 const SkMatrix& viewMatrix,
973 const SkRRect& rrect,
974 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800975 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700976 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700977 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400978 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700979 if (rrect.isEmpty()) {
980 return;
981 }
982
bsalomon7f0d9f32016-08-15 14:49:10 -0700983 GrNoClip noclip;
984 const GrClip* clip = &origClip;
985#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
986 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -0500987 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -0700988 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
989 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
990 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
991 SkRRect devRRect;
992 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
993 clip = &noclip;
994 }
995#endif
bsalomon6663acf2016-05-10 09:14:17 -0700996 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700997
Robert Phillips72152832017-01-25 17:31:35 -0500998 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700999 const SkStrokeRec stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -07001000
csmartdaltone0d36292016-07-29 08:14:20 -07001001 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1002 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001003 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001004 std::unique_ptr<GrDrawOp> op(
1005 ir->recordRRect(rrect, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001006 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001007 this->addDrawOp(*clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001008 return;
1009 }
1010 }
1011
Brian Salomon54d212e2017-03-21 14:22:38 -04001012 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001013 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001014 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001015 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -05001016 GrOvalOpFactory::MakeRRectOp(paint.getColor(),
1017 paint.usesDistanceVectorField(),
1018 viewMatrix,
1019 rrect,
1020 stroke,
1021 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001022 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001023 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001024 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), *clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001025 return;
1026 }
robertphillipsea461502015-05-26 11:38:03 -07001027 }
robertphillipsb56f9272016-02-25 11:03:52 -08001028
1029 SkPath path;
1030 path.setIsVolatile(true);
1031 path.addRRect(rrect);
Brian Salomon82f44312017-01-11 13:42:54 -05001032 this->internalDrawPath(*clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001033}
1034
Jim Van Verthc5903412016-11-17 15:27:09 -05001035///////////////////////////////////////////////////////////////////////////////
1036
1037void GrRenderTargetContext::drawShadowRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001038 GrPaint&& paint,
Jim Van Verthc5903412016-11-17 15:27:09 -05001039 const SkMatrix& viewMatrix,
1040 const SkRRect& rrect,
1041 SkScalar blurRadius,
1042 const GrStyle& style) {
1043 ASSERT_SINGLE_OWNER
1044 RETURN_IF_ABANDONED
1045 SkDEBUGCODE(this->validate();)
1046 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect");
1047 if (rrect.isEmpty()) {
1048 return;
1049 }
1050
1051 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1052
Robert Phillips72152832017-01-25 17:31:35 -05001053 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001054 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001055 // TODO: add instancing support?
Jim Van Verthc5903412016-11-17 15:27:09 -05001056
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001057 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001058 std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(
1059 paint.getColor(), viewMatrix, rrect, blurRadius, stroke, shaderCaps);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001060 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001061 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001062 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001063 return;
Jim Van Verthc5903412016-11-17 15:27:09 -05001064 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001065}
1066
1067///////////////////////////////////////////////////////////////////////////////
1068
Brian Osman11052242016-10-27 14:47:55 -04001069bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001070 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001071 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001072 const SkMatrix& viewMatrix,
1073 const SkRRect& origOuter,
1074 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001075 SkASSERT(!origInner.isEmpty());
1076 SkASSERT(!origOuter.isEmpty());
1077
csmartdaltone0d36292016-07-29 08:14:20 -07001078 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001079 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001080 std::unique_ptr<GrDrawOp> op(ir->recordDRRect(
1081 origOuter, origInner, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001082 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001083 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001084 return true;
1085 }
1086 }
1087
Brian Salomon54d212e2017-03-21 14:22:38 -04001088 GrAAType aaType = this->decideAAType(aa);
robertphillips00095892016-02-29 13:50:40 -08001089
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001090 GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
1091 if (GrAAType::kCoverage == aaType) {
1092 innerEdgeType = kInverseFillAA_GrProcessorEdgeType;
1093 outerEdgeType = kFillAA_GrProcessorEdgeType;
1094 } else {
1095 innerEdgeType = kInverseFillBW_GrProcessorEdgeType;
1096 outerEdgeType = kFillBW_GrProcessorEdgeType;
1097 }
robertphillips00095892016-02-29 13:50:40 -08001098
1099 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1100 SkMatrix inverseVM;
1101 if (!viewMatrix.isIdentity()) {
1102 if (!origInner.transform(viewMatrix, inner.writable())) {
1103 return false;
1104 }
1105 if (!origOuter.transform(viewMatrix, outer.writable())) {
1106 return false;
1107 }
1108 if (!viewMatrix.invert(&inverseVM)) {
1109 return false;
1110 }
1111 } else {
1112 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001113 }
robertphillips00095892016-02-29 13:50:40 -08001114
robertphillips00095892016-02-29 13:50:40 -08001115 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -07001116 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -08001117 if (!innerEffect) {
1118 return false;
1119 }
1120
bungeman06ca8ec2016-06-09 08:01:03 -07001121 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -08001122 if (!outerEffect) {
1123 return false;
1124 }
1125
Brian Salomon82f44312017-01-11 13:42:54 -05001126 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1127 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001128
1129 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001130 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001131 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1132 }
halcanary9d524f22016-03-29 09:03:52 -07001133
Brian Salomon82f44312017-01-11 13:42:54 -05001134 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1135 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001136 return true;
1137}
1138
Brian Osman11052242016-10-27 14:47:55 -04001139void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001140 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001141 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001142 const SkMatrix& viewMatrix,
1143 const SkRRect& outer,
1144 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001145 ASSERT_SINGLE_OWNER
1146 RETURN_IF_ABANDONED
1147 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001148 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
robertphillips00095892016-02-29 13:50:40 -08001149
1150 SkASSERT(!outer.isEmpty());
1151 SkASSERT(!inner.isEmpty());
1152
Robert Phillips72152832017-01-25 17:31:35 -05001153 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001154
Brian Salomon82f44312017-01-11 13:42:54 -05001155 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001156 return;
1157 }
1158
1159 SkPath path;
1160 path.setIsVolatile(true);
1161 path.addRRect(inner);
1162 path.addRRect(outer);
1163 path.setFillType(SkPath::kEvenOdd_FillType);
1164
Brian Salomon82f44312017-01-11 13:42:54 -05001165 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -08001166}
1167
robertphillipsea461502015-05-26 11:38:03 -07001168///////////////////////////////////////////////////////////////////////////////
1169
msarettcc319b92016-08-25 18:07:18 -07001170static inline bool is_int(float x) {
1171 return x == (float) sk_float_round2int(x);
1172}
1173
Brian Osman11052242016-10-27 14:47:55 -04001174void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001175 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001176 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001177 const SkMatrix& viewMatrix,
1178 const SkRegion& region,
1179 const GrStyle& style) {
msarettcc319b92016-08-25 18:07:18 -07001180 ASSERT_SINGLE_OWNER
1181 RETURN_IF_ABANDONED
1182 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001183 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
msarettcc319b92016-08-25 18:07:18 -07001184
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001185 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001186 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001187 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001188 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1189 is_int(viewMatrix.getTranslateX()) &&
1190 is_int(viewMatrix.getTranslateY())) {
1191 aa = GrAA::kNo;
1192 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001193 }
msarettcc319b92016-08-25 18:07:18 -07001194 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001195 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001196 SkPath path;
1197 region.getBoundaryPath(&path);
Brian Salomon82f44312017-01-11 13:42:54 -05001198 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001199 }
1200
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001201 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
Brian Salomon82f44312017-01-11 13:42:54 -05001202 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001203 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001204}
1205
Brian Osman11052242016-10-27 14:47:55 -04001206void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001207 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001208 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001209 const SkMatrix& viewMatrix,
1210 const SkRect& oval,
1211 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001212 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001213 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001214 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001215 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001216
robertphillipsea461502015-05-26 11:38:03 -07001217 if (oval.isEmpty()) {
1218 return;
1219 }
1220
bsalomon6663acf2016-05-10 09:14:17 -07001221 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001222
Robert Phillips72152832017-01-25 17:31:35 -05001223 AutoCheckFlush acf(this->drawingManager());
bsalomon6663acf2016-05-10 09:14:17 -07001224 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -07001225
csmartdaltone0d36292016-07-29 08:14:20 -07001226 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1227 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001228 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001229 std::unique_ptr<GrDrawOp> op(
1230 ir->recordOval(oval, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001231 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001232 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001233 return;
1234 }
1235 }
1236
Brian Salomon54d212e2017-03-21 14:22:38 -04001237 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001238 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001239 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001240 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon289e3d82016-12-14 15:52:56 -05001241 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001242 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001243 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001244 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001245 return;
1246 }
robertphillipsea461502015-05-26 11:38:03 -07001247 }
robertphillipsb56f9272016-02-25 11:03:52 -08001248
1249 SkPath path;
1250 path.setIsVolatile(true);
1251 path.addOval(oval);
Brian Salomon82f44312017-01-11 13:42:54 -05001252 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001253}
1254
Brian Osman11052242016-10-27 14:47:55 -04001255void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001256 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001257 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001258 const SkMatrix& viewMatrix,
1259 const SkRect& oval,
1260 SkScalar startAngle,
1261 SkScalar sweepAngle,
1262 bool useCenter,
1263 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001264 ASSERT_SINGLE_OWNER
1265 RETURN_IF_ABANDONED
1266 SkDEBUGCODE(this->validate();)
1267 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawArc");
1268
1269 AutoCheckFlush acf(this->drawingManager());
1270
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001271 GrAAType aaType = this->decideAAType(aa);
1272 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001273 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001274 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
1275 viewMatrix,
1276 oval,
1277 startAngle,
1278 sweepAngle,
1279 useCenter,
1280 style,
1281 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001282 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001283 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001284 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001285 return;
1286 }
1287 }
1288 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001289 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1290 style.isSimpleFill());
Brian Salomon82f44312017-01-11 13:42:54 -05001291 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001292}
1293
Brian Osman11052242016-10-27 14:47:55 -04001294void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001295 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001296 const SkMatrix& viewMatrix,
1297 int imageWidth,
1298 int imageHeight,
1299 std::unique_ptr<SkLatticeIter> iter,
1300 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001301 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001302 RETURN_IF_ABANDONED
1303 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001304 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001305
Robert Phillips72152832017-01-25 17:31:35 -05001306 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001307
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001308 std::unique_ptr<GrLegacyMeshDrawOp> op = GrLatticeOp::MakeNonAA(
Brian Salomon649a3412017-03-09 13:50:43 -05001309 paint.getColor(), viewMatrix, imageWidth, imageHeight, std::move(iter), dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001310
Brian Salomon82f44312017-01-11 13:42:54 -05001311 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001312 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001313}
1314
Brian Osman11052242016-10-27 14:47:55 -04001315void GrRenderTargetContext::prepareForExternalIO() {
robertphillips8c523e02016-07-26 07:41:00 -07001316 ASSERT_SINGLE_OWNER
1317 RETURN_IF_ABANDONED
1318 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001319 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
robertphillips8c523e02016-07-26 07:41:00 -07001320
Robert Phillips7ee385e2017-03-30 08:02:11 -04001321 this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get());
robertphillips8c523e02016-07-26 07:41:00 -07001322}
joshualitt33a5fce2015-11-18 13:28:51 -08001323
Brian Osman11052242016-10-27 14:47:55 -04001324void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001325 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001326 const SkMatrix& viewMatrix,
1327 const SkRect& rect,
1328 const SkRect* localRect,
1329 const SkMatrix* localMatrix,
1330 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001331 GrAAType hwOrNoneAAType) {
1332 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
1333 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001334 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill(
1335 paint.getColor(), viewMatrix, rect, localRect, localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -05001336 GrPipelineBuilder pipelineBuilder(std::move(paint), hwOrNoneAAType);
robertphillips44302392016-07-08 14:43:03 -07001337 if (ss) {
1338 pipelineBuilder.setUserStencil(ss);
1339 }
Brian Salomone14bd802017-04-04 15:13:25 -04001340 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -07001341}
1342
robertphillipsea461502015-05-26 11:38:03 -07001343// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001344static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001345
1346 if (path.isInverseFillType()) {
1347 return false;
1348 }
1349
1350 // TODO: this restriction could be lifted if we were willing to apply
1351 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001352 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001353 return false;
1354 }
1355
1356 SkPath::Direction dirs[2];
1357 if (!path.isNestedFillRects(rects, dirs)) {
1358 return false;
1359 }
1360
1361 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1362 // The two rects need to be wound opposite to each other
1363 return false;
1364 }
1365
1366 // Right now, nested rects where the margin is not the same width
1367 // all around do not render correctly
1368 const SkScalar* outer = rects[0].asScalars();
1369 const SkScalar* inner = rects[1].asScalars();
1370
1371 bool allEq = true;
1372
1373 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1374 bool allGoE1 = margin >= SK_Scalar1;
1375
1376 for (int i = 1; i < 4; ++i) {
1377 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1378 if (temp < SK_Scalar1) {
1379 allGoE1 = false;
1380 }
1381 if (!SkScalarNearlyEqual(margin, temp)) {
1382 allEq = false;
1383 }
1384 }
1385
1386 return allEq || allGoE1;
1387}
1388
Brian Osman11052242016-10-27 14:47:55 -04001389void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001390 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001391 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001392 const SkMatrix& viewMatrix,
1393 const SkPath& path,
1394 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001395 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001396 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001397 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001398 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001399
robertphillipsea461502015-05-26 11:38:03 -07001400 if (path.isEmpty()) {
1401 if (path.isInverseFillType()) {
Brian Salomon82f44312017-01-11 13:42:54 -05001402 this->drawPaint(clip, std::move(paint), viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001403 }
1404 return;
1405 }
1406
Robert Phillips72152832017-01-25 17:31:35 -05001407 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001408
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001409 GrAAType aaType = this->decideAAType(aa);
1410 if (GrAAType::kCoverage == aaType && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001411 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001412 // Concave AA paths are expensive - try to avoid them for special cases
1413 SkRect rects[2];
1414
bsalomon6663acf2016-05-10 09:14:17 -07001415 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001416 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -05001417 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001418 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001419 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001420 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon40ef4852016-05-02 13:22:13 -07001421 }
robertphillipsea461502015-05-26 11:38:03 -07001422 return;
1423 }
1424 }
1425 SkRect ovalRect;
1426 bool isOval = path.isOval(&ovalRect);
1427
1428 if (isOval && !path.isInverseFillType()) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001429 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001430 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeOvalOp(
Brian Salomon289e3d82016-12-14 15:52:56 -05001431 paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001432 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001433 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001434 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001435 return;
1436 }
1437 }
1438 }
robertphillips4bc31812016-03-01 12:22:49 -08001439
1440 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1441 // Scratch textures can be recycled after they are returned to the texture
1442 // cache. This presents a potential hazard for buffered drawing. However,
1443 // the writePixels that uploads to the scratch will perform a flush so we're
1444 // OK.
Brian Salomon82f44312017-01-11 13:42:54 -05001445 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001446}
1447
Brian Osman11052242016-10-27 14:47:55 -04001448bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip,
1449 const GrUserStencilSettings* ss,
1450 SkRegion::Op op,
1451 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001452 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001453 const SkMatrix& viewMatrix,
1454 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001455 ASSERT_SINGLE_OWNER_PRIV
1456 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001457 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001458 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
1459 "GrRenderTargetContextPriv::drawAndStencilPath");
robertphillips391395d2016-03-02 09:26:36 -08001460
1461 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001462 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001463 SkRect::MakeIWH(fRenderTargetContext->width(),
1464 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001465 return true;
1466 }
1467
Robert Phillips72152832017-01-25 17:31:35 -05001468 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001469
1470 // An Assumption here is that path renderer would use some form of tweaking
1471 // the src color (either the input alpha or in the frag shader) to implement
1472 // aa. If we have some future driver-mojo path AA that can do the right
1473 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001474 GrAAType aaType = fRenderTargetContext->decideAAType(aa);
robertphillips976f5f02016-06-03 10:59:20 -07001475 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001476
bsalomon8acedde2016-06-24 10:42:16 -07001477 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001478 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Osman11052242016-10-27 14:47:55 -04001479 canDrawArgs.fShaderCaps =
Robert Phillips72152832017-01-25 17:31:35 -05001480 fRenderTargetContext->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips391395d2016-03-02 09:26:36 -08001481 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001482 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001483 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001484 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001485
1486 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001487 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001488 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001489 if (!pr) {
1490 return false;
1491 }
1492
1493 GrPaint paint;
1494 paint.setCoverageSetOpXPFactory(op, invert);
1495
Brian Salomon82f44312017-01-11 13:42:54 -05001496 GrPathRenderer::DrawPathArgs args{
Robert Phillips256c37b2017-03-01 14:32:46 -05001497 fRenderTargetContext->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001498 std::move(paint),
1499 ss,
1500 fRenderTargetContext,
1501 &clip,
1502 &viewMatrix,
1503 &shape,
1504 aaType,
1505 fRenderTargetContext->isGammaCorrect()};
robertphillips391395d2016-03-02 09:26:36 -08001506 pr->drawPath(args);
1507 return true;
1508}
1509
Brian Osman11052242016-10-27 14:47:55 -04001510SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001511 ASSERT_SINGLE_OWNER_PRIV
1512
Brian Osman11052242016-10-27 14:47:55 -04001513 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001514 return SkBudgeted::kNo;
1515 }
1516
Brian Osman11052242016-10-27 14:47:55 -04001517 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001518
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001519 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001520}
1521
Brian Osman11052242016-10-27 14:47:55 -04001522void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001523 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001524 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001525 const SkMatrix& viewMatrix,
1526 const SkPath& path,
1527 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001528 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001529 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001530 SkASSERT(!path.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001531 GrShape shape;
robertphillipsea461502015-05-26 11:38:03 -07001532
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001533 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true);
1534 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) {
1535 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and
1536 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1537 // smoother hairlines than MSAA.
1538 aaType = GrAAType::kCoverage;
bsalomon0a0f67e2016-06-28 11:56:42 -07001539 }
robertphillips68737822015-10-29 12:12:21 -07001540 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Robert Phillips72152832017-01-25 17:31:35 -05001541 canDrawArgs.fShaderCaps = this->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips68737822015-10-29 12:12:21 -07001542 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001543 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001544 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001545
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001546 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001547 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001548 do {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001549 shape = GrShape(path, style);
bsalomon8acedde2016-06-24 10:42:16 -07001550 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001551 return;
1552 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001553
1554 canDrawArgs.fAAType = aaType;
1555
1556 // Try a 1st time without applying any of the style to the geometry (and barring sw)
Robert Phillips72152832017-01-25 17:31:35 -05001557 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001558 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1559
1560 if (!pr && shape.style().pathEffect()) {
1561 // It didn't work above, so try again with the path effect applied.
1562 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
bsalomon8acedde2016-06-24 10:42:16 -07001563 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001564 return;
1565 }
Robert Phillips72152832017-01-25 17:31:35 -05001566 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
bsalomon6663acf2016-05-10 09:14:17 -07001567 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001568 if (!pr) {
1569 if (shape.style().applies()) {
1570 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1571 if (shape.isEmpty()) {
1572 return;
1573 }
1574 }
1575 // This time, allow SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001576 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001577 }
Brian Salomon0abc8b42016-12-13 10:22:54 -05001578 if (!pr && GrAATypeIsHW(aaType)) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001579 // There are exceptional cases where we may wind up falling back to coverage based AA
1580 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions).
1581 aaType = GrAAType::kCoverage;
1582 } else {
1583 break;
1584 }
1585 } while(true);
robertphillipsea461502015-05-26 11:38:03 -07001586
bsalomon8acedde2016-06-24 10:42:16 -07001587 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001588#ifdef SK_DEBUG
1589 SkDebugf("Unable to find path renderer compatible with path.\n");
1590#endif
1591 return;
1592 }
1593
Robert Phillips256c37b2017-03-01 14:32:46 -05001594 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001595 std::move(paint),
1596 &GrUserStencilSettings::kUnused,
1597 this,
1598 &clip,
1599 &viewMatrix,
1600 &shape,
1601 aaType,
1602 this->isGammaCorrect()};
bsalomon0aff2fa2015-07-31 06:48:27 -07001603 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001604}
1605
Brian Salomon467921e2017-03-06 16:17:12 -05001606static void op_bounds(SkRect* bounds, const GrOp* op) {
1607 *bounds = op->bounds();
1608 if (op->hasZeroArea()) {
1609 if (op->hasAABloat()) {
1610 bounds->outset(0.5f, 0.5f);
1611 } else {
1612 // We don't know which way the particular GPU will snap lines or points at integer
1613 // coords. So we ensure that the bounds is large enough for either snap.
1614 SkRect before = *bounds;
1615 bounds->roundOut(bounds);
1616 if (bounds->fLeft == before.fLeft) {
1617 bounds->fLeft -= 1;
1618 }
1619 if (bounds->fTop == before.fTop) {
1620 bounds->fTop -= 1;
1621 }
1622 if (bounds->fRight == before.fRight) {
1623 bounds->fRight += 1;
1624 }
1625 if (bounds->fBottom == before.fBottom) {
1626 bounds->fBottom += 1;
1627 }
1628 }
1629 }
1630}
1631
Brian Salomon54d212e2017-03-21 14:22:38 -04001632uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001633 ASSERT_SINGLE_OWNER
Robert Phillipsc0138922017-03-08 11:50:55 -05001634 if (this->drawingManager()->wasAbandoned()) {
1635 return SK_InvalidUniqueID;
1636 }
robertphillips2e1e51f2015-10-15 08:01:48 -07001637 SkDEBUGCODE(this->validate();)
Brian Salomon42521e82016-12-07 16:44:58 -05001638 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
robertphillips2d70dcb2015-10-06 07:38:23 -07001639
Brian Salomon467921e2017-03-06 16:17:12 -05001640 // Setup clip
1641 SkRect bounds;
1642 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04001643 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04001644 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1645 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1646 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1647 &bounds)) {
1648 return SK_InvalidUniqueID;
1649 }
1650
1651 // This forces instantiation of the render target.
1652 GrRenderTarget* rt = this->accessRenderTarget();
1653 if (!rt) {
1654 return SK_InvalidUniqueID;
1655 }
1656
1657 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1658 appliedClip.hasStencilClip()) {
1659 if (!fContext->resourceProvider()->attachStencilAttachment(rt)) {
1660 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
1661 return SK_InvalidUniqueID;
1662 }
1663 }
1664
1665 GrXferProcessor::DstTexture dstTexture;
1666 if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001667 this->setupDstTexture(rt, clip, op->bounds(), &dstTexture);
1668 if (!dstTexture.texture()) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001669 return SK_InvalidUniqueID;
1670 }
1671 }
1672
1673 op->setClippedBounds(bounds);
1674 return this->getOpList()->addOp(std::move(op), this, std::move(appliedClip), dstTexture);
1675}
1676
Brian Salomone14bd802017-04-04 15:13:25 -04001677uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(GrPipelineBuilder&& pipelineBuilder,
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001678 const GrClip& clip,
1679 std::unique_ptr<GrLegacyMeshDrawOp> op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001680 ASSERT_SINGLE_OWNER
1681 if (this->drawingManager()->wasAbandoned()) {
1682 return SK_InvalidUniqueID;
1683 }
1684 SkDEBUGCODE(this->validate();)
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001685 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addLegacyMeshDrawOp");
Brian Salomon54d212e2017-03-21 14:22:38 -04001686
1687 // Setup clip
1688 SkRect bounds;
1689 op_bounds(&bounds, op.get());
1690 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -05001691 if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
Brian Salomon97180af2017-03-14 13:42:58 -04001692 pipelineBuilder.hasUserStencilSettings(), &appliedClip, &bounds)) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001693 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001694 }
1695
1696 // This forces instantiation of the render target. Pipeline creation is moving to flush time
1697 // by which point instantiation must have occurred anyway.
1698 GrRenderTarget* rt = this->accessRenderTarget();
1699 if (!rt) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001700 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001701 }
1702
1703 GrResourceProvider* resourceProvider = fContext->resourceProvider();
1704 if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
1705 if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
1706 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
Robert Phillipsc0138922017-03-08 11:50:55 -05001707 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001708 }
1709 }
1710
Brian Salomona811b122017-03-30 08:21:32 -04001711 GrProcessorSet::Analysis analysis;
Brian Salomone14bd802017-04-04 15:13:25 -04001712 op->analyzeProcessors(&analysis, &pipelineBuilder, &appliedClip, *this->caps());
Brian Salomon467921e2017-03-06 16:17:12 -05001713
1714 GrPipeline::InitArgs args;
1715 pipelineBuilder.getPipelineInitArgs(&args);
1716 args.fAppliedClip = &appliedClip;
1717 args.fRenderTarget = rt;
1718 args.fCaps = this->caps();
Brian Salomone14bd802017-04-04 15:13:25 -04001719 args.fXPInputColor = analysis.outputColor();
1720 args.fXPInputCoverage = analysis.outputCoverage();
Brian Salomon467921e2017-03-06 16:17:12 -05001721
Brian Salomon31853842017-03-28 16:32:05 -04001722 if (analysis.requiresDstTexture()) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001723 this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
1724 if (!args.fDstTexture.texture()) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001725 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001726 }
1727 }
Brian Salomone14bd802017-04-04 15:13:25 -04001728 op->initPipeline(args, analysis);
Brian Salomon467921e2017-03-06 16:17:12 -05001729 // TODO: We need to add pipeline dependencies on textures, etc before recording this op.
Brian Salomon97180af2017-03-14 13:42:58 -04001730 op->setClippedBounds(bounds);
Robert Phillipsc0138922017-03-08 11:50:55 -05001731 return this->getOpList()->addOp(std::move(op), this);
Brian Salomon467921e2017-03-06 16:17:12 -05001732}
1733
Robert Phillips9a121cc2017-04-06 21:17:15 +00001734void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& clip,
Brian Salomon467921e2017-03-06 16:17:12 -05001735 const SkRect& opBounds,
1736 GrXferProcessor::DstTexture* dstTexture) {
1737 if (this->caps()->textureBarrierSupport()) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001738 if (GrTexture* rtTex = rt->asTexture()) {
Brian Salomon467921e2017-03-06 16:17:12 -05001739 // The render target is a texture, so we can read from it directly in the shader. The XP
1740 // will be responsible to detect this situation and request a texture barrier.
Robert Phillips9a121cc2017-04-06 21:17:15 +00001741 dstTexture->setTexture(sk_ref_sp(rtTex));
Brian Salomon467921e2017-03-06 16:17:12 -05001742 dstTexture->setOffset(0, 0);
Robert Phillips9a121cc2017-04-06 21:17:15 +00001743 return;
Brian Salomon467921e2017-03-06 16:17:12 -05001744 }
1745 }
1746
Robert Phillips9a121cc2017-04-06 21:17:15 +00001747 SkIRect copyRect = SkIRect::MakeWH(rt->width(), rt->height());
Brian Salomon467921e2017-03-06 16:17:12 -05001748
Eric Karl74480882017-04-03 14:49:05 -07001749 SkIRect clippedRect;
Robert Phillips9a121cc2017-04-06 21:17:15 +00001750 clip.getConservativeBounds(rt->width(), rt->height(), &clippedRect);
Eric Karl72e551e2017-04-04 13:42:10 -07001751 SkIRect drawIBounds;
Brian Salomon467921e2017-03-06 16:17:12 -05001752 opBounds.roundOut(&drawIBounds);
Brian Salomon859621f2017-03-16 09:21:54 -04001753 // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
1754 drawIBounds.outset(1, 1);
Eric Karl72e551e2017-04-04 13:42:10 -07001755 if (!clippedRect.intersect(drawIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001756#ifdef SK_DEBUG
Robert Phillips9a121cc2017-04-06 21:17:15 +00001757 GrCapsDebugf(this->caps(), "Missed an early reject. "
1758 "Bailing on draw from setupDstTexture.\n");
Brian Salomon467921e2017-03-06 16:17:12 -05001759#endif
Robert Phillips9a121cc2017-04-06 21:17:15 +00001760 return;
Brian Salomon467921e2017-03-06 16:17:12 -05001761 }
1762
1763 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
1764 // have per-sample dst values by making the copy multisampled.
1765 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07001766 bool rectsMustMatch = false;
1767 bool disallowSubrect = false;
Robert Phillips9a121cc2017-04-06 21:17:15 +00001768 if (!this->caps()->initDescForDstCopy(rt, &desc, &rectsMustMatch, &disallowSubrect)) {
1769 desc.fOrigin = kDefault_GrSurfaceOrigin;
Brian Salomon467921e2017-03-06 16:17:12 -05001770 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillips9a121cc2017-04-06 21:17:15 +00001771 desc.fConfig = rt->config();
Brian Salomon467921e2017-03-06 16:17:12 -05001772 }
1773
Eric Karl74480882017-04-03 14:49:05 -07001774 if (!disallowSubrect) {
1775 copyRect = clippedRect;
1776 }
Brian Salomon467921e2017-03-06 16:17:12 -05001777
Robert Phillips9a121cc2017-04-06 21:17:15 +00001778 SkIPoint dstPoint;
1779 SkIPoint dstOffset;
1780 static const uint32_t kFlags = 0;
1781 sk_sp<GrTexture> copy;
Eric Karl74480882017-04-03 14:49:05 -07001782 if (rectsMustMatch) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001783 SkASSERT(desc.fOrigin == rt->origin());
1784 desc.fWidth = rt->width();
1785 desc.fHeight = rt->height();
Eric Karl74480882017-04-03 14:49:05 -07001786 dstPoint = {copyRect.fLeft, copyRect.fTop};
1787 dstOffset = {0, 0};
Robert Phillips9a121cc2017-04-06 21:17:15 +00001788 copy = fContext->resourceProvider()->createTexture(desc, SkBudgeted::kYes, kFlags);
Eric Karl74480882017-04-03 14:49:05 -07001789 } else {
1790 desc.fWidth = copyRect.width();
1791 desc.fHeight = copyRect.height();
1792 dstPoint = {0, 0};
1793 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillips9a121cc2017-04-06 21:17:15 +00001794 copy.reset(fContext->resourceProvider()->createApproxTexture(desc, kFlags));
Eric Karl74480882017-04-03 14:49:05 -07001795 }
Brian Salomon467921e2017-03-06 16:17:12 -05001796
1797 if (!copy) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001798 SkDebugf("Failed to create temporary copy of destination texture.\n");
1799 return;
Brian Salomon467921e2017-03-06 16:17:12 -05001800 }
Eric Karl74480882017-04-03 14:49:05 -07001801
Robert Phillips9a121cc2017-04-06 21:17:15 +00001802 this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint);
Brian Salomon467921e2017-03-06 16:17:12 -05001803 dstTexture->setTexture(std::move(copy));
Eric Karl74480882017-04-03 14:49:05 -07001804 dstTexture->setOffset(dstOffset);
robertphillips2334fb62015-06-17 05:43:33 -07001805}