blob: 60a213fd478c38aa464b87c18fd8c0ce09dd8539 [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
robertphillipsea461502015-05-26 11:38:03 -07008#include "GrBatchTest.h"
jvanverth31ff7622015-08-07 10:09:28 -07009#include "GrColor.h"
Brian Osman11052242016-10-27 14:47:55 -040010#include "GrRenderTargetContext.h"
11#include "GrRenderTargetContextPriv.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"
18#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070019#include "GrResourceProvider.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070020#include "SkSurfacePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070021
Brian Salomon89527432016-12-16 09:52:16 -050022#include "ops/GrClearOp.h"
23#include "ops/GrDrawAtlasOp.h"
24#include "ops/GrDrawVerticesOp.h"
25#include "ops/GrLatticeOp.h"
26#include "ops/GrOp.h"
27#include "ops/GrOvalOpFactory.h"
28#include "ops/GrRectOpFactory.h"
29#include "ops/GrRegionOp.h"
30#include "ops/GrShadowRRectOp.h"
joshualitt74417822015-08-07 11:42:16 -070031
robertphillips00095892016-02-29 13:50:40 -080032#include "effects/GrRRectEffect.h"
33
csmartdaltona7f29642016-07-07 08:49:11 -070034#include "instanced/InstancedRendering.h"
35
joshualitte8042922015-12-11 06:11:21 -080036#include "text/GrAtlasTextContext.h"
37#include "text/GrStencilAndCoverTextContext.h"
38
joshualittbc907352016-01-13 06:45:40 -080039#include "../private/GrAuditTrail.h"
40
robertphillips1da3ecd2016-08-31 14:54:15 -070041#include "SkGr.h"
msarett10e3d9b2016-08-18 15:46:03 -070042#include "SkLatticeIter.h"
reeda39667c2016-08-22 06:39:49 -070043#include "SkMatrixPriv.h"
msarett10e3d9b2016-08-18 15:46:03 -070044
robertphillips77a2e522015-10-17 07:43:27 -070045#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080046#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080047 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080048#define ASSERT_SINGLE_OWNER_PRIV \
Brian Osman11052242016-10-27 14:47:55 -040049 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070050#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
Brian Osman11052242016-10-27 14:47:55 -040051#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->fDrawingManager->wasAbandoned()) { return; }
robertphillips7761d612016-05-16 09:14:53 -070052#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
Brian Osman11052242016-10-27 14:47:55 -040053#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->fDrawingManager->wasAbandoned()) { return false; }
robertphillips7761d612016-05-16 09:14:53 -070054#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070055
csmartdaltona7f29642016-07-07 08:49:11 -070056using gr_instanced::InstancedRendering;
57
robertphillipsea461502015-05-26 11:38:03 -070058class AutoCheckFlush {
59public:
halcanary9d524f22016-03-29 09:03:52 -070060 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070061 SkASSERT(fDrawingManager);
62 }
bsalomonb77a9072016-09-07 10:02:04 -070063 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070064
65private:
robertphillips77a2e522015-10-17 07:43:27 -070066 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070067};
68
Brian Osman11052242016-10-27 14:47:55 -040069bool GrRenderTargetContext::wasAbandoned() const {
robertphillips7761d612016-05-16 09:14:53 -070070 return fDrawingManager->wasAbandoned();
71}
72
Robert Phillipsf2361d22016-10-25 14:20:06 -040073// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress
Brian Osman11052242016-10-27 14:47:55 -040074// GrOpLists to be picked up and added to by renderTargetContexts lower in the call
Robert Phillipsf2361d22016-10-25 14:20:06 -040075// stack. When this occurs with a closed GrOpList, a new one will be allocated
Brian Osman11052242016-10-27 14:47:55 -040076// when the renderTargetContext attempts to use it (via getOpList).
77GrRenderTargetContext::GrRenderTargetContext(GrContext* context,
78 GrDrawingManager* drawingMgr,
Robert Phillipsc7635fa2016-10-28 13:25:24 -040079 sk_sp<GrRenderTargetProxy> rtp,
Brian Osman11052242016-10-27 14:47:55 -040080 sk_sp<SkColorSpace> colorSpace,
81 const SkSurfaceProps* surfaceProps,
82 GrAuditTrail* auditTrail,
83 GrSingleOwner* singleOwner)
Brian Osman45580d32016-11-23 09:37:01 -050084 : GrSurfaceContext(context, auditTrail, singleOwner)
85 , fDrawingManager(drawingMgr)
Robert Phillipsc7635fa2016-10-28 13:25:24 -040086 , fRenderTargetProxy(std::move(rtp))
87 , fOpList(SkSafeRef(fRenderTargetProxy->getLastRenderTargetOpList()))
Robert Phillipsc7635fa2016-10-28 13:25:24 -040088 , fInstancedPipelineInfo(fRenderTargetProxy.get())
brianosmandfe4f2e2016-07-21 13:28:36 -070089 , fColorSpace(std::move(colorSpace))
brianosman5a7ae7e2016-09-12 12:07:25 -070090 , fColorXformFromSRGB(nullptr)
joshualittde8dc7e2016-01-08 10:09:13 -080091 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualitt6d0872d2016-01-11 08:27:48 -080092{
brianosman5a7ae7e2016-09-12 12:07:25 -070093 if (fColorSpace) {
94 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
Brian Osman526972e2016-10-24 09:24:02 -040095 auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
msarettc71a9b72016-09-16 11:01:27 -070096 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
brianosman5a7ae7e2016-09-12 12:07:25 -070097 }
robertphillips2e1e51f2015-10-15 08:01:48 -070098 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070099}
100
robertphillips2e1e51f2015-10-15 08:01:48 -0700101#ifdef SK_DEBUG
Brian Osman11052242016-10-27 14:47:55 -0400102void GrRenderTargetContext::validate() const {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400103 SkASSERT(fRenderTargetProxy);
104 fRenderTargetProxy->validate(fContext);
robertphillipsa106c622015-10-16 09:07:06 -0700105
Robert Phillipsf2361d22016-10-25 14:20:06 -0400106 if (fOpList && !fOpList->isClosed()) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400107 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700108 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700109}
110#endif
111
Brian Osman11052242016-10-27 14:47:55 -0400112GrRenderTargetContext::~GrRenderTargetContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800113 ASSERT_SINGLE_OWNER
Robert Phillipsf2361d22016-10-25 14:20:06 -0400114 SkSafeUnref(fOpList);
robertphillipsa106c622015-10-16 09:07:06 -0700115}
116
Robert Phillipseaa86252016-11-08 13:49:39 +0000117GrRenderTarget* GrRenderTargetContext::instantiate() {
118 return fRenderTargetProxy->instantiate(fContext->textureProvider());
119}
120
121GrTextureProxy* GrRenderTargetContext::asDeferredTexture() {
122 return fRenderTargetProxy->asTextureProxy();
123}
124
Brian Osman11052242016-10-27 14:47:55 -0400125GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
joshualitt1de610a2016-01-06 08:26:09 -0800126 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700127 SkDEBUGCODE(this->validate();)
128
Robert Phillipsf2361d22016-10-25 14:20:06 -0400129 if (!fOpList || fOpList->isClosed()) {
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400130 fOpList = fDrawingManager->newOpList(fRenderTargetProxy.get());
robertphillipsa106c622015-10-16 09:07:06 -0700131 }
132
Robert Phillipsf2361d22016-10-25 14:20:06 -0400133 return fOpList;
robertphillipsa106c622015-10-16 09:07:06 -0700134}
135
Robert Phillipse2f7d182016-12-15 09:23:05 -0500136// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
137bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
138 const SkIRect& srcRect,
139 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800140 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800141 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700142 SkDEBUGCODE(this->validate();)
Robert Phillipse2f7d182016-12-15 09:23:05 -0500143 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
144
145 // TODO: defer instantiation until flush time
146 sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->textureProvider())));
147 if (!src) {
148 return false;
149 }
robertphillips2d70dcb2015-10-06 07:38:23 -0700150
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400151 // TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget
152 sk_sp<GrRenderTarget> rt(
153 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500154 if (!rt) {
155 return false;
156 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400157
Robert Phillipse2f7d182016-12-15 09:23:05 -0500158 return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700159}
160
Brian Osman11052242016-10-27 14:47:55 -0400161void GrRenderTargetContext::drawText(const GrClip& clip, const GrPaint& grPaint,
162 const SkPaint& skPaint,
163 const SkMatrix& viewMatrix,
164 const char text[], size_t byteLength,
165 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800166 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700167 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700168 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400169 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700170
brianosman86e76262016-08-11 12:17:31 -0700171 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
172 atlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
173 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700174}
robertphillipscaef3452015-11-11 13:18:11 -0800175
Brian Osman11052242016-10-27 14:47:55 -0400176void GrRenderTargetContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
177 const SkPaint& skPaint,
178 const SkMatrix& viewMatrix,
179 const char text[], size_t byteLength,
180 const SkScalar pos[], int scalarsPerPosition,
181 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800182 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700183 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700184 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400185 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700186
brianosman86e76262016-08-11 12:17:31 -0700187 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
188 atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
189 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
190 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700191
192}
robertphillipscaef3452015-11-11 13:18:11 -0800193
Brian Osman11052242016-10-27 14:47:55 -0400194void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
195 const SkMatrix& viewMatrix, const SkTextBlob* blob,
196 SkScalar x, SkScalar y,
197 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800198 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700199 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700200 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400201 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700202
brianosman86e76262016-08-11 12:17:31 -0700203 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
204 atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
205 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700206}
207
Brian Osman11052242016-10-27 14:47:55 -0400208void GrRenderTargetContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800209 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700210 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700211 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400212 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700213
robertphillips77a2e522015-10-17 07:43:27 -0700214 AutoCheckFlush acf(fDrawingManager);
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400215
216 // TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget
217 sk_sp<GrRenderTarget> rt(
218 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500219 if (!rt) {
220 return;
221 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400222
223 this->getOpList()->discard(rt.get());
robertphillipsea461502015-05-26 11:38:03 -0700224}
225
Brian Osman11052242016-10-27 14:47:55 -0400226void GrRenderTargetContext::clear(const SkIRect* rect,
227 const GrColor color,
228 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800229 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700230 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700231 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400232 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700233
robertphillips77a2e522015-10-17 07:43:27 -0700234 AutoCheckFlush acf(fDrawingManager);
csmartdalton29df7602016-08-31 11:55:52 -0700235 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
236}
robertphillips9199a9f2016-07-13 07:48:43 -0700237
Robert Phillips784b7bf2016-12-09 13:35:02 -0500238void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) {
239 ASSERT_SINGLE_OWNER_PRIV
240 RETURN_IF_ABANDONED_PRIV
241 SkDEBUGCODE(fRenderTargetContext->validate();)
242 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
243 "GrRenderTargetContext::absClear");
244
245 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager);
246
247 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth(
248 *fRenderTargetContext->caps()),
249 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight(
250 *fRenderTargetContext->caps()));
251
252 if (clearRect) {
253 if (clearRect->contains(rtRect)) {
254 clearRect = nullptr; // full screen
255 } else {
256 if (!rtRect.intersect(*clearRect)) {
257 return;
258 }
259 }
260 }
261
262 // TODO: in a post-MDB world this should be handled at the OpList level.
263 // An op-list that is initially cleared and has no other ops should receive an
264 // extra draw.
265 if (fRenderTargetContext->fContext->caps()->useDrawInsteadOfClear()) {
266 // This works around a driver bug with clear by drawing a rect instead.
267 // The driver will ignore a clear if it is the only thing rendered to a
268 // target before the target is read.
269 GrPaint paint;
270 paint.setColor4f(GrColor4f::FromGrColor(color));
271 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
272
273 // We don't call drawRect() here to avoid the cropping to the, possibly smaller,
274 // RenderTargetProxy bounds
275 fRenderTargetContext->drawNonAAFilledRect(GrNoClip(), paint, SkMatrix::I(),
276 SkRect::Make(rtRect),
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500277 nullptr, nullptr, nullptr, GrAAType::kNone);
Robert Phillips784b7bf2016-12-09 13:35:02 -0500278
279 } else {
280 if (!fRenderTargetContext->accessRenderTarget()) {
281 return;
282 }
283
284 // This path doesn't handle coalescing of full screen clears b.c. it
285 // has to clear the entire render target - not just the content area.
286 // It could be done but will take more finagling.
Brian Salomonfc527d22016-12-14 21:07:01 -0500287 sk_sp<GrOp> op(GrClearOp::Make(rtRect, color, fRenderTargetContext->accessRenderTarget(),
288 !clearRect));
289 if (!op) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500290 return;
291 }
Brian Salomonfc527d22016-12-14 21:07:01 -0500292 fRenderTargetContext->getOpList()->addOp(std::move(op));
Robert Phillips784b7bf2016-12-09 13:35:02 -0500293 }
294}
295
Brian Osman11052242016-10-27 14:47:55 -0400296void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
297 const GrColor color,
298 bool canIgnoreClip) {
csmartdalton29df7602016-08-31 11:55:52 -0700299 ASSERT_SINGLE_OWNER_PRIV
300 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400301 SkDEBUGCODE(fRenderTargetContext->validate();)
302 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
303 "GrRenderTargetContextPriv::clear");
csmartdalton29df7602016-08-31 11:55:52 -0700304
Brian Osman11052242016-10-27 14:47:55 -0400305 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager);
306 fRenderTargetContext->internalClear(clip, color, canIgnoreClip);
csmartdalton29df7602016-08-31 11:55:52 -0700307}
308
Brian Osman11052242016-10-27 14:47:55 -0400309void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
310 const GrColor color,
311 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700312 bool isFull = false;
313 if (!clip.hasWindowRectangles()) {
314 isFull = !clip.scissorEnabled() ||
315 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
316 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
317 }
robertphillips9199a9f2016-07-13 07:48:43 -0700318
319 if (fContext->caps()->useDrawInsteadOfClear()) {
320 // This works around a driver bug with clear by drawing a rect instead.
321 // The driver will ignore a clear if it is the only thing rendered to a
322 // target before the target is read.
Robert Phillips784b7bf2016-12-09 13:35:02 -0500323 SkIRect clearRect = SkIRect::MakeWH(this->width(), this->height());
csmartdalton29df7602016-08-31 11:55:52 -0700324 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700325 this->discard();
Robert Phillips93f16332016-11-23 19:37:13 -0500326 } else if (!clearRect.intersect(clip.scissorRect())) {
csmartdalton29df7602016-08-31 11:55:52 -0700327 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700328 }
329
330 GrPaint paint;
331 paint.setColor4f(GrColor4f::FromGrColor(color));
Mike Reed7d954ad2016-10-28 15:42:34 -0400332 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc));
robertphillips9199a9f2016-07-13 07:48:43 -0700333
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500334 this->drawRect(clip, paint, GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect));
bsalomon9f129de2016-08-10 16:31:05 -0700335 } else if (isFull) {
Robert Phillipse60ad622016-11-17 10:22:48 -0500336 if (this->accessRenderTarget()) {
337 this->getOpList()->fullClear(this->accessRenderTarget(), color);
338 }
robertphillips9199a9f2016-07-13 07:48:43 -0700339 } else {
Robert Phillipse60ad622016-11-17 10:22:48 -0500340 if (!this->accessRenderTarget()) {
341 return;
342 }
Brian Salomon7dae46a2016-12-14 16:21:37 -0500343 sk_sp<GrOp> op(GrClearOp::Make(clip, color, this->accessRenderTarget()));
Brian Salomon42521e82016-12-07 16:44:58 -0500344 if (!op) {
csmartdalton29df7602016-08-31 11:55:52 -0700345 return;
346 }
Brian Salomon42521e82016-12-07 16:44:58 -0500347 this->getOpList()->addOp(std::move(op));
robertphillips9199a9f2016-07-13 07:48:43 -0700348 }
robertphillipsea461502015-05-26 11:38:03 -0700349}
350
Brian Osman11052242016-10-27 14:47:55 -0400351void GrRenderTargetContext::drawPaint(const GrClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500352 const GrPaint& paint,
Brian Osman11052242016-10-27 14:47:55 -0400353 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800354 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700355 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700356 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400357 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700358
robertphillipsea461502015-05-26 11:38:03 -0700359 // set rect to be big enough to fill the space, but not super-huge, so we
360 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700361
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400362 SkRect r = fRenderTargetProxy->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700363
bsalomoncb31e512016-08-26 10:48:19 -0700364 SkRRect rrect;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500365 GrAA aa;
bsalomoncb31e512016-08-26 10:48:19 -0700366 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
367 // transformation for non-rect rrects. Rects caused a performance regression on an Android
368 // test that needs investigation. We also skip cases where there are fragment processors
369 // because they may depend on having correct local coords and this path draws in device space
370 // without a local matrix.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500371 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) {
372 this->drawRRect(GrNoClip(), paint, aa, SkMatrix::I(), rrect, GrStyle::SimpleFill());
bsalomoncb31e512016-08-26 10:48:19 -0700373 return;
374 }
375
robertphillipsea461502015-05-26 11:38:03 -0700376
377 bool isPerspective = viewMatrix.hasPerspective();
378
379 // We attempt to map r by the inverse matrix and draw that. mapRect will
380 // map the four corners and bound them with a new rect. This will not
381 // produce a correct result for some perspective matrices.
382 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700383 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700384 SkDebugf("Could not invert matrix\n");
385 return;
386 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500387 this->drawRect(clip, paint, GrAA::kNo, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700388 } else {
389 SkMatrix localMatrix;
390 if (!viewMatrix.invert(&localMatrix)) {
391 SkDebugf("Could not invert matrix\n");
392 return;
393 }
394
robertphillips77a2e522015-10-17 07:43:27 -0700395 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700396
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500397 this->drawNonAAFilledRect(clip, paint, SkMatrix::I(), r, nullptr, &localMatrix,
398 nullptr, GrAAType::kNone);
robertphillipsea461502015-05-26 11:38:03 -0700399 }
400}
401
robertphillipsea461502015-05-26 11:38:03 -0700402static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
403 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
404 point.fY >= rect.fTop && point.fY <= rect.fBottom;
405}
406
bsalomonc55271f2015-11-09 11:55:57 -0800407static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
408 return viewMatrix.preservesRightAngles();
409}
410
csmartdalton97f6cd52016-07-13 13:37:08 -0700411// Attempts to crop a rect and optional local rect to the clip boundaries.
412// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700413static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700414 const SkMatrix& viewMatrix, SkRect* rect,
415 SkRect* localRect = nullptr) {
416 if (!viewMatrix.rectStaysRect()) {
417 return true;
418 }
419
csmartdalton97f6cd52016-07-13 13:37:08 -0700420 SkIRect clipDevBounds;
421 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700422
robertphillips13a7eee2016-08-31 15:06:24 -0700423 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700424 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
425 return false;
426 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700427
428 if (localRect) {
429 if (!rect->intersects(clipBounds)) {
430 return false;
431 }
432 const SkScalar dx = localRect->width() / rect->width();
433 const SkScalar dy = localRect->height() / rect->height();
434 if (clipBounds.fLeft > rect->fLeft) {
435 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
436 rect->fLeft = clipBounds.fLeft;
437 }
438 if (clipBounds.fTop > rect->fTop) {
439 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
440 rect->fTop = clipBounds.fTop;
441 }
442 if (clipBounds.fRight < rect->fRight) {
443 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
444 rect->fRight = clipBounds.fRight;
445 }
446 if (clipBounds.fBottom < rect->fBottom) {
447 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
448 rect->fBottom = clipBounds.fBottom;
449 }
450 return true;
451 }
452
453 return rect->intersect(clipBounds);
454}
455
Brian Osman11052242016-10-27 14:47:55 -0400456bool GrRenderTargetContext::drawFilledRect(const GrClip& clip,
457 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500458 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400459 const SkMatrix& viewMatrix,
460 const SkRect& rect,
461 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700462 SkRect croppedRect = rect;
Robert Phillips784b7bf2016-12-09 13:35:02 -0500463 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700464 return true;
465 }
robertphillips44302392016-07-08 14:43:03 -0700466
Brian Salomon42521e82016-12-07 16:44:58 -0500467 sk_sp<GrDrawOp> op;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500468 GrAAType aaType;
robertphillips44302392016-07-08 14:43:03 -0700469
csmartdaltone0d36292016-07-29 08:14:20 -0700470 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400471 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon99ad1642016-12-16 09:50:45 -0500472 op = ir->recordRect(croppedRect, viewMatrix, paint.getColor(), aa, fInstancedPipelineInfo,
473 &aaType);
Brian Salomon42521e82016-12-07 16:44:58 -0500474 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500475 GrPipelineBuilder pipelineBuilder(paint, aaType);
robertphillips44302392016-07-08 14:43:03 -0700476 if (ss) {
477 pipelineBuilder.setUserStencil(ss);
478 }
Brian Salomon21aa35f2016-12-09 16:01:53 -0500479 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700480 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700481 }
482 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500483 aaType = this->decideAAType(aa);
484 if (GrAAType::kCoverage == aaType) {
robertphillips391395d2016-03-02 09:26:36 -0800485 // The fill path can handle rotation but not skew.
486 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
487 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700488 viewMatrix.mapRect(&devBoundRect, croppedRect);
robertphillips44302392016-07-08 14:43:03 -0700489
Brian Salomon6a639042016-12-14 11:08:17 -0500490 op = GrRectOpFactory::MakeAAFill(paint, viewMatrix, rect, croppedRect, devBoundRect);
Brian Salomon42521e82016-12-07 16:44:58 -0500491 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500492 GrPipelineBuilder pipelineBuilder(paint, aaType);
robertphillips44302392016-07-08 14:43:03 -0700493 if (ss) {
494 pipelineBuilder.setUserStencil(ss);
495 }
Brian Salomon21aa35f2016-12-09 16:01:53 -0500496 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700497 return true;
498 }
robertphillips391395d2016-03-02 09:26:36 -0800499 }
500 } else {
csmartdalton34ee0c92016-07-27 13:22:27 -0700501 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500502 aaType);
robertphillips44302392016-07-08 14:43:03 -0700503 return true;
robertphillips391395d2016-03-02 09:26:36 -0800504 }
505
robertphillips44302392016-07-08 14:43:03 -0700506 return false;
robertphillips391395d2016-03-02 09:26:36 -0800507}
508
Brian Osman11052242016-10-27 14:47:55 -0400509void GrRenderTargetContext::drawRect(const GrClip& clip,
510 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500511 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400512 const SkMatrix& viewMatrix,
513 const SkRect& rect,
514 const GrStyle* style) {
bsalomon6663acf2016-05-10 09:14:17 -0700515 if (!style) {
516 style = &GrStyle::SimpleFill();
517 }
joshualitt1de610a2016-01-06 08:26:09 -0800518 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700519 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700520 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400521 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700522
bsalomon6663acf2016-05-10 09:14:17 -0700523 // Path effects should've been devolved to a path in SkGpuDevice
524 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700525
robertphillips77a2e522015-10-17 07:43:27 -0700526 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700527
bsalomon6663acf2016-05-10 09:14:17 -0700528 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700529 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
530
531 if (!fContext->caps()->useDrawInsteadOfClear()) {
532 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
533 // checking cases where the RT is fully inside a stroke.
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400534 SkRect rtRect = fRenderTargetProxy->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700535 // Does the clip contain the entire RT?
536 if (clip.quickContains(rtRect)) {
537 SkMatrix invM;
538 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700539 return;
540 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700541 // Does the rect bound the RT?
542 SkPoint srcSpaceRTQuad[4];
543 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
544 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
545 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
546 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
547 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
548 // Will it blend?
549 GrColor clearColor;
550 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700551 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700552 return;
553 }
554 }
robertphillipsea461502015-05-26 11:38:03 -0700555 }
556 }
robertphillips44302392016-07-08 14:43:03 -0700557
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500558 if (this->drawFilledRect(clip, paint, aa, viewMatrix, rect, nullptr)) {
robertphillips44302392016-07-08 14:43:03 -0700559 return;
560 }
bsalomona7d85ba2016-07-06 11:54:59 -0700561 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
562 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
563 if ((!rect.width() || !rect.height()) &&
564 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
565 SkScalar r = stroke.getWidth() / 2;
566 // TODO: Move these stroke->fill fallbacks to GrShape?
567 switch (stroke.getJoin()) {
568 case SkPaint::kMiter_Join:
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500569 this->drawRect(clip, paint, aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700570 {rect.fLeft - r, rect.fTop - r,
571 rect.fRight + r, rect.fBottom + r},
572 &GrStyle::SimpleFill());
573 return;
574 case SkPaint::kRound_Join:
575 // Raster draws nothing when both dimensions are empty.
576 if (rect.width() || rect.height()){
577 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500578 this->drawRRect(clip, paint, aa, viewMatrix, rrect, GrStyle::SimpleFill());
bsalomona7d85ba2016-07-06 11:54:59 -0700579 return;
580 }
581 case SkPaint::kBevel_Join:
582 if (!rect.width()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500583 this->drawRect(clip, paint, aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700584 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
585 &GrStyle::SimpleFill());
586 } else {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500587 this->drawRect(clip, paint, aa, viewMatrix,
bsalomona7d85ba2016-07-06 11:54:59 -0700588 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
589 &GrStyle::SimpleFill());
590 }
591 return;
592 }
593 }
robertphillips44302392016-07-08 14:43:03 -0700594
robertphillips44302392016-07-08 14:43:03 -0700595 bool snapToPixelCenters = false;
Brian Salomon42521e82016-12-07 16:44:58 -0500596 sk_sp<GrDrawOp> op;
robertphillips44302392016-07-08 14:43:03 -0700597
robertphillips391395d2016-03-02 09:26:36 -0800598 GrColor color = paint.getColor();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500599 GrAAType aaType = this->decideAAType(aa);
600 if (GrAAType::kCoverage == aaType) {
cdaltonbb539482016-01-04 09:48:25 -0800601 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
602 if (viewMatrix.rectStaysRect()) {
Brian Salomon6a639042016-12-14 11:08:17 -0500603 op = GrRectOpFactory::MakeAAStroke(color, viewMatrix, rect, stroke);
cdaltonbb539482016-01-04 09:48:25 -0800604 }
robertphillipsea461502015-05-26 11:38:03 -0700605 } else {
robertphillips391395d2016-03-02 09:26:36 -0800606 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700607 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800608 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700609 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400610 !fRenderTargetProxy->isUnifiedMultisampled();
Brian Salomon6a639042016-12-14 11:08:17 -0500611 op = GrRectOpFactory::MakeNonAAStroke(color, viewMatrix, rect, stroke,
612 snapToPixelCenters);
robertphillips391395d2016-03-02 09:26:36 -0800613 }
robertphillips4bc31812016-03-01 12:22:49 -0800614
Brian Salomon42521e82016-12-07 16:44:58 -0500615 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500616 GrPipelineBuilder pipelineBuilder(paint, aaType);
robertphillips4bc31812016-03-01 12:22:49 -0800617
robertphillips44302392016-07-08 14:43:03 -0700618 if (snapToPixelCenters) {
619 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
620 snapToPixelCenters);
621 }
622
Brian Salomon21aa35f2016-12-09 16:01:53 -0500623 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -0700624 return;
robertphillips4bc31812016-03-01 12:22:49 -0800625 }
robertphillips4bc31812016-03-01 12:22:49 -0800626 }
halcanary9d524f22016-03-29 09:03:52 -0700627
robertphillips4bc31812016-03-01 12:22:49 -0800628 SkPath path;
629 path.setIsVolatile(true);
630 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500631 this->internalDrawPath(clip, paint, aa, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700632}
633
Robert Phillipsec2249f2016-11-09 08:54:35 -0500634int GrRenderTargetContextPriv::maxWindowRectangles() const {
635 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles(
636 *fRenderTargetContext->fContext->caps());
637}
638
Brian Osman11052242016-10-27 14:47:55 -0400639void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700640 ASSERT_SINGLE_OWNER_PRIV
641 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400642 SkDEBUGCODE(fRenderTargetContext->validate();)
643 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
644 "GrRenderTargetContextPriv::clearStencilClip");
robertphillips976f5f02016-06-03 10:59:20 -0700645
Brian Osman11052242016-10-27 14:47:55 -0400646 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager);
Robert Phillipse60ad622016-11-17 10:22:48 -0500647 if (!fRenderTargetContext->accessRenderTarget()) {
648 return;
649 }
Brian Osman11052242016-10-27 14:47:55 -0400650 fRenderTargetContext->getOpList()->clearStencilClip(clip, insideStencilMask,
651 fRenderTargetContext->accessRenderTarget());
robertphillips976f5f02016-06-03 10:59:20 -0700652}
653
Brian Osman11052242016-10-27 14:47:55 -0400654void GrRenderTargetContextPriv::stencilPath(const GrClip& clip,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500655 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400656 const SkMatrix& viewMatrix,
657 const GrPath* path) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500658 SkASSERT(aaType != GrAAType::kCoverage);
659 fRenderTargetContext->getOpList()->stencilPath(fRenderTargetContext, clip, aaType, viewMatrix,
Brian Osman11052242016-10-27 14:47:55 -0400660 path);
robertphillips976f5f02016-06-03 10:59:20 -0700661}
662
Brian Osman11052242016-10-27 14:47:55 -0400663void GrRenderTargetContextPriv::stencilRect(const GrClip& clip,
664 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500665 GrAAType aaType,
Brian Osman11052242016-10-27 14:47:55 -0400666 const SkMatrix& viewMatrix,
667 const SkRect& rect) {
robertphillips976f5f02016-06-03 10:59:20 -0700668 ASSERT_SINGLE_OWNER_PRIV
669 RETURN_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400670 SkDEBUGCODE(fRenderTargetContext->validate();)
671 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
672 "GrRenderTargetContext::stencilRect");
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500673 SkASSERT(GrAAType::kCoverage != aaType);
Brian Osman11052242016-10-27 14:47:55 -0400674 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager);
robertphillips976f5f02016-06-03 10:59:20 -0700675
676 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700677 paint.setXPFactory(GrDisableColorXPFactory::Make());
robertphillips976f5f02016-06-03 10:59:20 -0700678
Brian Osman11052242016-10-27 14:47:55 -0400679 fRenderTargetContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500680 aaType);
robertphillips976f5f02016-06-03 10:59:20 -0700681}
682
Brian Osman11052242016-10-27 14:47:55 -0400683bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip,
684 const GrUserStencilSettings* ss,
685 SkRegion::Op op,
686 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500687 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400688 const SkMatrix& viewMatrix,
689 const SkRect& rect) {
robertphillips391395d2016-03-02 09:26:36 -0800690 ASSERT_SINGLE_OWNER_PRIV
691 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -0400692 SkDEBUGCODE(fRenderTargetContext->validate();)
693 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
694 "GrRenderTargetContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800695
Brian Osman11052242016-10-27 14:47:55 -0400696 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager);
robertphillips391395d2016-03-02 09:26:36 -0800697
698 GrPaint paint;
robertphillips391395d2016-03-02 09:26:36 -0800699 paint.setCoverageSetOpXPFactory(op, invert);
700
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500701 if (fRenderTargetContext->drawFilledRect(clip, paint, aa, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800702 return true;
703 }
robertphillips391395d2016-03-02 09:26:36 -0800704 SkPath path;
705 path.setIsVolatile(true);
706 path.addRect(rect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500707 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800708}
709
Brian Osman11052242016-10-27 14:47:55 -0400710void GrRenderTargetContext::fillRectToRect(const GrClip& clip,
711 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500712 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400713 const SkMatrix& viewMatrix,
714 const SkRect& rectToDraw,
715 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800716 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700717 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700718 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400719 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700720
csmartdalton97f6cd52016-07-13 13:37:08 -0700721 SkRect croppedRect = rectToDraw;
722 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700723 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
724 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700725 return;
726 }
727
robertphillips77a2e522015-10-17 07:43:27 -0700728 AutoCheckFlush acf(fDrawingManager);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500729 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -0700730
csmartdaltone0d36292016-07-29 08:14:20 -0700731 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400732 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon42521e82016-12-07 16:44:58 -0500733 sk_sp<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500734 croppedLocalRect, aa, fInstancedPipelineInfo, &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -0500735 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500736 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500737 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700738 return;
739 }
740 }
741
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500742 aaType = this->decideAAType(aa);
743 if (GrAAType::kCoverage != aaType) {
744 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect, nullptr,
745 nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700746 return;
joshualitt04194f32016-01-13 10:08:27 -0800747 }
bsalomonbb243832016-07-22 07:10:19 -0700748
csmartdaltonfc49d562016-07-26 17:05:47 -0700749 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomon6a639042016-12-14 11:08:17 -0500750 sk_sp<GrDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(paint.getColor(), viewMatrix,
751 croppedRect, croppedLocalRect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500752 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon24f19782016-12-13 15:10:11 -0500753 this->addDrawOp(pipelineBuilder, clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700754 return;
755 }
756
757 SkMatrix viewAndUnLocalMatrix;
758 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
759 SkDebugf("fillRectToRect called with empty local matrix.\n");
760 return;
761 }
762 viewAndUnLocalMatrix.postConcat(viewMatrix);
763
764 SkPath path;
765 path.setIsVolatile(true);
766 path.addRect(localRect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500767 this->internalDrawPath(clip, paint, aa, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700768}
769
Brian Osman11052242016-10-27 14:47:55 -0400770void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip,
771 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500772 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400773 const SkMatrix& viewMatrix,
774 const SkRect& rectToDraw,
775 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800776 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700777 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700778 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400779 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700780
csmartdalton97f6cd52016-07-13 13:37:08 -0700781 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700782 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700783 return;
784 }
785
robertphillips77a2e522015-10-17 07:43:27 -0700786 AutoCheckFlush acf(fDrawingManager);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500787 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -0700788
csmartdaltone0d36292016-07-29 08:14:20 -0700789 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400790 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon42521e82016-12-07 16:44:58 -0500791 sk_sp<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(), localMatrix,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500792 aa, fInstancedPipelineInfo, &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -0500793 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500794 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500795 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700796 return;
797 }
798 }
799
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500800 aaType = this->decideAAType(aa);
801 if (GrAAType::kCoverage != aaType) {
802 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, &localMatrix,
803 nullptr, aaType);
csmartdaltonfc49d562016-07-26 17:05:47 -0700804 return;
bsalomonc55271f2015-11-09 11:55:57 -0800805 }
robertphillips4bc31812016-03-01 12:22:49 -0800806
csmartdaltonfc49d562016-07-26 17:05:47 -0700807 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
Brian Salomon6a639042016-12-14 11:08:17 -0500808 sk_sp<GrDrawOp> op =
809 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500810 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500811 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltonfc49d562016-07-26 17:05:47 -0700812 return;
813 }
814
815 SkMatrix viewAndUnLocalMatrix;
816 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
817 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
818 return;
819 }
820 viewAndUnLocalMatrix.postConcat(viewMatrix);
821
822 SkPath path;
823 path.setIsVolatile(true);
824 path.addRect(rectToDraw);
825 path.transform(localMatrix);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500826 this->internalDrawPath(clip, paint, aa, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700827}
828
Brian Osman11052242016-10-27 14:47:55 -0400829void GrRenderTargetContext::drawVertices(const GrClip& clip,
830 const GrPaint& paint,
831 const SkMatrix& viewMatrix,
832 GrPrimitiveType primitiveType,
833 int vertexCount,
834 const SkPoint positions[],
835 const SkPoint texCoords[],
836 const GrColor colors[],
837 const uint16_t indices[],
838 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800839 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700840 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700841 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400842 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700843
robertphillips77a2e522015-10-17 07:43:27 -0700844 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700845
robertphillipsea461502015-05-26 11:38:03 -0700846 // TODO clients should give us bounds
847 SkRect bounds;
848 if (!bounds.setBoundsCheck(positions, vertexCount)) {
849 SkDebugf("drawVertices call empty bounds\n");
850 return;
851 }
852
853 viewMatrix.mapRect(&bounds);
854
Brian Salomonfc527d22016-12-14 21:07:01 -0500855 sk_sp<GrDrawOp> op =
856 GrDrawVerticesOp::Make(paint.getColor(), primitiveType, viewMatrix, positions,
857 vertexCount, indices, indexCount, colors, texCoords, bounds);
robertphillipsea461502015-05-26 11:38:03 -0700858
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500859 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500860 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -0700861}
862
863///////////////////////////////////////////////////////////////////////////////
864
Brian Osman11052242016-10-27 14:47:55 -0400865void GrRenderTargetContext::drawAtlas(const GrClip& clip,
866 const GrPaint& paint,
867 const SkMatrix& viewMatrix,
868 int spriteCount,
869 const SkRSXform xform[],
870 const SkRect texRect[],
871 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800872 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700873 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700874 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400875 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700876
robertphillips77a2e522015-10-17 07:43:27 -0700877 AutoCheckFlush acf(fDrawingManager);
halcanary9d524f22016-03-29 09:03:52 -0700878
Brian Salomonfc527d22016-12-14 21:07:01 -0500879 sk_sp<GrDrawOp> op =
880 GrDrawAtlasOp::Make(paint.getColor(), viewMatrix, spriteCount, xform, texRect, colors);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500881 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500882 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
jvanverth31ff7622015-08-07 10:09:28 -0700883}
884
885///////////////////////////////////////////////////////////////////////////////
886
Brian Osman11052242016-10-27 14:47:55 -0400887void GrRenderTargetContext::drawRRect(const GrClip& origClip,
888 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500889 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400890 const SkMatrix& viewMatrix,
891 const SkRRect& rrect,
892 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800893 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700894 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700895 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -0400896 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700897 if (rrect.isEmpty()) {
898 return;
899 }
900
bsalomon7f0d9f32016-08-15 14:49:10 -0700901 GrNoClip noclip;
902 const GrClip* clip = &origClip;
903#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
904 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
Brian Salomon42521e82016-12-07 16:44:58 -0500905 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
bsalomon7f0d9f32016-08-15 14:49:10 -0700906 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
907 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
908 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
909 SkRRect devRRect;
910 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
911 clip = &noclip;
912 }
913#endif
bsalomon6663acf2016-05-10 09:14:17 -0700914 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700915
csmartdaltona7f29642016-07-07 08:49:11 -0700916 AutoCheckFlush acf(fDrawingManager);
917 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500918 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -0700919
csmartdaltone0d36292016-07-29 08:14:20 -0700920 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
921 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400922 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500923 sk_sp<GrDrawOp> op(ir->recordRRect(rrect, viewMatrix, paint.getColor(), aa,
924 fInstancedPipelineInfo, &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -0500925 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500926 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500927 this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -0700928 return;
929 }
930 }
931
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500932 aaType = this->decideAAType(aa);
933 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -0500934 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomon289e3d82016-12-14 15:52:56 -0500935 sk_sp<GrDrawOp> op = GrOvalOpFactory::MakeRRectOp(paint.getColor(),
936 paint.usesDistanceVectorField(),
937 viewMatrix,
938 rrect,
939 stroke,
940 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -0500941 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500942 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500943 this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -0800944 return;
945 }
robertphillipsea461502015-05-26 11:38:03 -0700946 }
robertphillipsb56f9272016-02-25 11:03:52 -0800947
948 SkPath path;
949 path.setIsVolatile(true);
950 path.addRRect(rrect);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500951 this->internalDrawPath(*clip, paint, aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700952}
953
Jim Van Verthc5903412016-11-17 15:27:09 -0500954///////////////////////////////////////////////////////////////////////////////
955
956void GrRenderTargetContext::drawShadowRRect(const GrClip& clip,
957 const GrPaint& paint,
958 const SkMatrix& viewMatrix,
959 const SkRRect& rrect,
960 SkScalar blurRadius,
961 const GrStyle& style) {
962 ASSERT_SINGLE_OWNER
963 RETURN_IF_ABANDONED
964 SkDEBUGCODE(this->validate();)
965 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect");
966 if (rrect.isEmpty()) {
967 return;
968 }
969
970 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
971
972 AutoCheckFlush acf(fDrawingManager);
973 const SkStrokeRec stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500974 // TODO: add instancing support?
Jim Van Verthc5903412016-11-17 15:27:09 -0500975
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500976 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomonfc527d22016-12-14 21:07:01 -0500977 sk_sp<GrDrawOp> op = GrShadowRRectOp::Make(paint.getColor(), viewMatrix, rrect, blurRadius,
978 stroke, shaderCaps);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500979 if (op) {
980 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -0500981 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500982 return;
Jim Van Verthc5903412016-11-17 15:27:09 -0500983 }
Jim Van Verthc5903412016-11-17 15:27:09 -0500984}
985
986///////////////////////////////////////////////////////////////////////////////
987
Brian Osman11052242016-10-27 14:47:55 -0400988bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
989 const GrPaint& paintIn,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500990 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -0400991 const SkMatrix& viewMatrix,
992 const SkRRect& origOuter,
993 const SkRRect& origInner) {
robertphillips00095892016-02-29 13:50:40 -0800994 SkASSERT(!origInner.isEmpty());
995 SkASSERT(!origOuter.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500996 GrAAType aaType;
robertphillips00095892016-02-29 13:50:40 -0800997
csmartdaltone0d36292016-07-29 08:14:20 -0700998 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400999 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon42521e82016-12-07 16:44:58 -05001000 sk_sp<GrDrawOp> op(ir->recordDRRect(origOuter, origInner, viewMatrix, paintIn.getColor(),
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001001 aa, fInstancedPipelineInfo, &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -05001002 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001003 GrPipelineBuilder pipelineBuilder(paintIn, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001004 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001005 return true;
1006 }
1007 }
1008
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001009 aaType = this->decideAAType(aa);
robertphillips00095892016-02-29 13:50:40 -08001010
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001011 GrPrimitiveEdgeType innerEdgeType, outerEdgeType;
1012 if (GrAAType::kCoverage == aaType) {
1013 innerEdgeType = kInverseFillAA_GrProcessorEdgeType;
1014 outerEdgeType = kFillAA_GrProcessorEdgeType;
1015 } else {
1016 innerEdgeType = kInverseFillBW_GrProcessorEdgeType;
1017 outerEdgeType = kFillBW_GrProcessorEdgeType;
1018 }
robertphillips00095892016-02-29 13:50:40 -08001019
1020 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1021 SkMatrix inverseVM;
1022 if (!viewMatrix.isIdentity()) {
1023 if (!origInner.transform(viewMatrix, inner.writable())) {
1024 return false;
1025 }
1026 if (!origOuter.transform(viewMatrix, outer.writable())) {
1027 return false;
1028 }
1029 if (!viewMatrix.invert(&inverseVM)) {
1030 return false;
1031 }
1032 } else {
1033 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -07001034 }
robertphillips00095892016-02-29 13:50:40 -08001035
1036 GrPaint grPaint(paintIn);
robertphillips00095892016-02-29 13:50:40 -08001037
1038 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -07001039 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -08001040 if (!innerEffect) {
1041 return false;
1042 }
1043
bungeman06ca8ec2016-06-09 08:01:03 -07001044 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -08001045 if (!outerEffect) {
1046 return false;
1047 }
1048
bungeman06ca8ec2016-06-09 08:01:03 -07001049 grPaint.addCoverageFragmentProcessor(std::move(innerEffect));
1050 grPaint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -08001051
1052 SkRect bounds = outer->getBounds();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001053 if (GrAAType::kCoverage == aaType) {
robertphillips00095892016-02-29 13:50:40 -08001054 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1055 }
halcanary9d524f22016-03-29 09:03:52 -07001056
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001057 this->fillRectWithLocalMatrix(clip, grPaint, GrAA::kNo, SkMatrix::I(), bounds, inverseVM);
robertphillips00095892016-02-29 13:50:40 -08001058 return true;
1059}
1060
Brian Osman11052242016-10-27 14:47:55 -04001061void GrRenderTargetContext::drawDRRect(const GrClip& clip,
1062 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001063 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001064 const SkMatrix& viewMatrix,
1065 const SkRRect& outer,
1066 const SkRRect& inner) {
robertphillips00095892016-02-29 13:50:40 -08001067 ASSERT_SINGLE_OWNER
1068 RETURN_IF_ABANDONED
1069 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001070 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect");
robertphillips00095892016-02-29 13:50:40 -08001071
1072 SkASSERT(!outer.isEmpty());
1073 SkASSERT(!inner.isEmpty());
1074
1075 AutoCheckFlush acf(fDrawingManager);
1076
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001077 if (this->drawFilledDRRect(clip, paint, aa, viewMatrix, outer, inner)) {
robertphillips00095892016-02-29 13:50:40 -08001078 return;
1079 }
1080
1081 SkPath path;
1082 path.setIsVolatile(true);
1083 path.addRRect(inner);
1084 path.addRRect(outer);
1085 path.setFillType(SkPath::kEvenOdd_FillType);
1086
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001087 this->internalDrawPath(clip, paint, aa, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -08001088}
1089
robertphillipsea461502015-05-26 11:38:03 -07001090///////////////////////////////////////////////////////////////////////////////
1091
msarettcc319b92016-08-25 18:07:18 -07001092static inline bool is_int(float x) {
1093 return x == (float) sk_float_round2int(x);
1094}
1095
Brian Osman11052242016-10-27 14:47:55 -04001096void GrRenderTargetContext::drawRegion(const GrClip& clip,
1097 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001098 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001099 const SkMatrix& viewMatrix,
1100 const SkRegion& region,
1101 const GrStyle& style) {
msarettcc319b92016-08-25 18:07:18 -07001102 ASSERT_SINGLE_OWNER
1103 RETURN_IF_ABANDONED
1104 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001105 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion");
msarettcc319b92016-08-25 18:07:18 -07001106
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001107 if (GrAA::kYes == aa) {
Brian Salomonfc527d22016-12-14 21:07:01 -05001108 // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
Brian Salomonc57c7c92016-12-06 14:47:34 -05001109 // to see whether aa is really required.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001110 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1111 is_int(viewMatrix.getTranslateX()) &&
1112 is_int(viewMatrix.getTranslateY())) {
1113 aa = GrAA::kNo;
1114 }
Brian Salomonc57c7c92016-12-06 14:47:34 -05001115 }
msarettcc319b92016-08-25 18:07:18 -07001116 bool complexStyle = !style.isSimpleFill();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001117 if (complexStyle || GrAA::kYes == aa) {
msarettcc319b92016-08-25 18:07:18 -07001118 SkPath path;
1119 region.getBoundaryPath(&path);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001120 return this->drawPath(clip, paint, aa, viewMatrix, path, style);
msarettcc319b92016-08-25 18:07:18 -07001121 }
1122
Brian Salomonfc527d22016-12-14 21:07:01 -05001123 sk_sp<GrDrawOp> op = GrRegionOp::Make(paint.getColor(), viewMatrix, region);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001124 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001125 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
msarettcc319b92016-08-25 18:07:18 -07001126}
1127
Brian Osman11052242016-10-27 14:47:55 -04001128void GrRenderTargetContext::drawOval(const GrClip& clip,
1129 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001130 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001131 const SkMatrix& viewMatrix,
1132 const SkRect& oval,
1133 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001134 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001135 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001136 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001137 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001138
robertphillipsea461502015-05-26 11:38:03 -07001139 if (oval.isEmpty()) {
1140 return;
1141 }
1142
bsalomon6663acf2016-05-10 09:14:17 -07001143 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001144
robertphillips77a2e522015-10-17 07:43:27 -07001145 AutoCheckFlush acf(fDrawingManager);
bsalomon6663acf2016-05-10 09:14:17 -07001146 const SkStrokeRec& stroke = style.strokeRec();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001147 GrAAType aaType;
csmartdaltona7f29642016-07-07 08:49:11 -07001148
csmartdaltone0d36292016-07-29 08:14:20 -07001149 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1150 stroke.isFillStyle()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -04001151 InstancedRendering* ir = this->getOpList()->instancedRendering();
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001152 sk_sp<GrDrawOp> op(ir->recordOval(oval, viewMatrix, paint.getColor(), aa,
1153 fInstancedPipelineInfo, &aaType));
Brian Salomon42521e82016-12-07 16:44:58 -05001154 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001155 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001156 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
csmartdaltona7f29642016-07-07 08:49:11 -07001157 return;
1158 }
1159 }
1160
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001161 aaType = this->decideAAType(aa);
1162 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001163 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomon289e3d82016-12-14 15:52:56 -05001164 sk_sp<GrDrawOp> op =
1165 GrOvalOpFactory::MakeOvalOp(paint.getColor(), viewMatrix, oval, stroke, shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001166 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001167 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001168 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillipsb56f9272016-02-25 11:03:52 -08001169 return;
1170 }
robertphillipsea461502015-05-26 11:38:03 -07001171 }
robertphillipsb56f9272016-02-25 11:03:52 -08001172
1173 SkPath path;
1174 path.setIsVolatile(true);
1175 path.addOval(oval);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001176 this->internalDrawPath(clip, paint, aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001177}
1178
Brian Osman11052242016-10-27 14:47:55 -04001179void GrRenderTargetContext::drawArc(const GrClip& clip,
1180 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001181 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001182 const SkMatrix& viewMatrix,
1183 const SkRect& oval,
1184 SkScalar startAngle,
1185 SkScalar sweepAngle,
1186 bool useCenter,
1187 const GrStyle& style) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001188 GrAAType aaType = this->decideAAType(aa);
1189 if (GrAAType::kCoverage == aaType) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001190 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomon289e3d82016-12-14 15:52:56 -05001191 sk_sp<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(paint.getColor(),
1192 viewMatrix,
1193 oval,
1194 startAngle,
1195 sweepAngle,
1196 useCenter,
1197 style,
1198 shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001199 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001200 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001201 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
bsalomon4f3a0ca2016-08-22 13:14:26 -07001202 return;
1203 }
1204 }
1205 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001206 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1207 style.isSimpleFill());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001208 this->internalDrawPath(clip, paint, aa, viewMatrix, path, style);
bsalomon4f3a0ca2016-08-22 13:14:26 -07001209}
1210
Brian Osman11052242016-10-27 14:47:55 -04001211void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
1212 const GrPaint& paint,
1213 const SkMatrix& viewMatrix,
1214 int imageWidth,
1215 int imageHeight,
1216 std::unique_ptr<SkLatticeIter> iter,
1217 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001218 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001219 RETURN_IF_ABANDONED
1220 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001221 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001222
1223 AutoCheckFlush acf(fDrawingManager);
1224
Brian Salomonfc527d22016-12-14 21:07:01 -05001225 sk_sp<GrDrawOp> op = GrLatticeOp::MakeNonAA(paint.getColor(), viewMatrix, imageWidth,
1226 imageHeight, std::move(iter), dst);
joshualitt33a5fce2015-11-18 13:28:51 -08001227
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001228 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001229 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
joshualitt33a5fce2015-11-18 13:28:51 -08001230}
1231
Brian Osman11052242016-10-27 14:47:55 -04001232void GrRenderTargetContext::prepareForExternalIO() {
robertphillips8c523e02016-07-26 07:41:00 -07001233 ASSERT_SINGLE_OWNER
1234 RETURN_IF_ABANDONED
1235 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001236 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO");
robertphillips8c523e02016-07-26 07:41:00 -07001237
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001238 // Deferral of the VRAM resources must end in this instance anyway
1239 sk_sp<GrRenderTarget> rt(
1240 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -05001241 if (!rt) {
1242 return;
1243 }
robertphillips8c523e02016-07-26 07:41:00 -07001244
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001245 ASSERT_OWNED_RESOURCE(rt);
1246
1247 fDrawingManager->prepareSurfaceForExternalIO(rt.get());
robertphillips8c523e02016-07-26 07:41:00 -07001248}
joshualitt33a5fce2015-11-18 13:28:51 -08001249
Brian Osman11052242016-10-27 14:47:55 -04001250void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip,
1251 const GrPaint& paint,
1252 const SkMatrix& viewMatrix,
1253 const SkRect& rect,
1254 const SkRect* localRect,
1255 const SkMatrix* localMatrix,
1256 const GrUserStencilSettings* ss,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001257 GrAAType hwOrNoneAAType) {
1258 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType);
1259 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled());
Brian Salomon6a639042016-12-14 11:08:17 -05001260 sk_sp<GrDrawOp> op = GrRectOpFactory::MakeNonAAFill(paint.getColor(), viewMatrix, rect,
1261 localRect, localMatrix);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001262 GrPipelineBuilder pipelineBuilder(paint, hwOrNoneAAType);
robertphillips44302392016-07-08 14:43:03 -07001263 if (ss) {
1264 pipelineBuilder.setUserStencil(ss);
1265 }
Brian Salomon21aa35f2016-12-09 16:01:53 -05001266 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips44302392016-07-08 14:43:03 -07001267}
1268
Brian Osman11052242016-10-27 14:47:55 -04001269bool GrRenderTargetContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer,
1270 size_t dstRowBytes, int x, int y) {
robertphillips1da3ecd2016-08-31 14:54:15 -07001271 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1272 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
1273 if (kUnknown_GrPixelConfig == config) {
1274 return false;
1275 }
1276
1277 uint32_t flags = 0;
1278 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
1279 flags = GrContext::kUnpremul_PixelOpsFlag;
1280 }
1281
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001282 // Deferral of the VRAM resources must end in this instance anyway
1283 sk_sp<GrRenderTarget> rt(
1284 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -05001285 if (!rt) {
1286 return false;
1287 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001288
1289 return rt->readPixels(x, y, dstInfo.width(), dstInfo.height(),
1290 config, dstBuffer, dstRowBytes, flags);
robertphillips1da3ecd2016-08-31 14:54:15 -07001291}
1292
Brian Osman11052242016-10-27 14:47:55 -04001293bool GrRenderTargetContext::writePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
1294 size_t srcRowBytes, int x, int y) {
robertphillips1da3ecd2016-08-31 14:54:15 -07001295 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1296 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
1297 if (kUnknown_GrPixelConfig == config) {
1298 return false;
1299 }
1300 uint32_t flags = 0;
1301 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
1302 flags = GrContext::kUnpremul_PixelOpsFlag;
1303 }
1304
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001305 // Deferral of the VRAM resources must end in this instance anyway
1306 sk_sp<GrRenderTarget> rt(
1307 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -05001308 if (!rt) {
1309 return false;
1310 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001311
1312 return rt->writePixels(x, y, srcInfo.width(), srcInfo.height(),
1313 config, srcBuffer, srcRowBytes, flags);
robertphillips1da3ecd2016-08-31 14:54:15 -07001314}
1315
robertphillipsea461502015-05-26 11:38:03 -07001316// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001317static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001318
1319 if (path.isInverseFillType()) {
1320 return false;
1321 }
1322
1323 // TODO: this restriction could be lifted if we were willing to apply
1324 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001325 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001326 return false;
1327 }
1328
1329 SkPath::Direction dirs[2];
1330 if (!path.isNestedFillRects(rects, dirs)) {
1331 return false;
1332 }
1333
1334 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1335 // The two rects need to be wound opposite to each other
1336 return false;
1337 }
1338
1339 // Right now, nested rects where the margin is not the same width
1340 // all around do not render correctly
1341 const SkScalar* outer = rects[0].asScalars();
1342 const SkScalar* inner = rects[1].asScalars();
1343
1344 bool allEq = true;
1345
1346 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1347 bool allGoE1 = margin >= SK_Scalar1;
1348
1349 for (int i = 1; i < 4; ++i) {
1350 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1351 if (temp < SK_Scalar1) {
1352 allGoE1 = false;
1353 }
1354 if (!SkScalarNearlyEqual(margin, temp)) {
1355 allEq = false;
1356 }
1357 }
1358
1359 return allEq || allGoE1;
1360}
1361
Brian Osman11052242016-10-27 14:47:55 -04001362void GrRenderTargetContext::drawPath(const GrClip& clip,
1363 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001364 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001365 const SkMatrix& viewMatrix,
1366 const SkPath& path,
1367 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001368 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001369 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001370 SkDEBUGCODE(this->validate();)
Brian Osman11052242016-10-27 14:47:55 -04001371 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001372
robertphillipsea461502015-05-26 11:38:03 -07001373 if (path.isEmpty()) {
1374 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -07001375 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001376 }
1377 return;
1378 }
1379
robertphillips77a2e522015-10-17 07:43:27 -07001380 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -07001381
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001382 GrAAType aaType = this->decideAAType(aa);
1383 if (GrAAType::kCoverage == aaType && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001384 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001385 // Concave AA paths are expensive - try to avoid them for special cases
1386 SkRect rects[2];
1387
bsalomon6663acf2016-05-10 09:14:17 -07001388 if (fills_as_nested_rects(viewMatrix, path, rects)) {
Brian Salomon6a639042016-12-14 11:08:17 -05001389 sk_sp<GrDrawOp> op =
1390 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001391 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001392 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001393 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
bsalomon40ef4852016-05-02 13:22:13 -07001394 }
robertphillipsea461502015-05-26 11:38:03 -07001395 return;
1396 }
1397 }
1398 SkRect ovalRect;
1399 bool isOval = path.isOval(&ovalRect);
1400
1401 if (isOval && !path.isInverseFillType()) {
Brian Salomon94efbf52016-11-29 13:43:05 -05001402 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Brian Salomon289e3d82016-12-14 15:52:56 -05001403 sk_sp<GrDrawOp> op = GrOvalOpFactory::MakeOvalOp(
1404 paint.getColor(), viewMatrix, ovalRect, style.strokeRec(), shaderCaps);
Brian Salomon42521e82016-12-07 16:44:58 -05001405 if (op) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001406 GrPipelineBuilder pipelineBuilder(paint, aaType);
Brian Salomon21aa35f2016-12-09 16:01:53 -05001407 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillipsea461502015-05-26 11:38:03 -07001408 return;
1409 }
1410 }
1411 }
robertphillips4bc31812016-03-01 12:22:49 -08001412
1413 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1414 // Scratch textures can be recycled after they are returned to the texture
1415 // cache. This presents a potential hazard for buffered drawing. However,
1416 // the writePixels that uploads to the scratch will perform a flush so we're
1417 // OK.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001418 this->internalDrawPath(clip, paint, aa, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001419}
1420
Brian Osman11052242016-10-27 14:47:55 -04001421bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip,
1422 const GrUserStencilSettings* ss,
1423 SkRegion::Op op,
1424 bool invert,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001425 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001426 const SkMatrix& viewMatrix,
1427 const SkPath& path) {
robertphillips391395d2016-03-02 09:26:36 -08001428 ASSERT_SINGLE_OWNER_PRIV
1429 RETURN_FALSE_IF_ABANDONED_PRIV
Brian Osman11052242016-10-27 14:47:55 -04001430 SkDEBUGCODE(fRenderTargetContext->validate();)
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001431 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
1432 "GrRenderTargetContextPriv::drawAndStencilPath");
robertphillips391395d2016-03-02 09:26:36 -08001433
1434 if (path.isEmpty() && path.isInverseFillType()) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001435 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(),
Brian Osman11052242016-10-27 14:47:55 -04001436 SkRect::MakeIWH(fRenderTargetContext->width(),
1437 fRenderTargetContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001438 return true;
1439 }
1440
Brian Osman11052242016-10-27 14:47:55 -04001441 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager);
robertphillips391395d2016-03-02 09:26:36 -08001442
1443 // An Assumption here is that path renderer would use some form of tweaking
1444 // the src color (either the input alpha or in the frag shader) to implement
1445 // aa. If we have some future driver-mojo path AA that can do the right
1446 // thing WRT to the blend then we'll need some query on the PR.
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001447 GrAAType aaType = fRenderTargetContext->decideAAType(aa);
robertphillips976f5f02016-06-03 10:59:20 -07001448 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001449
bsalomon8acedde2016-06-24 10:42:16 -07001450 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001451 GrPathRenderer::CanDrawPathArgs canDrawArgs;
Brian Osman11052242016-10-27 14:47:55 -04001452 canDrawArgs.fShaderCaps =
1453 fRenderTargetContext->fDrawingManager->getContext()->caps()->shaderCaps();
robertphillips391395d2016-03-02 09:26:36 -08001454 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001455 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001456 canDrawArgs.fAAType = aaType;
cdalton93a379b2016-05-11 13:58:08 -07001457 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001458
1459 // Don't allow the SW renderer
Brian Salomon82125e92016-12-10 09:35:48 -05001460 GrPathRenderer* pr = fRenderTargetContext->fDrawingManager->getPathRenderer(
Brian Salomon36aa1762016-12-10 13:24:02 -05001461 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
robertphillips391395d2016-03-02 09:26:36 -08001462 if (!pr) {
1463 return false;
1464 }
1465
1466 GrPaint paint;
1467 paint.setCoverageSetOpXPFactory(op, invert);
1468
robertphillips391395d2016-03-02 09:26:36 -08001469 GrPathRenderer::DrawPathArgs args;
Brian Osman11052242016-10-27 14:47:55 -04001470 args.fResourceProvider =
1471 fRenderTargetContext->fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001472 args.fPaint = &paint;
1473 args.fUserStencilSettings = ss;
Brian Osman11052242016-10-27 14:47:55 -04001474 args.fRenderTargetContext = fRenderTargetContext;
cdalton862cff32016-05-12 15:09:48 -07001475 args.fClip = &clip;
robertphillips391395d2016-03-02 09:26:36 -08001476 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001477 args.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001478 args.fAAType = aaType;
Brian Osman11052242016-10-27 14:47:55 -04001479 args.fGammaCorrect = fRenderTargetContext->isGammaCorrect();
robertphillips391395d2016-03-02 09:26:36 -08001480 pr->drawPath(args);
1481 return true;
1482}
1483
Brian Osman11052242016-10-27 14:47:55 -04001484SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
robertphillips714712b2016-08-04 06:20:45 -07001485 ASSERT_SINGLE_OWNER_PRIV
1486
Brian Osman11052242016-10-27 14:47:55 -04001487 if (fRenderTargetContext->wasAbandoned()) {
robertphillips714712b2016-08-04 06:20:45 -07001488 return SkBudgeted::kNo;
1489 }
1490
Brian Osman11052242016-10-27 14:47:55 -04001491 SkDEBUGCODE(fRenderTargetContext->validate();)
robertphillips714712b2016-08-04 06:20:45 -07001492
Robert Phillipsc7635fa2016-10-28 13:25:24 -04001493 return fRenderTargetContext->fRenderTargetProxy->isBudgeted();
robertphillips714712b2016-08-04 06:20:45 -07001494}
1495
Brian Osman11052242016-10-27 14:47:55 -04001496void GrRenderTargetContext::internalDrawPath(const GrClip& clip,
1497 const GrPaint& paint,
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001498 GrAA aa,
Brian Osman11052242016-10-27 14:47:55 -04001499 const SkMatrix& viewMatrix,
1500 const SkPath& path,
1501 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001502 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001503 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001504 SkASSERT(!path.isEmpty());
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001505 GrShape shape;
robertphillipsea461502015-05-26 11:38:03 -07001506
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001507 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true);
1508 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) {
1509 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and
1510 // cover path renderer (i.e. default path renderer). The hairline renderer produces much
1511 // smoother hairlines than MSAA.
1512 aaType = GrAAType::kCoverage;
bsalomon0a0f67e2016-06-28 11:56:42 -07001513 }
robertphillips68737822015-10-29 12:12:21 -07001514 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1515 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1516 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001517 canDrawArgs.fShape = &shape;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001518 canDrawArgs.fHasUserStencilSettings = false;
robertphillips68737822015-10-29 12:12:21 -07001519
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001520 GrPathRenderer* pr;
Brian Salomon82125e92016-12-10 09:35:48 -05001521 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001522 do {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001523 shape = GrShape(path, style);
bsalomon8acedde2016-06-24 10:42:16 -07001524 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001525 return;
1526 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001527
1528 canDrawArgs.fAAType = aaType;
1529
1530 // Try a 1st time without applying any of the style to the geometry (and barring sw)
Brian Salomon82125e92016-12-10 09:35:48 -05001531 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001532 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1533
1534 if (!pr && shape.style().pathEffect()) {
1535 // It didn't work above, so try again with the path effect applied.
1536 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
bsalomon8acedde2016-06-24 10:42:16 -07001537 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001538 return;
1539 }
Brian Salomon82125e92016-12-10 09:35:48 -05001540 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, kType);
bsalomon6663acf2016-05-10 09:14:17 -07001541 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001542 if (!pr) {
1543 if (shape.style().applies()) {
1544 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1545 if (shape.isEmpty()) {
1546 return;
1547 }
1548 }
1549 // This time, allow SW renderer
Brian Salomon82125e92016-12-10 09:35:48 -05001550 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, kType);
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001551 }
Brian Salomon0abc8b42016-12-13 10:22:54 -05001552 if (!pr && GrAATypeIsHW(aaType)) {
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001553 // There are exceptional cases where we may wind up falling back to coverage based AA
1554 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions).
1555 aaType = GrAAType::kCoverage;
1556 } else {
1557 break;
1558 }
1559 } while(true);
robertphillipsea461502015-05-26 11:38:03 -07001560
bsalomon8acedde2016-06-24 10:42:16 -07001561 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001562#ifdef SK_DEBUG
1563 SkDebugf("Unable to find path renderer compatible with path.\n");
1564#endif
1565 return;
1566 }
1567
bsalomon0aff2fa2015-07-31 06:48:27 -07001568 GrPathRenderer::DrawPathArgs args;
robertphillips77a2e522015-10-17 07:43:27 -07001569 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001570 args.fPaint = &paint;
1571 args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
Brian Osman11052242016-10-27 14:47:55 -04001572 args.fRenderTargetContext = this;
cdalton862cff32016-05-12 15:09:48 -07001573 args.fClip = &clip;
bsalomon0aff2fa2015-07-31 06:48:27 -07001574 args.fViewMatrix = &viewMatrix;
Brian Salomon0e8fc8b2016-12-09 15:10:07 -05001575 args.fShape = &shape;
1576 args.fAAType = aaType;
brianosman0e3c5542016-04-13 13:56:21 -07001577 args.fGammaCorrect = this->isGammaCorrect();
bsalomon0aff2fa2015-07-31 06:48:27 -07001578 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001579}
1580
Brian Salomon42521e82016-12-07 16:44:58 -05001581void GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
Brian Salomon24f19782016-12-13 15:10:11 -05001582 sk_sp<GrDrawOp> op) {
joshualitt1de610a2016-01-06 08:26:09 -08001583 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001584 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001585 SkDEBUGCODE(this->validate();)
Brian Salomon42521e82016-12-07 16:44:58 -05001586 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp");
robertphillips2d70dcb2015-10-06 07:38:23 -07001587
Brian Salomon24f19782016-12-13 15:10:11 -05001588 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op));
robertphillips2334fb62015-06-17 05:43:33 -07001589}