blob: 76a67c083e6a61c42bdfbbb1bccc4846f736f9b5 [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"
Brian Salomon467921e2017-03-06 16:17:12 -050028#include "ops/GrDrawOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050029#include "ops/GrDrawAtlasOp.h"
30#include "ops/GrDrawVerticesOp.h"
31#include "ops/GrLatticeOp.h"
32#include "ops/GrOp.h"
33#include "ops/GrOvalOpFactory.h"
34#include "ops/GrRectOpFactory.h"
35#include "ops/GrRegionOp.h"
36#include "ops/GrShadowRRectOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050037#include "ops/GrStencilPathOp.h"
joshualitte8042922015-12-11 06:11:21 -080038#include "text/GrAtlasTextContext.h"
39#include "text/GrStencilAndCoverTextContext.h"
joshualittbc907352016-01-13 06:45:40 -080040#include "../private/GrAuditTrail.h"
41
Robert Phillips72152832017-01-25 17:31:35 -050042#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080043#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080044 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080045#define ASSERT_SINGLE_OWNER_PRIV \
Brian Osman11052242016-10-27 14:47:55 -040046 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->fSingleOwner);)
Robert Phillips72152832017-01-25 17:31:35 -050047#define RETURN_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return; }
48#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
49#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
50#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
51#define RETURN_NULL_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070052
csmartdaltona7f29642016-07-07 08:49:11 -070053using gr_instanced::InstancedRendering;
54
robertphillipsea461502015-05-26 11:38:03 -070055class AutoCheckFlush {
56public:
halcanary9d524f22016-03-29 09:03:52 -070057 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070058 SkASSERT(fDrawingManager);
59 }
bsalomonb77a9072016-09-07 10:02:04 -070060 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070061
62private:
robertphillips77a2e522015-10-17 07:43:27 -070063 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070064};
65
Brian Osman11052242016-10-27 14:47:55 -040066bool GrRenderTargetContext::wasAbandoned() const {
Robert Phillips72152832017-01-25 17:31:35 -050067 return this->drawingManager()->wasAbandoned();
robertphillips7761d612016-05-16 09:14:53 -070068}
69
Robert Phillipsf2361d22016-10-25 14:20:06 -040070// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -040071// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -040072// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -040073// when the renderTargetContext attempts to use it (via getOpList).
74GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
75 GrDrawingManager* drawingMgr,
Robert Phillipsc7635fa2016-10-28 13:25:24 -040076 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -040077 sk_sp<SkColorSpace> colorSpace,
78 const SkSurfaceProps* surfaceProps,
79 GrAuditTrail* auditTrail,
80 GrSingleOwner* singleOwner)
Robert Phillips72152832017-01-25 17:31:35 -050081 : GrSurfaceContext(context, drawingMgr, std::move(colorSpace), auditTrail, singleOwner)
Robert Phillipsc7635fa2016-10-28 13:25:24 -040082 , fRenderTargetProxy(std::move(rtp))
83 , fOpList(SkSafeRef(fRenderTargetProxy->getLastRenderTargetOpList()))
Robert Phillipsc7635fa2016-10-28 13:25:24 -040084 , fInstancedPipelineInfo(fRenderTargetProxy.get())
brianosman5a7ae7e2016-09-12 12:07:25 -070085 , fColorXformFromSRGB(nullptr)
Robert Phillips2c862492017-01-18 10:08:39 -050086 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) {
brianosman5a7ae7e2016-09-12 12:07:25 -070087 if (fColorSpace) {
88 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
Matt Sarett77a7a1b2017-02-07 13:56:11 -050089 auto srgbColorSpace = SkColorSpace::MakeSRGB();
msarettc71a9b72016-09-16 11:01:27 -070090 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
brianosman5a7ae7e2016-09-12 12:07:25 -070091 }
robertphillips2e1e51f2015-10-15 08:01:48 -070092 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070093}
94
robertphillips2e1e51f2015-10-15 08:01:48 -070095#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -040096void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -040097 SkASSERT(fRenderTargetProxy);
98 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -070099
Robert Phillipsf2361d22016-10-25 14:20:06 -0400100 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400101 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700102 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700103}
104#endif
105
Brian Osman11052242016-10-27 14:47:55 -0400106GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800107 ASSERT_SINGLE_OWNER
Robert Phillipsf2361d22016-10-25 14:20:06 -0400108 SkSafeUnref(fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700109}
110
Robert Phillipsf200a902017-01-30 13:27:37 -0500111GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000112 return fRenderTargetProxy->asTextureProxy();
113}
114
Robert Phillipsf200a902017-01-30 13:27:37 -0500115sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
116 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
117}
118
Brian Osman11052242016-10-27 14:47:55 -0400119GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800120 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700121 SkDEBUGCODE(this->validate();)
122
Robert Phillipsf2361d22016-10-25 14:20:06 -0400123 if (!fOpList || fOpList->isClosed()) {
Robert Phillips72152832017-01-25 17:31:35 -0500124 fOpList = this->drawingManager()->newOpList(fRenderTargetProxy.get());
robertphillipsa106c622015-10-16 09:07:06 -0700125 }
126
Robert Phillipsf2361d22016-10-25 14:20:06 -0400127 return fOpList;
robertphillipsa106c622015-10-16 09:07:06 -0700128}
129
Robert Phillipse2f7d182016-12-15 09:23:05 -0500130// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
131bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
132 const SkIRect& srcRect,
133 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800134 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800135 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700136 SkDEBUGCODE(this->validate();)
Robert Phillips9a121cc2017-04-06 21:17:15 +0000137 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500138
Robert Phillips9a121cc2017-04-06 21:17:15 +0000139 // TODO: defer instantiation until flush time
140 sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->resourceProvider())));
141 if (!src) {
142 return false;
143 }
144
145 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
146 sk_sp<GrRenderTarget> rt(
147 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
148 if (!rt) {
149 return false;
150 }
151
152 return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700153}
154
Robert Phillips2c862492017-01-18 10:08:39 -0500155// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
156bool GrRenderTargetContext::onReadPixels(const SkImageInfo& dstInfo, void* dstBuffer,
Robert Phillipsb726d582017-03-09 16:36:32 -0500157 size_t dstRowBytes, int x, int y, uint32_t flags) {
Robert Phillips2c862492017-01-18 10:08:39 -0500158 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
159 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
160 if (kUnknown_GrPixelConfig == config) {
161 return false;
162 }
163
Robert Phillipsb726d582017-03-09 16:36:32 -0500164 // TODO: this seems to duplicate code in SkImage_Gpu::onReadPixels
Robert Phillips2c862492017-01-18 10:08:39 -0500165 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400166 flags |= GrContextPriv::kUnpremul_PixelOpsFlag;
Robert Phillips2c862492017-01-18 10:08:39 -0500167 }
168
Robert Phillipse78b7252017-04-06 07:59:41 -0400169 return fContext->contextPriv().readSurfacePixels(fRenderTargetProxy.get(),
170 this->getColorSpace(), x, y,
171 dstInfo.width(), dstInfo.height(), config,
172 dstInfo.colorSpace(),
173 dstBuffer, dstRowBytes, flags);
Robert Phillips2c862492017-01-18 10:08:39 -0500174}
175
176// TODO: move this (and GrTextureContext::onReadPixels) to GrSurfaceContext?
177bool GrRenderTargetContext::onWritePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
Robert Phillips30f9bc62017-02-22 15:28:38 -0500178 size_t srcRowBytes, int x, int y, uint32_t flags) {
Robert Phillips2c862492017-01-18 10:08:39 -0500179 // TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
180 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
181 if (kUnknown_GrPixelConfig == config) {
182 return false;
183 }
Robert Phillips2c862492017-01-18 10:08:39 -0500184 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400185 flags |= GrContextPriv::kUnpremul_PixelOpsFlag;
Robert Phillips2c862492017-01-18 10:08:39 -0500186 }
187
Robert Phillipse78b7252017-04-06 07:59:41 -0400188 return fContext->contextPriv().writeSurfacePixels(fRenderTargetProxy.get(),
189 this->getColorSpace(), x, y,
190 srcInfo.width(), srcInfo.height(),
191 config, srcInfo.colorSpace(),
192 srcBuffer, srcRowBytes, flags);
Robert Phillips2c862492017-01-18 10:08:39 -0500193}
194
195
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500196void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint,
Brian Salomon82f44312017-01-11 13:42:54 -0500197 const SkMatrix& viewMatrix, const char text[],
198 size_t byteLength, SkScalar x, SkScalar y,
199 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800200 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700201 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700202 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400203 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700204
Robert Phillips72152832017-01-25 17:31:35 -0500205 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500206 atlasTextContext->drawText(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, text,
207 byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700208}
robertphillipscaef3452015-11-11 13:18:11 -0800209
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500210void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
211 const SkMatrix& viewMatrix, const char text[],
212 size_t byteLength, const SkScalar pos[],
Brian Salomon82f44312017-01-11 13:42:54 -0500213 int scalarsPerPosition, const SkPoint& offset,
214 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800215 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700216 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700217 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400218 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700219
Robert Phillips72152832017-01-25 17:31:35 -0500220 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500221 atlasTextContext->drawPosText(fContext, this, clip, paint, viewMatrix, fSurfaceProps, text,
222 byteLength, pos, scalarsPerPosition, offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700223}
robertphillipscaef3452015-11-11 13:18:11 -0800224
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500225void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
Brian Osman11052242016-10-27 14:47:55 -0400226 const SkMatrix& viewMatrix, const SkTextBlob* blob,
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500227 SkScalar x, SkScalar y, SkDrawFilter* filter,
228 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800229 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700230 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700231 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400232 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700233
Robert Phillips72152832017-01-25 17:31:35 -0500234 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500235 atlasTextContext->drawTextBlob(fContext, this, clip, paint, viewMatrix, fSurfaceProps, blob, x,
236 y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700237}
238
Brian Osman11052242016-10-27 14:47:55 -0400239void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800240 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700241 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700242 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400243 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700244
Robert Phillips72152832017-01-25 17:31:35 -0500245 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400246
Brian Salomon69868af2016-12-22 15:42:51 -0500247 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400248 sk_sp<GrRenderTarget> rt(
Brian Osman32342f02017-03-04 08:12:46 -0500249 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->resourceProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500250 if (!rt) {
251 return;
252 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400253
Brian Salomon69868af2016-12-22 15:42:51 -0500254 this->getOpList()->discard(this);
robertphillipsea461502015-05-26 11:38:03 -0700255}
256
Brian Osman11052242016-10-27 14:47:55 -0400257void GrRenderTargetContext::clear(const SkIRect* rect,
258 const GrColor color,
259 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800260 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700261 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700262 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400263 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700264
Robert Phillips72152832017-01-25 17:31:35 -0500265 AutoCheckFlush acf(this->drawingManager());
csmartdalton29df7602016-08-31 11:55:52 -0700266 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
267}
robertphillips9199a9f2016-07-13 07:48:43 -0700268
Robert Phillips784b7bf2016-12-09 13:35:02 -0500269void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
270 ASSERT_SINGLE_OWNER_PRIV
271 RETURN_IF_ABANDONED_PRIV
272 SkDEBUGCODE(fRenderTargetContext->validate();)
273 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
274 "GrRenderTargetContext::absClear");
275
Robert Phillips72152832017-01-25 17:31:35 -0500276 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500277
278 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(
279 *fRenderTargetContext->caps()),
280 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight(
281 *fRenderTargetContext->caps()));
282
283 if (clearRect) {
284 if (clearRect->contains(rtRect)) {
285 clearRect = nullptr; // full screen
286 } else {
287 if (!rtRect.intersect(*clearRect)) {
288 return;
289 }
290 }
291 }
292
293 // TODO: in a post-MDB world this should be handled at the OpList level.
294 // An op-list that is initially cleared and has no other ops should receive an
295 // extra draw.
296 if (fRenderTargetContext->fContext->caps()->useDrawInsteadOfClear()) {
297 // This works around a driver bug with clear by drawing a rect instead.
298 // The driver will ignore a clear if it is the only thing rendered to a
299 // target before the target is read.
300 GrPaint paint;
301 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500302 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
Robert Phillips784b7bf2016-12-09 13:35:02 -0500303
304 // We don't call drawRect() here to avoid the cropping to the, possibly smaller,
305 // RenderTargetProxy bounds
Brian Salomon82f44312017-01-11 13:42:54 -0500306 fRenderTargetContext->drawNonAAFilledRect(GrNoClip(), std::move(paint), SkMatrix::I(),
307 SkRect::Make(rtRect), nullptr, nullptr, nullptr,
308 GrAAType::kNone);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500309
310 } else {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500311 // This path doesn't handle coalescing of full screen clears b.c. it
312 // has to clear the entire render target - not just the content area.
313 // It could be done but will take more finagling.
Robert Phillipsf7a72612017-03-31 10:03:45 -0400314 std::unique_ptr<GrOp> op(GrClearOp::Make(rtRect, color, fRenderTargetContext, !clearRect));
Brian Salomonfc527d22016-12-14 21:07:01 -0500315 if (!op) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500316 return;
317 }
Brian Salomon69868af2016-12-22 15:42:51 -0500318 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500319 }
320}
321
Brian Osman11052242016-10-27 14:47:55 -0400322void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
323 const GrColor color,
324 bool canIgnoreClip) {
csmartdalton29df7602016-08-31 11:55:52 -0700325 ASSERT_SINGLE_OWNER_PRIV
326 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400327 SkDEBUGCODE(fRenderTargetContext->validate();)
328 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
329 "GrRenderTargetContextPriv::clear");
csmartdalton29df7602016-08-31 11:55:52 -0700330
Robert Phillips72152832017-01-25 17:31:35 -0500331 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Osman11052242016-10-27 14:47:55 -0400332 fRenderTargetContext->internalClear(clip, color, canIgnoreClip);
csmartdalton29df7602016-08-31 11:55:52 -0700333}
334
Brian Osman11052242016-10-27 14:47:55 -0400335void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
336 const GrColor color,
337 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700338 bool isFull = false;
339 if (!clip.hasWindowRectangles()) {
340 isFull = !clip.scissorEnabled() ||
341 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
342 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
343 }
robertphillips9199a9f2016-07-13 07:48:43 -0700344
345 if (fContext->caps()->useDrawInsteadOfClear()) {
346 // This works around a driver bug with clear by drawing a rect instead.
347 // The driver will ignore a clear if it is the only thing rendered to a
348 // target before the target is read.
Robert Phillips784b7bf2016-12-09 13:35:02 -0500349 SkIRect clearRect = SkIRect::MakeWH(this->width(), this->height());
csmartdalton29df7602016-08-31 11:55:52 -0700350 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700351 this->discard();
Robert Phillips93f16332016-11-23 19:37:13 -0500352 } else if (!clearRect.intersect(clip.scissorRect())) {
csmartdalton29df7602016-08-31 11:55:52 -0700353 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700354 }
355
356 GrPaint paint;
357 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500358 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips9199a9f2016-07-13 07:48:43 -0700359
Brian Salomon82f44312017-01-11 13:42:54 -0500360 this->drawRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect));
bsalomon9f129de2016-08-10 16:31:05 -0700361 } else if (isFull) {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400362 this->getOpList()->fullClear(this, color);
robertphillips9199a9f2016-07-13 07:48:43 -0700363 } else {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400364 std::unique_ptr<GrOp> op(GrClearOp::Make(clip, color, this));
Brian Salomon42521e82016-12-07 16:44:58 -0500365 if (!op) {
csmartdalton29df7602016-08-31 11:55:52 -0700366 return;
367 }
Brian Salomon69868af2016-12-22 15:42:51 -0500368 this->getOpList()->addOp(std::move(op), this);
robertphillips9199a9f2016-07-13 07:48:43 -0700369 }
robertphillipsea461502015-05-26 11:38:03 -0700370}
371
Brian Osman11052242016-10-27 14:47:55 -0400372void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500373 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400374 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800375 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700376 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700377 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400378 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700379
robertphillipsea461502015-05-26 11:38:03 -0700380 // set rect to be big enough to fill the space, but not super-huge, so we
381 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700382
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400383 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700384
bsalomoncb31e512016-08-26 10:48:19 -0700385 SkRRect rrect;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500386 GrAA aa;
bsalomoncb31e512016-08-26 10:48:19 -0700387 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
388 // transformation for non-rect rrects. Rects caused a performance regression on an Android
389 // test that needs investigation. We also skip cases where there are fragment processors
390 // because they may depend on having correct local coords and this path draws in device space
391 // without a local matrix.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500392 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500393 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
394 GrStyle::SimpleFill());
bsalomoncb31e512016-08-26 10:48:19 -0700395 return;
396 }
397
robertphillipsea461502015-05-26 11:38:03 -0700398
399 bool isPerspective = viewMatrix.hasPerspective();
400
401 // We attempt to map r by the inverse matrix and draw that. mapRect will
402 // map the four corners and bound them with a new rect. This will not
403 // produce a correct result for some perspective matrices.
404 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700405 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700406 SkDebugf("Could not invert matrix\n");
407 return;
408 }
Brian Salomon82f44312017-01-11 13:42:54 -0500409 this->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700410 } else {
411 SkMatrix localMatrix;
412 if (!viewMatrix.invert(&localMatrix)) {
413 SkDebugf("Could not invert matrix\n");
414 return;
415 }
416
Robert Phillips72152832017-01-25 17:31:35 -0500417 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700418
Brian Salomon82f44312017-01-11 13:42:54 -0500419 this->drawNonAAFilledRect(clip, std::move(paint), SkMatrix::I(), r, nullptr, &localMatrix,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500420 nullptr, GrAAType::kNone);
robertphillipsea461502015-05-26 11:38:03 -0700421 }
422}
423
robertphillipsea461502015-05-26 11:38:03 -0700424static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
425 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
426 point.fY >= rect.fTop && point.fY <= rect.fBottom;
427}
428
bsalomonc55271f2015-11-09 11:55:57 -0800429static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
430 return viewMatrix.preservesRightAngles();
431}
432
csmartdalton97f6cd52016-07-13 13:37:08 -0700433// Attempts to crop a rect and optional local rect to the clip boundaries.
434// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700435static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700436 const SkMatrix& viewMatrix, SkRect* rect,
437 SkRect* localRect = nullptr) {
438 if (!viewMatrix.rectStaysRect()) {
439 return true;
440 }
441
csmartdalton97f6cd52016-07-13 13:37:08 -0700442 SkIRect clipDevBounds;
443 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700444
robertphillips13a7eee2016-08-31 15:06:24 -0700445 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700446 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
447 return false;
448 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700449
450 if (localRect) {
451 if (!rect->intersects(clipBounds)) {
452 return false;
453 }
454 const SkScalar dx = localRect->width() / rect->width();
455 const SkScalar dy = localRect->height() / rect->height();
456 if (clipBounds.fLeft > rect->fLeft) {
457 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
458 rect->fLeft = clipBounds.fLeft;
459 }
460 if (clipBounds.fTop > rect->fTop) {
461 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
462 rect->fTop = clipBounds.fTop;
463 }
464 if (clipBounds.fRight < rect->fRight) {
465 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
466 rect->fRight = clipBounds.fRight;
467 }
468 if (clipBounds.fBottom < rect->fBottom) {
469 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
470 rect->fBottom = clipBounds.fBottom;
471 }
472 return true;
473 }
474
475 return rect->intersect(clipBounds);
476}
477
Brian Osman11052242016-10-27 14:47:55 -0400478bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500479 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500480 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400481 const SkMatrix& viewMatrix,
482 const SkRect& rect,
483 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700484 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500485 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700486 return true;
487 }
robertphillips44302392016-07-08 14:43:03 -0700488
Brian Salomon54d212e2017-03-21 14:22:38 -0400489 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
490 (!ss || ss->isDisabled(false))) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400491 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400492 std::unique_ptr<GrDrawOp> op = ir->recordRect(croppedRect, viewMatrix, std::move(paint), aa,
493 fInstancedPipelineInfo);
Brian Salomon42521e82016-12-07 16:44:58 -0500494 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400495 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700496 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700497 }
498 }
Brian Salomon54d212e2017-03-21 14:22:38 -0400499 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500500 if (GrAAType::kCoverage == aaType) {
robertphillips391395d2016-03-02 09:26:36 -0800501 // The fill path can handle rotation but not skew.
502 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
503 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700504 viewMatrix.mapRect(&devBoundRect, croppedRect);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400505 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -0500506 GrRectOpFactory::MakeAAFill(paint, viewMatrix, rect, croppedRect, devBoundRect);
Brian Salomon42521e82016-12-07 16:44:58 -0500507 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500508 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
robertphillips44302392016-07-08 14:43:03 -0700509 if (ss) {
510 pipelineBuilder.setUserStencil(ss);
511 }
Brian Salomone14bd802017-04-04 15:13:25 -0400512 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700513 return true;
514 }
robertphillips391395d2016-03-02 09:26:36 -0800515 }
516 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500517 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr, nullptr,
518 ss, aaType);
robertphillips44302392016-07-08 14:43:03 -0700519 return true;
robertphillips391395d2016-03-02 09:26:36 -0800520 }
521
robertphillips44302392016-07-08 14:43:03 -0700522 return false;
robertphillips391395d2016-03-02 09:26:36 -0800523}
524
Brian Osman11052242016-10-27 14:47:55 -0400525void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500526 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500527 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400528 const SkMatrix& viewMatrix,
529 const SkRect& rect,
530 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700531 if (!style) {
532 style = &GrStyle::SimpleFill();
533 }
joshualitt1de610a2016-01-06 08:26:09 -0800534 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700535 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700536 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400537 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700538
bsalomon6663acf2016-05-10 09:14:17 -0700539 // Path effects should've been devolved to a path in SkGpuDevice
540 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700541
Robert Phillips72152832017-01-25 17:31:35 -0500542 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700543
bsalomon6663acf2016-05-10 09:14:17 -0700544 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700545 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
546
547 if (!fContext->caps()->useDrawInsteadOfClear()) {
548 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
549 // checking cases where the RT is fully inside a stroke.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400550 SkRect rtRect = fRenderTargetProxy->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700551 // Does the clip contain the entire RT?
552 if (clip.quickContains(rtRect)) {
553 SkMatrix invM;
554 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700555 return;
556 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700557 // Does the rect bound the RT?
558 SkPoint srcSpaceRTQuad[4];
559 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
560 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
561 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
562 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
563 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
564 // Will it blend?
565 GrColor clearColor;
566 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700567 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700568 return;
569 }
570 }
robertphillipsea461502015-05-26 11:38:03 -0700571 }
572 }
robertphillips44302392016-07-08 14:43:03 -0700573
Brian Salomon82f44312017-01-11 13:42:54 -0500574 if (this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, nullptr)) {
robertphillips44302392016-07-08 14:43:03 -0700575 return;
576 }
bsalomona7d85ba2016-07-06 11:54:59 -0700577 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
578 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
579 if ((!rect.width() || !rect.height()) &&
580 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
581 SkScalar r = stroke.getWidth() / 2;
582 // TODO: Move these stroke->fill fallbacks to GrShape?
583 switch (stroke.getJoin()) {
584 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500585 this->drawRect(
586 clip, std::move(paint), aa, viewMatrix,
587 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
588 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700589 return;
590 case SkPaint::kRound_Join:
591 // Raster draws nothing when both dimensions are empty.
592 if (rect.width() || rect.height()){
593 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500594 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
595 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700596 return;
597 }
598 case SkPaint::kBevel_Join:
599 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500600 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700601 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
602 &GrStyle::SimpleFill());
603 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500604 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700605 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
606 &GrStyle::SimpleFill());
607 }
608 return;
609 }
610 }
robertphillips44302392016-07-08 14:43:03 -0700611
robertphillips44302392016-07-08 14:43:03 -0700612 bool snapToPixelCenters = false;
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400613 std::unique_ptr<GrLegacyMeshDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700614
robertphillips391395d2016-03-02 09:26:36 -0800615 GrColor color = paint.getColor();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500616 GrAAType aaType = this->decideAAType(aa);
617 if (GrAAType::kCoverage == aaType) {
cdaltonbb539482016-01-04 09:48:25 -0800618 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
619 if (viewMatrix.rectStaysRect()) {
Brian Salomon6a639042016-12-14 11:08:17 -0500620 op = GrRectOpFactory::MakeAAStroke(color, viewMatrix, rect, stroke);
cdaltonbb539482016-01-04 09:48:25 -0800621 }
robertphillipsea461502015-05-26 11:38:03 -0700622 } else {
robertphillips391395d2016-03-02 09:26:36 -0800623 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700624 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800625 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700626 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400627 !fRenderTargetProxy->isUnifiedMultisampled();
Brian Salomon6a639042016-12-14 11:08:17 -0500628 op = GrRectOpFactory::MakeNonAAStroke(color, viewMatrix, rect, stroke,
629 snapToPixelCenters);
robertphillips391395d2016-03-02 09:26:36 -0800630 }
robertphillips4bc31812016-03-01 12:22:49 -0800631
Brian Salomon42521e82016-12-07 16:44:58 -0500632 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500633 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon189098e72017-01-19 09:55:19 -0500634 pipelineBuilder.setSnapVerticesToPixelCenters(snapToPixelCenters);
Brian Salomone14bd802017-04-04 15:13:25 -0400635 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700636 return;
robertphillips4bc31812016-03-01 12:22:49 -0800637 }
robertphillips4bc31812016-03-01 12:22:49 -0800638 }
halcanary9d524f22016-03-29 09:03:52 -0700639
robertphillips4bc31812016-03-01 12:22:49 -0800640 SkPath path;
641 path.setIsVolatile(true);
642 path.addRect(rect);
Brian Salomon82f44312017-01-11 13:42:54 -0500643 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700644}
645
Robert Phillipsec2249f2016-11-09 08:54:35 -0500646int GrRenderTargetContextPriv::maxWindowRectangles() const {
647 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
648 *fRenderTargetContext->fContext->caps());
649}
650
Brian Osman11052242016-10-27 14:47:55 -0400651void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700652 ASSERT_SINGLE_OWNER_PRIV
653 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400654 SkDEBUGCODE(fRenderTargetContext->validate();)
655 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
656 "GrRenderTargetContextPriv::clearStencilClip");
robertphillips976f5f02016-06-03 10:59:20 -0700657
Robert Phillips72152832017-01-25 17:31:35 -0500658 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Salomon69868af2016-12-22 15:42:51 -0500659 // TODO: This needs to be fixed up since it ends the deferral of the GrRenderTarget.
Robert Phillipse60ad622016-11-17 10:22:48 -0500660 if (!fRenderTargetContext->accessRenderTarget()) {
661 return;
662 }
Brian Osman11052242016-10-27 14:47:55 -0400663 fRenderTargetContext->getOpList()->clearStencilClip(clip, insideStencilMask,
Brian Salomon69868af2016-12-22 15:42:51 -0500664 fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700665}
666
Brian Osman11052242016-10-27 14:47:55 -0400667void GrRenderTargetContextPriv::stencilPath(const GrClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500668 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400669 const SkMatrix& viewMatrix,
670 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500671 ASSERT_SINGLE_OWNER_PRIV
672 RETURN_IF_ABANDONED_PRIV
673 SkDEBUGCODE(fRenderTargetContext->validate();)
674 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
675 "GrRenderTargetContext::stencilPath");
676
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500677 SkASSERT(aaType != GrAAType::kCoverage);
Brian Salomon467921e2017-03-06 16:17:12 -0500678
679 bool useHWAA = GrAATypeIsHW(aaType);
680 // TODO: extract portions of checkDraw that are relevant to path stenciling.
681 SkASSERT(path);
682 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
683
684 // FIXME: Use path bounds instead of this WAR once
685 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
686 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
687
688 // Setup clip
Brian Salomon97180af2017-03-14 13:42:58 -0400689 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -0500690 if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true,
Brian Salomon97180af2017-03-14 13:42:58 -0400691 &appliedClip, &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500692 return;
693 }
694
695 // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
696 // attempt this in a situation that would require coverage AA.
697 SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
698
699 GrRenderTarget* rt = fRenderTargetContext->accessRenderTarget();
700 if (!rt) {
701 return;
702 }
703 GrStencilAttachment* stencilAttachment =
704 fRenderTargetContext->fContext->resourceProvider()->attachStencilAttachment(rt);
705 if (!stencilAttachment) {
706 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
707 return;
708 }
709
710 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
711 useHWAA,
712 path->getFillType(),
713 appliedClip.hasStencilClip(),
714 stencilAttachment->bits(),
715 appliedClip.scissorState(),
716 fRenderTargetContext->accessRenderTarget(),
717 path);
Brian Salomon97180af2017-03-14 13:42:58 -0400718 op->setClippedBounds(bounds);
Brian Salomon467921e2017-03-06 16:17:12 -0500719 fRenderTargetContext->getOpList()->recordOp(std::move(op), fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700720}
721
Brian Osman11052242016-10-27 14:47:55 -0400722void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
723 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500724 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400725 const SkMatrix& viewMatrix,
726 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700727 ASSERT_SINGLE_OWNER_PRIV
728 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400729 SkDEBUGCODE(fRenderTargetContext->validate();)
730 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
731 "GrRenderTargetContext::stencilRect");
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500732 SkASSERT(GrAAType::kCoverage != aaType);
Robert Phillips72152832017-01-25 17:31:35 -0500733 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700734
735 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500736 paint.setXPFactory(GrDisableColorXPFactory::Get());
robertphillips976f5f02016-06-03 10:59:20 -0700737
Brian Salomon82f44312017-01-11 13:42:54 -0500738 fRenderTargetContext->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, rect, nullptr,
739 nullptr, ss, aaType);
robertphillips976f5f02016-06-03 10:59:20 -0700740}
741
Brian Osman11052242016-10-27 14:47:55 -0400742bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip,
743 const GrUserStencilSettings* ss,
744 SkRegion::Op op,
745 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500746 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400747 const SkMatrix& viewMatrix,
748 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800749 ASSERT_SINGLE_OWNER_PRIV
750 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400751 SkDEBUGCODE(fRenderTargetContext->validate();)
752 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
753 "GrRenderTargetContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800754
Robert Phillips72152832017-01-25 17:31:35 -0500755 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800756
757 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800758 paint.setCoverageSetOpXPFactory(op, invert);
759
Brian Salomon82f44312017-01-11 13:42:54 -0500760 if (fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800761 return true;
762 }
robertphillips391395d2016-03-02 09:26:36 -0800763 SkPath path;
764 path.setIsVolatile(true);
765 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500766 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800767}
768
Brian Osman11052242016-10-27 14:47:55 -0400769void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500770 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500771 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400772 const SkMatrix& viewMatrix,
773 const SkRect& rectToDraw,
774 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800775 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700776 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700777 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400778 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700779
csmartdalton97f6cd52016-07-13 13:37:08 -0700780 SkRect croppedRect = rectToDraw;
781 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700782 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
783 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700784 return;
785 }
786
Robert Phillips72152832017-01-25 17:31:35 -0500787 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700788
csmartdaltone0d36292016-07-29 08:14:20 -0700789 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400790 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400791 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
792 croppedLocalRect, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500793 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400794 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700795 return;
796 }
797 }
798
Brian Salomon54d212e2017-03-21 14:22:38 -0400799 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500800 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500801 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect,
802 &croppedLocalRect, nullptr, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700803 return;
joshualitt04194f32016-01-13 10:08:27 -0800804 }
bsalomonbb243832016-07-22 07:10:19 -0700805
csmartdaltonfc49d562016-07-26 17:05:47 -0700806 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400807 std::unique_ptr<GrLegacyMeshDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(
Brian Salomonf8334782017-01-03 09:42:58 -0500808 paint.getColor(), viewMatrix, croppedRect, croppedLocalRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500809 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -0400810 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700811 return;
812 }
813
814 SkMatrix viewAndUnLocalMatrix;
815 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
816 SkDebugf("fillRectToRect called with empty local matrix.\n");
817 return;
818 }
819 viewAndUnLocalMatrix.postConcat(viewMatrix);
820
821 SkPath path;
822 path.setIsVolatile(true);
823 path.addRect(localRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500824 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700825}
826
Brian Osman11052242016-10-27 14:47:55 -0400827void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500828 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500829 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400830 const SkMatrix& viewMatrix,
831 const SkRect& rectToDraw,
832 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800833 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700834 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700835 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400836 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700837
csmartdalton97f6cd52016-07-13 13:37:08 -0700838 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700839 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700840 return;
841 }
842
Robert Phillips72152832017-01-25 17:31:35 -0500843 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700844
csmartdaltone0d36292016-07-29 08:14:20 -0700845 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400846 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400847 std::unique_ptr<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, std::move(paint),
848 localMatrix, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500849 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400850 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700851 return;
852 }
853 }
854
Brian Salomon54d212e2017-03-21 14:22:38 -0400855 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500856 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500857 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr,
858 &localMatrix, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700859 return;
bsalomonc55271f2015-11-09 11:55:57 -0800860 }
robertphillips4bc31812016-03-01 12:22:49 -0800861
csmartdaltonfc49d562016-07-26 17:05:47 -0700862 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400863 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -0500864 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500865 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -0400866 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700867 return;
868 }
869
870 SkMatrix viewAndUnLocalMatrix;
871 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
872 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
873 return;
874 }
875 viewAndUnLocalMatrix.postConcat(viewMatrix);
876
877 SkPath path;
878 path.setIsVolatile(true);
879 path.addRect(rectToDraw);
880 path.transform(localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -0500881 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700882}
883
Brian Osman11052242016-10-27 14:47:55 -0400884void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500885 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400886 const SkMatrix& viewMatrix,
887 GrPrimitiveType primitiveType,
888 int vertexCount,
889 const SkPoint positions[],
890 const SkPoint texCoords[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500891 const uint32_t colors[],
Brian Osman11052242016-10-27 14:47:55 -0400892 const uint16_t indices[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500893 int indexCount,
894 ColorArrayType colorArrayType) {
joshualitt1de610a2016-01-06 08:26:09 -0800895 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700896 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700897 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400898 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700899
Robert Phillips72152832017-01-25 17:31:35 -0500900 AutoCheckFlush acf(this->drawingManager());
robertphillips2e1e51f2015-10-15 08:01:48 -0700901
robertphillipsea461502015-05-26 11:38:03 -0700902 // TODO clients should give us bounds
903 SkRect bounds;
904 if (!bounds.setBoundsCheck(positions, vertexCount)) {
905 SkDebugf("drawVertices call empty bounds\n");
906 return;
907 }
908
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400909 std::unique_ptr<GrLegacyMeshDrawOp> op = GrDrawVerticesOp::Make(
Brian Salomon3de0aee2017-01-29 09:34:17 -0500910 paint.getColor(), primitiveType, viewMatrix, positions, vertexCount, indices,
911 indexCount, colors, texCoords, bounds, colorArrayType);
Brian Salomon199fb872017-02-06 09:41:10 -0500912 if (!op) {
913 return;
914 }
915 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400916 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
Brian Salomon199fb872017-02-06 09:41:10 -0500917}
robertphillipsea461502015-05-26 11:38:03 -0700918
Brian Salomon199fb872017-02-06 09:41:10 -0500919void GrRenderTargetContext::drawVertices(const GrClip& clip,
920 GrPaint&& paint,
921 const SkMatrix& viewMatrix,
Mike Reed5fa66452017-03-16 09:06:34 -0400922 sk_sp<SkVertices> vertices) {
Brian Salomon199fb872017-02-06 09:41:10 -0500923 ASSERT_SINGLE_OWNER
924 RETURN_IF_ABANDONED
925 SkDEBUGCODE(this->validate();)
926 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
927
928 AutoCheckFlush acf(this->drawingManager());
929
930 SkASSERT(vertices);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400931 std::unique_ptr<GrLegacyMeshDrawOp> op =
Mike Reed5fa66452017-03-16 09:06:34 -0400932 GrDrawVerticesOp::Make(paint.getColor(), std::move(vertices), viewMatrix);
Brian Salomon199fb872017-02-06 09:41:10 -0500933 if (!op) {
934 return;
935 }
Brian Salomon82f44312017-01-11 13:42:54 -0500936 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400937 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700938}
939
940///////////////////////////////////////////////////////////////////////////////
941
Brian Osman11052242016-10-27 14:47:55 -0400942void GrRenderTargetContext::drawAtlas(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500943 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400944 const SkMatrix& viewMatrix,
945 int spriteCount,
946 const SkRSXform xform[],
947 const SkRect texRect[],
948 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800949 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700950 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700951 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400952 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700953
Robert Phillips72152832017-01-25 17:31:35 -0500954 AutoCheckFlush acf(this->drawingManager());
halcanary9d524f22016-03-29 09:03:52 -0700955
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400956 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomonfc527d22016-12-14 21:07:01 -0500957 GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
Brian Salomon82f44312017-01-11 13:42:54 -0500958 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400959 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -0700960}
961
962///////////////////////////////////////////////////////////////////////////////
963
Brian Osman11052242016-10-27 14:47:55 -0400964void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500965 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500966 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400967 const SkMatrix& viewMatrix,
968 const SkRRect& rrect,
969 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800970 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700971 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700972 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400973 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700974 if (rrect.isEmpty()) {
975 return;
976 }
977
bsalomon7f0d9f32016-08-15 14:49:10 -0700978 GrNoClip noclip;
979 const GrClip* clip = &origClip;
980#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
981 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -0500982 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -0700983 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
984 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
985 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
986 SkRRect devRRect;
987 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
988 clip = &noclip;
989 }
990#endif
bsalomon6663acf2016-05-10 09:14:17 -0700991 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700992
Robert Phillips72152832017-01-25 17:31:35 -0500993 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700994 const SkStrokeRec stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -0700995
csmartdaltone0d36292016-07-29 08:14:20 -0700996 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
997 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400998 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -0400999 std::unique_ptr<GrDrawOp> op(
1000 ir->recordRRect(rrect, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001001 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001002 this->addDrawOp(*clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001003 return;
1004 }
1005 }
1006
Brian Salomon54d212e2017-03-21 14:22:38 -04001007 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001008 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001009 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001010 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -05001011 GrOvalOpFactory::MakeRRectOp(paint.getColor(),
1012 paint.usesDistanceVectorField(),
1013 viewMatrix,
1014 rrect,
1015 stroke,
1016 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001017 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001018 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001019 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), *clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001020 return;
1021 }
robertphillipsea461502015-05-26 11:38:03 -07001022 }
robertphillipsb56f9272016-02-25 11:03:52 -08001023
1024 SkPath path;
1025 path.setIsVolatile(true);
1026 path.addRRect(rrect);
Brian Salomon82f44312017-01-11 13:42:54 -05001027 this->internalDrawPath(*clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001028}
1029
Jim Van Verthc5903412016-11-17 15:27:09 -05001030///////////////////////////////////////////////////////////////////////////////
1031
1032void GrRenderTargetContext::drawShadowRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001033 GrPaint&& paint,
Jim Van Verthc5903412016-11-17 15:27:09 -05001034 const SkMatrix& viewMatrix,
1035 const SkRRect& rrect,
1036 SkScalar blurRadius,
1037 const GrStyle& style) {
1038 ASSERT_SINGLE_OWNER
1039 RETURN_IF_ABANDONED
1040 SkDEBUGCODE(this->validate();)
1041 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect");
1042 if (rrect.isEmpty()) {
1043 return;
1044 }
1045
1046 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1047
Robert Phillips72152832017-01-25 17:31:35 -05001048 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001049 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001050 // TODO: add instancing support?
Jim Van Verthc5903412016-11-17 15:27:09 -05001051
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001052 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001053 std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(
1054 paint.getColor(), viewMatrix, rrect, blurRadius, stroke, shaderCaps);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001055 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001056 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001057 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001058 return;
Jim Van Verthc5903412016-11-17 15:27:09 -05001059 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001060}
1061
1062///////////////////////////////////////////////////////////////////////////////
1063
Brian Osman11052242016-10-27 14:47:55 -04001064bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001065 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001066 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001067 const SkMatrix& viewMatrix,
1068 const SkRRect& origOuter,
1069 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001070 SkASSERT(!origInner.isEmpty());
1071 SkASSERT(!origOuter.isEmpty());
1072
csmartdaltone0d36292016-07-29 08:14:20 -07001073 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001074 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001075 std::unique_ptr<GrDrawOp> op(ir->recordDRRect(
1076 origOuter, origInner, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001077 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001078 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001079 return true;
1080 }
1081 }
1082
Brian Salomon54d212e2017-03-21 14:22:38 -04001083 GrAAType aaType = this->decideAAType(aa);
robertphillips00095892016-02-29 13:50:40 -08001084
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001085 GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
1086 if (GrAAType::kCoverage == aaType) {
1087 innerEdgeType = kInverseFillAA_GrProcessorEdgeType;
1088 outerEdgeType = kFillAA_GrProcessorEdgeType;
1089 } else {
1090 innerEdgeType = kInverseFillBW_GrProcessorEdgeType;
1091 outerEdgeType = kFillBW_GrProcessorEdgeType;
1092 }
robertphillips00095892016-02-29 13:50:40 -08001093
1094 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1095 SkMatrix inverseVM;
1096 if (!viewMatrix.isIdentity()) {
1097 if (!origInner.transform(viewMatrix, inner.writable())) {
1098 return false;
1099 }
1100 if (!origOuter.transform(viewMatrix, outer.writable())) {
1101 return false;
1102 }
1103 if (!viewMatrix.invert(&inverseVM)) {
1104 return false;
1105 }
1106 } else {
1107 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001108 }
robertphillips00095892016-02-29 13:50:40 -08001109
robertphillips00095892016-02-29 13:50:40 -08001110 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -07001111 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -08001112 if (!innerEffect) {
1113 return false;
1114 }
1115
bungeman06ca8ec2016-06-09 08:01:03 -07001116 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -08001117 if (!outerEffect) {
1118 return false;
1119 }
1120
Brian Salomon82f44312017-01-11 13:42:54 -05001121 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1122 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001123
1124 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001125 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001126 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1127 }
halcanary9d524f22016-03-29 09:03:52 -07001128
Brian Salomon82f44312017-01-11 13:42:54 -05001129 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1130 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001131 return true;
1132}
1133
Brian Osman11052242016-10-27 14:47:55 -04001134void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001135 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001136 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001137 const SkMatrix& viewMatrix,
1138 const SkRRect& outer,
1139 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001140 ASSERT_SINGLE_OWNER
1141 RETURN_IF_ABANDONED
1142 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001143 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
robertphillips00095892016-02-29 13:50:40 -08001144
1145 SkASSERT(!outer.isEmpty());
1146 SkASSERT(!inner.isEmpty());
1147
Robert Phillips72152832017-01-25 17:31:35 -05001148 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001149
Brian Salomon82f44312017-01-11 13:42:54 -05001150 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001151 return;
1152 }
1153
1154 SkPath path;
1155 path.setIsVolatile(true);
1156 path.addRRect(inner);
1157 path.addRRect(outer);
1158 path.setFillType(SkPath::kEvenOdd_FillType);
1159
Brian Salomon82f44312017-01-11 13:42:54 -05001160 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -08001161}
1162
robertphillipsea461502015-05-26 11:38:03 -07001163///////////////////////////////////////////////////////////////////////////////
1164
msarettcc319b92016-08-25 18:07:18 -07001165static inline bool is_int(float x) {
1166 return x == (float) sk_float_round2int(x);
1167}
1168
Brian Osman11052242016-10-27 14:47:55 -04001169void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001170 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001171 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001172 const SkMatrix& viewMatrix,
1173 const SkRegion& region,
1174 const GrStyle& style) {
msarettcc319b92016-08-25 18:07:18 -07001175 ASSERT_SINGLE_OWNER
1176 RETURN_IF_ABANDONED
1177 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001178 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
msarettcc319b92016-08-25 18:07:18 -07001179
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001180 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001181 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001182 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001183 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1184 is_int(viewMatrix.getTranslateX()) &&
1185 is_int(viewMatrix.getTranslateY())) {
1186 aa = GrAA::kNo;
1187 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001188 }
msarettcc319b92016-08-25 18:07:18 -07001189 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001190 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001191 SkPath path;
1192 region.getBoundaryPath(&path);
Brian Salomon82f44312017-01-11 13:42:54 -05001193 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001194 }
1195
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001196 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
Brian Salomon82f44312017-01-11 13:42:54 -05001197 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001198 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001199}
1200
Brian Osman11052242016-10-27 14:47:55 -04001201void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001202 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001203 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001204 const SkMatrix& viewMatrix,
1205 const SkRect& oval,
1206 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001207 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001208 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001209 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001210 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001211
robertphillipsea461502015-05-26 11:38:03 -07001212 if (oval.isEmpty()) {
1213 return;
1214 }
1215
bsalomon6663acf2016-05-10 09:14:17 -07001216 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001217
Robert Phillips72152832017-01-25 17:31:35 -05001218 AutoCheckFlush acf(this->drawingManager());
bsalomon6663acf2016-05-10 09:14:17 -07001219 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -07001220
csmartdaltone0d36292016-07-29 08:14:20 -07001221 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1222 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001223 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon54d212e2017-03-21 14:22:38 -04001224 std::unique_ptr<GrDrawOp> op(
1225 ir->recordOval(oval, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001226 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001227 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001228 return;
1229 }
1230 }
1231
Brian Salomon54d212e2017-03-21 14:22:38 -04001232 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001233 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001234 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001235 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon289e3d82016-12-14 15:52:56 -05001236 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001237 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001238 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001239 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001240 return;
1241 }
robertphillipsea461502015-05-26 11:38:03 -07001242 }
robertphillipsb56f9272016-02-25 11:03:52 -08001243
1244 SkPath path;
1245 path.setIsVolatile(true);
1246 path.addOval(oval);
Brian Salomon82f44312017-01-11 13:42:54 -05001247 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001248}
1249
Brian Osman11052242016-10-27 14:47:55 -04001250void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001251 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001252 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001253 const SkMatrix& viewMatrix,
1254 const SkRect& oval,
1255 SkScalar startAngle,
1256 SkScalar sweepAngle,
1257 bool useCenter,
1258 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001259 ASSERT_SINGLE_OWNER
1260 RETURN_IF_ABANDONED
1261 SkDEBUGCODE(this->validate();)
1262 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawArc");
1263
1264 AutoCheckFlush acf(this->drawingManager());
1265
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001266 GrAAType aaType = this->decideAAType(aa);
1267 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001268 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001269 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
1270 viewMatrix,
1271 oval,
1272 startAngle,
1273 sweepAngle,
1274 useCenter,
1275 style,
1276 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001277 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001278 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001279 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001280 return;
1281 }
1282 }
1283 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001284 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1285 style.isSimpleFill());
Brian Salomon82f44312017-01-11 13:42:54 -05001286 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001287}
1288
Brian Osman11052242016-10-27 14:47:55 -04001289void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001290 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001291 const SkMatrix& viewMatrix,
1292 int imageWidth,
1293 int imageHeight,
1294 std::unique_ptr<SkLatticeIter> iter,
1295 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001296 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001297 RETURN_IF_ABANDONED
1298 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001299 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001300
Robert Phillips72152832017-01-25 17:31:35 -05001301 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001302
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001303 std::unique_ptr<GrLegacyMeshDrawOp> op = GrLatticeOp::MakeNonAA(
Brian Salomon649a3412017-03-09 13:50:43 -05001304 paint.getColor(), viewMatrix, imageWidth, imageHeight, std::move(iter), dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001305
Brian Salomon82f44312017-01-11 13:42:54 -05001306 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001307 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001308}
1309
Brian Osman11052242016-10-27 14:47:55 -04001310void GrRenderTargetContext::prepareForExternalIO() {
robertphillips8c523e02016-07-26 07:41:00 -07001311 ASSERT_SINGLE_OWNER
1312 RETURN_IF_ABANDONED
1313 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001314 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
robertphillips8c523e02016-07-26 07:41:00 -07001315
Robert Phillips7ee385e2017-03-30 08:02:11 -04001316 this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get());
robertphillips8c523e02016-07-26 07:41:00 -07001317}
joshualitt33a5fce2015-11-18 13:28:51 -08001318
Brian Osman11052242016-10-27 14:47:55 -04001319void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001320 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001321 const SkMatrix& viewMatrix,
1322 const SkRect& rect,
1323 const SkRect* localRect,
1324 const SkMatrix* localMatrix,
1325 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001326 GrAAType hwOrNoneAAType) {
1327 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
1328 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001329 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill(
1330 paint.getColor(), viewMatrix, rect, localRect, localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -05001331 GrPipelineBuilder pipelineBuilder(std::move(paint), hwOrNoneAAType);
robertphillips44302392016-07-08 14:43:03 -07001332 if (ss) {
1333 pipelineBuilder.setUserStencil(ss);
1334 }
Brian Salomone14bd802017-04-04 15:13:25 -04001335 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -07001336}
1337
robertphillipsea461502015-05-26 11:38:03 -07001338// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001339static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001340
1341 if (path.isInverseFillType()) {
1342 return false;
1343 }
1344
1345 // TODO: this restriction could be lifted if we were willing to apply
1346 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001347 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001348 return false;
1349 }
1350
1351 SkPath::Direction dirs[2];
1352 if (!path.isNestedFillRects(rects, dirs)) {
1353 return false;
1354 }
1355
1356 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1357 // The two rects need to be wound opposite to each other
1358 return false;
1359 }
1360
1361 // Right now, nested rects where the margin is not the same width
1362 // all around do not render correctly
1363 const SkScalar* outer = rects[0].asScalars();
1364 const SkScalar* inner = rects[1].asScalars();
1365
1366 bool allEq = true;
1367
1368 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1369 bool allGoE1 = margin >= SK_Scalar1;
1370
1371 for (int i = 1; i < 4; ++i) {
1372 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1373 if (temp < SK_Scalar1) {
1374 allGoE1 = false;
1375 }
1376 if (!SkScalarNearlyEqual(margin, temp)) {
1377 allEq = false;
1378 }
1379 }
1380
1381 return allEq || allGoE1;
1382}
1383
Brian Osman11052242016-10-27 14:47:55 -04001384void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001385 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001386 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001387 const SkMatrix& viewMatrix,
1388 const SkPath& path,
1389 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001390 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001391 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001392 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001393 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001394
robertphillipsea461502015-05-26 11:38:03 -07001395 if (path.isEmpty()) {
1396 if (path.isInverseFillType()) {
Brian Salomon82f44312017-01-11 13:42:54 -05001397 this->drawPaint(clip, std::move(paint), viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001398 }
1399 return;
1400 }
1401
Robert Phillips72152832017-01-25 17:31:35 -05001402 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001403
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001404 GrAAType aaType = this->decideAAType(aa);
1405 if (GrAAType::kCoverage == aaType && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001406 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001407 // Concave AA paths are expensive - try to avoid them for special cases
1408 SkRect rects[2];
1409
bsalomon6663acf2016-05-10 09:14:17 -07001410 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001411 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -05001412 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001413 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001414 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001415 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon40ef4852016-05-02 13:22:13 -07001416 }
robertphillipsea461502015-05-26 11:38:03 -07001417 return;
1418 }
1419 }
1420 SkRect ovalRect;
1421 bool isOval = path.isOval(&ovalRect);
1422
1423 if (isOval && !path.isInverseFillType()) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001424 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001425 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeOvalOp(
Brian Salomon289e3d82016-12-14 15:52:56 -05001426 paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001427 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001428 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001429 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001430 return;
1431 }
1432 }
1433 }
robertphillips4bc31812016-03-01 12:22:49 -08001434
1435 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1436 // Scratch textures can be recycled after they are returned to the texture
1437 // cache. This presents a potential hazard for buffered drawing. However,
1438 // the writePixels that uploads to the scratch will perform a flush so we're
1439 // OK.
Brian Salomon82f44312017-01-11 13:42:54 -05001440 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001441}
1442
Brian Osman11052242016-10-27 14:47:55 -04001443bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip,
1444 const GrUserStencilSettings* ss,
1445 SkRegion::Op op,
1446 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001447 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001448 const SkMatrix& viewMatrix,
1449 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001450 ASSERT_SINGLE_OWNER_PRIV
1451 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001452 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001453 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
1454 "GrRenderTargetContextPriv::drawAndStencilPath");
robertphillips391395d2016-03-02 09:26:36 -08001455
1456 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001457 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001458 SkRect::MakeIWH(fRenderTargetContext->width(),
1459 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001460 return true;
1461 }
1462
Robert Phillips72152832017-01-25 17:31:35 -05001463 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001464
1465 // An Assumption here is that path renderer would use some form of tweaking
1466 // the src color (either the input alpha or in the frag shader) to implement
1467 // aa. If we have some future driver-mojo path AA that can do the right
1468 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001469 GrAAType aaType = fRenderTargetContext->decideAAType(aa);
robertphillips976f5f02016-06-03 10:59:20 -07001470 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001471
bsalomon8acedde2016-06-24 10:42:16 -07001472 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001473 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Osman11052242016-10-27 14:47:55 -04001474 canDrawArgs.fShaderCaps =
Robert Phillips72152832017-01-25 17:31:35 -05001475 fRenderTargetContext->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips391395d2016-03-02 09:26:36 -08001476 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001477 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001478 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001479 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001480
1481 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001482 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001483 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001484 if (!pr) {
1485 return false;
1486 }
1487
1488 GrPaint paint;
1489 paint.setCoverageSetOpXPFactory(op, invert);
1490
Brian Salomon82f44312017-01-11 13:42:54 -05001491 GrPathRenderer::DrawPathArgs args{
Robert Phillips256c37b2017-03-01 14:32:46 -05001492 fRenderTargetContext->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001493 std::move(paint),
1494 ss,
1495 fRenderTargetContext,
1496 &clip,
1497 &viewMatrix,
1498 &shape,
1499 aaType,
1500 fRenderTargetContext->isGammaCorrect()};
robertphillips391395d2016-03-02 09:26:36 -08001501 pr->drawPath(args);
1502 return true;
1503}
1504
Brian Osman11052242016-10-27 14:47:55 -04001505SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001506 ASSERT_SINGLE_OWNER_PRIV
1507
Brian Osman11052242016-10-27 14:47:55 -04001508 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001509 return SkBudgeted::kNo;
1510 }
1511
Brian Osman11052242016-10-27 14:47:55 -04001512 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001513
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001514 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001515}
1516
Brian Osman11052242016-10-27 14:47:55 -04001517void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001518 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001519 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001520 const SkMatrix& viewMatrix,
1521 const SkPath& path,
1522 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001523 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001524 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001525 SkASSERT(!path.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001526 GrShape shape;
robertphillipsea461502015-05-26 11:38:03 -07001527
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001528 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true);
1529 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) {
1530 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and
1531 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1532 // smoother hairlines than MSAA.
1533 aaType = GrAAType::kCoverage;
bsalomon0a0f67e2016-06-28 11:56:42 -07001534 }
robertphillips68737822015-10-29 12:12:21 -07001535 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Robert Phillips72152832017-01-25 17:31:35 -05001536 canDrawArgs.fShaderCaps = this->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips68737822015-10-29 12:12:21 -07001537 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001538 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001539 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001540
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001541 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001542 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001543 do {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001544 shape = GrShape(path, style);
bsalomon8acedde2016-06-24 10:42:16 -07001545 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001546 return;
1547 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001548
1549 canDrawArgs.fAAType = aaType;
1550
1551 // Try a 1st time without applying any of the style to the geometry (and barring sw)
Robert Phillips72152832017-01-25 17:31:35 -05001552 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001553 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1554
1555 if (!pr && shape.style().pathEffect()) {
1556 // It didn't work above, so try again with the path effect applied.
1557 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
bsalomon8acedde2016-06-24 10:42:16 -07001558 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001559 return;
1560 }
Robert Phillips72152832017-01-25 17:31:35 -05001561 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
bsalomon6663acf2016-05-10 09:14:17 -07001562 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001563 if (!pr) {
1564 if (shape.style().applies()) {
1565 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1566 if (shape.isEmpty()) {
1567 return;
1568 }
1569 }
1570 // This time, allow SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001571 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001572 }
Brian Salomon0abc8b42016-12-13 10:22:54 -05001573 if (!pr && GrAATypeIsHW(aaType)) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001574 // There are exceptional cases where we may wind up falling back to coverage based AA
1575 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions).
1576 aaType = GrAAType::kCoverage;
1577 } else {
1578 break;
1579 }
1580 } while(true);
robertphillipsea461502015-05-26 11:38:03 -07001581
bsalomon8acedde2016-06-24 10:42:16 -07001582 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001583#ifdef SK_DEBUG
1584 SkDebugf("Unable to find path renderer compatible with path.\n");
1585#endif
1586 return;
1587 }
1588
Robert Phillips256c37b2017-03-01 14:32:46 -05001589 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001590 std::move(paint),
1591 &GrUserStencilSettings::kUnused,
1592 this,
1593 &clip,
1594 &viewMatrix,
1595 &shape,
1596 aaType,
1597 this->isGammaCorrect()};
bsalomon0aff2fa2015-07-31 06:48:27 -07001598 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001599}
1600
Brian Salomon467921e2017-03-06 16:17:12 -05001601static void op_bounds(SkRect* bounds, const GrOp* op) {
1602 *bounds = op->bounds();
1603 if (op->hasZeroArea()) {
1604 if (op->hasAABloat()) {
1605 bounds->outset(0.5f, 0.5f);
1606 } else {
1607 // We don't know which way the particular GPU will snap lines or points at integer
1608 // coords. So we ensure that the bounds is large enough for either snap.
1609 SkRect before = *bounds;
1610 bounds->roundOut(bounds);
1611 if (bounds->fLeft == before.fLeft) {
1612 bounds->fLeft -= 1;
1613 }
1614 if (bounds->fTop == before.fTop) {
1615 bounds->fTop -= 1;
1616 }
1617 if (bounds->fRight == before.fRight) {
1618 bounds->fRight += 1;
1619 }
1620 if (bounds->fBottom == before.fBottom) {
1621 bounds->fBottom += 1;
1622 }
1623 }
1624 }
1625}
1626
Brian Salomon54d212e2017-03-21 14:22:38 -04001627uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001628 ASSERT_SINGLE_OWNER
Robert Phillipsc0138922017-03-08 11:50:55 -05001629 if (this->drawingManager()->wasAbandoned()) {
1630 return SK_InvalidUniqueID;
1631 }
robertphillips2e1e51f2015-10-15 08:01:48 -07001632 SkDEBUGCODE(this->validate();)
Brian Salomon42521e82016-12-07 16:44:58 -05001633 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
robertphillips2d70dcb2015-10-06 07:38:23 -07001634
Brian Salomon467921e2017-03-06 16:17:12 -05001635 // Setup clip
1636 SkRect bounds;
1637 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04001638 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04001639 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1640 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1641 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1642 &bounds)) {
1643 return SK_InvalidUniqueID;
1644 }
1645
1646 // This forces instantiation of the render target.
1647 GrRenderTarget* rt = this->accessRenderTarget();
1648 if (!rt) {
1649 return SK_InvalidUniqueID;
1650 }
1651
1652 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1653 appliedClip.hasStencilClip()) {
1654 if (!fContext->resourceProvider()->attachStencilAttachment(rt)) {
1655 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
1656 return SK_InvalidUniqueID;
1657 }
1658 }
1659
1660 GrXferProcessor::DstTexture dstTexture;
1661 if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001662 this->setupDstTexture(rt, clip, op->bounds(), &dstTexture);
1663 if (!dstTexture.texture()) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001664 return SK_InvalidUniqueID;
1665 }
1666 }
1667
1668 op->setClippedBounds(bounds);
1669 return this->getOpList()->addOp(std::move(op), this, std::move(appliedClip), dstTexture);
1670}
1671
Brian Salomone14bd802017-04-04 15:13:25 -04001672uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(GrPipelineBuilder&& pipelineBuilder,
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001673 const GrClip& clip,
1674 std::unique_ptr<GrLegacyMeshDrawOp> op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001675 ASSERT_SINGLE_OWNER
1676 if (this->drawingManager()->wasAbandoned()) {
1677 return SK_InvalidUniqueID;
1678 }
1679 SkDEBUGCODE(this->validate();)
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001680 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addLegacyMeshDrawOp");
Brian Salomon54d212e2017-03-21 14:22:38 -04001681
1682 // Setup clip
1683 SkRect bounds;
1684 op_bounds(&bounds, op.get());
1685 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -05001686 if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
Brian Salomon97180af2017-03-14 13:42:58 -04001687 pipelineBuilder.hasUserStencilSettings(), &appliedClip, &bounds)) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001688 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001689 }
1690
1691 // This forces instantiation of the render target. Pipeline creation is moving to flush time
1692 // by which point instantiation must have occurred anyway.
1693 GrRenderTarget* rt = this->accessRenderTarget();
1694 if (!rt) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001695 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001696 }
1697
1698 GrResourceProvider* resourceProvider = fContext->resourceProvider();
1699 if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
1700 if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
1701 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
Robert Phillipsc0138922017-03-08 11:50:55 -05001702 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001703 }
1704 }
1705
Brian Salomona811b122017-03-30 08:21:32 -04001706 GrProcessorSet::Analysis analysis;
Brian Salomone14bd802017-04-04 15:13:25 -04001707 op->analyzeProcessors(&analysis, &pipelineBuilder, &appliedClip, *this->caps());
Brian Salomon467921e2017-03-06 16:17:12 -05001708
1709 GrPipeline::InitArgs args;
1710 pipelineBuilder.getPipelineInitArgs(&args);
1711 args.fAppliedClip = &appliedClip;
1712 args.fRenderTarget = rt;
1713 args.fCaps = this->caps();
Brian Salomone14bd802017-04-04 15:13:25 -04001714 args.fXPInputColor = analysis.outputColor();
1715 args.fXPInputCoverage = analysis.outputCoverage();
Brian Salomon467921e2017-03-06 16:17:12 -05001716
Brian Salomon31853842017-03-28 16:32:05 -04001717 if (analysis.requiresDstTexture()) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001718 this->setupDstTexture(rt, clip, bounds, &args.fDstTexture);
1719 if (!args.fDstTexture.texture()) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001720 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001721 }
1722 }
Brian Salomone14bd802017-04-04 15:13:25 -04001723 op->initPipeline(args, analysis);
Brian Salomon467921e2017-03-06 16:17:12 -05001724 // TODO: We need to add pipeline dependencies on textures, etc before recording this op.
Brian Salomon97180af2017-03-14 13:42:58 -04001725 op->setClippedBounds(bounds);
Robert Phillipsc0138922017-03-08 11:50:55 -05001726 return this->getOpList()->addOp(std::move(op), this);
Brian Salomon467921e2017-03-06 16:17:12 -05001727}
1728
Robert Phillips9a121cc2017-04-06 21:17:15 +00001729void GrRenderTargetContext::setupDstTexture(GrRenderTarget* rt, const GrClip& clip,
Brian Salomon467921e2017-03-06 16:17:12 -05001730 const SkRect& opBounds,
1731 GrXferProcessor::DstTexture* dstTexture) {
1732 if (this->caps()->textureBarrierSupport()) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001733 if (GrTexture* rtTex = rt->asTexture()) {
Brian Salomon467921e2017-03-06 16:17:12 -05001734 // The render target is a texture, so we can read from it directly in the shader. The XP
1735 // will be responsible to detect this situation and request a texture barrier.
Robert Phillips9a121cc2017-04-06 21:17:15 +00001736 dstTexture->setTexture(sk_ref_sp(rtTex));
Brian Salomon467921e2017-03-06 16:17:12 -05001737 dstTexture->setOffset(0, 0);
Robert Phillips9a121cc2017-04-06 21:17:15 +00001738 return;
Brian Salomon467921e2017-03-06 16:17:12 -05001739 }
1740 }
1741
Robert Phillips9a121cc2017-04-06 21:17:15 +00001742 SkIRect copyRect = SkIRect::MakeWH(rt->width(), rt->height());
Brian Salomon467921e2017-03-06 16:17:12 -05001743
Eric Karl74480882017-04-03 14:49:05 -07001744 SkIRect clippedRect;
Robert Phillips9a121cc2017-04-06 21:17:15 +00001745 clip.getConservativeBounds(rt->width(), rt->height(), &clippedRect);
Eric Karl72e551e2017-04-04 13:42:10 -07001746 SkIRect drawIBounds;
Brian Salomon467921e2017-03-06 16:17:12 -05001747 opBounds.roundOut(&drawIBounds);
Brian Salomon859621f2017-03-16 09:21:54 -04001748 // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
1749 drawIBounds.outset(1, 1);
Eric Karl72e551e2017-04-04 13:42:10 -07001750 if (!clippedRect.intersect(drawIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001751#ifdef SK_DEBUG
Robert Phillips9a121cc2017-04-06 21:17:15 +00001752 GrCapsDebugf(this->caps(), "Missed an early reject. "
1753 "Bailing on draw from setupDstTexture.\n");
Brian Salomon467921e2017-03-06 16:17:12 -05001754#endif
Robert Phillips9a121cc2017-04-06 21:17:15 +00001755 return;
Brian Salomon467921e2017-03-06 16:17:12 -05001756 }
1757
1758 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
1759 // have per-sample dst values by making the copy multisampled.
1760 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07001761 bool rectsMustMatch = false;
1762 bool disallowSubrect = false;
Robert Phillips9a121cc2017-04-06 21:17:15 +00001763 if (!this->caps()->initDescForDstCopy(rt, &desc, &rectsMustMatch, &disallowSubrect)) {
1764 desc.fOrigin = kDefault_GrSurfaceOrigin;
Brian Salomon467921e2017-03-06 16:17:12 -05001765 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillips9a121cc2017-04-06 21:17:15 +00001766 desc.fConfig = rt->config();
Brian Salomon467921e2017-03-06 16:17:12 -05001767 }
1768
Eric Karl74480882017-04-03 14:49:05 -07001769 if (!disallowSubrect) {
1770 copyRect = clippedRect;
1771 }
Brian Salomon467921e2017-03-06 16:17:12 -05001772
Robert Phillips9a121cc2017-04-06 21:17:15 +00001773 SkIPoint dstPoint;
1774 SkIPoint dstOffset;
1775 static const uint32_t kFlags = 0;
1776 sk_sp<GrTexture> copy;
Eric Karl74480882017-04-03 14:49:05 -07001777 if (rectsMustMatch) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001778 SkASSERT(desc.fOrigin == rt->origin());
1779 desc.fWidth = rt->width();
1780 desc.fHeight = rt->height();
Eric Karl74480882017-04-03 14:49:05 -07001781 dstPoint = {copyRect.fLeft, copyRect.fTop};
1782 dstOffset = {0, 0};
Robert Phillips9a121cc2017-04-06 21:17:15 +00001783 copy = fContext->resourceProvider()->createTexture(desc, SkBudgeted::kYes, kFlags);
Eric Karl74480882017-04-03 14:49:05 -07001784 } else {
1785 desc.fWidth = copyRect.width();
1786 desc.fHeight = copyRect.height();
1787 dstPoint = {0, 0};
1788 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillips9a121cc2017-04-06 21:17:15 +00001789 copy.reset(fContext->resourceProvider()->createApproxTexture(desc, kFlags));
Eric Karl74480882017-04-03 14:49:05 -07001790 }
Brian Salomon467921e2017-03-06 16:17:12 -05001791
1792 if (!copy) {
Robert Phillips9a121cc2017-04-06 21:17:15 +00001793 SkDebugf("Failed to create temporary copy of destination texture.\n");
1794 return;
Brian Salomon467921e2017-03-06 16:17:12 -05001795 }
Eric Karl74480882017-04-03 14:49:05 -07001796
Robert Phillips9a121cc2017-04-06 21:17:15 +00001797 this->getOpList()->copySurface(copy.get(), rt, copyRect, dstPoint);
Brian Salomon467921e2017-03-06 16:17:12 -05001798 dstTexture->setTexture(std::move(copy));
Eric Karl74480882017-04-03 14:49:05 -07001799 dstTexture->setOffset(dstOffset);
robertphillips2334fb62015-06-17 05:43:33 -07001800}