blob: 6e724414d1c44b2c8116cbf1132b6e06f40dada0 [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 Salomonff574e02017-05-03 14:00:51 -040030#include "ops/GrDrawOp.h"
Brian Salomon0f353322017-05-03 20:58:59 +000031#include "ops/GrDrawAtlasOp.h"
Brian Salomon89527432016-12-16 09:52:16 -050032#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"
Brian Salomon0f353322017-05-03 20:58:59 +000042#include "../private/GrAuditTrail.h"
joshualittbc907352016-01-13 06:45:40 -080043
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 Phillips4a395042017-04-24 16:27:17 +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
Jim Van Verth57061ee2017-04-28 17:30:30 -04001003 std::unique_ptr<GrLegacyMeshDrawOp> op = GrShadowRRectOp::Make(paint.getColor(), viewMatrix,
1004 rrect, blurRadius, stroke);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001005 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001006 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001007 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001008 return;
Jim Van Verthc5903412016-11-17 15:27:09 -05001009 }
Jim Van Verthc5903412016-11-17 15:27:09 -05001010}
1011
1012///////////////////////////////////////////////////////////////////////////////
1013
Brian Osman11052242016-10-27 14:47:55 -04001014bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001015 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001016 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001017 const SkMatrix& viewMatrix,
1018 const SkRRect& origOuter,
1019 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -08001020 SkASSERT(!origInner.isEmpty());
1021 SkASSERT(!origOuter.isEmpty());
1022
csmartdaltone0d36292016-07-29 08:14:20 -07001023 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipse3302df2017-04-24 07:31:02 -04001024 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
1025 std::unique_ptr<GrDrawOp> op(oa->recordDRRect(
Brian Salomon54d212e2017-03-21 14:22:38 -04001026 origOuter, origInner, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001027 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001028 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001029 return true;
1030 }
1031 }
1032
Brian Salomon54d212e2017-03-21 14:22:38 -04001033 GrAAType aaType = this->decideAAType(aa);
robertphillips00095892016-02-29 13:50:40 -08001034
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001035 GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
1036 if (GrAAType::kCoverage == aaType) {
1037 innerEdgeType = kInverseFillAA_GrProcessorEdgeType;
1038 outerEdgeType = kFillAA_GrProcessorEdgeType;
1039 } else {
1040 innerEdgeType = kInverseFillBW_GrProcessorEdgeType;
1041 outerEdgeType = kFillBW_GrProcessorEdgeType;
1042 }
robertphillips00095892016-02-29 13:50:40 -08001043
1044 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1045 SkMatrix inverseVM;
1046 if (!viewMatrix.isIdentity()) {
1047 if (!origInner.transform(viewMatrix, inner.writable())) {
1048 return false;
1049 }
1050 if (!origOuter.transform(viewMatrix, outer.writable())) {
1051 return false;
1052 }
1053 if (!viewMatrix.invert(&inverseVM)) {
1054 return false;
1055 }
1056 } else {
1057 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001058 }
robertphillips00095892016-02-29 13:50:40 -08001059
robertphillips00095892016-02-29 13:50:40 -08001060 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -07001061 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -08001062 if (!innerEffect) {
1063 return false;
1064 }
1065
bungeman06ca8ec2016-06-09 08:01:03 -07001066 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -08001067 if (!outerEffect) {
1068 return false;
1069 }
1070
Brian Salomon82f44312017-01-11 13:42:54 -05001071 paint.addCoverageFragmentProcessor(std::move(innerEffect));
1072 paint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001073
1074 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001075 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001076 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1077 }
halcanary9d524f22016-03-29 09:03:52 -07001078
Brian Salomon82f44312017-01-11 13:42:54 -05001079 this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1080 inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001081 return true;
1082}
1083
Brian Osman11052242016-10-27 14:47:55 -04001084void GrRenderTargetContext::drawDRRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001085 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001086 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001087 const SkMatrix& viewMatrix,
1088 const SkRRect& outer,
1089 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001090 ASSERT_SINGLE_OWNER
1091 RETURN_IF_ABANDONED
1092 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001093 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
robertphillips00095892016-02-29 13:50:40 -08001094
1095 SkASSERT(!outer.isEmpty());
1096 SkASSERT(!inner.isEmpty());
1097
Robert Phillips72152832017-01-25 17:31:35 -05001098 AutoCheckFlush acf(this->drawingManager());
robertphillips00095892016-02-29 13:50:40 -08001099
Brian Salomon82f44312017-01-11 13:42:54 -05001100 if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001101 return;
1102 }
1103
1104 SkPath path;
1105 path.setIsVolatile(true);
1106 path.addRRect(inner);
1107 path.addRRect(outer);
1108 path.setFillType(SkPath::kEvenOdd_FillType);
1109
Brian Salomon82f44312017-01-11 13:42:54 -05001110 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -08001111}
1112
robertphillipsea461502015-05-26 11:38:03 -07001113///////////////////////////////////////////////////////////////////////////////
1114
msarettcc319b92016-08-25 18:07:18 -07001115static inline bool is_int(float x) {
1116 return x == (float) sk_float_round2int(x);
1117}
1118
Brian Osman11052242016-10-27 14:47:55 -04001119void GrRenderTargetContext::drawRegion(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001120 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001121 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001122 const SkMatrix& viewMatrix,
1123 const SkRegion& region,
1124 const GrStyle& style) {
msarettcc319b92016-08-25 18:07:18 -07001125 ASSERT_SINGLE_OWNER
1126 RETURN_IF_ABANDONED
1127 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001128 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
msarettcc319b92016-08-25 18:07:18 -07001129
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001130 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001131 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001132 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001133 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1134 is_int(viewMatrix.getTranslateX()) &&
1135 is_int(viewMatrix.getTranslateY())) {
1136 aa = GrAA::kNo;
1137 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001138 }
msarettcc319b92016-08-25 18:07:18 -07001139 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001140 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001141 SkPath path;
1142 region.getBoundaryPath(&path);
Brian Salomon82f44312017-01-11 13:42:54 -05001143 return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001144 }
1145
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001146 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
Brian Salomon82f44312017-01-11 13:42:54 -05001147 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001148 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001149}
1150
Brian Osman11052242016-10-27 14:47:55 -04001151void GrRenderTargetContext::drawOval(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001152 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001153 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001154 const SkMatrix& viewMatrix,
1155 const SkRect& oval,
1156 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001157 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001158 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001159 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001160 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001161
robertphillipsea461502015-05-26 11:38:03 -07001162 if (oval.isEmpty()) {
1163 return;
1164 }
1165
bsalomon6663acf2016-05-10 09:14:17 -07001166 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001167
Robert Phillips72152832017-01-25 17:31:35 -05001168 AutoCheckFlush acf(this->drawingManager());
bsalomon6663acf2016-05-10 09:14:17 -07001169 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltona7f29642016-07-07 08:49:11 -07001170
csmartdaltone0d36292016-07-29 08:14:20 -07001171 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1172 stroke.isFillStyle()) {
Robert Phillipse3302df2017-04-24 07:31:02 -04001173 gr_instanced::OpAllocator* oa = this->drawingManager()->instancingAllocator();
Brian Salomon54d212e2017-03-21 14:22:38 -04001174 std::unique_ptr<GrDrawOp> op(
Robert Phillipse3302df2017-04-24 07:31:02 -04001175 oa->recordOval(oval, viewMatrix, std::move(paint), aa, fInstancedPipelineInfo));
Brian Salomon42521e82016-12-07 16:44:58 -05001176 if (op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001177 this->addDrawOp(clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001178 return;
1179 }
1180 }
1181
Brian Salomon54d212e2017-03-21 14:22:38 -04001182 GrAAType aaType = this->decideAAType(aa);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001183 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001184 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001185 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon289e3d82016-12-14 15:52:56 -05001186 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001187 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001188 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001189 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001190 return;
1191 }
robertphillipsea461502015-05-26 11:38:03 -07001192 }
robertphillipsb56f9272016-02-25 11:03:52 -08001193
1194 SkPath path;
1195 path.setIsVolatile(true);
1196 path.addOval(oval);
Brian Salomon82f44312017-01-11 13:42:54 -05001197 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001198}
1199
Brian Osman11052242016-10-27 14:47:55 -04001200void GrRenderTargetContext::drawArc(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001201 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001202 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001203 const SkMatrix& viewMatrix,
1204 const SkRect& oval,
1205 SkScalar startAngle,
1206 SkScalar sweepAngle,
1207 bool useCenter,
1208 const GrStyle& style) {
Robert Phillipsf1d0ced2017-02-10 09:31:01 -05001209 ASSERT_SINGLE_OWNER
1210 RETURN_IF_ABANDONED
1211 SkDEBUGCODE(this->validate();)
1212 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawArc");
1213
1214 AutoCheckFlush acf(this->drawingManager());
1215
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001216 GrAAType aaType = this->decideAAType(aa);
1217 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001218 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001219 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
1220 viewMatrix,
1221 oval,
1222 startAngle,
1223 sweepAngle,
1224 useCenter,
1225 style,
1226 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001227 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001228 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001229 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001230 return;
1231 }
1232 }
1233 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001234 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1235 style.isSimpleFill());
Brian Salomon82f44312017-01-11 13:42:54 -05001236 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001237}
1238
Brian Osman11052242016-10-27 14:47:55 -04001239void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001240 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001241 const SkMatrix& viewMatrix,
1242 int imageWidth,
1243 int imageHeight,
1244 std::unique_ptr<SkLatticeIter> iter,
1245 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001246 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001247 RETURN_IF_ABANDONED
1248 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001249 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001250
Robert Phillips72152832017-01-25 17:31:35 -05001251 AutoCheckFlush acf(this->drawingManager());
joshualitt33a5fce2015-11-18 13:28:51 -08001252
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001253 std::unique_ptr<GrLegacyMeshDrawOp> op = GrLatticeOp::MakeNonAA(
Brian Salomon649a3412017-03-09 13:50:43 -05001254 paint.getColor(), viewMatrix, imageWidth, imageHeight, std::move(iter), dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001255
Brian Salomon82f44312017-01-11 13:42:54 -05001256 GrPipelineBuilder pipelineBuilder(std::move(paint), GrAAType::kNone);
Brian Salomone14bd802017-04-04 15:13:25 -04001257 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001258}
1259
Brian Osman11052242016-10-27 14:47:55 -04001260void GrRenderTargetContext::prepareForExternalIO() {
robertphillips8c523e02016-07-26 07:41:00 -07001261 ASSERT_SINGLE_OWNER
1262 RETURN_IF_ABANDONED
1263 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001264 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
robertphillips8c523e02016-07-26 07:41:00 -07001265
Robert Phillips7ee385e2017-03-30 08:02:11 -04001266 this->drawingManager()->prepareSurfaceForExternalIO(fRenderTargetProxy.get());
robertphillips8c523e02016-07-26 07:41:00 -07001267}
joshualitt33a5fce2015-11-18 13:28:51 -08001268
Brian Osman11052242016-10-27 14:47:55 -04001269void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001270 GrPaint&& paint,
Brian Osman11052242016-10-27 14:47:55 -04001271 const SkMatrix& viewMatrix,
1272 const SkRect& rect,
1273 const SkRect* localRect,
1274 const SkMatrix* localMatrix,
1275 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001276 GrAAType hwOrNoneAAType) {
1277 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
Brian Salomon0f353322017-05-03 20:58:59 +00001278 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001279 std::unique_ptr<GrLegacyMeshDrawOp> op = GrRectOpFactory::MakeNonAAFill(
1280 paint.getColor(), viewMatrix, rect, localRect, localMatrix);
Brian Salomon82f44312017-01-11 13:42:54 -05001281 GrPipelineBuilder pipelineBuilder(std::move(paint), hwOrNoneAAType);
robertphillips44302392016-07-08 14:43:03 -07001282 if (ss) {
1283 pipelineBuilder.setUserStencil(ss);
1284 }
Brian Salomone14bd802017-04-04 15:13:25 -04001285 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -07001286}
1287
robertphillipsea461502015-05-26 11:38:03 -07001288// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001289static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001290
1291 if (path.isInverseFillType()) {
1292 return false;
1293 }
1294
1295 // TODO: this restriction could be lifted if we were willing to apply
1296 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001297 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001298 return false;
1299 }
1300
1301 SkPath::Direction dirs[2];
1302 if (!path.isNestedFillRects(rects, dirs)) {
1303 return false;
1304 }
1305
1306 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1307 // The two rects need to be wound opposite to each other
1308 return false;
1309 }
1310
1311 // Right now, nested rects where the margin is not the same width
1312 // all around do not render correctly
1313 const SkScalar* outer = rects[0].asScalars();
1314 const SkScalar* inner = rects[1].asScalars();
1315
1316 bool allEq = true;
1317
1318 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1319 bool allGoE1 = margin >= SK_Scalar1;
1320
1321 for (int i = 1; i < 4; ++i) {
1322 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1323 if (temp < SK_Scalar1) {
1324 allGoE1 = false;
1325 }
1326 if (!SkScalarNearlyEqual(margin, temp)) {
1327 allEq = false;
1328 }
1329 }
1330
1331 return allEq || allGoE1;
1332}
1333
Brian Osman11052242016-10-27 14:47:55 -04001334void GrRenderTargetContext::drawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001335 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001336 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001337 const SkMatrix& viewMatrix,
1338 const SkPath& path,
1339 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001340 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001341 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001342 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001343 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001344
robertphillipsea461502015-05-26 11:38:03 -07001345 if (path.isEmpty()) {
1346 if (path.isInverseFillType()) {
Brian Salomon82f44312017-01-11 13:42:54 -05001347 this->drawPaint(clip, std::move(paint), viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001348 }
1349 return;
1350 }
1351
Robert Phillips72152832017-01-25 17:31:35 -05001352 AutoCheckFlush acf(this->drawingManager());
robertphillipsea461502015-05-26 11:38:03 -07001353
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001354 GrAAType aaType = this->decideAAType(aa);
1355 if (GrAAType::kCoverage == aaType && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001356 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001357 // Concave AA paths are expensive - try to avoid them for special cases
1358 SkRect rects[2];
1359
bsalomon6663acf2016-05-10 09:14:17 -07001360 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001361 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomon6a639042016-12-14 11:08:17 -05001362 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001363 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001364 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001365 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
bsalomon40ef4852016-05-02 13:22:13 -07001366 }
robertphillipsea461502015-05-26 11:38:03 -07001367 return;
1368 }
1369 }
1370 SkRect ovalRect;
1371 bool isOval = path.isOval(&ovalRect);
1372
1373 if (isOval && !path.isInverseFillType()) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001374 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001375 std::unique_ptr<GrLegacyMeshDrawOp> op = GrOvalOpFactory::MakeOvalOp(
Brian Salomon289e3d82016-12-14 15:52:56 -05001376 paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001377 if (op) {
Brian Salomon82f44312017-01-11 13:42:54 -05001378 GrPipelineBuilder pipelineBuilder(std::move(paint), aaType);
Brian Salomone14bd802017-04-04 15:13:25 -04001379 this->addLegacyMeshDrawOp(std::move(pipelineBuilder), clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001380 return;
1381 }
1382 }
1383 }
robertphillips4bc31812016-03-01 12:22:49 -08001384
1385 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1386 // Scratch textures can be recycled after they are returned to the texture
1387 // cache. This presents a potential hazard for buffered drawing. However,
1388 // the writePixels that uploads to the scratch will perform a flush so we're
1389 // OK.
Brian Salomon82f44312017-01-11 13:42:54 -05001390 this->internalDrawPath(clip, std::move(paint), aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001391}
1392
Brian Osman11052242016-10-27 14:47:55 -04001393bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip,
1394 const GrUserStencilSettings* ss,
1395 SkRegion::Op op,
1396 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001397 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001398 const SkMatrix& viewMatrix,
1399 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001400 ASSERT_SINGLE_OWNER_PRIV
1401 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001402 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001403 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
1404 "GrRenderTargetContextPriv::drawAndStencilPath");
robertphillips391395d2016-03-02 09:26:36 -08001405
1406 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001407 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001408 SkRect::MakeIWH(fRenderTargetContext->width(),
1409 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001410 return true;
1411 }
1412
Robert Phillips72152832017-01-25 17:31:35 -05001413 AutoCheckFlush acf(fRenderTargetContext->drawingManager());
robertphillips391395d2016-03-02 09:26:36 -08001414
1415 // An Assumption here is that path renderer would use some form of tweaking
1416 // the src color (either the input alpha or in the frag shader) to implement
1417 // aa. If we have some future driver-mojo path AA that can do the right
1418 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001419 GrAAType aaType = fRenderTargetContext->decideAAType(aa);
robertphillips976f5f02016-06-03 10:59:20 -07001420 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001421
bsalomon8acedde2016-06-24 10:42:16 -07001422 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001423 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Osman11052242016-10-27 14:47:55 -04001424 canDrawArgs.fShaderCaps =
Robert Phillips72152832017-01-25 17:31:35 -05001425 fRenderTargetContext->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips391395d2016-03-02 09:26:36 -08001426 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001427 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001428 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001429 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001430
1431 // Don't allow the SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001432 GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001433 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001434 if (!pr) {
1435 return false;
1436 }
1437
1438 GrPaint paint;
1439 paint.setCoverageSetOpXPFactory(op, invert);
1440
Brian Salomon82f44312017-01-11 13:42:54 -05001441 GrPathRenderer::DrawPathArgs args{
Robert Phillips256c37b2017-03-01 14:32:46 -05001442 fRenderTargetContext->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001443 std::move(paint),
1444 ss,
1445 fRenderTargetContext,
1446 &clip,
1447 &viewMatrix,
1448 &shape,
1449 aaType,
1450 fRenderTargetContext->isGammaCorrect()};
robertphillips391395d2016-03-02 09:26:36 -08001451 pr->drawPath(args);
1452 return true;
1453}
1454
Brian Osman11052242016-10-27 14:47:55 -04001455SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001456 ASSERT_SINGLE_OWNER_PRIV
1457
Brian Osman11052242016-10-27 14:47:55 -04001458 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001459 return SkBudgeted::kNo;
1460 }
1461
Brian Osman11052242016-10-27 14:47:55 -04001462 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001463
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001464 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001465}
1466
Brian Osman11052242016-10-27 14:47:55 -04001467void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
Brian Salomon82f44312017-01-11 13:42:54 -05001468 GrPaint&& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001469 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001470 const SkMatrix& viewMatrix,
1471 const SkPath& path,
1472 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001473 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001474 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001475 SkASSERT(!path.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001476 GrShape shape;
robertphillipsea461502015-05-26 11:38:03 -07001477
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001478 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true);
1479 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) {
1480 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and
1481 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1482 // smoother hairlines than MSAA.
1483 aaType = GrAAType::kCoverage;
bsalomon0a0f67e2016-06-28 11:56:42 -07001484 }
robertphillips68737822015-10-29 12:12:21 -07001485 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Robert Phillips72152832017-01-25 17:31:35 -05001486 canDrawArgs.fShaderCaps = this->drawingManager()->getContext()->caps()->shaderCaps();
robertphillips68737822015-10-29 12:12:21 -07001487 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001488 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001489 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001490
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001491 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001492 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001493 do {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001494 shape = GrShape(path, style);
bsalomon8acedde2016-06-24 10:42:16 -07001495 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001496 return;
1497 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001498
1499 canDrawArgs.fAAType = aaType;
1500
1501 // Try a 1st time without applying any of the style to the geometry (and barring sw)
Robert Phillips72152832017-01-25 17:31:35 -05001502 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001503 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1504
1505 if (!pr && shape.style().pathEffect()) {
1506 // It didn't work above, so try again with the path effect applied.
1507 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
bsalomon8acedde2016-06-24 10:42:16 -07001508 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001509 return;
1510 }
Robert Phillips72152832017-01-25 17:31:35 -05001511 pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
bsalomon6663acf2016-05-10 09:14:17 -07001512 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001513 if (!pr) {
1514 if (shape.style().applies()) {
1515 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1516 if (shape.isEmpty()) {
1517 return;
1518 }
1519 }
1520 // This time, allow SW renderer
Robert Phillips72152832017-01-25 17:31:35 -05001521 pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001522 }
Brian Salomon0abc8b42016-12-13 10:22:54 -05001523 if (!pr && GrAATypeIsHW(aaType)) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001524 // There are exceptional cases where we may wind up falling back to coverage based AA
1525 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions).
1526 aaType = GrAAType::kCoverage;
1527 } else {
1528 break;
1529 }
1530 } while(true);
robertphillipsea461502015-05-26 11:38:03 -07001531
bsalomon8acedde2016-06-24 10:42:16 -07001532 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001533#ifdef SK_DEBUG
1534 SkDebugf("Unable to find path renderer compatible with path.\n");
1535#endif
1536 return;
1537 }
1538
Robert Phillips256c37b2017-03-01 14:32:46 -05001539 GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
Brian Salomon82f44312017-01-11 13:42:54 -05001540 std::move(paint),
1541 &GrUserStencilSettings::kUnused,
1542 this,
1543 &clip,
1544 &viewMatrix,
1545 &shape,
1546 aaType,
1547 this->isGammaCorrect()};
bsalomon0aff2fa2015-07-31 06:48:27 -07001548 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001549}
1550
Brian Salomon467921e2017-03-06 16:17:12 -05001551static void op_bounds(SkRect* bounds, const GrOp* op) {
1552 *bounds = op->bounds();
1553 if (op->hasZeroArea()) {
1554 if (op->hasAABloat()) {
1555 bounds->outset(0.5f, 0.5f);
1556 } else {
1557 // We don't know which way the particular GPU will snap lines or points at integer
1558 // coords. So we ensure that the bounds is large enough for either snap.
1559 SkRect before = *bounds;
1560 bounds->roundOut(bounds);
1561 if (bounds->fLeft == before.fLeft) {
1562 bounds->fLeft -= 1;
1563 }
1564 if (bounds->fTop == before.fTop) {
1565 bounds->fTop -= 1;
1566 }
1567 if (bounds->fRight == before.fRight) {
1568 bounds->fRight += 1;
1569 }
1570 if (bounds->fBottom == before.fBottom) {
1571 bounds->fBottom += 1;
1572 }
1573 }
1574 }
1575}
1576
Brian Salomon54d212e2017-03-21 14:22:38 -04001577uint32_t GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001578 ASSERT_SINGLE_OWNER
Robert Phillipsc0138922017-03-08 11:50:55 -05001579 if (this->drawingManager()->wasAbandoned()) {
1580 return SK_InvalidUniqueID;
1581 }
robertphillips2e1e51f2015-10-15 08:01:48 -07001582 SkDEBUGCODE(this->validate();)
Brian Salomon42521e82016-12-07 16:44:58 -05001583 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
robertphillips2d70dcb2015-10-06 07:38:23 -07001584
Brian Salomon467921e2017-03-06 16:17:12 -05001585 // Setup clip
1586 SkRect bounds;
1587 op_bounds(&bounds, op.get());
Brian Salomon97180af2017-03-14 13:42:58 -04001588 GrAppliedClip appliedClip;
Brian Salomon54d212e2017-03-21 14:22:38 -04001589 GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
1590 if (!clip.apply(fContext, this, fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA,
1591 fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil, &appliedClip,
1592 &bounds)) {
1593 return SK_InvalidUniqueID;
1594 }
1595
1596 // This forces instantiation of the render target.
1597 GrRenderTarget* rt = this->accessRenderTarget();
1598 if (!rt) {
1599 return SK_InvalidUniqueID;
1600 }
1601
1602 if (fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil ||
1603 appliedClip.hasStencilClip()) {
1604 if (!fContext->resourceProvider()->attachStencilAttachment(rt)) {
1605 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
1606 return SK_InvalidUniqueID;
1607 }
1608 }
1609
1610 GrXferProcessor::DstTexture dstTexture;
1611 if (op->xpRequiresDstTexture(*this->caps(), &appliedClip)) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001612 if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, op->bounds(), &dstTexture)) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001613 return SK_InvalidUniqueID;
1614 }
1615 }
1616
1617 op->setClippedBounds(bounds);
1618 return this->getOpList()->addOp(std::move(op), this, std::move(appliedClip), dstTexture);
1619}
1620
Brian Salomone14bd802017-04-04 15:13:25 -04001621uint32_t GrRenderTargetContext::addLegacyMeshDrawOp(GrPipelineBuilder&& pipelineBuilder,
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001622 const GrClip& clip,
1623 std::unique_ptr<GrLegacyMeshDrawOp> op) {
Brian Salomon54d212e2017-03-21 14:22:38 -04001624 ASSERT_SINGLE_OWNER
1625 if (this->drawingManager()->wasAbandoned()) {
1626 return SK_InvalidUniqueID;
1627 }
1628 SkDEBUGCODE(this->validate();)
Brian Salomond3ccb0a2017-04-03 10:38:00 -04001629 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addLegacyMeshDrawOp");
Brian Salomon54d212e2017-03-21 14:22:38 -04001630
1631 // Setup clip
1632 SkRect bounds;
1633 op_bounds(&bounds, op.get());
1634 GrAppliedClip appliedClip;
Brian Salomon467921e2017-03-06 16:17:12 -05001635 if (!clip.apply(fContext, this, pipelineBuilder.isHWAntialias(),
Brian Salomon97180af2017-03-14 13:42:58 -04001636 pipelineBuilder.hasUserStencilSettings(), &appliedClip, &bounds)) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001637 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001638 }
1639
1640 // This forces instantiation of the render target. Pipeline creation is moving to flush time
1641 // by which point instantiation must have occurred anyway.
1642 GrRenderTarget* rt = this->accessRenderTarget();
1643 if (!rt) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001644 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001645 }
1646
1647 GrResourceProvider* resourceProvider = fContext->resourceProvider();
Brian Salomon48d1b4c2017-04-08 07:38:53 -04001648 bool usesStencil = pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip();
1649 if (usesStencil) {
Brian Salomon467921e2017-03-06 16:17:12 -05001650 if (!resourceProvider->attachStencilAttachment(this->accessRenderTarget())) {
1651 SkDebugf("ERROR creating stencil attachment. Draw skipped.\n");
Robert Phillipsc0138922017-03-08 11:50:55 -05001652 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001653 }
1654 }
1655
Brian Salomon48d1b4c2017-04-08 07:38:53 -04001656 bool isMixedSamples = fRenderTargetProxy->isMixedSampled() &&
1657 (pipelineBuilder.isHWAntialias() || usesStencil);
1658
1659 GrColor overrideColor;
1660 GrProcessorSet::Analysis analysis = op->analyzeUpdateAndRecordProcessors(
1661 &pipelineBuilder, &appliedClip, isMixedSamples, *this->caps(), &overrideColor);
Brian Salomon467921e2017-03-06 16:17:12 -05001662
1663 GrPipeline::InitArgs args;
1664 pipelineBuilder.getPipelineInitArgs(&args);
1665 args.fAppliedClip = &appliedClip;
1666 args.fRenderTarget = rt;
1667 args.fCaps = this->caps();
Brian Salomon467921e2017-03-06 16:17:12 -05001668
Brian Salomon31853842017-03-28 16:32:05 -04001669 if (analysis.requiresDstTexture()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001670 if (!this->setupDstTexture(fRenderTargetProxy.get(), clip, bounds, &args.fDstTexture)) {
Robert Phillipsc0138922017-03-08 11:50:55 -05001671 return SK_InvalidUniqueID;
Brian Salomon467921e2017-03-06 16:17:12 -05001672 }
1673 }
Brian Salomon48d1b4c2017-04-08 07:38:53 -04001674 op->initPipeline(args, analysis, overrideColor);
Robert Phillipsf5442bb2017-04-17 14:18:34 -04001675
1676 // Add the pipeline dependencies on textures, etc before recording this op.
1677 op->addDependenciesTo(fRenderTargetProxy.get());
1678
Brian Salomon97180af2017-03-14 13:42:58 -04001679 op->setClippedBounds(bounds);
Robert Phillipsc0138922017-03-08 11:50:55 -05001680 return this->getOpList()->addOp(std::move(op), this);
Brian Salomon467921e2017-03-06 16:17:12 -05001681}
1682
Robert Phillipsbf25d432017-04-07 10:08:53 -04001683bool GrRenderTargetContext::setupDstTexture(GrRenderTargetProxy* rtProxy, const GrClip& clip,
Brian Salomon467921e2017-03-06 16:17:12 -05001684 const SkRect& opBounds,
1685 GrXferProcessor::DstTexture* dstTexture) {
1686 if (this->caps()->textureBarrierSupport()) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001687 if (GrTextureProxy* texProxy = rtProxy->asTextureProxy()) {
1688 // MDB TODO: remove this instantiation. Blocked on making DstTexture be proxy-based
1689 sk_sp<GrTexture> tex(sk_ref_sp(texProxy->instantiate(fContext->resourceProvider())));
1690 if (!tex) {
1691 SkDebugf("setupDstTexture: instantiation of src texture failed.\n");
1692 return false; // We have bigger problems now
1693 }
1694
Brian Salomon467921e2017-03-06 16:17:12 -05001695 // The render target is a texture, so we can read from it directly in the shader. The XP
1696 // will be responsible to detect this situation and request a texture barrier.
Robert Phillipsbf25d432017-04-07 10:08:53 -04001697 dstTexture->setTexture(std::move(tex));
Brian Salomon467921e2017-03-06 16:17:12 -05001698 dstTexture->setOffset(0, 0);
Robert Phillipsbf25d432017-04-07 10:08:53 -04001699 return true;
Brian Salomon467921e2017-03-06 16:17:12 -05001700 }
1701 }
1702
Robert Phillipsbf25d432017-04-07 10:08:53 -04001703 SkIRect copyRect = SkIRect::MakeWH(rtProxy->width(), rtProxy->height());
Brian Salomon467921e2017-03-06 16:17:12 -05001704
Eric Karl74480882017-04-03 14:49:05 -07001705 SkIRect clippedRect;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001706 clip.getConservativeBounds(rtProxy->width(), rtProxy->height(), &clippedRect);
Eric Karl72e551e2017-04-04 13:42:10 -07001707 SkIRect drawIBounds;
Brian Salomon467921e2017-03-06 16:17:12 -05001708 opBounds.roundOut(&drawIBounds);
Brian Salomon859621f2017-03-16 09:21:54 -04001709 // Cover up for any precision issues by outsetting the op bounds a pixel in each direction.
1710 drawIBounds.outset(1, 1);
Eric Karl72e551e2017-04-04 13:42:10 -07001711 if (!clippedRect.intersect(drawIBounds)) {
Brian Salomon467921e2017-03-06 16:17:12 -05001712#ifdef SK_DEBUG
Robert Phillipsbf25d432017-04-07 10:08:53 -04001713 GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
Brian Salomon467921e2017-03-06 16:17:12 -05001714#endif
Robert Phillipsbf25d432017-04-07 10:08:53 -04001715 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05001716 }
1717
1718 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
1719 // have per-sample dst values by making the copy multisampled.
1720 GrSurfaceDesc desc;
Eric Karl74480882017-04-03 14:49:05 -07001721 bool rectsMustMatch = false;
1722 bool disallowSubrect = false;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001723 if (!this->caps()->initDescForDstCopy(rtProxy, &desc, &rectsMustMatch, &disallowSubrect)) {
1724 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
Brian Salomon467921e2017-03-06 16:17:12 -05001725 desc.fFlags = kRenderTarget_GrSurfaceFlag;
Robert Phillipsbf25d432017-04-07 10:08:53 -04001726 desc.fConfig = rtProxy->config();
Brian Salomon467921e2017-03-06 16:17:12 -05001727 }
1728
Eric Karl74480882017-04-03 14:49:05 -07001729 if (!disallowSubrect) {
1730 copyRect = clippedRect;
1731 }
Brian Salomon467921e2017-03-06 16:17:12 -05001732
Robert Phillipsbf25d432017-04-07 10:08:53 -04001733 SkIPoint dstPoint, dstOffset;
1734 SkBackingFit fit;
Eric Karl74480882017-04-03 14:49:05 -07001735 if (rectsMustMatch) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001736 SkASSERT(desc.fOrigin == rtProxy->origin());
1737 desc.fWidth = rtProxy->width();
1738 desc.fHeight = rtProxy->height();
Eric Karl74480882017-04-03 14:49:05 -07001739 dstPoint = {copyRect.fLeft, copyRect.fTop};
1740 dstOffset = {0, 0};
Robert Phillipsbf25d432017-04-07 10:08:53 -04001741 fit = SkBackingFit::kExact;
Eric Karl74480882017-04-03 14:49:05 -07001742 } else {
1743 desc.fWidth = copyRect.width();
1744 desc.fHeight = copyRect.height();
1745 dstPoint = {0, 0};
1746 dstOffset = {copyRect.fLeft, copyRect.fTop};
Robert Phillipsbf25d432017-04-07 10:08:53 -04001747 fit = SkBackingFit::kApprox;
Eric Karl74480882017-04-03 14:49:05 -07001748 }
Brian Salomon467921e2017-03-06 16:17:12 -05001749
Robert Phillipsbf25d432017-04-07 10:08:53 -04001750 sk_sp<GrSurfaceContext> sContext = fContext->contextPriv().makeDeferredSurfaceContext(
1751 desc,
1752 fit,
1753 SkBudgeted::kYes);
1754 if (!sContext) {
1755 SkDebugf("setupDstTexture: surfaceContext creation failed.\n");
1756 return false;
1757 }
1758
1759 if (!sContext->copy(rtProxy, copyRect, dstPoint)) {
1760 SkDebugf("setupDstTexture: copy failed.\n");
1761 return false;
1762 }
1763
1764 GrTextureProxy* copyProxy = sContext->asTextureProxy();
1765 // MDB TODO: remove this instantiation once DstTexture is proxy-backed
1766 sk_sp<GrTexture> copy(sk_ref_sp(copyProxy->instantiate(fContext->resourceProvider())));
Brian Salomon467921e2017-03-06 16:17:12 -05001767 if (!copy) {
Robert Phillipsbf25d432017-04-07 10:08:53 -04001768 SkDebugf("setupDstTexture: instantiation of copied texture failed.\n");
1769 return false;
Brian Salomon467921e2017-03-06 16:17:12 -05001770 }
Eric Karl74480882017-04-03 14:49:05 -07001771
Brian Salomon467921e2017-03-06 16:17:12 -05001772 dstTexture->setTexture(std::move(copy));
Eric Karl74480882017-04-03 14:49:05 -07001773 dstTexture->setOffset(dstOffset);
Robert Phillipsbf25d432017-04-07 10:08:53 -04001774 return true;
robertphillips2334fb62015-06-17 05:43:33 -07001775}