blob: 41fa6dce0de38a0a84d25846c03cfb75379f05e8 [file] [log] [blame]
robertphillipsea461502015-05-26 11:38:03 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Brian Osman11052242016-10-27 14:47:55 -04008#include "GrRenderTargetContext.h"
Brian Salomon467921e2017-03-06 16:17:12 -05009#include "GrAppliedClip.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050010#include "GrColor.h"
Robert Phillipse78b7252017-04-06 07:59:41 -040011#include "GrContextPriv.h"
robertphillips77a2e522015-10-17 07:43:27 -070012#include "GrDrawingManager.h"
csmartdalton02fa32c2016-08-19 13:29:27 -070013#include "GrFixedClip.h"
robertphillips714712b2016-08-04 06:20:45 -070014#include "GrGpuResourcePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070015#include "GrPathRenderer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070016#include "GrPipelineBuilder.h"
robertphillips2334fb62015-06-17 05:43:33 -070017#include "GrRenderTarget.h"
Brian Salomon5ec9def2016-12-20 15:34:05 -050018#include "GrRenderTargetContextPriv.h"
robertphillips2334fb62015-06-17 05:43:33 -070019#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070020#include "GrResourceProvider.h"
Brian Salomon467921e2017-03-06 16:17:12 -050021#include "GrStencilAttachment.h"
22#include "SkLatticeIter.h"
23#include "SkMatrixPriv.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070024#include "SkSurfacePriv.h"
Brian Salomon467921e2017-03-06 16:17:12 -050025#include "effects/GrRRectEffect.h"
26#include "instanced/InstancedRendering.h"
Brian Salomon89527432016-12-16 09:52:16 -050027#include "ops/GrClearOp.h"
Robert Phillipsb9a02a12017-04-06 11:08:40 -040028#include "ops/GrClearStencilClipOp.h"
Robert Phillipse4407212017-04-13 10:13:16 -040029#include "ops/GrDiscardOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050030#include "ops/GrDrawOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050031#include "ops/GrDrawAtlasOp.h"
32#include "ops/GrDrawVerticesOp.h"
33#include "ops/GrLatticeOp.h"
34#include "ops/GrOp.h"
35#include "ops/GrOvalOpFactory.h"
36#include "ops/GrRectOpFactory.h"
37#include "ops/GrRegionOp.h"
38#include "ops/GrShadowRRectOp.h"
Brian Salomon467921e2017-03-06 16:17:12 -050039#include "ops/GrStencilPathOp.h"
joshualitte8042922015-12-11 06:11:21 -080040#include "text/GrAtlasTextContext.h"
41#include "text/GrStencilAndCoverTextContext.h"
joshualittbc907352016-01-13 06:45:40 -080042#include "../private/GrAuditTrail.h"
43
Robert Phillips72152832017-01-25 17:31:35 -050044#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080045#define ASSERT_SINGLE_OWNER \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -040046 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
robertphillips391395d2016-03-02 09:26:36 -080047#define ASSERT_SINGLE_OWNER_PRIV \
Robert Phillipsa90aa2b2017-04-10 08:19:26 -040048 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
Robert Phillips72152832017-01-25 17:31:35 -050049#define RETURN_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return; }
50#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return; }
51#define RETURN_FALSE_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return false; }
52#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->drawingManager()->wasAbandoned()) { return false; }
53#define RETURN_NULL_IF_ABANDONED if (this->drawingManager()->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070054
55class 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))
Robert Phillipsdc83b892017-04-13 12:23:54 -040083 , fOpList(sk_ref_sp(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 Phillipsdc83b892017-04-13 12:23:54 -0400101 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList.get());
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
robertphillipsa106c622015-10-16 09:07:06 -0700108}
109
Robert Phillipsf200a902017-01-30 13:27:37 -0500110GrTextureProxy* GrRenderTargetContext::asTextureProxy() {
Robert Phillipseaa86252016-11-08 13:49:39 +0000111 return fRenderTargetProxy->asTextureProxy();
112}
113
Robert Phillipsf200a902017-01-30 13:27:37 -0500114sk_sp<GrTextureProxy> GrRenderTargetContext::asTextureProxyRef() {
115 return sk_ref_sp(fRenderTargetProxy->asTextureProxy());
116}
117
Brian Osman11052242016-10-27 14:47:55 -0400118GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800119 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700120 SkDEBUGCODE(this->validate();)
121
Robert Phillipsf2361d22016-10-25 14:20:06 -0400122 if (!fOpList || fOpList->isClosed()) {
Robert Phillipsdc83b892017-04-13 12:23:54 -0400123 fOpList = this->drawingManager()->newRTOpList(fRenderTargetProxy);
robertphillipsa106c622015-10-16 09:07:06 -0700124 }
125
Robert Phillipsdc83b892017-04-13 12:23:54 -0400126 return fOpList.get();
robertphillipsa106c622015-10-16 09:07:06 -0700127}
128
Robert Phillips7ce67db2017-04-18 17:10:13 +0000129// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
Robert Phillipse2f7d182016-12-15 09:23:05 -0500130bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
131 const SkIRect& srcRect,
132 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800133 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800134 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700135 SkDEBUGCODE(this->validate();)
Robert Phillipsbf25d432017-04-07 10:08:53 -0400136 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::onCopy");
Robert Phillipse2f7d182016-12-15 09:23:05 -0500137
Robert Phillipsbf25d432017-04-07 10:08:53 -0400138 return this->getOpList()->copySurface(fContext->resourceProvider(),
Robert Phillips178ce3e2017-04-13 09:15:47 -0400139 this, srcProxy, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700140}
141
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500142void GrRenderTargetContext::drawText(const GrClip& clip, const SkPaint& skPaint,
Brian Salomon82f44312017-01-11 13:42:54 -0500143 const SkMatrix& viewMatrix, const char text[],
144 size_t byteLength, SkScalar x, SkScalar y,
145 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800146 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700147 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700148 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400149 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700150
Robert Phillips72152832017-01-25 17:31:35 -0500151 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500152 atlasTextContext->drawText(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, text,
153 byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700154}
robertphillipscaef3452015-11-11 13:18:11 -0800155
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500156void GrRenderTargetContext::drawPosText(const GrClip& clip, const SkPaint& paint,
157 const SkMatrix& viewMatrix, const char text[],
158 size_t byteLength, const SkScalar pos[],
Brian Salomon82f44312017-01-11 13:42:54 -0500159 int scalarsPerPosition, const SkPoint& offset,
160 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800161 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700162 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700163 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400164 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700165
Robert Phillips72152832017-01-25 17:31:35 -0500166 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500167 atlasTextContext->drawPosText(fContext, this, clip, paint, viewMatrix, fSurfaceProps, text,
168 byteLength, pos, scalarsPerPosition, offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700169}
robertphillipscaef3452015-11-11 13:18:11 -0800170
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500171void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& paint,
Brian Osman11052242016-10-27 14:47:55 -0400172 const SkMatrix& viewMatrix, const SkTextBlob* blob,
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500173 SkScalar x, SkScalar y, SkDrawFilter* filter,
174 const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800175 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700176 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700177 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400178 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700179
Robert Phillips72152832017-01-25 17:31:35 -0500180 GrAtlasTextContext* atlasTextContext = this->drawingManager()->getAtlasTextContext();
Brian Salomon6f1d36c2017-01-13 12:02:17 -0500181 atlasTextContext->drawTextBlob(fContext, this, clip, paint, viewMatrix, fSurfaceProps, blob, x,
182 y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700183}
184
Brian Osman11052242016-10-27 14:47:55 -0400185void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800186 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700187 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700188 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400189 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700190
Robert Phillips72152832017-01-25 17:31:35 -0500191 AutoCheckFlush acf(this->drawingManager());
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400192
Robert Phillipse4407212017-04-13 10:13:16 -0400193 // Currently this just inserts a discard op. However, once in MDB this can remove all the
194 // previously recorded ops and change the load op to discard.
195 if (this->caps()->discardRenderTargetSupport()) {
196 std::unique_ptr<GrOp> op(GrDiscardOp::Make(this));
197 if (!op) {
198 return;
199 }
200 this->getOpList()->addOp(std::move(op), this);
201 }
robertphillipsea461502015-05-26 11:38:03 -0700202}
203
Brian Osman11052242016-10-27 14:47:55 -0400204void GrRenderTargetContext::clear(const SkIRect* rect,
205 const GrColor color,
206 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800207 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700208 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700209 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400210 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700211
Robert Phillips72152832017-01-25 17:31:35 -0500212 AutoCheckFlush acf(this->drawingManager());
csmartdalton29df7602016-08-31 11:55:52 -0700213 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
214}
robertphillips9199a9f2016-07-13 07:48:43 -0700215
Robert Phillips784b7bf2016-12-09 13:35:02 -0500216void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
217 ASSERT_SINGLE_OWNER_PRIV
218 RETURN_IF_ABANDONED_PRIV
219 SkDEBUGCODE(fRenderTargetContext->validate();)
220 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
221 "GrRenderTargetContext::absClear");
222
Robert Phillips72152832017-01-25 17:31:35 -0500223 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillips784b7bf2016-12-09 13:35:02 -0500224
225 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(
226 *fRenderTargetContext->caps()),
227 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight(
228 *fRenderTargetContext->caps()));
229
230 if (clearRect) {
231 if (clearRect->contains(rtRect)) {
232 clearRect = nullptr; // full screen
233 } else {
234 if (!rtRect.intersect(*clearRect)) {
235 return;
236 }
237 }
238 }
239
240 // TODO: in a post-MDB world this should be handled at the OpList level.
241 // An op-list that is initially cleared and has no other ops should receive an
242 // extra draw.
243 if (fRenderTargetContext->fContext->caps()->useDrawInsteadOfClear()) {
244 // This works around a driver bug with clear by drawing a rect instead.
245 // The driver will ignore a clear if it is the only thing rendered to a
246 // target before the target is read.
247 GrPaint paint;
248 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500249 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
Robert Phillips784b7bf2016-12-09 13:35:02 -0500250
251 // We don't call drawRect() here to avoid the cropping to the, possibly smaller,
252 // RenderTargetProxy bounds
Brian Salomon82f44312017-01-11 13:42:54 -0500253 fRenderTargetContext->drawNonAAFilledRect(GrNoClip(), std::move(paint), SkMatrix::I(),
254 SkRect::Make(rtRect), nullptr, nullptr, nullptr,
255 GrAAType::kNone);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500256
257 } else {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500258 // This path doesn't handle coalescing of full screen clears b.c. it
259 // has to clear the entire render target - not just the content area.
260 // It could be done but will take more finagling.
Robert Phillipsf7a72612017-03-31 10:03:45 -0400261 std::unique_ptr<GrOp> op(GrClearOp::Make(rtRect, color, fRenderTargetContext, !clearRect));
Brian Salomonfc527d22016-12-14 21:07:01 -0500262 if (!op) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500263 return;
264 }
Brian Salomon69868af2016-12-22 15:42:51 -0500265 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500266 }
267}
268
Brian Osman11052242016-10-27 14:47:55 -0400269void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
270 const GrColor color,
271 bool canIgnoreClip) {
csmartdalton29df7602016-08-31 11:55:52 -0700272 ASSERT_SINGLE_OWNER_PRIV
273 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400274 SkDEBUGCODE(fRenderTargetContext->validate();)
275 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
276 "GrRenderTargetContextPriv::clear");
csmartdalton29df7602016-08-31 11:55:52 -0700277
Robert Phillips72152832017-01-25 17:31:35 -0500278 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Brian Osman11052242016-10-27 14:47:55 -0400279 fRenderTargetContext->internalClear(clip, color, canIgnoreClip);
csmartdalton29df7602016-08-31 11:55:52 -0700280}
281
Brian Osman11052242016-10-27 14:47:55 -0400282void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
283 const GrColor color,
284 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700285 bool isFull = false;
286 if (!clip.hasWindowRectangles()) {
287 isFull = !clip.scissorEnabled() ||
288 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
289 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
290 }
robertphillips9199a9f2016-07-13 07:48:43 -0700291
292 if (fContext->caps()->useDrawInsteadOfClear()) {
293 // This works around a driver bug with clear by drawing a rect instead.
294 // The driver will ignore a clear if it is the only thing rendered to a
295 // target before the target is read.
Robert Phillips784b7bf2016-12-09 13:35:02 -0500296 SkIRect clearRect = SkIRect::MakeWH(this->width(), this->height());
csmartdalton29df7602016-08-31 11:55:52 -0700297 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700298 this->discard();
Robert Phillips93f16332016-11-23 19:37:13 -0500299 } else if (!clearRect.intersect(clip.scissorRect())) {
csmartdalton29df7602016-08-31 11:55:52 -0700300 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700301 }
302
303 GrPaint paint;
304 paint.setColor4f(GrColor4f::FromGrColor(color));
Brian Salomona1633922017-01-09 11:46:10 -0500305 paint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
robertphillips9199a9f2016-07-13 07:48:43 -0700306
Brian Salomon82f44312017-01-11 13:42:54 -0500307 this->drawRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect));
bsalomon9f129de2016-08-10 16:31:05 -0700308 } else if (isFull) {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400309 this->getOpList()->fullClear(this, color);
robertphillips9199a9f2016-07-13 07:48:43 -0700310 } else {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400311 std::unique_ptr<GrOp> op(GrClearOp::Make(clip, color, this));
Brian Salomon42521e82016-12-07 16:44:58 -0500312 if (!op) {
csmartdalton29df7602016-08-31 11:55:52 -0700313 return;
314 }
Brian Salomon69868af2016-12-22 15:42:51 -0500315 this->getOpList()->addOp(std::move(op), this);
robertphillips9199a9f2016-07-13 07:48:43 -0700316 }
robertphillipsea461502015-05-26 11:38:03 -0700317}
318
Brian Osman11052242016-10-27 14:47:55 -0400319void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500320 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400321 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800322 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700323 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700324 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400325 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700326
robertphillipsea461502015-05-26 11:38:03 -0700327 // set rect to be big enough to fill the space, but not super-huge, so we
328 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700329
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400330 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700331
bsalomoncb31e512016-08-26 10:48:19 -0700332 SkRRect rrect;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500333 GrAA aa;
bsalomoncb31e512016-08-26 10:48:19 -0700334 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
335 // transformation for non-rect rrects. Rects caused a performance regression on an Android
336 // test that needs investigation. We also skip cases where there are fragment processors
337 // because they may depend on having correct local coords and this path draws in device space
338 // without a local matrix.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500339 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500340 this->drawRRect(GrNoClip(), std::move(paint), aa, SkMatrix::I(), rrect,
341 GrStyle::SimpleFill());
bsalomoncb31e512016-08-26 10:48:19 -0700342 return;
343 }
344
robertphillipsea461502015-05-26 11:38:03 -0700345
346 bool isPerspective = viewMatrix.hasPerspective();
347
348 // We attempt to map r by the inverse matrix and draw that. mapRect will
349 // map the four corners and bound them with a new rect. This will not
350 // produce a correct result for some perspective matrices.
351 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700352 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700353 SkDebugf("Could not invert matrix\n");
354 return;
355 }
Brian Salomon82f44312017-01-11 13:42:54 -0500356 this->drawRect(clip, std::move(paint), GrAA::kNo, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700357 } else {
358 SkMatrix localMatrix;
359 if (!viewMatrix.invert(&localMatrix)) {
360 SkDebugf("Could not invert matrix\n");
361 return;
362 }
363
Robert Phillips72152832017-01-25 17:31:35 -0500364 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700365
Brian Salomon82f44312017-01-11 13:42:54 -0500366 this->drawNonAAFilledRect(clip, std::move(paint), SkMatrix::I(), r, nullptr, &localMatrix,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500367 nullptr, GrAAType::kNone);
robertphillipsea461502015-05-26 11:38:03 -0700368 }
369}
370
robertphillipsea461502015-05-26 11:38:03 -0700371static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
372 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
373 point.fY >= rect.fTop && point.fY <= rect.fBottom;
374}
375
bsalomonc55271f2015-11-09 11:55:57 -0800376static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
377 return viewMatrix.preservesRightAngles();
378}
379
csmartdalton97f6cd52016-07-13 13:37:08 -0700380// Attempts to crop a rect and optional local rect to the clip boundaries.
381// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700382static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700383 const SkMatrix& viewMatrix, SkRect* rect,
384 SkRect* localRect = nullptr) {
385 if (!viewMatrix.rectStaysRect()) {
386 return true;
387 }
388
csmartdalton97f6cd52016-07-13 13:37:08 -0700389 SkIRect clipDevBounds;
390 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700391
robertphillips13a7eee2016-08-31 15:06:24 -0700392 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700393 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
394 return false;
395 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700396
397 if (localRect) {
398 if (!rect->intersects(clipBounds)) {
399 return false;
400 }
401 const SkScalar dx = localRect->width() / rect->width();
402 const SkScalar dy = localRect->height() / rect->height();
403 if (clipBounds.fLeft > rect->fLeft) {
404 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
405 rect->fLeft = clipBounds.fLeft;
406 }
407 if (clipBounds.fTop > rect->fTop) {
408 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
409 rect->fTop = clipBounds.fTop;
410 }
411 if (clipBounds.fRight < rect->fRight) {
412 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
413 rect->fRight = clipBounds.fRight;
414 }
415 if (clipBounds.fBottom < rect->fBottom) {
416 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
417 rect->fBottom = clipBounds.fBottom;
418 }
419 return true;
420 }
421
422 return rect->intersect(clipBounds);
423}
424
Brian Osman11052242016-10-27 14:47:55 -0400425bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500426 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500427 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400428 const SkMatrix& viewMatrix,
429 const SkRect& rect,
430 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700431 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500432 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700433 return true;
434 }
robertphillips44302392016-07-08 14:43:03 -0700435
Brian Salomon54d212e2017-03-21 14:22:38 -0400436 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
437 (!ss || ss->isDisabled(false))) {
Robert Phillipse3302df2017-04-24 07:31:02 -0400438 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
439 std::unique_ptr<GrDrawOp> op = oa->recordRect(croppedRect, viewMatrix, std::move(paint),
440 aa, fInstancedPipelineInfo);
Brian Salomon42521e82016-12-07 16:44:58 -0500441 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400442 this->addDrawOp(clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700443 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700444 }
445 }
Brian Salomon54d212e2017-03-21 14:22:38 -0400446 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500447 if (GrAAType::kCoverage == aaType) {
robertphillips391395d2016-03-02 09:26:36 -0800448 // The fill path can handle rotation but not skew.
449 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
450 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700451 viewMatrix.mapRect(&devBoundRect, croppedRect);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400452 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -0500453 GrRectOpFactory::MakeAAFill(paint, viewMatrix, rect, croppedRect, devBoundRect);
Brian Salomon42521e82016-12-07 16:44:58 -0500454 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500455 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
robertphillips44302392016-07-08 14:43:03 -0700456 if (ss) {
457 pipelineBuilder.setUserStencil(ss);
458 }
Brian Salomone14bd802017-04-04 15:13:25 -0400459 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700460 return true;
461 }
robertphillips391395d2016-03-02 09:26:36 -0800462 }
463 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500464 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr, nullptr,
465 ss, aaType);
robertphillips44302392016-07-08 14:43:03 -0700466 return true;
robertphillips391395d2016-03-02 09:26:36 -0800467 }
468
robertphillips44302392016-07-08 14:43:03 -0700469 return false;
robertphillips391395d2016-03-02 09:26:36 -0800470}
471
Brian Osman11052242016-10-27 14:47:55 -0400472void GrRenderTargetContext::drawRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500473 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500474 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400475 const SkMatrix& viewMatrix,
476 const SkRect& rect,
477 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700478 if (!style) {
479 style = &GrStyle::SimpleFill();
480 }
joshualitt1de610a2016-01-06 08:26:09 -0800481 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700482 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700483 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400484 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700485
bsalomon6663acf2016-05-10 09:14:17 -0700486 // Path effects should've been devolved to a path in SkGpuDevice
487 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700488
Robert Phillips72152832017-01-25 17:31:35 -0500489 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -0700490
bsalomon6663acf2016-05-10 09:14:17 -0700491 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700492 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
493
494 if (!fContext->caps()->useDrawInsteadOfClear()) {
495 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
496 // checking cases where the RT is fully inside a stroke.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400497 SkRect rtRect = fRenderTargetProxy->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700498 // Does the clip contain the entire RT?
499 if (clip.quickContains(rtRect)) {
500 SkMatrix invM;
501 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700502 return;
503 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700504 // Does the rect bound the RT?
505 SkPoint srcSpaceRTQuad[4];
506 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
507 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
508 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
509 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
510 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
511 // Will it blend?
512 GrColor clearColor;
513 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700514 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700515 return;
516 }
517 }
robertphillipsea461502015-05-26 11:38:03 -0700518 }
519 }
robertphillips44302392016-07-08 14:43:03 -0700520
Brian Salomon82f44312017-01-11 13:42:54 -0500521 if (this->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, nullptr)) {
robertphillips44302392016-07-08 14:43:03 -0700522 return;
523 }
bsalomona7d85ba2016-07-06 11:54:59 -0700524 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
525 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
526 if ((!rect.width() || !rect.height()) &&
527 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
528 SkScalar r = stroke.getWidth() / 2;
529 // TODO: Move these stroke->fill fallbacks to GrShape?
530 switch (stroke.getJoin()) {
531 case SkPaint::kMiter_Join:
Brian Salomon82f44312017-01-11 13:42:54 -0500532 this->drawRect(
533 clip, std::move(paint), aa, viewMatrix,
534 {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
535 &GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700536 return;
537 case SkPaint::kRound_Join:
538 // Raster draws nothing when both dimensions are empty.
539 if (rect.width() || rect.height()){
540 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon82f44312017-01-11 13:42:54 -0500541 this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
542 GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700543 return;
544 }
545 case SkPaint::kBevel_Join:
546 if (!rect.width()) {
Brian Salomon82f44312017-01-11 13:42:54 -0500547 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700548 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
549 &GrStyle::SimpleFill());
550 } else {
Brian Salomon82f44312017-01-11 13:42:54 -0500551 this->drawRect(clip, std::move(paint), aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700552 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
553 &GrStyle::SimpleFill());
554 }
555 return;
556 }
557 }
robertphillips44302392016-07-08 14:43:03 -0700558
robertphillips44302392016-07-08 14:43:03 -0700559 bool snapToPixelCenters = false;
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400560 std::unique_ptr<GrLegacyMeshDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700561
robertphillips391395d2016-03-02 09:26:36 -0800562 GrColor color = paint.getColor();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500563 GrAAType aaType = this->decideAAType(aa);
564 if (GrAAType::kCoverage == aaType) {
cdaltonbb539482016-01-04 09:48:25 -0800565 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
566 if (viewMatrix.rectStaysRect()) {
Brian Salomon6a639042016-12-14 11:08:17 -0500567 op = GrRectOpFactory::MakeAAStroke(color, viewMatrix, rect, stroke);
cdaltonbb539482016-01-04 09:48:25 -0800568 }
robertphillipsea461502015-05-26 11:38:03 -0700569 } else {
robertphillips391395d2016-03-02 09:26:36 -0800570 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700571 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800572 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700573 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400574 !fRenderTargetProxy->isUnifiedMultisampled();
Brian Salomon6a639042016-12-14 11:08:17 -0500575 op = GrRectOpFactory::MakeNonAAStroke(color, viewMatrix, rect, stroke,
576 snapToPixelCenters);
robertphillips391395d2016-03-02 09:26:36 -0800577 }
robertphillips4bc31812016-03-01 12:22:49 -0800578
Brian Salomon42521e82016-12-07 16:44:58 -0500579 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500580 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomon189098e72017-01-19 09:55:19 -0500581 pipelineBuilder.setSnapVerticesToPixelCenters(snapToPixelCenters);
Brian Salomone14bd802017-04-04 15:13:25 -0400582 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700583 return;
robertphillips4bc31812016-03-01 12:22:49 -0800584 }
robertphillips4bc31812016-03-01 12:22:49 -0800585 }
halcanary9d524f22016-03-29 09:03:52 -0700586
robertphillips4bc31812016-03-01 12:22:49 -0800587 SkPath path;
588 path.setIsVolatile(true);
589 path.addRect(rect);
Brian Salomon82f44312017-01-11 13:42:54 -0500590 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700591}
592
Robert Phillipsec2249f2016-11-09 08:54:35 -0500593int GrRenderTargetContextPriv::maxWindowRectangles() const {
594 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
595 *fRenderTargetContext->fContext->caps());
596}
597
Brian Osman11052242016-10-27 14:47:55 -0400598void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700599 ASSERT_SINGLE_OWNER_PRIV
600 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400601 SkDEBUGCODE(fRenderTargetContext->validate();)
602 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
603 "GrRenderTargetContextPriv::clearStencilClip");
robertphillips976f5f02016-06-03 10:59:20 -0700604
Robert Phillips72152832017-01-25 17:31:35 -0500605 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400606
607 std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(clip, insideStencilMask,
608 fRenderTargetContext));
609 if (!op) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500610 return;
611 }
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400612 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700613}
614
Brian Osman11052242016-10-27 14:47:55 -0400615void GrRenderTargetContextPriv::stencilPath(const GrClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500616 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400617 const SkMatrix& viewMatrix,
618 const GrPath* path) {
Brian Salomon467921e2017-03-06 16:17:12 -0500619 ASSERT_SINGLE_OWNER_PRIV
620 RETURN_IF_ABANDONED_PRIV
621 SkDEBUGCODE(fRenderTargetContext->validate();)
622 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
623 "GrRenderTargetContext::stencilPath");
624
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500625 SkASSERT(aaType != GrAAType::kCoverage);
Brian Salomon467921e2017-03-06 16:17:12 -0500626
627 bool useHWAA = GrAATypeIsHW(aaType);
628 // TODO: extract portions of checkDraw that are relevant to path stenciling.
629 SkASSERT(path);
630 SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
631
632 // FIXME: Use path bounds instead of this WAR once
633 // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
634 SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
635
636 // Setup clip
Brian Salomon97180af2017-03-14 13:42:58 -0400637 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -0500638 if (!clip.apply(fRenderTargetContext->fContext, fRenderTargetContext, useHWAA, true,
Brian Salomon97180af2017-03-14 13:42:58 -0400639 &appliedClip, &bounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -0500640 return;
641 }
642
643 // Coverage AA does not make sense when rendering to the stencil buffer. The caller should never
644 // attempt this in a situation that would require coverage AA.
645 SkASSERT(!appliedClip.clipCoverageFragmentProcessor());
646
647 GrRenderTarget* rt = fRenderTargetContext->accessRenderTarget();
648 if (!rt) {
649 return;
650 }
651 GrStencilAttachment* stencilAttachment =
652 fRenderTargetContext->fContext->resourceProvider()->attachStencilAttachment(rt);
653 if (!stencilAttachment) {
654 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
655 return;
656 }
657
658 std::unique_ptr<GrOp> op = GrStencilPathOp::Make(viewMatrix,
659 useHWAA,
660 path->getFillType(),
661 appliedClip.hasStencilClip(),
662 stencilAttachment->bits(),
663 appliedClip.scissorState(),
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400664 fRenderTargetContext,
Brian Salomon467921e2017-03-06 16:17:12 -0500665 path);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400666 if (!op) {
667 return;
668 }
Brian Salomon97180af2017-03-14 13:42:58 -0400669 op->setClippedBounds(bounds);
Robert Phillipsb9a02a12017-04-06 11:08:40 -0400670 fRenderTargetContext->getOpList()->addOp(std::move(op), fRenderTargetContext);
robertphillips976f5f02016-06-03 10:59:20 -0700671}
672
Brian Osman11052242016-10-27 14:47:55 -0400673void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
674 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500675 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400676 const SkMatrix& viewMatrix,
677 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700678 ASSERT_SINGLE_OWNER_PRIV
679 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400680 SkDEBUGCODE(fRenderTargetContext->validate();)
681 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
682 "GrRenderTargetContext::stencilRect");
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500683 SkASSERT(GrAAType::kCoverage != aaType);
Robert Phillips72152832017-01-25 17:31:35 -0500684 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips976f5f02016-06-03 10:59:20 -0700685
686 GrPaint paint;
Brian Salomona1633922017-01-09 11:46:10 -0500687 paint.setXPFactory(GrDisableColorXPFactory::Get());
robertphillips976f5f02016-06-03 10:59:20 -0700688
Brian Salomon82f44312017-01-11 13:42:54 -0500689 fRenderTargetContext->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, rect, nullptr,
690 nullptr, ss, aaType);
robertphillips976f5f02016-06-03 10:59:20 -0700691}
692
Brian Osman11052242016-10-27 14:47:55 -0400693bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip,
694 const GrUserStencilSettings* ss,
695 SkRegion::Op op,
696 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500697 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400698 const SkMatrix& viewMatrix,
699 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800700 ASSERT_SINGLE_OWNER_PRIV
701 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400702 SkDEBUGCODE(fRenderTargetContext->validate();)
703 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
704 "GrRenderTargetContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800705
Robert Phillips72152832017-01-25 17:31:35 -0500706 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -0800707
708 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800709 paint.setCoverageSetOpXPFactory(op, invert);
710
Brian Salomon82f44312017-01-11 13:42:54 -0500711 if (fRenderTargetContext->drawFilledRect(clip, std::move(paint), aa, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800712 return true;
713 }
robertphillips391395d2016-03-02 09:26:36 -0800714 SkPath path;
715 path.setIsVolatile(true);
716 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500717 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800718}
719
Brian Osman11052242016-10-27 14:47:55 -0400720void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500721 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500722 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400723 const SkMatrix& viewMatrix,
724 const SkRect& rectToDraw,
725 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800726 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700727 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700728 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400729 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700730
csmartdalton97f6cd52016-07-13 13:37:08 -0700731 SkRect croppedRect = rectToDraw;
732 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700733 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
734 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700735 return;
736 }
737
Robert Phillips72152832017-01-25 17:31:35 -0500738 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700739
csmartdaltone0d36292016-07-29 08:14:20 -0700740 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipse3302df2017-04-24 07:31:02 -0400741 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
742 std::unique_ptr<GrDrawOp> op(oa->recordRect(croppedRect, viewMatrix, std::move(paint),
Brian Salomon54d212e2017-03-21 14:22:38 -0400743 croppedLocalRect, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500744 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400745 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700746 return;
747 }
748 }
749
Brian Salomon54d212e2017-03-21 14:22:38 -0400750 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500751 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500752 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect,
753 &croppedLocalRect, nullptr, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700754 return;
joshualitt04194f32016-01-13 10:08:27 -0800755 }
bsalomonbb243832016-07-22 07:10:19 -0700756
csmartdaltonfc49d562016-07-26 17:05:47 -0700757 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400758 std::unique_ptr<GrLegacyMeshDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(
Brian Salomonf8334782017-01-03 09:42:58 -0500759 paint.getColor(), viewMatrix, croppedRect, croppedLocalRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500760 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -0400761 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700762 return;
763 }
764
765 SkMatrix viewAndUnLocalMatrix;
766 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
767 SkDebugf("fillRectToRect called with empty local matrix.\n");
768 return;
769 }
770 viewAndUnLocalMatrix.postConcat(viewMatrix);
771
772 SkPath path;
773 path.setIsVolatile(true);
774 path.addRect(localRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500775 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700776}
777
Brian Osman11052242016-10-27 14:47:55 -0400778void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500779 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500780 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400781 const SkMatrix& viewMatrix,
782 const SkRect& rectToDraw,
783 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800784 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700785 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700786 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400787 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700788
csmartdalton97f6cd52016-07-13 13:37:08 -0700789 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700790 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700791 return;
792 }
793
Robert Phillips72152832017-01-25 17:31:35 -0500794 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700795
csmartdaltone0d36292016-07-29 08:14:20 -0700796 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipse3302df2017-04-24 07:31:02 -0400797 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
798 std::unique_ptr<GrDrawOp> op(oa->recordRect(croppedRect, viewMatrix, std::move(paint),
Brian Salomon54d212e2017-03-21 14:22:38 -0400799 localMatrix, aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500800 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400801 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700802 return;
803 }
804 }
805
Brian Salomon54d212e2017-03-21 14:22:38 -0400806 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500807 if (GrAAType::kCoverage != aaType) {
Brian Salomon82f44312017-01-11 13:42:54 -0500808 this->drawNonAAFilledRect(clip, std::move(paint), viewMatrix, croppedRect, nullptr,
809 &localMatrix, nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700810 return;
bsalomonc55271f2015-11-09 11:55:57 -0800811 }
robertphillips4bc31812016-03-01 12:22:49 -0800812
csmartdaltonfc49d562016-07-26 17:05:47 -0700813 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400814 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -0500815 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
Brian Salomon82f44312017-01-11 13:42:54 -0500816 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -0400817 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700818 return;
819 }
820
821 SkMatrix viewAndUnLocalMatrix;
822 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
823 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
824 return;
825 }
826 viewAndUnLocalMatrix.postConcat(viewMatrix);
827
828 SkPath path;
829 path.setIsVolatile(true);
830 path.addRect(rectToDraw);
831 path.transform(localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -0500832 this->internalDrawPath(clip, std::move(paint), aa, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700833}
834
Brian Osman11052242016-10-27 14:47:55 -0400835void GrRenderTargetContext::drawVertices(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500836 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400837 const SkMatrix& viewMatrix,
838 GrPrimitiveType primitiveType,
839 int vertexCount,
840 const SkPoint positions[],
841 const SkPoint texCoords[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500842 const uint32_t colors[],
Brian Osman11052242016-10-27 14:47:55 -0400843 const uint16_t indices[],
Brian Salomon3de0aee2017-01-29 09:34:17 -0500844 int indexCount,
845 ColorArrayType colorArrayType) {
joshualitt1de610a2016-01-06 08:26:09 -0800846 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700847 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700848 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400849 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700850
Robert Phillips72152832017-01-25 17:31:35 -0500851 AutoCheckFlush acf(this->drawingManager());
robertphillips2e1e51f2015-10-15 08:01:48 -0700852
robertphillipsea461502015-05-26 11:38:03 -0700853 // TODO clients should give us bounds
854 SkRect bounds;
855 if (!bounds.setBoundsCheck(positions, vertexCount)) {
856 SkDebugf("drawVertices call empty bounds\n");
857 return;
858 }
859
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400860 std::unique_ptr<GrLegacyMeshDrawOp> op = GrDrawVerticesOp::Make(
Brian Salomon3de0aee2017-01-29 09:34:17 -0500861 paint.getColor(), primitiveType, viewMatrix, positions, vertexCount, indices,
862 indexCount, colors, texCoords, bounds, colorArrayType);
Brian Salomon199fb872017-02-06 09:41:10 -0500863 if (!op) {
864 return;
865 }
866 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400867 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
Brian Salomon199fb872017-02-06 09:41:10 -0500868}
robertphillipsea461502015-05-26 11:38:03 -0700869
Brian Salomon199fb872017-02-06 09:41:10 -0500870void GrRenderTargetContext::drawVertices(const GrClip& clip,
871 GrPaint&& paint,
872 const SkMatrix& viewMatrix,
Mike Reed5fa66452017-03-16 09:06:34 -0400873 sk_sp<SkVertices> vertices) {
Brian Salomon199fb872017-02-06 09:41:10 -0500874 ASSERT_SINGLE_OWNER
875 RETURN_IF_ABANDONED
876 SkDEBUGCODE(this->validate();)
877 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
878
879 AutoCheckFlush acf(this->drawingManager());
880
881 SkASSERT(vertices);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400882 std::unique_ptr<GrLegacyMeshDrawOp> op =
Mike Reed5fa66452017-03-16 09:06:34 -0400883 GrDrawVerticesOp::Make(paint.getColor(), std::move(vertices), viewMatrix);
Brian Salomon199fb872017-02-06 09:41:10 -0500884 if (!op) {
885 return;
886 }
Brian Salomon82f44312017-01-11 13:42:54 -0500887 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400888 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700889}
890
891///////////////////////////////////////////////////////////////////////////////
892
Brian Osman11052242016-10-27 14:47:55 -0400893void GrRenderTargetContext::drawAtlas(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500894 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -0400895 const SkMatrix& viewMatrix,
896 int spriteCount,
897 const SkRSXform xform[],
898 const SkRect texRect[],
899 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800900 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700901 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700902 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400903 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700904
Robert Phillips72152832017-01-25 17:31:35 -0500905 AutoCheckFlush acf(this->drawingManager());
halcanary9d524f22016-03-29 09:03:52 -0700906
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400907 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomonfc527d22016-12-14 21:07:01 -0500908 GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
Brian Salomon82f44312017-01-11 13:42:54 -0500909 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -0400910 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -0700911}
912
913///////////////////////////////////////////////////////////////////////////////
914
Brian Osman11052242016-10-27 14:47:55 -0400915void GrRenderTargetContext::drawRRect(const GrClip& origClip,
Brian Salomon82f44312017-01-11 13:42:54 -0500916 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500917 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400918 const SkMatrix& viewMatrix,
919 const SkRRect& rrect,
920 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800921 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700922 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700923 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400924 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700925 if (rrect.isEmpty()) {
926 return;
927 }
928
bsalomon7f0d9f32016-08-15 14:49:10 -0700929 GrNoClip noclip;
930 const GrClip* clip = &origClip;
931#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
932 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -0500933 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -0700934 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
935 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
936 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
937 SkRRect devRRect;
938 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
939 clip = &noclip;
940 }
941#endif
bsalomon6663acf2016-05-10 09:14:17 -0700942 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700943
Robert Phillips72152832017-01-25 17:31:35 -0500944 AutoCheckFlush acf(this->drawingManager());
csmartdaltona7f29642016-07-07 08:49:11 -0700945 const SkStrokeRec stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -0700946
csmartdaltone0d36292016-07-29 08:14:20 -0700947 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
948 stroke.isFillStyle()) {
Robert Phillipse3302df2017-04-24 07:31:02 -0400949 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
Brian Salomon54d212e2017-03-21 14:22:38 -0400950 std::unique_ptr<GrDrawOp> op(
Robert Phillipse3302df2017-04-24 07:31:02 -0400951 oa->recordRRect(rrect, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -0500952 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -0400953 this->addDrawOp(*clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700954 return;
955 }
956 }
957
Brian Salomon54d212e2017-03-21 14:22:38 -0400958 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500959 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -0500960 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400961 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon649a3412017-03-09 13:50:43 -0500962 GrOvalOpFactory::MakeRRectOp(paint.getColor(),
963 paint.usesDistanceVectorField(),
964 viewMatrix,
965 rrect,
966 stroke,
967 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -0500968 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -0500969 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -0400970 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), *clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -0800971 return;
972 }
robertphillipsea461502015-05-26 11:38:03 -0700973 }
robertphillipsb56f9272016-02-25 11:03:52 -0800974
975 SkPath path;
976 path.setIsVolatile(true);
977 path.addRRect(rrect);
Brian Salomon82f44312017-01-11 13:42:54 -0500978 this->internalDrawPath(*clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700979}
980
Jim Van Verthc5903412016-11-17 15:27:09 -0500981///////////////////////////////////////////////////////////////////////////////
982
983void GrRenderTargetContext::drawShadowRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -0500984 GrPaint&& paint,
Jim Van Verthc5903412016-11-17 15:27:09 -0500985 const SkMatrix& viewMatrix,
986 const SkRRect& rrect,
987 SkScalar blurRadius,
988 const GrStyle& style) {
989 ASSERT_SINGLE_OWNER
990 RETURN_IF_ABANDONED
991 SkDEBUGCODE(this->validate();)
992 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect");
993 if (rrect.isEmpty()) {
994 return;
995 }
996
997 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
998
Robert Phillips72152832017-01-25 17:31:35 -0500999 AutoCheckFlush acf(this->drawingManager());
Jim Van Verthc5903412016-11-17 15:27:09 -05001000 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001001 // TODO: add instancing support?
Jim Van Verthc5903412016-11-17 15:27:09 -05001002
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001003 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001004 std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(
1005 paint.getColor(), viewMatrix, rrect, blurRadius, stroke, shaderCaps);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001006 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001007 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001008 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001009 return;
Jim Van Verthc5903412016-11-17 15:27:09 -05001010 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001011}
1012
1013///////////////////////////////////////////////////////////////////////////////
1014
Brian Osman11052242016-10-27 14:47:55 -04001015bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001016 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001017 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001018 const SkMatrix& viewMatrix,
1019 const SkRRect& origOuter,
1020 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001021 SkASSERT(!origInner.isEmpty());
1022 SkASSERT(!origOuter.isEmpty());
1023
csmartdaltone0d36292016-07-29 08:14:20 -07001024 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipse3302df2017-04-24 07:31:02 -04001025 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
1026 std::unique_ptr<GrDrawOp> op(oa->recordDRRect(
Brian Salomon54d212e2017-03-21 14:22:38 -04001027 origOuter, origInner, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001028 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001029 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001030 return true;
1031 }
1032 }
1033
Brian Salomon54d212e2017-03-21 14:22:38 -04001034 GrAAType aaType = this->decideAAType(aa);
robertphillips00095892016-02-29 13:50:40 -08001035
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001036 GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
1037 if (GrAAType::kCoverage == aaType) {
1038 innerEdgeType = kInverseFillAA_GrProcessorEdgeType;
1039 outerEdgeType = kFillAA_GrProcessorEdgeType;
1040 } else {
1041 innerEdgeType = kInverseFillBW_GrProcessorEdgeType;
1042 outerEdgeType = kFillBW_GrProcessorEdgeType;
1043 }
robertphillips00095892016-02-29 13:50:40 -08001044
1045 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1046 SkMatrix inverseVM;
1047 if (!viewMatrix.isIdentity()) {
1048 if (!origInner.transform(viewMatrix, inner.writable())) {
1049 return false;
1050 }
1051 if (!origOuter.transform(viewMatrix, outer.writable())) {
1052 return false;
1053 }
1054 if (!viewMatrix.invert(&inverseVM)) {
1055 return false;
1056 }
1057 } else {
1058 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001059 }
robertphillips00095892016-02-29 13:50:40 -08001060
robertphillips00095892016-02-29 13:50:40 -08001061 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -07001062 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -08001063 if (!innerEffect) {
1064 return false;
1065 }
1066
bungeman06ca8ec2016-06-09 08:01:03 -07001067 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -08001068 if (!outerEffect) {
1069 return false;
1070 }
1071
Brian Salomon82f44312017-01-11 13:42:54 -05001072 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1073 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001074
1075 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001076 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001077 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1078 }
halcanary9d524f22016-03-29 09:03:52 -07001079
Brian Salomon82f44312017-01-11 13:42:54 -05001080 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1081 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001082 return true;
1083}
1084
Brian Osman11052242016-10-27 14:47:55 -04001085void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001086 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001087 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001088 const SkMatrix& viewMatrix,
1089 const SkRRect& outer,
1090 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001091 ASSERT_SINGLE_OWNER
1092 RETURN_IF_ABANDONED
1093 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001094 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
robertphillips00095892016-02-29 13:50:40 -08001095
1096 SkASSERT(!outer.isEmpty());
1097 SkASSERT(!inner.isEmpty());
1098
Robert Phillips72152832017-01-25 17:31:35 -05001099 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001100
Brian Salomon82f44312017-01-11 13:42:54 -05001101 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001102 return;
1103 }
1104
1105 SkPath path;
1106 path.setIsVolatile(true);
1107 path.addRRect(inner);
1108 path.addRRect(outer);
1109 path.setFillType(SkPath::kEvenOdd_FillType);
1110
Brian Salomon82f44312017-01-11 13:42:54 -05001111 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -08001112}
1113
robertphillipsea461502015-05-26 11:38:03 -07001114///////////////////////////////////////////////////////////////////////////////
1115
msarettcc319b92016-08-25 18:07:18 -07001116static inline bool is_int(float x) {
1117 return x == (float) sk_float_round2int(x);
1118}
1119
Brian Osman11052242016-10-27 14:47:55 -04001120void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001121 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001122 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001123 const SkMatrix& viewMatrix,
1124 const SkRegion& region,
1125 const GrStyle& style) {
msarettcc319b92016-08-25 18:07:18 -07001126 ASSERT_SINGLE_OWNER
1127 RETURN_IF_ABANDONED
1128 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001129 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
msarettcc319b92016-08-25 18:07:18 -07001130
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001131 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001132 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001133 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001134 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1135 is_int(viewMatrix.getTranslateX()) &&
1136 is_int(viewMatrix.getTranslateY())) {
1137 aa = GrAA::kNo;
1138 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001139 }
msarettcc319b92016-08-25 18:07:18 -07001140 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001141 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001142 SkPath path;
1143 region.getBoundaryPath(&path);
Brian Salomon82f44312017-01-11 13:42:54 -05001144 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001145 }
1146
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001147 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
Brian Salomon82f44312017-01-11 13:42:54 -05001148 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001149 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001150}
1151
Brian Osman11052242016-10-27 14:47:55 -04001152void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001153 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001154 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001155 const SkMatrix& viewMatrix,
1156 const SkRect& oval,
1157 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001158 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001159 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001160 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001161 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001162
robertphillipsea461502015-05-26 11:38:03 -07001163 if (oval.isEmpty()) {
1164 return;
1165 }
1166
bsalomon6663acf2016-05-10 09:14:17 -07001167 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001168
Robert Phillips72152832017-01-25 17:31:35 -05001169 AutoCheckFlush acf(this->drawingManager());
bsalomon6663acf2016-05-10 09:14:17 -07001170 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -07001171
csmartdaltone0d36292016-07-29 08:14:20 -07001172 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1173 stroke.isFillStyle()) {
Robert Phillipse3302df2017-04-24 07:31:02 -04001174 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
Brian Salomon54d212e2017-03-21 14:22:38 -04001175 std::unique_ptr<GrDrawOp> op(
Robert Phillipse3302df2017-04-24 07:31:02 -04001176 oa->recordOval(oval, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001177 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001178 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001179 return;
1180 }
1181 }
1182
Brian Salomon54d212e2017-03-21 14:22:38 -04001183 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001184 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001185 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001186 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon289e3d82016-12-14 15:52:56 -05001187 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001188 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001189 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001190 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001191 return;
1192 }
robertphillipsea461502015-05-26 11:38:03 -07001193 }
robertphillipsb56f9272016-02-25 11:03:52 -08001194
1195 SkPath path;
1196 path.setIsVolatile(true);
1197 path.addOval(oval);
Brian Salomon82f44312017-01-11 13:42:54 -05001198 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001199}
1200
Brian Osman11052242016-10-27 14:47:55 -04001201void GrRenderTargetContext::drawArc(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 SkScalar startAngle,
1207 SkScalar sweepAngle,
1208 bool useCenter,
1209 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001210 ASSERT_SINGLE_OWNER
1211 RETURN_IF_ABANDONED
1212 SkDEBUGCODE(this->validate();)
1213 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawArc");
1214
1215 AutoCheckFlush acf(this->drawingManager());
1216
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001217 GrAAType aaType = this->decideAAType(aa);
1218 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001219 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001220 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
1221 viewMatrix,
1222 oval,
1223 startAngle,
1224 sweepAngle,
1225 useCenter,
1226 style,
1227 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001228 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001229 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001230 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001231 return;
1232 }
1233 }
1234 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001235 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1236 style.isSimpleFill());
Brian Salomon82f44312017-01-11 13:42:54 -05001237 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001238}
1239
Brian Osman11052242016-10-27 14:47:55 -04001240void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001241 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001242 const SkMatrix& viewMatrix,
1243 int imageWidth,
1244 int imageHeight,
1245 std::unique_ptr<SkLatticeIter> iter,
1246 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001247 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001248 RETURN_IF_ABANDONED
1249 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001250 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001251
Robert Phillips72152832017-01-25 17:31:35 -05001252 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001253
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001254 std::unique_ptr<GrLegacyMeshDrawOp> op = GrLatticeOp::MakeNonAA(
Brian Salomon649a3412017-03-09 13:50:43 -05001255 paint.getColor(), viewMatrix, imageWidth, imageHeight, std::move(iter), dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001256
Brian Salomon82f44312017-01-11 13:42:54 -05001257 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001258 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001259}
1260
Brian Osman11052242016-10-27 14:47:55 -04001261void GrRenderTargetContext::prepareForExternalIO() {
robertphillips8c523e02016-07-26 07:41:00 -07001262 ASSERT_SINGLE_OWNER
1263 RETURN_IF_ABANDONED
1264 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001265 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
robertphillips8c523e02016-07-26 07:41:00 -07001266
Robert Phillips7ee385e2017-03-30 08:02:11 -04001267 this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get());
robertphillips8c523e02016-07-26 07:41:00 -07001268}
joshualitt33a5fce2015-11-18 13:28:51 -08001269
Brian Osman11052242016-10-27 14:47:55 -04001270void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001271 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001272 const SkMatrix& viewMatrix,
1273 const SkRect& rect,
1274 const SkRect* localRect,
1275 const SkMatrix* localMatrix,
1276 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001277 GrAAType hwOrNoneAAType) {
1278 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
1279 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001280 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill(
1281 paint.getColor(), viewMatrix, rect, localRect, localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -05001282 GrPipelineBuilder pipelineBuilder(std::move(paint), hwOrNoneAAType);
robertphillips44302392016-07-08 14:43:03 -07001283 if (ss) {
1284 pipelineBuilder.setUserStencil(ss);
1285 }
Brian Salomone14bd802017-04-04 15:13:25 -04001286 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -07001287}
1288
robertphillipsea461502015-05-26 11:38:03 -07001289// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001290static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001291
1292 if (path.isInverseFillType()) {
1293 return false;
1294 }
1295
1296 // TODO: this restriction could be lifted if we were willing to apply
1297 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001298 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001299 return false;
1300 }
1301
1302 SkPath::Direction dirs[2];
1303 if (!path.isNestedFillRects(rects, dirs)) {
1304 return false;
1305 }
1306
1307 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1308 // The two rects need to be wound opposite to each other
1309 return false;
1310 }
1311
1312 // Right now, nested rects where the margin is not the same width
1313 // all around do not render correctly
1314 const SkScalar* outer = rects[0].asScalars();
1315 const SkScalar* inner = rects[1].asScalars();
1316
1317 bool allEq = true;
1318
1319 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1320 bool allGoE1 = margin >= SK_Scalar1;
1321
1322 for (int i = 1; i < 4; ++i) {
1323 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1324 if (temp < SK_Scalar1) {
1325 allGoE1 = false;
1326 }
1327 if (!SkScalarNearlyEqual(margin, temp)) {
1328 allEq = false;
1329 }
1330 }
1331
1332 return allEq || allGoE1;
1333}
1334
Brian Osman11052242016-10-27 14:47:55 -04001335void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001336 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001337 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001338 const SkMatrix& viewMatrix,
1339 const SkPath& path,
1340 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001341 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001342 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001343 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001344 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001345
robertphillipsea461502015-05-26 11:38:03 -07001346 if (path.isEmpty()) {
1347 if (path.isInverseFillType()) {
Brian Salomon82f44312017-01-11 13:42:54 -05001348 this->drawPaint(clip, std::move(paint), viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001349 }
1350 return;
1351 }
1352
Robert Phillips72152832017-01-25 17:31:35 -05001353 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001354
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001355 GrAAType aaType = this->decideAAType(aa);
1356 if (GrAAType::kCoverage == aaType && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001357 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001358 // Concave AA paths are expensive - try to avoid them for special cases
1359 SkRect rects[2];
1360
bsalomon6663acf2016-05-10 09:14:17 -07001361 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001362 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -05001363 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001364 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001365 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001366 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon40ef4852016-05-02 13:22:13 -07001367 }
robertphillipsea461502015-05-26 11:38:03 -07001368 return;
1369 }
1370 }
1371 SkRect ovalRect;
1372 bool isOval = path.isOval(&ovalRect);
1373
1374 if (isOval && !path.isInverseFillType()) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001375 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001376 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeOvalOp(
Brian Salomon289e3d82016-12-14 15:52:56 -05001377 paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001378 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001379 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001380 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001381 return;
1382 }
1383 }
1384 }
robertphillips4bc31812016-03-01 12:22:49 -08001385
1386 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1387 // Scratch textures can be recycled after they are returned to the texture
1388 // cache. This presents a potential hazard for buffered drawing. However,
1389 // the writePixels that uploads to the scratch will perform a flush so we're
1390 // OK.
Brian Salomon82f44312017-01-11 13:42:54 -05001391 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001392}
1393
Brian Osman11052242016-10-27 14:47:55 -04001394bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip,
1395 const GrUserStencilSettings* ss,
1396 SkRegion::Op op,
1397 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001398 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001399 const SkMatrix& viewMatrix,
1400 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001401 ASSERT_SINGLE_OWNER_PRIV
1402 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001403 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001404 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
1405 "GrRenderTargetContextPriv::drawAndStencilPath");
robertphillips391395d2016-03-02 09:26:36 -08001406
1407 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001408 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001409 SkRect::MakeIWH(fRenderTargetContext->width(),
1410 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001411 return true;
1412 }
1413
Robert Phillips72152832017-01-25 17:31:35 -05001414 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001415
1416 // An Assumption here is that path renderer would use some form of tweaking
1417 // the src color (either the input alpha or in the frag shader) to implement
1418 // aa. If we have some future driver-mojo path AA that can do the right
1419 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001420 GrAAType aaType = fRenderTargetContext->decideAAType(aa);
robertphillips976f5f02016-06-03 10:59:20 -07001421 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001422
bsalomon8acedde2016-06-24 10:42:16 -07001423 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001424 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Osman11052242016-10-27 14:47:55 -04001425 canDrawArgs.fShaderCaps =
Robert Phillips72152832017-01-25 17:31:35 -05001426 fRenderTargetContext->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips391395d2016-03-02 09:26:36 -08001427 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001428 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001429 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001430 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001431
1432 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001433 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001434 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001435 if (!pr) {
1436 return false;
1437 }
1438
1439 GrPaint paint;
1440 paint.setCoverageSetOpXPFactory(op, invert);
1441
Brian Salomon82f44312017-01-11 13:42:54 -05001442 GrPathRenderer::DrawPathArgs args{
Robert Phillips256c37b2017-03-01 14:32:46 -05001443 fRenderTargetContext->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001444 std::move(paint),
1445 ss,
1446 fRenderTargetContext,
1447 &clip,
1448 &viewMatrix,
1449 &shape,
1450 aaType,
1451 fRenderTargetContext->isGammaCorrect()};
robertphillips391395d2016-03-02 09:26:36 -08001452 pr->drawPath(args);
1453 return true;
1454}
1455
Brian Osman11052242016-10-27 14:47:55 -04001456SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001457 ASSERT_SINGLE_OWNER_PRIV
1458
Brian Osman11052242016-10-27 14:47:55 -04001459 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001460 return SkBudgeted::kNo;
1461 }
1462
Brian Osman11052242016-10-27 14:47:55 -04001463 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001464
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001465 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001466}
1467
Brian Osman11052242016-10-27 14:47:55 -04001468void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001469 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001470 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001471 const SkMatrix& viewMatrix,
1472 const SkPath& path,
1473 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001474 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001475 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001476 SkASSERT(!path.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001477 GrShape shape;
robertphillipsea461502015-05-26 11:38:03 -07001478
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001479 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true);
1480 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) {
1481 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and
1482 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1483 // smoother hairlines than MSAA.
1484 aaType = GrAAType::kCoverage;
bsalomon0a0f67e2016-06-28 11:56:42 -07001485 }
robertphillips68737822015-10-29 12:12:21 -07001486 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Robert Phillips72152832017-01-25 17:31:35 -05001487 canDrawArgs.fShaderCaps = this->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips68737822015-10-29 12:12:21 -07001488 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001489 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001490 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001491
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001492 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001493 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001494 do {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001495 shape = GrShape(path, style);
bsalomon8acedde2016-06-24 10:42:16 -07001496 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001497 return;
1498 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001499
1500 canDrawArgs.fAAType = aaType;
1501
1502 // Try a 1st time without applying any of the style to the geometry (and barring sw)
Robert Phillips72152832017-01-25 17:31:35 -05001503 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001504 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1505
1506 if (!pr && shape.style().pathEffect()) {
1507 // It didn't work above, so try again with the path effect applied.
1508 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
bsalomon8acedde2016-06-24 10:42:16 -07001509 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001510 return;
1511 }
Robert Phillips72152832017-01-25 17:31:35 -05001512 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
bsalomon6663acf2016-05-10 09:14:17 -07001513 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001514 if (!pr) {
1515 if (shape.style().applies()) {
1516 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1517 if (shape.isEmpty()) {
1518 return;
1519 }
1520 }
1521 // This time, allow SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001522 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001523 }
Brian Salomon0abc8b42016-12-13 10:22:54 -05001524 if (!pr && GrAATypeIsHW(aaType)) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001525 // There are exceptional cases where we may wind up falling back to coverage based AA
1526 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions).
1527 aaType = GrAAType::kCoverage;
1528 } else {
1529 break;
1530 }
1531 } while(true);
robertphillipsea461502015-05-26 11:38:03 -07001532
bsalomon8acedde2016-06-24 10:42:16 -07001533 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001534#ifdef SK_DEBUG
1535 SkDebugf("Unable to find path renderer compatible with path.\n");
1536#endif
1537 return;
1538 }
1539
Robert Phillips256c37b2017-03-01 14:32:46 -05001540 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001541 std::move(paint),
1542 &GrUserStencilSettings::kUnused,
1543 this,
1544 &clip,
1545 &viewMatrix,
1546 &shape,
1547 aaType,
1548 this->isGammaCorrect()};
bsalomon0aff2fa2015-07-31 06:48:27 -07001549 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001550}
1551
Brian Salomon467921e2017-03-06 16:17:12 -05001552static void op_bounds(SkRect* bounds, const GrOp* op) {
1553 *bounds = op->bounds();
1554 if (op->hasZeroArea()) {
1555 if (op->hasAABloat()) {
1556 bounds->outset(0.5f, 0.5f);
1557 } else {
1558 // We don't know which way the particular GPU will snap lines or points at integer
1559 // coords. So we ensure that the bounds is large enough for either snap.
1560 SkRect before = *bounds;
1561 bounds->roundOut(bounds);
1562 if (bounds->fLeft == before.fLeft) {
1563 bounds->fLeft -= 1;
1564 }
1565 if (bounds->fTop == before.fTop) {
1566 bounds->fTop -= 1;
1567 }
1568 if (bounds->fRight == before.fRight) {
1569 bounds->fRight += 1;
1570 }
1571 if (bounds->fBottom == before.fBottom) {
1572 bounds->fBottom += 1;
1573 }
1574 }
1575 }
1576}
1577
Brian Salomon54d212e2017-03-21 14:22:38 -04001578uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001579 ASSERT_SINGLE_OWNER
Robert Phillipsc0138922017-03-08 11:50:55 -05001580 if (this->drawingManager()->wasAbandoned()) {
1581 return SK_InvalidUniqueID;
1582 }
robertphillips2e1e51f2015-10-15 08:01:48 -07001583 SkDEBUGCODE(this->validate();)
Brian Salomon42521e82016-12-07 16:44:58 -05001584 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
robertphillips2d70dcb2015-10-06 07:38:23 -07001585
Brian Salomon467921e2017-03-06 16:17:12 -05001586 // Setup clip
1587 SkRect bounds;
1588 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04001589 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04001590 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1591 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1592 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1593 &bounds)) {
1594 return SK_InvalidUniqueID;
1595 }
1596
1597 // This forces instantiation of the render target.
1598 GrRenderTarget* rt = this->accessRenderTarget();
1599 if (!rt) {
1600 return SK_InvalidUniqueID;
1601 }
1602
1603 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1604 appliedClip.hasStencilClip()) {
1605 if (!fContext->resourceProvider()->attachStencilAttachment(rt)) {
1606 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
1607 return SK_InvalidUniqueID;
1608 }
1609 }
1610
1611 GrXferProcessor::DstTexture dstTexture;
1612 if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001613 if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, op->bounds(), &dstTexture)) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001614 return SK_InvalidUniqueID;
1615 }
1616 }
1617
1618 op->setClippedBounds(bounds);
1619 return this->getOpList()->addOp(std::move(op), this, std::move(appliedClip), dstTexture);
1620}
1621
Brian Salomone14bd802017-04-04 15:13:25 -04001622uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(GrPipelineBuilder&& pipelineBuilder,
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001623 const GrClip& clip,
1624 std::unique_ptr<GrLegacyMeshDrawOp> op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001625 ASSERT_SINGLE_OWNER
1626 if (this->drawingManager()->wasAbandoned()) {
1627 return SK_InvalidUniqueID;
1628 }
1629 SkDEBUGCODE(this->validate();)
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001630 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addLegacyMeshDrawOp");
Brian Salomon54d212e2017-03-21 14:22:38 -04001631
1632 // Setup clip
1633 SkRect bounds;
1634 op_bounds(&bounds, op.get());
1635 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -05001636 if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
Brian Salomon97180af2017-03-14 13:42:58 -04001637 pipelineBuilder.hasUserStencilSettings(), &appliedClip, &bounds)) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001638 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001639 }
1640
1641 // This forces instantiation of the render target. Pipeline creation is moving to flush time
1642 // by which point instantiation must have occurred anyway.
1643 GrRenderTarget* rt = this->accessRenderTarget();
1644 if (!rt) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001645 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001646 }
1647
1648 GrResourceProvider* resourceProvider = fContext->resourceProvider();
Brian Salomon48d1b4c2017-04-08 07:38:53 -04001649 bool usesStencil = pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip();
1650 if (usesStencil) {
Brian Salomon467921e2017-03-06 16:17:12 -05001651 if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
1652 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
Robert Phillipsc0138922017-03-08 11:50:55 -05001653 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001654 }
1655 }
1656
Brian Salomon48d1b4c2017-04-08 07:38:53 -04001657 bool isMixedSamples = fRenderTargetProxy->isMixedSampled() &&
1658 (pipelineBuilder.isHWAntialias() || usesStencil);
1659
1660 GrColor overrideColor;
1661 GrProcessorSet::Analysis analysis = op->analyzeUpdateAndRecordProcessors(
1662 &pipelineBuilder, &appliedClip, isMixedSamples, *this->caps(), &overrideColor);
Brian Salomon467921e2017-03-06 16:17:12 -05001663
1664 GrPipeline::InitArgs args;
1665 pipelineBuilder.getPipelineInitArgs(&args);
1666 args.fAppliedClip = &appliedClip;
1667 args.fRenderTarget = rt;
1668 args.fCaps = this->caps();
Brian Salomon467921e2017-03-06 16:17:12 -05001669
Brian Salomon31853842017-03-28 16:32:05 -04001670 if (analysis.requiresDstTexture()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001671 if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, bounds, &args.fDstTexture)) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001672 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001673 }
1674 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -04001675 op->initPipeline(args, analysis, overrideColor);
Robert Phillipsf5442bb2017-04-17 14:18:34 -04001676
1677 // Add the pipeline dependencies on textures, etc before recording this op.
1678 op->addDependenciesTo(fRenderTargetProxy.get());
1679
Brian Salomon97180af2017-03-14 13:42:58 -04001680 op->setClippedBounds(bounds);
Robert Phillipsc0138922017-03-08 11:50:55 -05001681 return this->getOpList()->addOp(std::move(op), this);
Brian Salomon467921e2017-03-06 16:17:12 -05001682}
1683
Robert Phillipsbf25d432017-04-07 10:08:53 -04001684bool GrRenderTargetContext::setupDstTexture(GrRenderTargetProxy* rtProxy, const GrClip& clip,
Brian Salomon467921e2017-03-06 16:17:12 -05001685 const SkRect& opBounds,
1686 GrXferProcessor::DstTexture* dstTexture) {
1687 if (this->caps()->textureBarrierSupport()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001688 if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
1689 // MDB TODO: remove this instantiation. Blocked on making DstTexture be proxy-based
1690 sk_sp<GrTexture> tex(sk_ref_sp(texProxy->instantiate(fContext->resourceProvider())));
1691 if (!tex) {
1692 SkDebugf("setupDstTexture: instantiation of src texture failed.\n");
1693 return false; // We have bigger problems now
1694 }
1695
Brian Salomon467921e2017-03-06 16:17:12 -05001696 // The render target is a texture, so we can read from it directly in the shader. The XP
1697 // will be responsible to detect this situation and request a texture barrier.
Robert Phillipsbf25d432017-04-07 10:08:53 -04001698 dstTexture->setTexture(std::move(tex));
Brian Salomon467921e2017-03-06 16:17:12 -05001699 dstTexture->setOffset(0, 0);
Robert Phillipsbf25d432017-04-07 10:08:53 -04001700 return true;
Brian Salomon467921e2017-03-06 16:17:12 -05001701 }
1702 }
1703
Robert Phillipsbf25d432017-04-07 10:08:53 -04001704 SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
Brian Salomon467921e2017-03-06 16:17:12 -05001705
Eric Karl74480882017-04-03 14:49:05 -07001706 SkIRect clippedRect;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001707 clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
Eric Karl72e551e2017-04-04 13:42:10 -07001708 SkIRect drawIBounds;
Brian Salomon467921e2017-03-06 16:17:12 -05001709 opBounds.roundOut(&drawIBounds);
Brian Salomon859621f2017-03-16 09:21:54 -04001710 // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
1711 drawIBounds.outset(1, 1);
Eric Karl72e551e2017-04-04 13:42:10 -07001712 if (!clippedRect.intersect(drawIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001713#ifdef SK_DEBUG
Robert Phillipsbf25d432017-04-07 10:08:53 -04001714 GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
Brian Salomon467921e2017-03-06 16:17:12 -05001715#endif
Robert Phillipsbf25d432017-04-07 10:08:53 -04001716 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05001717 }
1718
1719 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
1720 // have per-sample dst values by making the copy multisampled.
1721 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07001722 bool rectsMustMatch = false;
1723 bool disallowSubrect = false;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001724 if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &rectsMustMatch, &disallowSubrect)) {
1725 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
Brian Salomon467921e2017-03-06 16:17:12 -05001726 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001727 desc.fConfig = rtProxy->config();
Brian Salomon467921e2017-03-06 16:17:12 -05001728 }
1729
Eric Karl74480882017-04-03 14:49:05 -07001730 if (!disallowSubrect) {
1731 copyRect = clippedRect;
1732 }
Brian Salomon467921e2017-03-06 16:17:12 -05001733
Robert Phillipsbf25d432017-04-07 10:08:53 -04001734 SkIPoint dstPoint, dstOffset;
1735 SkBackingFit fit;
Eric Karl74480882017-04-03 14:49:05 -07001736 if (rectsMustMatch) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001737 SkASSERT(desc.fOrigin == rtProxy->origin());
1738 desc.fWidth = rtProxy->width();
1739 desc.fHeight = rtProxy->height();
Eric Karl74480882017-04-03 14:49:05 -07001740 dstPoint = {copyRect.fLeft, copyRect.fTop};
1741 dstOffset = {0, 0};
Robert Phillipsbf25d432017-04-07 10:08:53 -04001742 fit = SkBackingFit::kExact;
Eric Karl74480882017-04-03 14:49:05 -07001743 } else {
1744 desc.fWidth = copyRect.width();
1745 desc.fHeight = copyRect.height();
1746 dstPoint = {0, 0};
1747 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillipsbf25d432017-04-07 10:08:53 -04001748 fit = SkBackingFit::kApprox;
Eric Karl74480882017-04-03 14:49:05 -07001749 }
Brian Salomon467921e2017-03-06 16:17:12 -05001750
Robert Phillipsbf25d432017-04-07 10:08:53 -04001751 sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeDeferredSurfaceContext(
1752 desc,
1753 fit,
1754 SkBudgeted::kYes);
1755 if (!sContext) {
1756 SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
1757 return false;
1758 }
1759
1760 if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
1761 SkDebugf("setupDstTexture: copy failed.\n");
1762 return false;
1763 }
1764
1765 GrTextureProxy* copyProxy = sContext->asTextureProxy();
1766 // MDB TODO: remove this instantiation once DstTexture is proxy-backed
1767 sk_sp<GrTexture> copy(sk_ref_sp(copyProxy->instantiate(fContext->resourceProvider())));
Brian Salomon467921e2017-03-06 16:17:12 -05001768 if (!copy) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001769 SkDebugf("setupDstTexture: instantiation of copied texture failed.\n");
1770 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05001771 }
Eric Karl74480882017-04-03 14:49:05 -07001772
Brian Salomon467921e2017-03-06 16:17:12 -05001773 dstTexture->setTexture(std::move(copy));
Eric Karl74480882017-04-03 14:49:05 -07001774 dstTexture->setOffset(dstOffset);
Robert Phillipsbf25d432017-04-07 10:08:53 -04001775 return true;
robertphillips2334fb62015-06-17 05:43:33 -07001776}