blob: 266c50d70c60360fcae7435b2230444cba218d24 [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"
robertphillipsea461502015-05-26 11:38:03 -070010#include "GrDrawContext.h"
robertphillips391395d2016-03-02 09:26:36 -080011#include "GrDrawContextPriv.h"
robertphillips77a2e522015-10-17 07:43:27 -070012#include "GrDrawingManager.h"
robertphillipsea461502015-05-26 11:38:03 -070013#include "GrOvalRenderer.h"
14#include "GrPathRenderer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070015#include "GrPipelineBuilder.h"
robertphillips2334fb62015-06-17 05:43:33 -070016#include "GrRenderTarget.h"
17#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070018#include "GrResourceProvider.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070019#include "SkSurfacePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070020
joshualitt74417822015-08-07 11:42:16 -070021#include "batches/GrBatch.h"
robertphillips9199a9f2016-07-13 07:48:43 -070022#include "batches/GrClearBatch.h"
jvanverth14b88032015-08-07 12:18:54 -070023#include "batches/GrDrawAtlasBatch.h"
joshualitt2771b562015-08-07 12:46:26 -070024#include "batches/GrDrawVerticesBatch.h"
joshualitt7fc2a262015-08-10 10:30:14 -070025#include "batches/GrRectBatchFactory.h"
joshualitt33a5fce2015-11-18 13:28:51 -080026#include "batches/GrNinePatch.h" // TODO Factory
joshualitt74417822015-08-07 11:42:16 -070027
robertphillips00095892016-02-29 13:50:40 -080028#include "effects/GrRRectEffect.h"
29
csmartdaltona7f29642016-07-07 08:49:11 -070030#include "instanced/InstancedRendering.h"
31
joshualitte8042922015-12-11 06:11:21 -080032#include "text/GrAtlasTextContext.h"
33#include "text/GrStencilAndCoverTextContext.h"
34
joshualittbc907352016-01-13 06:45:40 -080035#include "../private/GrAuditTrail.h"
36
robertphillips77a2e522015-10-17 07:43:27 -070037#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080038#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080039 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080040#define ASSERT_SINGLE_OWNER_PRIV \
41 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070042#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
robertphillips976f5f02016-06-03 10:59:20 -070043#define RETURN_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return; }
robertphillips7761d612016-05-16 09:14:53 -070044#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
45#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return false; }
46#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070047
csmartdaltona7f29642016-07-07 08:49:11 -070048using gr_instanced::InstancedRendering;
49
robertphillipsea461502015-05-26 11:38:03 -070050class AutoCheckFlush {
51public:
halcanary9d524f22016-03-29 09:03:52 -070052 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070053 SkASSERT(fDrawingManager);
54 }
55 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070056
57private:
robertphillips77a2e522015-10-17 07:43:27 -070058 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070059};
60
robertphillips7761d612016-05-16 09:14:53 -070061bool GrDrawContext::wasAbandoned() const {
62 return fDrawingManager->wasAbandoned();
63}
64
robertphillipsa106c622015-10-16 09:07:06 -070065// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
66// drawTargets to be picked up and added to by drawContexts lower in the call
67// stack. When this occurs with a closed drawTarget, a new one will be allocated
68// when the drawContext attempts to use it (via getDrawTarget).
joshualitt1b39f432016-02-11 06:46:52 -080069GrDrawContext::GrDrawContext(GrContext* context,
70 GrDrawingManager* drawingMgr,
robertphillips6c7e3252016-04-27 10:47:51 -070071 sk_sp<GrRenderTarget> rt,
brianosmandfe4f2e2016-07-21 13:28:36 -070072 sk_sp<SkColorSpace> colorSpace,
joshualittde8dc7e2016-01-08 10:09:13 -080073 const SkSurfaceProps* surfaceProps,
joshualittbc907352016-01-13 06:45:40 -080074 GrAuditTrail* auditTrail,
joshualittde8dc7e2016-01-08 10:09:13 -080075 GrSingleOwner* singleOwner)
robertphillips77a2e522015-10-17 07:43:27 -070076 : fDrawingManager(drawingMgr)
robertphillips6c7e3252016-04-27 10:47:51 -070077 , fRenderTarget(std::move(rt))
78 , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
joshualitt1b39f432016-02-11 06:46:52 -080079 , fContext(context)
csmartdaltona7f29642016-07-07 08:49:11 -070080 , fInstancedPipelineInfo(fRenderTarget.get())
brianosmandfe4f2e2016-07-21 13:28:36 -070081 , fColorSpace(std::move(colorSpace))
joshualittde8dc7e2016-01-08 10:09:13 -080082 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080083 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080084#ifdef SK_DEBUG
85 , fSingleOwner(singleOwner)
86#endif
87{
robertphillips2e1e51f2015-10-15 08:01:48 -070088 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070089}
90
robertphillips2e1e51f2015-10-15 08:01:48 -070091#ifdef SK_DEBUG
92void GrDrawContext::validate() const {
93 SkASSERT(fRenderTarget);
94 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070095
96 if (fDrawTarget && !fDrawTarget->isClosed()) {
97 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
98 }
robertphillips2e1e51f2015-10-15 08:01:48 -070099}
100#endif
101
robertphillipsa106c622015-10-16 09:07:06 -0700102GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800103 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700104 SkSafeUnref(fDrawTarget);
105}
106
107GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -0800108 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700109 SkDEBUGCODE(this->validate();)
110
111 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips6c7e3252016-04-27 10:47:51 -0700112 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
robertphillipsa106c622015-10-16 09:07:06 -0700113 }
114
115 return fDrawTarget;
116}
117
bsalomonb8fea972016-02-16 07:34:17 -0800118bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800119 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800120 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700121 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800122 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700123
robertphillips6c7e3252016-04-27 10:47:51 -0700124 return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700125}
126
robertphillips2e1e51f2015-10-15 08:01:48 -0700127void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700128 const SkPaint& skPaint,
129 const SkMatrix& viewMatrix,
130 const char text[], size_t byteLength,
131 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800132 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700133 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700134 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800135 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700136
joshualitt96880d92016-02-16 10:36:53 -0800137 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800138 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700139 }
140
joshualitt96880d92016-02-16 10:36:53 -0800141 fAtlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
142 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700143}
robertphillipscaef3452015-11-11 13:18:11 -0800144
robertphillips2e1e51f2015-10-15 08:01:48 -0700145void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700146 const SkPaint& skPaint,
147 const SkMatrix& viewMatrix,
148 const char text[], size_t byteLength,
149 const SkScalar pos[], int scalarsPerPosition,
150 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800151 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700152 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700153 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800154 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700155
joshualitt96880d92016-02-16 10:36:53 -0800156 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800157 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700158 }
159
joshualitt96880d92016-02-16 10:36:53 -0800160 fAtlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
161 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
162 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700163
164}
robertphillipscaef3452015-11-11 13:18:11 -0800165
robertphillips2e1e51f2015-10-15 08:01:48 -0700166void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700167 const SkMatrix& viewMatrix, const SkTextBlob* blob,
168 SkScalar x, SkScalar y,
169 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800170 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700171 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700172 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800173 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700174
joshualitt96880d92016-02-16 10:36:53 -0800175 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800176 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700177 }
178
joshualitt96880d92016-02-16 10:36:53 -0800179 fAtlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
180 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700181}
182
robertphillips2e1e51f2015-10-15 08:01:48 -0700183void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800184 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700185 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700186 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800187 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700188
robertphillips77a2e522015-10-17 07:43:27 -0700189 AutoCheckFlush acf(fDrawingManager);
robertphillips6c7e3252016-04-27 10:47:51 -0700190 this->getDrawTarget()->discard(fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700191}
192
robertphillips2e1e51f2015-10-15 08:01:48 -0700193void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700194 const GrColor color,
195 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800196 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700197 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700198 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800199 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700200
robertphillips77a2e522015-10-17 07:43:27 -0700201 AutoCheckFlush acf(fDrawingManager);
robertphillips9199a9f2016-07-13 07:48:43 -0700202
203 const SkIRect rtRect = SkIRect::MakeWH(this->width(), this->height());
204 SkIRect clippedRect;
205 if (!rect ||
206 (canIgnoreRect && fContext->caps()->fullClearIsFree()) ||
207 rect->contains(rtRect)) {
208 rect = &rtRect;
209 } else {
210 clippedRect = *rect;
211 if (!clippedRect.intersect(rtRect)) {
212 return;
213 }
214 rect = &clippedRect;
215 }
216
217 if (fContext->caps()->useDrawInsteadOfClear()) {
218 // This works around a driver bug with clear by drawing a rect instead.
219 // The driver will ignore a clear if it is the only thing rendered to a
220 // target before the target is read.
221 if (rect == &rtRect) {
222 this->discard();
223 }
224
225 GrPaint paint;
226 paint.setColor4f(GrColor4f::FromGrColor(color));
227 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
228
229 this->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::Make(*rect));
230 } else {
231 sk_sp<GrBatch> batch = GrClearBatch::Make(*rect, color, this->accessRenderTarget());
232 this->getDrawTarget()->addBatch(std::move(batch));
233 }
robertphillipsea461502015-05-26 11:38:03 -0700234}
235
236
robertphillips2e1e51f2015-10-15 08:01:48 -0700237void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700238 const GrPaint& origPaint,
239 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800240 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700241 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700242 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800243 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700244
robertphillipsea461502015-05-26 11:38:03 -0700245 // set rect to be big enough to fill the space, but not super-huge, so we
246 // don't overflow fixed-point implementations
247 SkRect r;
248 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700249 SkIntToScalar(fRenderTarget->width()),
250 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700251 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
252
253 // by definition this fills the entire clip, no need for AA
254 if (paint->isAntiAlias()) {
255 paint.writable()->setAntiAlias(false);
256 }
257
258 bool isPerspective = viewMatrix.hasPerspective();
259
260 // We attempt to map r by the inverse matrix and draw that. mapRect will
261 // map the four corners and bound them with a new rect. This will not
262 // produce a correct result for some perspective matrices.
263 if (!isPerspective) {
264 SkMatrix inverse;
265 if (!viewMatrix.invert(&inverse)) {
266 SkDebugf("Could not invert matrix\n");
267 return;
268 }
269 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700270 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700271 } else {
272 SkMatrix localMatrix;
273 if (!viewMatrix.invert(&localMatrix)) {
274 SkDebugf("Could not invert matrix\n");
275 return;
276 }
277
robertphillips77a2e522015-10-17 07:43:27 -0700278 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700279
robertphillips44302392016-07-08 14:43:03 -0700280 this->drawNonAAFilledRect(clip, *paint, SkMatrix::I(), r, nullptr, &localMatrix, nullptr);
robertphillipsea461502015-05-26 11:38:03 -0700281 }
282}
283
robertphillipsea461502015-05-26 11:38:03 -0700284static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
285 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
286 point.fY >= rect.fTop && point.fY <= rect.fBottom;
287}
288
bsalomonc55271f2015-11-09 11:55:57 -0800289static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
290 return viewMatrix.preservesRightAngles();
291}
292
csmartdaltonecbc12b2016-06-08 10:08:43 -0700293static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt,
294 bool* useHWAA = nullptr) {
295 if (!paint.isAntiAlias()) {
296 if (useHWAA) {
297 *useHWAA = false;
298 }
299 return false;
300 } else {
301 if (useHWAA) {
bsalomonbb243832016-07-22 07:10:19 -0700302 *useHWAA = rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700303 }
bsalomonbb243832016-07-22 07:10:19 -0700304 return !rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700305 }
bsalomonc55271f2015-11-09 11:55:57 -0800306}
307
csmartdalton97f6cd52016-07-13 13:37:08 -0700308// Attempts to crop a rect and optional local rect to the clip boundaries.
309// Returns false if the draw can be skipped entirely.
310static bool crop_filled_rect(const GrRenderTarget* rt, const GrClip& clip,
311 const SkMatrix& viewMatrix, SkRect* rect,
312 SkRect* localRect = nullptr) {
313 if (!viewMatrix.rectStaysRect()) {
314 return true;
315 }
316
317 SkMatrix inverseViewMatrix;
318 if (!viewMatrix.invert(&inverseViewMatrix)) {
319 return false;
320 }
321
322 SkIRect clipDevBounds;
323 SkRect clipBounds;
324 SkASSERT(inverseViewMatrix.rectStaysRect());
325
326 clip.getConservativeBounds(rt->width(), rt->height(), &clipDevBounds);
327 inverseViewMatrix.mapRect(&clipBounds, SkRect::Make(clipDevBounds));
328
329 if (localRect) {
330 if (!rect->intersects(clipBounds)) {
331 return false;
332 }
333 const SkScalar dx = localRect->width() / rect->width();
334 const SkScalar dy = localRect->height() / rect->height();
335 if (clipBounds.fLeft > rect->fLeft) {
336 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
337 rect->fLeft = clipBounds.fLeft;
338 }
339 if (clipBounds.fTop > rect->fTop) {
340 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
341 rect->fTop = clipBounds.fTop;
342 }
343 if (clipBounds.fRight < rect->fRight) {
344 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
345 rect->fRight = clipBounds.fRight;
346 }
347 if (clipBounds.fBottom < rect->fBottom) {
348 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
349 rect->fBottom = clipBounds.fBottom;
350 }
351 return true;
352 }
353
354 return rect->intersect(clipBounds);
355}
356
robertphillips44302392016-07-08 14:43:03 -0700357bool GrDrawContext::drawFilledRect(const GrClip& clip,
358 const GrPaint& paint,
359 const SkMatrix& viewMatrix,
360 const SkRect& rect,
361 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700362 SkRect croppedRect = rect;
363 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect)) {
364 return true;
365 }
robertphillips44302392016-07-08 14:43:03 -0700366
367 SkAutoTUnref<GrDrawBatch> batch;
368 bool useHWAA;
369
csmartdaltona7f29642016-07-07 08:49:11 -0700370 if (InstancedRendering* ir = this->getDrawTarget()->instancedRendering()) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700371 batch.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
robertphillips44302392016-07-08 14:43:03 -0700372 paint.isAntiAlias(), fInstancedPipelineInfo,
373 &useHWAA));
374 if (batch) {
375 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
376 if (ss) {
377 pipelineBuilder.setUserStencil(ss);
378 }
379 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
380 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700381 }
382 }
robertphillips391395d2016-03-02 09:26:36 -0800383
robertphillips44302392016-07-08 14:43:03 -0700384 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillips391395d2016-03-02 09:26:36 -0800385 // The fill path can handle rotation but not skew.
386 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
387 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700388 viewMatrix.mapRect(&devBoundRect, croppedRect);
robertphillips44302392016-07-08 14:43:03 -0700389
390 batch.reset(GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix,
csmartdalton97f6cd52016-07-13 13:37:08 -0700391 croppedRect, devBoundRect));
robertphillips44302392016-07-08 14:43:03 -0700392 if (batch) {
393 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
394 if (ss) {
395 pipelineBuilder.setUserStencil(ss);
396 }
397 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
398 return true;
399 }
robertphillips391395d2016-03-02 09:26:36 -0800400 }
401 } else {
csmartdalton97f6cd52016-07-13 13:37:08 -0700402 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss);
robertphillips44302392016-07-08 14:43:03 -0700403 return true;
robertphillips391395d2016-03-02 09:26:36 -0800404 }
405
robertphillips44302392016-07-08 14:43:03 -0700406 return false;
robertphillips391395d2016-03-02 09:26:36 -0800407}
408
robertphillips2e1e51f2015-10-15 08:01:48 -0700409void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700410 const GrPaint& paint,
411 const SkMatrix& viewMatrix,
412 const SkRect& rect,
bsalomon6663acf2016-05-10 09:14:17 -0700413 const GrStyle* style) {
414 if (!style) {
415 style = &GrStyle::SimpleFill();
416 }
joshualitt1de610a2016-01-06 08:26:09 -0800417 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700418 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700419 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800420 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700421
bsalomon6663acf2016-05-10 09:14:17 -0700422 // Path effects should've been devolved to a path in SkGpuDevice
423 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700424
robertphillips77a2e522015-10-17 07:43:27 -0700425 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700426
bsalomon6663acf2016-05-10 09:14:17 -0700427 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700428 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
429
430 if (!fContext->caps()->useDrawInsteadOfClear()) {
431 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
432 // checking cases where the RT is fully inside a stroke.
433 SkRect rtRect;
434 fRenderTarget->getBoundsRect(&rtRect);
435 // Does the clip contain the entire RT?
436 if (clip.quickContains(rtRect)) {
437 SkMatrix invM;
438 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700439 return;
440 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700441 // Does the rect bound the RT?
442 SkPoint srcSpaceRTQuad[4];
443 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
444 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
445 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
446 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
447 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
448 // Will it blend?
449 GrColor clearColor;
450 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700451 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700452 return;
453 }
454 }
robertphillipsea461502015-05-26 11:38:03 -0700455 }
456 }
robertphillips44302392016-07-08 14:43:03 -0700457
458 if (this->drawFilledRect(clip, paint, viewMatrix, rect, nullptr)) {
459 return;
460 }
bsalomona7d85ba2016-07-06 11:54:59 -0700461 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
462 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
463 if ((!rect.width() || !rect.height()) &&
464 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
465 SkScalar r = stroke.getWidth() / 2;
466 // TODO: Move these stroke->fill fallbacks to GrShape?
467 switch (stroke.getJoin()) {
468 case SkPaint::kMiter_Join:
469 this->drawRect(clip, paint, viewMatrix,
470 {rect.fLeft - r, rect.fTop - r,
471 rect.fRight + r, rect.fBottom + r},
472 &GrStyle::SimpleFill());
473 return;
474 case SkPaint::kRound_Join:
475 // Raster draws nothing when both dimensions are empty.
476 if (rect.width() || rect.height()){
477 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
478 this->drawRRect(clip, paint, viewMatrix, rrect, GrStyle::SimpleFill());
479 return;
480 }
481 case SkPaint::kBevel_Join:
482 if (!rect.width()) {
483 this->drawRect(clip, paint, viewMatrix,
484 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
485 &GrStyle::SimpleFill());
486 } else {
487 this->drawRect(clip, paint, viewMatrix,
488 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
489 &GrStyle::SimpleFill());
490 }
491 return;
492 }
493 }
robertphillips44302392016-07-08 14:43:03 -0700494
495 bool useHWAA;
496 bool snapToPixelCenters = false;
497 SkAutoTUnref<GrDrawBatch> batch;
498
robertphillips391395d2016-03-02 09:26:36 -0800499 GrColor color = paint.getColor();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700500 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
cdaltonbb539482016-01-04 09:48:25 -0800501 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
502 if (viewMatrix.rectStaysRect()) {
bsalomona7d85ba2016-07-06 11:54:59 -0700503 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke));
cdaltonbb539482016-01-04 09:48:25 -0800504 }
robertphillipsea461502015-05-26 11:38:03 -0700505 } else {
robertphillips391395d2016-03-02 09:26:36 -0800506 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700507 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800508 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700509 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
510 !fRenderTarget->isUnifiedMultisampled();
511 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
512 stroke, snapToPixelCenters));
robertphillips391395d2016-03-02 09:26:36 -0800513 }
robertphillips4bc31812016-03-01 12:22:49 -0800514
robertphillips44302392016-07-08 14:43:03 -0700515 if (batch) {
516 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips4bc31812016-03-01 12:22:49 -0800517
robertphillips44302392016-07-08 14:43:03 -0700518 if (snapToPixelCenters) {
519 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
520 snapToPixelCenters);
521 }
522
523 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
524 return;
robertphillips4bc31812016-03-01 12:22:49 -0800525 }
robertphillips4bc31812016-03-01 12:22:49 -0800526 }
halcanary9d524f22016-03-29 09:03:52 -0700527
robertphillips4bc31812016-03-01 12:22:49 -0800528 SkPath path;
529 path.setIsVolatile(true);
530 path.addRect(rect);
bsalomon6663acf2016-05-10 09:14:17 -0700531 this->internalDrawPath(clip, paint, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700532}
533
robertphillips976f5f02016-06-03 10:59:20 -0700534void GrDrawContextPriv::clearStencilClip(const SkIRect& rect, bool insideClip) {
535 ASSERT_SINGLE_OWNER_PRIV
536 RETURN_IF_ABANDONED_PRIV
537 SkDEBUGCODE(fDrawContext->validate();)
538 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
539
540 AutoCheckFlush acf(fDrawContext->fDrawingManager);
541 fDrawContext->getDrawTarget()->clearStencilClip(rect, insideClip,
542 fDrawContext->accessRenderTarget());
543}
544
robertphillips59cf61a2016-07-13 09:18:21 -0700545void GrDrawContextPriv::stencilPath(const GrClip& clip,
546 const GrUserStencilSettings* ss,
547 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700548 const SkMatrix& viewMatrix,
robertphillips59cf61a2016-07-13 09:18:21 -0700549 const GrPath* path) {
550 fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, ss, useHWAA, viewMatrix, path);
robertphillips976f5f02016-06-03 10:59:20 -0700551}
552
553void GrDrawContextPriv::stencilRect(const GrFixedClip& clip,
554 const GrUserStencilSettings* ss,
csmartdalton656dbe42016-06-10 12:32:57 -0700555 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700556 const SkMatrix& viewMatrix,
557 const SkRect& rect) {
558 ASSERT_SINGLE_OWNER_PRIV
559 RETURN_IF_ABANDONED_PRIV
560 SkDEBUGCODE(fDrawContext->validate();)
561 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::stencilRect");
562
563 AutoCheckFlush acf(fDrawContext->fDrawingManager);
564
565 GrPaint paint;
csmartdalton656dbe42016-06-10 12:32:57 -0700566 paint.setAntiAlias(useHWAA);
bungeman06ca8ec2016-06-09 08:01:03 -0700567 paint.setXPFactory(GrDisableColorXPFactory::Make());
robertphillips976f5f02016-06-03 10:59:20 -0700568
csmartdalton656dbe42016-06-10 12:32:57 -0700569 SkASSERT(!useHWAA || fDrawContext->isStencilBufferMultisampled());
robertphillips976f5f02016-06-03 10:59:20 -0700570
robertphillips44302392016-07-08 14:43:03 -0700571 fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss);
robertphillips976f5f02016-06-03 10:59:20 -0700572}
573
cdalton846c0512016-05-13 10:25:00 -0700574bool GrDrawContextPriv::drawAndStencilRect(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -0700575 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -0800576 SkRegion::Op op,
577 bool invert,
578 bool doAA,
579 const SkMatrix& viewMatrix,
580 const SkRect& rect) {
581 ASSERT_SINGLE_OWNER_PRIV
582 RETURN_FALSE_IF_ABANDONED_PRIV
583 SkDEBUGCODE(fDrawContext->validate();)
robertphillips55fdccc2016-06-06 06:16:20 -0700584 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800585
586 AutoCheckFlush acf(fDrawContext->fDrawingManager);
587
588 GrPaint paint;
589 paint.setAntiAlias(doAA);
590 paint.setCoverageSetOpXPFactory(op, invert);
591
robertphillips44302392016-07-08 14:43:03 -0700592 if (fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800593 return true;
594 }
595
596 SkPath path;
597 path.setIsVolatile(true);
598 path.addRect(rect);
cdalton862cff32016-05-12 15:09:48 -0700599 return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800600}
601
bsalomona2e69fc2015-11-05 10:41:43 -0800602void GrDrawContext::fillRectToRect(const GrClip& clip,
603 const GrPaint& paint,
604 const SkMatrix& viewMatrix,
605 const SkRect& rectToDraw,
606 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800607 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700608 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700609 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800610 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700611
csmartdalton97f6cd52016-07-13 13:37:08 -0700612 SkRect croppedRect = rectToDraw;
613 SkRect croppedLocalRect = localRect;
614 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect, &croppedLocalRect)) {
615 return;
616 }
617
robertphillips77a2e522015-10-17 07:43:27 -0700618 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700619 bool useHWAA;
620
621 if (InstancedRendering* ir = this->getDrawTarget()->instancedRendering()) {
csmartdaltonfc49d562016-07-26 17:05:47 -0700622 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
623 croppedLocalRect, paint.isAntiAlias(),
624 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700625 if (batch) {
bsalomonbb243832016-07-22 07:10:19 -0700626 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
627 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700628 return;
629 }
630 }
631
csmartdaltonfc49d562016-07-26 17:05:47 -0700632 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700633 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect,
robertphillips44302392016-07-08 14:43:03 -0700634 nullptr, nullptr);
csmartdaltonfc49d562016-07-26 17:05:47 -0700635 return;
joshualitt04194f32016-01-13 10:08:27 -0800636 }
bsalomonbb243832016-07-22 07:10:19 -0700637
csmartdaltonfc49d562016-07-26 17:05:47 -0700638 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
639 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(),
640 viewMatrix,
641 croppedRect,
642 croppedLocalRect));
643 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
644 this->drawBatch(pipelineBuilder, clip, batch);
645 return;
646 }
647
648 SkMatrix viewAndUnLocalMatrix;
649 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
650 SkDebugf("fillRectToRect called with empty local matrix.\n");
651 return;
652 }
653 viewAndUnLocalMatrix.postConcat(viewMatrix);
654
655 SkPath path;
656 path.setIsVolatile(true);
657 path.addRect(localRect);
658 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700659}
660
bsalomona2e69fc2015-11-05 10:41:43 -0800661void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
662 const GrPaint& paint,
663 const SkMatrix& viewMatrix,
664 const SkRect& rectToDraw,
665 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800666 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700667 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700668 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800669 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700670
csmartdalton97f6cd52016-07-13 13:37:08 -0700671 SkRect croppedRect = rectToDraw;
672 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect)) {
673 return;
674 }
675
robertphillips77a2e522015-10-17 07:43:27 -0700676 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700677 bool useHWAA;
678
679 if (InstancedRendering* ir = this->getDrawTarget()->instancedRendering()) {
csmartdaltonfc49d562016-07-26 17:05:47 -0700680 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
681 localMatrix, paint.isAntiAlias(),
682 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700683 if (batch) {
684 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
685 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
686 return;
687 }
688 }
689
csmartdaltonfc49d562016-07-26 17:05:47 -0700690 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700691 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr,
robertphillips44302392016-07-08 14:43:03 -0700692 &localMatrix, nullptr);
csmartdaltonfc49d562016-07-26 17:05:47 -0700693 return;
bsalomonc55271f2015-11-09 11:55:57 -0800694 }
robertphillips4bc31812016-03-01 12:22:49 -0800695
csmartdaltonfc49d562016-07-26 17:05:47 -0700696 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
697 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix,
698 localMatrix, croppedRect));
699 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
700 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
701 return;
702 }
703
704 SkMatrix viewAndUnLocalMatrix;
705 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
706 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
707 return;
708 }
709 viewAndUnLocalMatrix.postConcat(viewMatrix);
710
711 SkPath path;
712 path.setIsVolatile(true);
713 path.addRect(rectToDraw);
714 path.transform(localMatrix);
715 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700716}
717
robertphillips2e1e51f2015-10-15 08:01:48 -0700718void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700719 const GrPaint& paint,
720 const SkMatrix& viewMatrix,
721 GrPrimitiveType primitiveType,
722 int vertexCount,
723 const SkPoint positions[],
724 const SkPoint texCoords[],
725 const GrColor colors[],
726 const uint16_t indices[],
727 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800728 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700729 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700730 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800731 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700732
robertphillips77a2e522015-10-17 07:43:27 -0700733 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700734
robertphillipsea461502015-05-26 11:38:03 -0700735 // TODO clients should give us bounds
736 SkRect bounds;
737 if (!bounds.setBoundsCheck(positions, vertexCount)) {
738 SkDebugf("drawVertices call empty bounds\n");
739 return;
740 }
741
742 viewMatrix.mapRect(&bounds);
743
744 // If we don't have AA then we outset for a half pixel in each direction to account for
bsalomondb4758c2015-11-23 11:14:20 -0800745 // snapping. We also do this for the "hair" primitive types: lines and points since they have
746 // a 1 pixel thickness in device space.
747 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
748 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700749 bounds.outset(0.5f, 0.5f);
750 }
751
bsalomond92b4192016-06-30 07:59:23 -0700752 SkAutoTUnref<GrDrawBatch> batch(new GrDrawVerticesBatch(paint.getColor(),
753 primitiveType, viewMatrix, positions,
754 vertexCount, indices, indexCount,
755 colors, texCoords, bounds));
robertphillipsea461502015-05-26 11:38:03 -0700756
csmartdaltonecbc12b2016-06-08 10:08:43 -0700757 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700758 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700759}
760
761///////////////////////////////////////////////////////////////////////////////
762
robertphillips2e1e51f2015-10-15 08:01:48 -0700763void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700764 const GrPaint& paint,
765 const SkMatrix& viewMatrix,
766 int spriteCount,
767 const SkRSXform xform[],
768 const SkRect texRect[],
769 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800770 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700771 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700772 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800773 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700774
robertphillips77a2e522015-10-17 07:43:27 -0700775 AutoCheckFlush acf(fDrawingManager);
halcanary9d524f22016-03-29 09:03:52 -0700776
bsalomon0432dd62016-06-30 07:19:27 -0700777 SkAutoTUnref<GrDrawBatch> batch(new GrDrawAtlasBatch(paint.getColor(), viewMatrix, spriteCount,
778 xform, texRect, colors));
halcanary9d524f22016-03-29 09:03:52 -0700779
csmartdaltonecbc12b2016-06-08 10:08:43 -0700780 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700781 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700782}
783
784///////////////////////////////////////////////////////////////////////////////
785
robertphillips2e1e51f2015-10-15 08:01:48 -0700786void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700787 const GrPaint& paint,
788 const SkMatrix& viewMatrix,
789 const SkRRect& rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700790 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800791 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700792 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700793 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800794 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700795
robertphillipsea461502015-05-26 11:38:03 -0700796 if (rrect.isEmpty()) {
797 return;
798 }
799
bsalomon6663acf2016-05-10 09:14:17 -0700800 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700801
csmartdaltona7f29642016-07-07 08:49:11 -0700802 AutoCheckFlush acf(fDrawingManager);
803 const SkStrokeRec stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700804 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -0700805
806 if (this->getDrawTarget()->instancedRendering() && stroke.isFillStyle()) {
807 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
808 SkAutoTUnref<GrDrawBatch> batch(ir->recordRRect(rrect, viewMatrix, paint.getColor(),
809 paint.isAntiAlias(), fInstancedPipelineInfo,
810 &useHWAA));
811 if (batch) {
812 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
813 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
814 return;
815 }
816 }
817
csmartdaltonecbc12b2016-06-08 10:08:43 -0700818 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800819 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800820 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800821 viewMatrix,
822 rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700823 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800824 shaderCaps));
825 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700826 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700827 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800828 return;
829 }
robertphillipsea461502015-05-26 11:38:03 -0700830 }
robertphillipsb56f9272016-02-25 11:03:52 -0800831
832 SkPath path;
833 path.setIsVolatile(true);
834 path.addRRect(rrect);
bsalomon6663acf2016-05-10 09:14:17 -0700835 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700836}
837
robertphillips00095892016-02-29 13:50:40 -0800838bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
839 const GrPaint& paintIn,
840 const SkMatrix& viewMatrix,
841 const SkRRect& origOuter,
842 const SkRRect& origInner) {
843 SkASSERT(!origInner.isEmpty());
844 SkASSERT(!origOuter.isEmpty());
845
csmartdaltona7f29642016-07-07 08:49:11 -0700846 if (InstancedRendering* ir = this->getDrawTarget()->instancedRendering()) {
847 bool useHWAA;
848 SkAutoTUnref<GrDrawBatch> batch(ir->recordDRRect(origOuter, origInner, viewMatrix,
849 paintIn.getColor(), paintIn.isAntiAlias(),
850 fInstancedPipelineInfo, &useHWAA));
851 if (batch) {
852 GrPipelineBuilder pipelineBuilder(paintIn, useHWAA);
853 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
854 return true;
855 }
856 }
857
robertphillips00095892016-02-29 13:50:40 -0800858 bool applyAA = paintIn.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
859
860 GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
861 kInverseFillBW_GrProcessorEdgeType;
862 GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
863 kFillBW_GrProcessorEdgeType;
864
865 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
866 SkMatrix inverseVM;
867 if (!viewMatrix.isIdentity()) {
868 if (!origInner.transform(viewMatrix, inner.writable())) {
869 return false;
870 }
871 if (!origOuter.transform(viewMatrix, outer.writable())) {
872 return false;
873 }
874 if (!viewMatrix.invert(&inverseVM)) {
875 return false;
876 }
877 } else {
878 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -0700879 }
robertphillips00095892016-02-29 13:50:40 -0800880
881 GrPaint grPaint(paintIn);
882 grPaint.setAntiAlias(false);
883
884 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -0700885 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -0800886 if (!innerEffect) {
887 return false;
888 }
889
bungeman06ca8ec2016-06-09 08:01:03 -0700890 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -0800891 if (!outerEffect) {
892 return false;
893 }
894
bungeman06ca8ec2016-06-09 08:01:03 -0700895 grPaint.addCoverageFragmentProcessor(std::move(innerEffect));
896 grPaint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -0800897
898 SkRect bounds = outer->getBounds();
899 if (applyAA) {
900 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
901 }
halcanary9d524f22016-03-29 09:03:52 -0700902
robertphillips00095892016-02-29 13:50:40 -0800903 this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
904 return true;
905}
906
907void GrDrawContext::drawDRRect(const GrClip& clip,
908 const GrPaint& paint,
909 const SkMatrix& viewMatrix,
910 const SkRRect& outer,
911 const SkRRect& inner) {
912 ASSERT_SINGLE_OWNER
913 RETURN_IF_ABANDONED
914 SkDEBUGCODE(this->validate();)
915 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
916
917 SkASSERT(!outer.isEmpty());
918 SkASSERT(!inner.isEmpty());
919
920 AutoCheckFlush acf(fDrawingManager);
921
922 if (this->drawFilledDRRect(clip, paint, viewMatrix, outer, inner)) {
923 return;
924 }
925
926 SkPath path;
927 path.setIsVolatile(true);
928 path.addRRect(inner);
929 path.addRRect(outer);
930 path.setFillType(SkPath::kEvenOdd_FillType);
931
bsalomon6663acf2016-05-10 09:14:17 -0700932 this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -0800933}
934
robertphillipsea461502015-05-26 11:38:03 -0700935///////////////////////////////////////////////////////////////////////////////
936
robertphillips2e1e51f2015-10-15 08:01:48 -0700937void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700938 const GrPaint& paint,
939 const SkMatrix& viewMatrix,
940 const SkRect& oval,
bsalomon6663acf2016-05-10 09:14:17 -0700941 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800942 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700943 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700944 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800945 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -0700946
robertphillipsea461502015-05-26 11:38:03 -0700947 if (oval.isEmpty()) {
948 return;
949 }
950
bsalomon6663acf2016-05-10 09:14:17 -0700951 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700952
robertphillips77a2e522015-10-17 07:43:27 -0700953 AutoCheckFlush acf(fDrawingManager);
bsalomon6663acf2016-05-10 09:14:17 -0700954 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700955 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -0700956
957 if (this->getDrawTarget()->instancedRendering() && stroke.isFillStyle()) {
958 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
959 SkAutoTUnref<GrDrawBatch> batch(ir->recordOval(oval, viewMatrix, paint.getColor(),
960 paint.isAntiAlias(), fInstancedPipelineInfo,
961 &useHWAA));
962 if (batch) {
963 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
964 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
965 return;
966 }
967 }
968
csmartdaltonecbc12b2016-06-08 10:08:43 -0700969 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800970 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800971 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800972 viewMatrix,
973 oval,
bsalomon6663acf2016-05-10 09:14:17 -0700974 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800975 shaderCaps));
976 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700977 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700978 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800979 return;
980 }
robertphillipsea461502015-05-26 11:38:03 -0700981 }
robertphillipsb56f9272016-02-25 11:03:52 -0800982
983 SkPath path;
984 path.setIsVolatile(true);
985 path.addOval(oval);
bsalomon6663acf2016-05-10 09:14:17 -0700986 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700987}
988
joshualitt33a5fce2015-11-18 13:28:51 -0800989void GrDrawContext::drawImageNine(const GrClip& clip,
990 const GrPaint& paint,
991 const SkMatrix& viewMatrix,
992 int imageWidth,
993 int imageHeight,
994 const SkIRect& center,
995 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -0800996 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -0800997 RETURN_IF_ABANDONED
998 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800999 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageNine");
joshualitt33a5fce2015-11-18 13:28:51 -08001000
1001 AutoCheckFlush acf(fDrawingManager);
1002
1003 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
1004 imageWidth, imageHeight,
1005 center, dst));
1006
csmartdaltonecbc12b2016-06-08 10:08:43 -07001007 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -07001008 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
joshualitt33a5fce2015-11-18 13:28:51 -08001009}
1010
robertphillips8c523e02016-07-26 07:41:00 -07001011void GrDrawContext::prepareForExternalIO() {
1012 ASSERT_SINGLE_OWNER
1013 RETURN_IF_ABANDONED
1014 SkDEBUGCODE(this->validate();)
1015 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::prepareForExternalIO");
1016
1017 ASSERT_OWNED_RESOURCE(fRenderTarget);
1018
1019 fDrawingManager->getContext()->prepareSurfaceForExternalIO(fRenderTarget.get());
1020}
joshualitt33a5fce2015-11-18 13:28:51 -08001021
robertphillips44302392016-07-08 14:43:03 -07001022void GrDrawContext::drawNonAAFilledRect(const GrClip& clip,
1023 const GrPaint& paint,
1024 const SkMatrix& viewMatrix,
1025 const SkRect& rect,
1026 const SkRect* localRect,
1027 const SkMatrix* localMatrix,
1028 const GrUserStencilSettings* ss) {
1029 SkAutoTUnref<GrDrawBatch> batch(
1030 GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, localRect,
1031 localMatrix));
1032 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
1033 if (ss) {
1034 pipelineBuilder.setUserStencil(ss);
1035 }
1036 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1037}
1038
robertphillipsea461502015-05-26 11:38:03 -07001039// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001040static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001041
1042 if (path.isInverseFillType()) {
1043 return false;
1044 }
1045
1046 // TODO: this restriction could be lifted if we were willing to apply
1047 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001048 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001049 return false;
1050 }
1051
1052 SkPath::Direction dirs[2];
1053 if (!path.isNestedFillRects(rects, dirs)) {
1054 return false;
1055 }
1056
1057 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1058 // The two rects need to be wound opposite to each other
1059 return false;
1060 }
1061
1062 // Right now, nested rects where the margin is not the same width
1063 // all around do not render correctly
1064 const SkScalar* outer = rects[0].asScalars();
1065 const SkScalar* inner = rects[1].asScalars();
1066
1067 bool allEq = true;
1068
1069 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1070 bool allGoE1 = margin >= SK_Scalar1;
1071
1072 for (int i = 1; i < 4; ++i) {
1073 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1074 if (temp < SK_Scalar1) {
1075 allGoE1 = false;
1076 }
1077 if (!SkScalarNearlyEqual(margin, temp)) {
1078 allEq = false;
1079 }
1080 }
1081
1082 return allEq || allGoE1;
1083}
1084
robertphillips2e1e51f2015-10-15 08:01:48 -07001085void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -07001086 const GrPaint& paint,
1087 const SkMatrix& viewMatrix,
1088 const SkPath& path,
bsalomon6663acf2016-05-10 09:14:17 -07001089 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001090 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001091 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001092 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001093 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001094
robertphillipsea461502015-05-26 11:38:03 -07001095 if (path.isEmpty()) {
1096 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -07001097 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001098 }
1099 return;
1100 }
1101
robertphillips77a2e522015-10-17 07:43:27 -07001102 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -07001103
csmartdaltonecbc12b2016-06-08 10:08:43 -07001104 bool useHWAA;
1105 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA) && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001106 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001107 // Concave AA paths are expensive - try to avoid them for special cases
1108 SkRect rects[2];
1109
bsalomon6663acf2016-05-10 09:14:17 -07001110 if (fills_as_nested_rects(viewMatrix, path, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -07001111 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
robertphillips4bc31812016-03-01 12:22:49 -08001112 paint.getColor(), viewMatrix, rects));
bsalomon40ef4852016-05-02 13:22:13 -07001113 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001114 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001115 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
bsalomon40ef4852016-05-02 13:22:13 -07001116 }
robertphillipsea461502015-05-26 11:38:03 -07001117 return;
1118 }
1119 }
1120 SkRect ovalRect;
1121 bool isOval = path.isOval(&ovalRect);
1122
1123 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -08001124 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -08001125 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillips0cc2f852016-02-24 13:36:56 -08001126 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -08001127 ovalRect,
bsalomon6663acf2016-05-10 09:14:17 -07001128 style.strokeRec(),
robertphillips0cc2f852016-02-24 13:36:56 -08001129 shaderCaps));
1130 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001131 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001132 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -07001133 return;
1134 }
1135 }
1136 }
robertphillips4bc31812016-03-01 12:22:49 -08001137
1138 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1139 // Scratch textures can be recycled after they are returned to the texture
1140 // cache. This presents a potential hazard for buffered drawing. However,
1141 // the writePixels that uploads to the scratch will perform a flush so we're
1142 // OK.
bsalomon6663acf2016-05-10 09:14:17 -07001143 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001144}
1145
cdalton846c0512016-05-13 10:25:00 -07001146bool GrDrawContextPriv::drawAndStencilPath(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -07001147 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -08001148 SkRegion::Op op,
1149 bool invert,
1150 bool doAA,
1151 const SkMatrix& viewMatrix,
1152 const SkPath& path) {
1153 ASSERT_SINGLE_OWNER_PRIV
1154 RETURN_FALSE_IF_ABANDONED_PRIV
1155 SkDEBUGCODE(fDrawContext->validate();)
1156 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath");
1157
1158 if (path.isEmpty() && path.isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -07001159 this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
robertphillips6c7e3252016-04-27 10:47:51 -07001160 SkRect::MakeIWH(fDrawContext->width(),
1161 fDrawContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001162 return true;
1163 }
1164
1165 AutoCheckFlush acf(fDrawContext->fDrawingManager);
1166
1167 // An Assumption here is that path renderer would use some form of tweaking
1168 // the src color (either the input alpha or in the frag shader) to implement
1169 // aa. If we have some future driver-mojo path AA that can do the right
1170 // thing WRT to the blend then we'll need some query on the PR.
1171 bool useCoverageAA = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled();
robertphillips976f5f02016-06-03 10:59:20 -07001172 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001173 bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled();
1174
1175 const GrPathRendererChain::DrawType type =
1176 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1177 : GrPathRendererChain::kColor_DrawType;
1178
bsalomon8acedde2016-06-24 10:42:16 -07001179 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001180 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1181 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
1182 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001183 canDrawArgs.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001184 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001185 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001186 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1187
1188 // Don't allow the SW renderer
1189 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1190 if (!pr) {
1191 return false;
1192 }
1193
1194 GrPaint paint;
1195 paint.setCoverageSetOpXPFactory(op, invert);
1196
robertphillips391395d2016-03-02 09:26:36 -08001197 GrPathRenderer::DrawPathArgs args;
robertphillips391395d2016-03-02 09:26:36 -08001198 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001199 args.fPaint = &paint;
1200 args.fUserStencilSettings = ss;
1201 args.fDrawContext = fDrawContext;
cdalton862cff32016-05-12 15:09:48 -07001202 args.fClip = &clip;
robertphillips391395d2016-03-02 09:26:36 -08001203 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001204 args.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001205 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001206 args.fGammaCorrect = fDrawContext->isGammaCorrect();
robertphillips391395d2016-03-02 09:26:36 -08001207 pr->drawPath(args);
1208 return true;
1209}
1210
robertphillips4bc31812016-03-01 12:22:49 -08001211void GrDrawContext::internalDrawPath(const GrClip& clip,
1212 const GrPaint& paint,
robertphillipsea461502015-05-26 11:38:03 -07001213 const SkMatrix& viewMatrix,
bsalomon8acedde2016-06-24 10:42:16 -07001214 const SkPath& path,
1215 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001216 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001217 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001218 SkASSERT(!path.isEmpty());
robertphillipsea461502015-05-26 11:38:03 -07001219
robertphillips6c7e3252016-04-27 10:47:51 -07001220 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
cdalton93a379b2016-05-11 13:58:08 -07001221 constexpr bool kHasUserStencilSettings = false;
robertphillips4bc31812016-03-01 12:22:49 -08001222 bool isStencilBufferMSAA = fRenderTarget->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -07001223
robertphillips68737822015-10-29 12:12:21 -07001224 const GrPathRendererChain::DrawType type =
1225 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1226 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -07001227
bsalomon8acedde2016-06-24 10:42:16 -07001228 GrShape shape(path, style);
bsalomon0a0f67e2016-06-28 11:56:42 -07001229 if (shape.isEmpty()) {
1230 return;
1231 }
robertphillips68737822015-10-29 12:12:21 -07001232 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1233 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1234 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001235 canDrawArgs.fShape = &shape;
robertphillips68737822015-10-29 12:12:21 -07001236 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001237 canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
robertphillips68737822015-10-29 12:12:21 -07001238 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1239
bsalomon6663acf2016-05-10 09:14:17 -07001240 // Try a 1st time without applying any of the style to the geometry (and barring sw)
robertphillips68737822015-10-29 12:12:21 -07001241 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
bsalomon6663acf2016-05-10 09:14:17 -07001242 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001243
bsalomon8acedde2016-06-24 10:42:16 -07001244 if (!pr && shape.style().pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001245 // It didn't work above, so try again with the path effect applied.
bsalomon8acedde2016-06-24 10:42:16 -07001246 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1247 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001248 return;
1249 }
robertphillips68737822015-10-29 12:12:21 -07001250 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -07001251 }
bsalomon6663acf2016-05-10 09:14:17 -07001252 if (!pr) {
bsalomon8acedde2016-06-24 10:42:16 -07001253 if (shape.style().applies()) {
1254 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1255 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001256 return;
1257 }
bsalomon6663acf2016-05-10 09:14:17 -07001258 }
robertphillipsea461502015-05-26 11:38:03 -07001259 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -07001260 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -07001261 }
1262
bsalomon8acedde2016-06-24 10:42:16 -07001263 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001264#ifdef SK_DEBUG
1265 SkDebugf("Unable to find path renderer compatible with path.\n");
1266#endif
1267 return;
1268 }
1269
bsalomon0aff2fa2015-07-31 06:48:27 -07001270 GrPathRenderer::DrawPathArgs args;
robertphillips77a2e522015-10-17 07:43:27 -07001271 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001272 args.fPaint = &paint;
1273 args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
1274 args.fDrawContext = this;
cdalton862cff32016-05-12 15:09:48 -07001275 args.fClip = &clip;
bsalomon0aff2fa2015-07-31 06:48:27 -07001276 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001277 args.fShape = canDrawArgs.fShape;
bsalomon0aff2fa2015-07-31 06:48:27 -07001278 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001279 args.fGammaCorrect = this->isGammaCorrect();
bsalomon0aff2fa2015-07-31 06:48:27 -07001280 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001281}
1282
bsalomonbb243832016-07-22 07:10:19 -07001283void GrDrawContext::drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
1284 GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -08001285 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001286 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001287 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001288 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -07001289
robertphillips976f5f02016-06-03 10:59:20 -07001290 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillips2334fb62015-06-17 05:43:33 -07001291}