blob: db144989621e7290c24ca00c07f3d482dae31074 [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"
robertphillips714712b2016-08-04 06:20:45 -070013#include "GrGpuResourcePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070014#include "GrOvalRenderer.h"
15#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
joshualitt74417822015-08-07 11:42:16 -070022#include "batches/GrBatch.h"
robertphillips9199a9f2016-07-13 07:48:43 -070023#include "batches/GrClearBatch.h"
jvanverth14b88032015-08-07 12:18:54 -070024#include "batches/GrDrawAtlasBatch.h"
joshualitt2771b562015-08-07 12:46:26 -070025#include "batches/GrDrawVerticesBatch.h"
joshualitt7fc2a262015-08-10 10:30:14 -070026#include "batches/GrRectBatchFactory.h"
joshualitt33a5fce2015-11-18 13:28:51 -080027#include "batches/GrNinePatch.h" // TODO Factory
joshualitt74417822015-08-07 11:42:16 -070028
robertphillips00095892016-02-29 13:50:40 -080029#include "effects/GrRRectEffect.h"
30
csmartdaltona7f29642016-07-07 08:49:11 -070031#include "instanced/InstancedRendering.h"
32
joshualitte8042922015-12-11 06:11:21 -080033#include "text/GrAtlasTextContext.h"
34#include "text/GrStencilAndCoverTextContext.h"
35
joshualittbc907352016-01-13 06:45:40 -080036#include "../private/GrAuditTrail.h"
37
msarett10e3d9b2016-08-18 15:46:03 -070038#include "SkLatticeIter.h"
39
robertphillips77a2e522015-10-17 07:43:27 -070040#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080041#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080042 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080043#define ASSERT_SINGLE_OWNER_PRIV \
44 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070045#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
robertphillips976f5f02016-06-03 10:59:20 -070046#define RETURN_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return; }
robertphillips7761d612016-05-16 09:14:53 -070047#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
48#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return false; }
49#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070050
csmartdaltona7f29642016-07-07 08:49:11 -070051using gr_instanced::InstancedRendering;
52
robertphillipsea461502015-05-26 11:38:03 -070053class AutoCheckFlush {
54public:
halcanary9d524f22016-03-29 09:03:52 -070055 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070056 SkASSERT(fDrawingManager);
57 }
58 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070059
60private:
robertphillips77a2e522015-10-17 07:43:27 -070061 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070062};
63
robertphillips7761d612016-05-16 09:14:53 -070064bool GrDrawContext::wasAbandoned() const {
65 return fDrawingManager->wasAbandoned();
66}
67
robertphillipsa106c622015-10-16 09:07:06 -070068// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
69// drawTargets to be picked up and added to by drawContexts lower in the call
70// stack. When this occurs with a closed drawTarget, a new one will be allocated
71// when the drawContext attempts to use it (via getDrawTarget).
joshualitt1b39f432016-02-11 06:46:52 -080072GrDrawContext::GrDrawContext(GrContext* context,
73 GrDrawingManager* drawingMgr,
robertphillips6c7e3252016-04-27 10:47:51 -070074 sk_sp<GrRenderTarget> rt,
brianosmandfe4f2e2016-07-21 13:28:36 -070075 sk_sp<SkColorSpace> colorSpace,
joshualittde8dc7e2016-01-08 10:09:13 -080076 const SkSurfaceProps* surfaceProps,
joshualittbc907352016-01-13 06:45:40 -080077 GrAuditTrail* auditTrail,
joshualittde8dc7e2016-01-08 10:09:13 -080078 GrSingleOwner* singleOwner)
robertphillips77a2e522015-10-17 07:43:27 -070079 : fDrawingManager(drawingMgr)
robertphillips6c7e3252016-04-27 10:47:51 -070080 , fRenderTarget(std::move(rt))
81 , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
joshualitt1b39f432016-02-11 06:46:52 -080082 , fContext(context)
csmartdaltona7f29642016-07-07 08:49:11 -070083 , fInstancedPipelineInfo(fRenderTarget.get())
brianosmandfe4f2e2016-07-21 13:28:36 -070084 , fColorSpace(std::move(colorSpace))
joshualittde8dc7e2016-01-08 10:09:13 -080085 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080086 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080087#ifdef SK_DEBUG
88 , fSingleOwner(singleOwner)
89#endif
90{
robertphillips2e1e51f2015-10-15 08:01:48 -070091 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070092}
93
robertphillips2e1e51f2015-10-15 08:01:48 -070094#ifdef SK_DEBUG
95void GrDrawContext::validate() const {
96 SkASSERT(fRenderTarget);
97 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070098
99 if (fDrawTarget && !fDrawTarget->isClosed()) {
100 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
101 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700102}
103#endif
104
robertphillipsa106c622015-10-16 09:07:06 -0700105GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800106 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700107 SkSafeUnref(fDrawTarget);
108}
109
110GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -0800111 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700112 SkDEBUGCODE(this->validate();)
113
114 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips6c7e3252016-04-27 10:47:51 -0700115 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
robertphillipsa106c622015-10-16 09:07:06 -0700116 }
117
118 return fDrawTarget;
119}
120
bsalomonb8fea972016-02-16 07:34:17 -0800121bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800122 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800123 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700124 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800125 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700126
robertphillips6c7e3252016-04-27 10:47:51 -0700127 return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700128}
129
robertphillips2e1e51f2015-10-15 08:01:48 -0700130void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700131 const SkPaint& skPaint,
132 const SkMatrix& viewMatrix,
133 const char text[], size_t byteLength,
134 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800135 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700136 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700137 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800138 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700139
brianosman86e76262016-08-11 12:17:31 -0700140 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
141 atlasTextContext->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
brianosman86e76262016-08-11 12:17:31 -0700156 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
157 atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
158 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
159 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700160
161}
robertphillipscaef3452015-11-11 13:18:11 -0800162
robertphillips2e1e51f2015-10-15 08:01:48 -0700163void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700164 const SkMatrix& viewMatrix, const SkTextBlob* blob,
165 SkScalar x, SkScalar y,
166 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800167 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700168 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700169 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800170 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700171
brianosman86e76262016-08-11 12:17:31 -0700172 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
173 atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
174 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700175}
176
robertphillips2e1e51f2015-10-15 08:01:48 -0700177void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800178 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700179 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700180 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800181 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700182
robertphillips77a2e522015-10-17 07:43:27 -0700183 AutoCheckFlush acf(fDrawingManager);
robertphillips6c7e3252016-04-27 10:47:51 -0700184 this->getDrawTarget()->discard(fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700185}
186
robertphillips2e1e51f2015-10-15 08:01:48 -0700187void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700188 const GrColor color,
189 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800190 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700191 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700192 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800193 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700194
robertphillips77a2e522015-10-17 07:43:27 -0700195 AutoCheckFlush acf(fDrawingManager);
robertphillips9199a9f2016-07-13 07:48:43 -0700196
197 const SkIRect rtRect = SkIRect::MakeWH(this->width(), this->height());
198 SkIRect clippedRect;
bsalomon9f129de2016-08-10 16:31:05 -0700199 bool isFull = false;
robertphillips9199a9f2016-07-13 07:48:43 -0700200 if (!rect ||
201 (canIgnoreRect && fContext->caps()->fullClearIsFree()) ||
202 rect->contains(rtRect)) {
203 rect = &rtRect;
bsalomon9f129de2016-08-10 16:31:05 -0700204 isFull = true;
robertphillips9199a9f2016-07-13 07:48:43 -0700205 } else {
206 clippedRect = *rect;
207 if (!clippedRect.intersect(rtRect)) {
208 return;
209 }
210 rect = &clippedRect;
211 }
212
213 if (fContext->caps()->useDrawInsteadOfClear()) {
214 // This works around a driver bug with clear by drawing a rect instead.
215 // The driver will ignore a clear if it is the only thing rendered to a
216 // target before the target is read.
217 if (rect == &rtRect) {
218 this->discard();
219 }
220
221 GrPaint paint;
222 paint.setColor4f(GrColor4f::FromGrColor(color));
223 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
224
225 this->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::Make(*rect));
bsalomon9f129de2016-08-10 16:31:05 -0700226 } else if (isFull) {
227 this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
robertphillips9199a9f2016-07-13 07:48:43 -0700228 } else {
bsalomonfd8d0132016-08-11 11:25:33 -0700229 sk_sp<GrBatch> batch(GrClearBatch::Make(*rect, color, this->accessRenderTarget()));
robertphillips9199a9f2016-07-13 07:48:43 -0700230 this->getDrawTarget()->addBatch(std::move(batch));
231 }
robertphillipsea461502015-05-26 11:38:03 -0700232}
233
234
robertphillips2e1e51f2015-10-15 08:01:48 -0700235void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700236 const GrPaint& origPaint,
237 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800238 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700239 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700240 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800241 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700242
robertphillipsea461502015-05-26 11:38:03 -0700243 // set rect to be big enough to fill the space, but not super-huge, so we
244 // don't overflow fixed-point implementations
245 SkRect r;
246 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700247 SkIntToScalar(fRenderTarget->width()),
248 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700249 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
250
251 // by definition this fills the entire clip, no need for AA
252 if (paint->isAntiAlias()) {
253 paint.writable()->setAntiAlias(false);
254 }
255
256 bool isPerspective = viewMatrix.hasPerspective();
257
258 // We attempt to map r by the inverse matrix and draw that. mapRect will
259 // map the four corners and bound them with a new rect. This will not
260 // produce a correct result for some perspective matrices.
261 if (!isPerspective) {
262 SkMatrix inverse;
263 if (!viewMatrix.invert(&inverse)) {
264 SkDebugf("Could not invert matrix\n");
265 return;
266 }
267 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700268 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700269 } else {
270 SkMatrix localMatrix;
271 if (!viewMatrix.invert(&localMatrix)) {
272 SkDebugf("Could not invert matrix\n");
273 return;
274 }
275
robertphillips77a2e522015-10-17 07:43:27 -0700276 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700277
csmartdalton34ee0c92016-07-27 13:22:27 -0700278 this->drawNonAAFilledRect(clip, *paint, SkMatrix::I(), r, nullptr, &localMatrix, nullptr,
279 false /* useHWAA */);
robertphillipsea461502015-05-26 11:38:03 -0700280 }
281}
282
robertphillipsea461502015-05-26 11:38:03 -0700283static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
284 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
285 point.fY >= rect.fTop && point.fY <= rect.fBottom;
286}
287
bsalomonc55271f2015-11-09 11:55:57 -0800288static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
289 return viewMatrix.preservesRightAngles();
290}
291
csmartdaltonecbc12b2016-06-08 10:08:43 -0700292static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt,
293 bool* useHWAA = nullptr) {
294 if (!paint.isAntiAlias()) {
295 if (useHWAA) {
296 *useHWAA = false;
297 }
298 return false;
299 } else {
300 if (useHWAA) {
bsalomonbb243832016-07-22 07:10:19 -0700301 *useHWAA = rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700302 }
bsalomonbb243832016-07-22 07:10:19 -0700303 return !rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700304 }
bsalomonc55271f2015-11-09 11:55:57 -0800305}
306
csmartdalton97f6cd52016-07-13 13:37:08 -0700307// Attempts to crop a rect and optional local rect to the clip boundaries.
308// Returns false if the draw can be skipped entirely.
309static bool crop_filled_rect(const GrRenderTarget* rt, const GrClip& clip,
310 const SkMatrix& viewMatrix, SkRect* rect,
311 SkRect* localRect = nullptr) {
312 if (!viewMatrix.rectStaysRect()) {
313 return true;
314 }
315
316 SkMatrix inverseViewMatrix;
317 if (!viewMatrix.invert(&inverseViewMatrix)) {
318 return false;
319 }
320
321 SkIRect clipDevBounds;
322 SkRect clipBounds;
323 SkASSERT(inverseViewMatrix.rectStaysRect());
324
325 clip.getConservativeBounds(rt->width(), rt->height(), &clipDevBounds);
326 inverseViewMatrix.mapRect(&clipBounds, SkRect::Make(clipDevBounds));
327
328 if (localRect) {
329 if (!rect->intersects(clipBounds)) {
330 return false;
331 }
332 const SkScalar dx = localRect->width() / rect->width();
333 const SkScalar dy = localRect->height() / rect->height();
334 if (clipBounds.fLeft > rect->fLeft) {
335 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
336 rect->fLeft = clipBounds.fLeft;
337 }
338 if (clipBounds.fTop > rect->fTop) {
339 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
340 rect->fTop = clipBounds.fTop;
341 }
342 if (clipBounds.fRight < rect->fRight) {
343 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
344 rect->fRight = clipBounds.fRight;
345 }
346 if (clipBounds.fBottom < rect->fBottom) {
347 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
348 rect->fBottom = clipBounds.fBottom;
349 }
350 return true;
351 }
352
353 return rect->intersect(clipBounds);
354}
355
robertphillips44302392016-07-08 14:43:03 -0700356bool GrDrawContext::drawFilledRect(const GrClip& clip,
357 const GrPaint& paint,
358 const SkMatrix& viewMatrix,
359 const SkRect& rect,
360 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700361 SkRect croppedRect = rect;
362 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect)) {
363 return true;
364 }
robertphillips44302392016-07-08 14:43:03 -0700365
366 SkAutoTUnref<GrDrawBatch> batch;
367 bool useHWAA;
368
csmartdaltone0d36292016-07-29 08:14:20 -0700369 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
370 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
dvonbeck09e12a62016-08-12 12:50:36 -0700390 batch.reset(GrRectBatchFactory::CreateAAFill(paint, viewMatrix, rect, croppedRect,
391 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 {
csmartdalton34ee0c92016-07-27 13:22:27 -0700402 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss,
403 useHWAA);
robertphillips44302392016-07-08 14:43:03 -0700404 return true;
robertphillips391395d2016-03-02 09:26:36 -0800405 }
406
robertphillips44302392016-07-08 14:43:03 -0700407 return false;
robertphillips391395d2016-03-02 09:26:36 -0800408}
409
robertphillips2e1e51f2015-10-15 08:01:48 -0700410void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700411 const GrPaint& paint,
412 const SkMatrix& viewMatrix,
413 const SkRect& rect,
bsalomon6663acf2016-05-10 09:14:17 -0700414 const GrStyle* style) {
415 if (!style) {
416 style = &GrStyle::SimpleFill();
417 }
joshualitt1de610a2016-01-06 08:26:09 -0800418 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700419 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700420 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800421 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700422
bsalomon6663acf2016-05-10 09:14:17 -0700423 // Path effects should've been devolved to a path in SkGpuDevice
424 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700425
robertphillips77a2e522015-10-17 07:43:27 -0700426 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700427
bsalomon6663acf2016-05-10 09:14:17 -0700428 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700429 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
430
431 if (!fContext->caps()->useDrawInsteadOfClear()) {
432 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
433 // checking cases where the RT is fully inside a stroke.
434 SkRect rtRect;
435 fRenderTarget->getBoundsRect(&rtRect);
436 // Does the clip contain the entire RT?
437 if (clip.quickContains(rtRect)) {
438 SkMatrix invM;
439 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700440 return;
441 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700442 // Does the rect bound the RT?
443 SkPoint srcSpaceRTQuad[4];
444 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
445 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
446 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
447 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
448 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
449 // Will it blend?
450 GrColor clearColor;
451 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700452 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700453 return;
454 }
455 }
robertphillipsea461502015-05-26 11:38:03 -0700456 }
457 }
robertphillips44302392016-07-08 14:43:03 -0700458
459 if (this->drawFilledRect(clip, paint, viewMatrix, rect, nullptr)) {
460 return;
461 }
bsalomona7d85ba2016-07-06 11:54:59 -0700462 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
463 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
464 if ((!rect.width() || !rect.height()) &&
465 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
466 SkScalar r = stroke.getWidth() / 2;
467 // TODO: Move these stroke->fill fallbacks to GrShape?
468 switch (stroke.getJoin()) {
469 case SkPaint::kMiter_Join:
470 this->drawRect(clip, paint, viewMatrix,
471 {rect.fLeft - r, rect.fTop - r,
472 rect.fRight + r, rect.fBottom + r},
473 &GrStyle::SimpleFill());
474 return;
475 case SkPaint::kRound_Join:
476 // Raster draws nothing when both dimensions are empty.
477 if (rect.width() || rect.height()){
478 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
479 this->drawRRect(clip, paint, viewMatrix, rrect, GrStyle::SimpleFill());
480 return;
481 }
482 case SkPaint::kBevel_Join:
483 if (!rect.width()) {
484 this->drawRect(clip, paint, viewMatrix,
485 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
486 &GrStyle::SimpleFill());
487 } else {
488 this->drawRect(clip, paint, viewMatrix,
489 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
490 &GrStyle::SimpleFill());
491 }
492 return;
493 }
494 }
robertphillips44302392016-07-08 14:43:03 -0700495
496 bool useHWAA;
497 bool snapToPixelCenters = false;
498 SkAutoTUnref<GrDrawBatch> batch;
499
robertphillips391395d2016-03-02 09:26:36 -0800500 GrColor color = paint.getColor();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700501 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
cdaltonbb539482016-01-04 09:48:25 -0800502 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
503 if (viewMatrix.rectStaysRect()) {
bsalomona7d85ba2016-07-06 11:54:59 -0700504 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke));
cdaltonbb539482016-01-04 09:48:25 -0800505 }
robertphillipsea461502015-05-26 11:38:03 -0700506 } else {
robertphillips391395d2016-03-02 09:26:36 -0800507 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700508 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800509 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700510 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
511 !fRenderTarget->isUnifiedMultisampled();
512 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
513 stroke, snapToPixelCenters));
robertphillips391395d2016-03-02 09:26:36 -0800514 }
robertphillips4bc31812016-03-01 12:22:49 -0800515
robertphillips44302392016-07-08 14:43:03 -0700516 if (batch) {
517 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips4bc31812016-03-01 12:22:49 -0800518
robertphillips44302392016-07-08 14:43:03 -0700519 if (snapToPixelCenters) {
520 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
521 snapToPixelCenters);
522 }
523
524 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
525 return;
robertphillips4bc31812016-03-01 12:22:49 -0800526 }
robertphillips4bc31812016-03-01 12:22:49 -0800527 }
halcanary9d524f22016-03-29 09:03:52 -0700528
robertphillips4bc31812016-03-01 12:22:49 -0800529 SkPath path;
530 path.setIsVolatile(true);
531 path.addRect(rect);
bsalomon6663acf2016-05-10 09:14:17 -0700532 this->internalDrawPath(clip, paint, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700533}
534
robertphillips976f5f02016-06-03 10:59:20 -0700535void GrDrawContextPriv::clearStencilClip(const SkIRect& rect, bool insideClip) {
536 ASSERT_SINGLE_OWNER_PRIV
537 RETURN_IF_ABANDONED_PRIV
538 SkDEBUGCODE(fDrawContext->validate();)
539 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
540
541 AutoCheckFlush acf(fDrawContext->fDrawingManager);
542 fDrawContext->getDrawTarget()->clearStencilClip(rect, insideClip,
543 fDrawContext->accessRenderTarget());
544}
545
robertphillips59cf61a2016-07-13 09:18:21 -0700546void GrDrawContextPriv::stencilPath(const GrClip& clip,
robertphillips59cf61a2016-07-13 09:18:21 -0700547 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700548 const SkMatrix& viewMatrix,
robertphillips59cf61a2016-07-13 09:18:21 -0700549 const GrPath* path) {
csmartdalton5c6fc4f2016-08-12 15:11:51 -0700550 fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, 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
csmartdalton34ee0c92016-07-27 13:22:27 -0700569 fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700570}
571
cdalton846c0512016-05-13 10:25:00 -0700572bool GrDrawContextPriv::drawAndStencilRect(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -0700573 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -0800574 SkRegion::Op op,
575 bool invert,
576 bool doAA,
577 const SkMatrix& viewMatrix,
578 const SkRect& rect) {
579 ASSERT_SINGLE_OWNER_PRIV
580 RETURN_FALSE_IF_ABANDONED_PRIV
581 SkDEBUGCODE(fDrawContext->validate();)
robertphillips55fdccc2016-06-06 06:16:20 -0700582 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800583
584 AutoCheckFlush acf(fDrawContext->fDrawingManager);
585
586 GrPaint paint;
587 paint.setAntiAlias(doAA);
588 paint.setCoverageSetOpXPFactory(op, invert);
589
robertphillips44302392016-07-08 14:43:03 -0700590 if (fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800591 return true;
592 }
593
594 SkPath path;
595 path.setIsVolatile(true);
596 path.addRect(rect);
cdalton862cff32016-05-12 15:09:48 -0700597 return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800598}
599
bsalomona2e69fc2015-11-05 10:41:43 -0800600void GrDrawContext::fillRectToRect(const GrClip& clip,
601 const GrPaint& paint,
602 const SkMatrix& viewMatrix,
603 const SkRect& rectToDraw,
604 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800605 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700606 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700607 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800608 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700609
csmartdalton97f6cd52016-07-13 13:37:08 -0700610 SkRect croppedRect = rectToDraw;
611 SkRect croppedLocalRect = localRect;
612 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect, &croppedLocalRect)) {
613 return;
614 }
615
robertphillips77a2e522015-10-17 07:43:27 -0700616 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700617 bool useHWAA;
618
csmartdaltone0d36292016-07-29 08:14:20 -0700619 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
620 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltonfc49d562016-07-26 17:05:47 -0700621 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
622 croppedLocalRect, paint.isAntiAlias(),
623 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700624 if (batch) {
bsalomonbb243832016-07-22 07:10:19 -0700625 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
626 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700627 return;
628 }
629 }
630
csmartdaltonfc49d562016-07-26 17:05:47 -0700631 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700632 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect,
csmartdalton34ee0c92016-07-27 13:22:27 -0700633 nullptr, nullptr, useHWAA);
csmartdaltonfc49d562016-07-26 17:05:47 -0700634 return;
joshualitt04194f32016-01-13 10:08:27 -0800635 }
bsalomonbb243832016-07-22 07:10:19 -0700636
csmartdaltonfc49d562016-07-26 17:05:47 -0700637 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
638 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(),
639 viewMatrix,
640 croppedRect,
641 croppedLocalRect));
642 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
643 this->drawBatch(pipelineBuilder, clip, batch);
644 return;
645 }
646
647 SkMatrix viewAndUnLocalMatrix;
648 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
649 SkDebugf("fillRectToRect called with empty local matrix.\n");
650 return;
651 }
652 viewAndUnLocalMatrix.postConcat(viewMatrix);
653
654 SkPath path;
655 path.setIsVolatile(true);
656 path.addRect(localRect);
657 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700658}
659
bsalomona2e69fc2015-11-05 10:41:43 -0800660void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
661 const GrPaint& paint,
662 const SkMatrix& viewMatrix,
663 const SkRect& rectToDraw,
664 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800665 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700666 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700667 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800668 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700669
csmartdalton97f6cd52016-07-13 13:37:08 -0700670 SkRect croppedRect = rectToDraw;
671 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect)) {
672 return;
673 }
674
robertphillips77a2e522015-10-17 07:43:27 -0700675 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700676 bool useHWAA;
677
csmartdaltone0d36292016-07-29 08:14:20 -0700678 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
679 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,
csmartdalton34ee0c92016-07-27 13:22:27 -0700692 &localMatrix, nullptr, useHWAA);
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
bsalomon7f0d9f32016-08-15 14:49:10 -0700786void GrDrawContext::drawRRect(const GrClip& origClip,
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");
robertphillipsea461502015-05-26 11:38:03 -0700795 if (rrect.isEmpty()) {
796 return;
797 }
798
bsalomon7f0d9f32016-08-15 14:49:10 -0700799 GrNoClip noclip;
800 const GrClip* clip = &origClip;
801#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
802 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
803 // draw is aa. Since our lower level clip code works from batch bounds, which are SkRects, it
804 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
805 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
806 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
807 SkRRect devRRect;
808 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
809 clip = &noclip;
810 }
811#endif
bsalomon6663acf2016-05-10 09:14:17 -0700812 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700813
csmartdaltona7f29642016-07-07 08:49:11 -0700814 AutoCheckFlush acf(fDrawingManager);
815 const SkStrokeRec stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700816 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -0700817
csmartdaltone0d36292016-07-29 08:14:20 -0700818 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
819 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700820 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
821 SkAutoTUnref<GrDrawBatch> batch(ir->recordRRect(rrect, viewMatrix, paint.getColor(),
822 paint.isAntiAlias(), fInstancedPipelineInfo,
823 &useHWAA));
824 if (batch) {
825 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
bsalomon7f0d9f32016-08-15 14:49:10 -0700826 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700827 return;
828 }
829 }
830
csmartdaltonecbc12b2016-06-08 10:08:43 -0700831 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800832 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800833 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800834 viewMatrix,
835 rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700836 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800837 shaderCaps));
838 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700839 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
bsalomon7f0d9f32016-08-15 14:49:10 -0700840 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800841 return;
842 }
robertphillipsea461502015-05-26 11:38:03 -0700843 }
robertphillipsb56f9272016-02-25 11:03:52 -0800844
845 SkPath path;
846 path.setIsVolatile(true);
847 path.addRRect(rrect);
bsalomon7f0d9f32016-08-15 14:49:10 -0700848 this->internalDrawPath(*clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700849}
850
robertphillips00095892016-02-29 13:50:40 -0800851bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
852 const GrPaint& paintIn,
853 const SkMatrix& viewMatrix,
854 const SkRRect& origOuter,
855 const SkRRect& origInner) {
856 SkASSERT(!origInner.isEmpty());
857 SkASSERT(!origOuter.isEmpty());
858
csmartdaltone0d36292016-07-29 08:14:20 -0700859 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700860 bool useHWAA;
csmartdaltone0d36292016-07-29 08:14:20 -0700861 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltona7f29642016-07-07 08:49:11 -0700862 SkAutoTUnref<GrDrawBatch> batch(ir->recordDRRect(origOuter, origInner, viewMatrix,
863 paintIn.getColor(), paintIn.isAntiAlias(),
864 fInstancedPipelineInfo, &useHWAA));
865 if (batch) {
866 GrPipelineBuilder pipelineBuilder(paintIn, useHWAA);
867 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
868 return true;
869 }
870 }
871
robertphillips00095892016-02-29 13:50:40 -0800872 bool applyAA = paintIn.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
873
874 GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
875 kInverseFillBW_GrProcessorEdgeType;
876 GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
877 kFillBW_GrProcessorEdgeType;
878
879 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
880 SkMatrix inverseVM;
881 if (!viewMatrix.isIdentity()) {
882 if (!origInner.transform(viewMatrix, inner.writable())) {
883 return false;
884 }
885 if (!origOuter.transform(viewMatrix, outer.writable())) {
886 return false;
887 }
888 if (!viewMatrix.invert(&inverseVM)) {
889 return false;
890 }
891 } else {
892 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -0700893 }
robertphillips00095892016-02-29 13:50:40 -0800894
895 GrPaint grPaint(paintIn);
896 grPaint.setAntiAlias(false);
897
898 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -0700899 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -0800900 if (!innerEffect) {
901 return false;
902 }
903
bungeman06ca8ec2016-06-09 08:01:03 -0700904 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -0800905 if (!outerEffect) {
906 return false;
907 }
908
bungeman06ca8ec2016-06-09 08:01:03 -0700909 grPaint.addCoverageFragmentProcessor(std::move(innerEffect));
910 grPaint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -0800911
912 SkRect bounds = outer->getBounds();
913 if (applyAA) {
914 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
915 }
halcanary9d524f22016-03-29 09:03:52 -0700916
robertphillips00095892016-02-29 13:50:40 -0800917 this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
918 return true;
919}
920
921void GrDrawContext::drawDRRect(const GrClip& clip,
922 const GrPaint& paint,
923 const SkMatrix& viewMatrix,
924 const SkRRect& outer,
925 const SkRRect& inner) {
926 ASSERT_SINGLE_OWNER
927 RETURN_IF_ABANDONED
928 SkDEBUGCODE(this->validate();)
929 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
930
931 SkASSERT(!outer.isEmpty());
932 SkASSERT(!inner.isEmpty());
933
934 AutoCheckFlush acf(fDrawingManager);
935
936 if (this->drawFilledDRRect(clip, paint, viewMatrix, outer, inner)) {
937 return;
938 }
939
940 SkPath path;
941 path.setIsVolatile(true);
942 path.addRRect(inner);
943 path.addRRect(outer);
944 path.setFillType(SkPath::kEvenOdd_FillType);
945
bsalomon6663acf2016-05-10 09:14:17 -0700946 this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -0800947}
948
robertphillipsea461502015-05-26 11:38:03 -0700949///////////////////////////////////////////////////////////////////////////////
950
robertphillips2e1e51f2015-10-15 08:01:48 -0700951void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700952 const GrPaint& paint,
953 const SkMatrix& viewMatrix,
954 const SkRect& oval,
bsalomon6663acf2016-05-10 09:14:17 -0700955 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800956 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700957 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700958 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800959 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -0700960
robertphillipsea461502015-05-26 11:38:03 -0700961 if (oval.isEmpty()) {
962 return;
963 }
964
bsalomon6663acf2016-05-10 09:14:17 -0700965 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700966
robertphillips77a2e522015-10-17 07:43:27 -0700967 AutoCheckFlush acf(fDrawingManager);
bsalomon6663acf2016-05-10 09:14:17 -0700968 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700969 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -0700970
csmartdaltone0d36292016-07-29 08:14:20 -0700971 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
972 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700973 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
974 SkAutoTUnref<GrDrawBatch> batch(ir->recordOval(oval, viewMatrix, paint.getColor(),
975 paint.isAntiAlias(), fInstancedPipelineInfo,
976 &useHWAA));
977 if (batch) {
978 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
979 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
980 return;
981 }
982 }
983
csmartdaltonecbc12b2016-06-08 10:08:43 -0700984 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800985 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800986 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800987 viewMatrix,
988 oval,
bsalomon6663acf2016-05-10 09:14:17 -0700989 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800990 shaderCaps));
991 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700992 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700993 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800994 return;
995 }
robertphillipsea461502015-05-26 11:38:03 -0700996 }
robertphillipsb56f9272016-02-25 11:03:52 -0800997
998 SkPath path;
999 path.setIsVolatile(true);
1000 path.addOval(oval);
bsalomon6663acf2016-05-10 09:14:17 -07001001 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001002}
1003
msarett10e3d9b2016-08-18 15:46:03 -07001004void GrDrawContext::drawImageLattice(const GrClip& clip,
1005 const GrPaint& paint,
1006 const SkMatrix& viewMatrix,
1007 int imageWidth,
1008 int imageHeight,
1009 std::unique_ptr<SkLatticeIter> iter,
1010 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001011 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001012 RETURN_IF_ABANDONED
1013 SkDEBUGCODE(this->validate();)
msarett10e3d9b2016-08-18 15:46:03 -07001014 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001015
1016 AutoCheckFlush acf(fDrawingManager);
1017
1018 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
1019 imageWidth, imageHeight,
msarett10e3d9b2016-08-18 15:46:03 -07001020 std::move(iter), dst));
joshualitt33a5fce2015-11-18 13:28:51 -08001021
csmartdaltonecbc12b2016-06-08 10:08:43 -07001022 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -07001023 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
joshualitt33a5fce2015-11-18 13:28:51 -08001024}
1025
robertphillips8c523e02016-07-26 07:41:00 -07001026void GrDrawContext::prepareForExternalIO() {
1027 ASSERT_SINGLE_OWNER
1028 RETURN_IF_ABANDONED
1029 SkDEBUGCODE(this->validate();)
1030 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::prepareForExternalIO");
1031
1032 ASSERT_OWNED_RESOURCE(fRenderTarget);
1033
1034 fDrawingManager->getContext()->prepareSurfaceForExternalIO(fRenderTarget.get());
1035}
joshualitt33a5fce2015-11-18 13:28:51 -08001036
robertphillips44302392016-07-08 14:43:03 -07001037void GrDrawContext::drawNonAAFilledRect(const GrClip& clip,
1038 const GrPaint& paint,
1039 const SkMatrix& viewMatrix,
1040 const SkRect& rect,
1041 const SkRect* localRect,
1042 const SkMatrix* localMatrix,
csmartdalton34ee0c92016-07-27 13:22:27 -07001043 const GrUserStencilSettings* ss,
1044 bool useHWAA) {
1045 SkASSERT(!useHWAA || this->isStencilBufferMultisampled());
robertphillips44302392016-07-08 14:43:03 -07001046 SkAutoTUnref<GrDrawBatch> batch(
1047 GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, localRect,
1048 localMatrix));
csmartdalton34ee0c92016-07-27 13:22:27 -07001049 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips44302392016-07-08 14:43:03 -07001050 if (ss) {
1051 pipelineBuilder.setUserStencil(ss);
1052 }
1053 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1054}
1055
robertphillipsea461502015-05-26 11:38:03 -07001056// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001057static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001058
1059 if (path.isInverseFillType()) {
1060 return false;
1061 }
1062
1063 // TODO: this restriction could be lifted if we were willing to apply
1064 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001065 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001066 return false;
1067 }
1068
1069 SkPath::Direction dirs[2];
1070 if (!path.isNestedFillRects(rects, dirs)) {
1071 return false;
1072 }
1073
1074 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1075 // The two rects need to be wound opposite to each other
1076 return false;
1077 }
1078
1079 // Right now, nested rects where the margin is not the same width
1080 // all around do not render correctly
1081 const SkScalar* outer = rects[0].asScalars();
1082 const SkScalar* inner = rects[1].asScalars();
1083
1084 bool allEq = true;
1085
1086 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1087 bool allGoE1 = margin >= SK_Scalar1;
1088
1089 for (int i = 1; i < 4; ++i) {
1090 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1091 if (temp < SK_Scalar1) {
1092 allGoE1 = false;
1093 }
1094 if (!SkScalarNearlyEqual(margin, temp)) {
1095 allEq = false;
1096 }
1097 }
1098
1099 return allEq || allGoE1;
1100}
1101
robertphillips2e1e51f2015-10-15 08:01:48 -07001102void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -07001103 const GrPaint& paint,
1104 const SkMatrix& viewMatrix,
1105 const SkPath& path,
bsalomon6663acf2016-05-10 09:14:17 -07001106 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001107 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001108 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001109 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001110 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001111
robertphillipsea461502015-05-26 11:38:03 -07001112 if (path.isEmpty()) {
1113 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -07001114 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001115 }
1116 return;
1117 }
1118
robertphillips77a2e522015-10-17 07:43:27 -07001119 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -07001120
csmartdaltonecbc12b2016-06-08 10:08:43 -07001121 bool useHWAA;
1122 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA) && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001123 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001124 // Concave AA paths are expensive - try to avoid them for special cases
1125 SkRect rects[2];
1126
bsalomon6663acf2016-05-10 09:14:17 -07001127 if (fills_as_nested_rects(viewMatrix, path, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -07001128 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
robertphillips4bc31812016-03-01 12:22:49 -08001129 paint.getColor(), viewMatrix, rects));
bsalomon40ef4852016-05-02 13:22:13 -07001130 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);
bsalomon40ef4852016-05-02 13:22:13 -07001133 }
robertphillipsea461502015-05-26 11:38:03 -07001134 return;
1135 }
1136 }
1137 SkRect ovalRect;
1138 bool isOval = path.isOval(&ovalRect);
1139
1140 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -08001141 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -08001142 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillips0cc2f852016-02-24 13:36:56 -08001143 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -08001144 ovalRect,
bsalomon6663acf2016-05-10 09:14:17 -07001145 style.strokeRec(),
robertphillips0cc2f852016-02-24 13:36:56 -08001146 shaderCaps));
1147 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001148 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001149 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -07001150 return;
1151 }
1152 }
1153 }
robertphillips4bc31812016-03-01 12:22:49 -08001154
1155 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1156 // Scratch textures can be recycled after they are returned to the texture
1157 // cache. This presents a potential hazard for buffered drawing. However,
1158 // the writePixels that uploads to the scratch will perform a flush so we're
1159 // OK.
bsalomon6663acf2016-05-10 09:14:17 -07001160 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001161}
1162
cdalton846c0512016-05-13 10:25:00 -07001163bool GrDrawContextPriv::drawAndStencilPath(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -07001164 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -08001165 SkRegion::Op op,
1166 bool invert,
1167 bool doAA,
1168 const SkMatrix& viewMatrix,
1169 const SkPath& path) {
1170 ASSERT_SINGLE_OWNER_PRIV
1171 RETURN_FALSE_IF_ABANDONED_PRIV
1172 SkDEBUGCODE(fDrawContext->validate();)
1173 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath");
1174
1175 if (path.isEmpty() && path.isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -07001176 this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
robertphillips6c7e3252016-04-27 10:47:51 -07001177 SkRect::MakeIWH(fDrawContext->width(),
1178 fDrawContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001179 return true;
1180 }
1181
1182 AutoCheckFlush acf(fDrawContext->fDrawingManager);
1183
1184 // An Assumption here is that path renderer would use some form of tweaking
1185 // the src color (either the input alpha or in the frag shader) to implement
1186 // aa. If we have some future driver-mojo path AA that can do the right
1187 // thing WRT to the blend then we'll need some query on the PR.
1188 bool useCoverageAA = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled();
robertphillips976f5f02016-06-03 10:59:20 -07001189 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001190 bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled();
1191
1192 const GrPathRendererChain::DrawType type =
1193 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1194 : GrPathRendererChain::kColor_DrawType;
1195
bsalomon8acedde2016-06-24 10:42:16 -07001196 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001197 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1198 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
1199 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001200 canDrawArgs.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001201 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001202 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001203 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1204
1205 // Don't allow the SW renderer
1206 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1207 if (!pr) {
1208 return false;
1209 }
1210
1211 GrPaint paint;
1212 paint.setCoverageSetOpXPFactory(op, invert);
1213
robertphillips391395d2016-03-02 09:26:36 -08001214 GrPathRenderer::DrawPathArgs args;
robertphillips391395d2016-03-02 09:26:36 -08001215 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001216 args.fPaint = &paint;
1217 args.fUserStencilSettings = ss;
1218 args.fDrawContext = fDrawContext;
cdalton862cff32016-05-12 15:09:48 -07001219 args.fClip = &clip;
robertphillips391395d2016-03-02 09:26:36 -08001220 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001221 args.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001222 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001223 args.fGammaCorrect = fDrawContext->isGammaCorrect();
robertphillips391395d2016-03-02 09:26:36 -08001224 pr->drawPath(args);
1225 return true;
1226}
1227
robertphillips714712b2016-08-04 06:20:45 -07001228SkBudgeted GrDrawContextPriv::isBudgeted() const {
1229 ASSERT_SINGLE_OWNER_PRIV
1230
1231 if (fDrawContext->wasAbandoned()) {
1232 return SkBudgeted::kNo;
1233 }
1234
1235 SkDEBUGCODE(fDrawContext->validate();)
1236
1237 return fDrawContext->fRenderTarget->resourcePriv().isBudgeted();
1238}
1239
robertphillips4bc31812016-03-01 12:22:49 -08001240void GrDrawContext::internalDrawPath(const GrClip& clip,
1241 const GrPaint& paint,
robertphillipsea461502015-05-26 11:38:03 -07001242 const SkMatrix& viewMatrix,
bsalomon8acedde2016-06-24 10:42:16 -07001243 const SkPath& path,
1244 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001245 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001246 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001247 SkASSERT(!path.isEmpty());
robertphillipsea461502015-05-26 11:38:03 -07001248
robertphillips6c7e3252016-04-27 10:47:51 -07001249 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
cdalton93a379b2016-05-11 13:58:08 -07001250 constexpr bool kHasUserStencilSettings = false;
robertphillips4bc31812016-03-01 12:22:49 -08001251 bool isStencilBufferMSAA = fRenderTarget->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -07001252
robertphillips68737822015-10-29 12:12:21 -07001253 const GrPathRendererChain::DrawType type =
1254 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1255 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -07001256
bsalomon8acedde2016-06-24 10:42:16 -07001257 GrShape shape(path, style);
bsalomon0a0f67e2016-06-28 11:56:42 -07001258 if (shape.isEmpty()) {
1259 return;
1260 }
robertphillips68737822015-10-29 12:12:21 -07001261 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1262 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1263 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001264 canDrawArgs.fShape = &shape;
robertphillips68737822015-10-29 12:12:21 -07001265 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001266 canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
robertphillips68737822015-10-29 12:12:21 -07001267 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1268
bsalomon6663acf2016-05-10 09:14:17 -07001269 // Try a 1st time without applying any of the style to the geometry (and barring sw)
robertphillips68737822015-10-29 12:12:21 -07001270 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
bsalomon6663acf2016-05-10 09:14:17 -07001271 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001272
bsalomon8acedde2016-06-24 10:42:16 -07001273 if (!pr && shape.style().pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001274 // It didn't work above, so try again with the path effect applied.
bsalomon8acedde2016-06-24 10:42:16 -07001275 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1276 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001277 return;
1278 }
robertphillips68737822015-10-29 12:12:21 -07001279 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -07001280 }
bsalomon6663acf2016-05-10 09:14:17 -07001281 if (!pr) {
bsalomon8acedde2016-06-24 10:42:16 -07001282 if (shape.style().applies()) {
1283 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1284 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001285 return;
1286 }
bsalomon6663acf2016-05-10 09:14:17 -07001287 }
robertphillipsea461502015-05-26 11:38:03 -07001288 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -07001289 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -07001290 }
1291
bsalomon8acedde2016-06-24 10:42:16 -07001292 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001293#ifdef SK_DEBUG
1294 SkDebugf("Unable to find path renderer compatible with path.\n");
1295#endif
1296 return;
1297 }
1298
bsalomon0aff2fa2015-07-31 06:48:27 -07001299 GrPathRenderer::DrawPathArgs args;
robertphillips77a2e522015-10-17 07:43:27 -07001300 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001301 args.fPaint = &paint;
1302 args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
1303 args.fDrawContext = this;
cdalton862cff32016-05-12 15:09:48 -07001304 args.fClip = &clip;
bsalomon0aff2fa2015-07-31 06:48:27 -07001305 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001306 args.fShape = canDrawArgs.fShape;
bsalomon0aff2fa2015-07-31 06:48:27 -07001307 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001308 args.fGammaCorrect = this->isGammaCorrect();
bsalomon0aff2fa2015-07-31 06:48:27 -07001309 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001310}
1311
bsalomonbb243832016-07-22 07:10:19 -07001312void GrDrawContext::drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
1313 GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -08001314 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001315 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001316 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001317 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -07001318
robertphillips976f5f02016-06-03 10:59:20 -07001319 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillips2334fb62015-06-17 05:43:33 -07001320}