blob: 76e0d8a66cd6900e473ce0e17f937e815e60e4f0 [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
robertphillips77a2e522015-10-17 07:43:27 -070038#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080039#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080040 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080041#define ASSERT_SINGLE_OWNER_PRIV \
42 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070043#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
robertphillips976f5f02016-06-03 10:59:20 -070044#define RETURN_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return; }
robertphillips7761d612016-05-16 09:14:53 -070045#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
46#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return false; }
47#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070048
csmartdaltona7f29642016-07-07 08:49:11 -070049using gr_instanced::InstancedRendering;
50
robertphillipsea461502015-05-26 11:38:03 -070051class AutoCheckFlush {
52public:
halcanary9d524f22016-03-29 09:03:52 -070053 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070054 SkASSERT(fDrawingManager);
55 }
56 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070057
58private:
robertphillips77a2e522015-10-17 07:43:27 -070059 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070060};
61
robertphillips7761d612016-05-16 09:14:53 -070062bool GrDrawContext::wasAbandoned() const {
63 return fDrawingManager->wasAbandoned();
64}
65
robertphillipsa106c622015-10-16 09:07:06 -070066// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
67// drawTargets to be picked up and added to by drawContexts lower in the call
68// stack. When this occurs with a closed drawTarget, a new one will be allocated
69// when the drawContext attempts to use it (via getDrawTarget).
joshualitt1b39f432016-02-11 06:46:52 -080070GrDrawContext::GrDrawContext(GrContext* context,
71 GrDrawingManager* drawingMgr,
robertphillips6c7e3252016-04-27 10:47:51 -070072 sk_sp<GrRenderTarget> rt,
brianosmandfe4f2e2016-07-21 13:28:36 -070073 sk_sp<SkColorSpace> colorSpace,
joshualittde8dc7e2016-01-08 10:09:13 -080074 const SkSurfaceProps* surfaceProps,
joshualittbc907352016-01-13 06:45:40 -080075 GrAuditTrail* auditTrail,
joshualittde8dc7e2016-01-08 10:09:13 -080076 GrSingleOwner* singleOwner)
robertphillips77a2e522015-10-17 07:43:27 -070077 : fDrawingManager(drawingMgr)
robertphillips6c7e3252016-04-27 10:47:51 -070078 , fRenderTarget(std::move(rt))
79 , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
joshualitt1b39f432016-02-11 06:46:52 -080080 , fContext(context)
csmartdaltona7f29642016-07-07 08:49:11 -070081 , fInstancedPipelineInfo(fRenderTarget.get())
brianosmandfe4f2e2016-07-21 13:28:36 -070082 , fColorSpace(std::move(colorSpace))
joshualittde8dc7e2016-01-08 10:09:13 -080083 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080084 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080085#ifdef SK_DEBUG
86 , fSingleOwner(singleOwner)
87#endif
88{
robertphillips2e1e51f2015-10-15 08:01:48 -070089 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070090}
91
robertphillips2e1e51f2015-10-15 08:01:48 -070092#ifdef SK_DEBUG
93void GrDrawContext::validate() const {
94 SkASSERT(fRenderTarget);
95 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070096
97 if (fDrawTarget && !fDrawTarget->isClosed()) {
98 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
99 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700100}
101#endif
102
robertphillipsa106c622015-10-16 09:07:06 -0700103GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800104 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700105 SkSafeUnref(fDrawTarget);
106}
107
108GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -0800109 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700110 SkDEBUGCODE(this->validate();)
111
112 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips6c7e3252016-04-27 10:47:51 -0700113 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
robertphillipsa106c622015-10-16 09:07:06 -0700114 }
115
116 return fDrawTarget;
117}
118
bsalomonb8fea972016-02-16 07:34:17 -0800119bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800120 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800121 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700122 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800123 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700124
robertphillips6c7e3252016-04-27 10:47:51 -0700125 return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700126}
127
robertphillips2e1e51f2015-10-15 08:01:48 -0700128void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700129 const SkPaint& skPaint,
130 const SkMatrix& viewMatrix,
131 const char text[], size_t byteLength,
132 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800133 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700134 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700135 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800136 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700137
brianosman86e76262016-08-11 12:17:31 -0700138 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
139 atlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
140 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700141}
robertphillipscaef3452015-11-11 13:18:11 -0800142
robertphillips2e1e51f2015-10-15 08:01:48 -0700143void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700144 const SkPaint& skPaint,
145 const SkMatrix& viewMatrix,
146 const char text[], size_t byteLength,
147 const SkScalar pos[], int scalarsPerPosition,
148 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800149 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700150 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700151 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800152 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700153
brianosman86e76262016-08-11 12:17:31 -0700154 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
155 atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
156 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
157 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700158
159}
robertphillipscaef3452015-11-11 13:18:11 -0800160
robertphillips2e1e51f2015-10-15 08:01:48 -0700161void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700162 const SkMatrix& viewMatrix, const SkTextBlob* blob,
163 SkScalar x, SkScalar y,
164 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800165 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700166 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700167 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800168 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700169
brianosman86e76262016-08-11 12:17:31 -0700170 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
171 atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
172 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700173}
174
robertphillips2e1e51f2015-10-15 08:01:48 -0700175void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800176 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700177 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700178 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800179 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700180
robertphillips77a2e522015-10-17 07:43:27 -0700181 AutoCheckFlush acf(fDrawingManager);
robertphillips6c7e3252016-04-27 10:47:51 -0700182 this->getDrawTarget()->discard(fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700183}
184
robertphillips2e1e51f2015-10-15 08:01:48 -0700185void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700186 const GrColor color,
187 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800188 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700189 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700190 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800191 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700192
robertphillips77a2e522015-10-17 07:43:27 -0700193 AutoCheckFlush acf(fDrawingManager);
robertphillips9199a9f2016-07-13 07:48:43 -0700194
195 const SkIRect rtRect = SkIRect::MakeWH(this->width(), this->height());
196 SkIRect clippedRect;
bsalomon9f129de2016-08-10 16:31:05 -0700197 bool isFull = false;
robertphillips9199a9f2016-07-13 07:48:43 -0700198 if (!rect ||
199 (canIgnoreRect && fContext->caps()->fullClearIsFree()) ||
200 rect->contains(rtRect)) {
201 rect = &rtRect;
bsalomon9f129de2016-08-10 16:31:05 -0700202 isFull = true;
robertphillips9199a9f2016-07-13 07:48:43 -0700203 } else {
204 clippedRect = *rect;
205 if (!clippedRect.intersect(rtRect)) {
206 return;
207 }
208 rect = &clippedRect;
209 }
210
211 if (fContext->caps()->useDrawInsteadOfClear()) {
212 // This works around a driver bug with clear by drawing a rect instead.
213 // The driver will ignore a clear if it is the only thing rendered to a
214 // target before the target is read.
215 if (rect == &rtRect) {
216 this->discard();
217 }
218
219 GrPaint paint;
220 paint.setColor4f(GrColor4f::FromGrColor(color));
221 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
222
223 this->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::Make(*rect));
bsalomon9f129de2016-08-10 16:31:05 -0700224 } else if (isFull) {
225 this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
robertphillips9199a9f2016-07-13 07:48:43 -0700226 } else {
bsalomonfd8d0132016-08-11 11:25:33 -0700227 sk_sp<GrBatch> batch(GrClearBatch::Make(*rect, color, this->accessRenderTarget()));
robertphillips9199a9f2016-07-13 07:48:43 -0700228 this->getDrawTarget()->addBatch(std::move(batch));
229 }
robertphillipsea461502015-05-26 11:38:03 -0700230}
231
232
robertphillips2e1e51f2015-10-15 08:01:48 -0700233void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700234 const GrPaint& origPaint,
235 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800236 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700237 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700238 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800239 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700240
robertphillipsea461502015-05-26 11:38:03 -0700241 // set rect to be big enough to fill the space, but not super-huge, so we
242 // don't overflow fixed-point implementations
243 SkRect r;
244 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700245 SkIntToScalar(fRenderTarget->width()),
246 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700247 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
248
249 // by definition this fills the entire clip, no need for AA
250 if (paint->isAntiAlias()) {
251 paint.writable()->setAntiAlias(false);
252 }
253
254 bool isPerspective = viewMatrix.hasPerspective();
255
256 // We attempt to map r by the inverse matrix and draw that. mapRect will
257 // map the four corners and bound them with a new rect. This will not
258 // produce a correct result for some perspective matrices.
259 if (!isPerspective) {
260 SkMatrix inverse;
261 if (!viewMatrix.invert(&inverse)) {
262 SkDebugf("Could not invert matrix\n");
263 return;
264 }
265 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700266 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700267 } else {
268 SkMatrix localMatrix;
269 if (!viewMatrix.invert(&localMatrix)) {
270 SkDebugf("Could not invert matrix\n");
271 return;
272 }
273
robertphillips77a2e522015-10-17 07:43:27 -0700274 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700275
csmartdalton34ee0c92016-07-27 13:22:27 -0700276 this->drawNonAAFilledRect(clip, *paint, SkMatrix::I(), r, nullptr, &localMatrix, nullptr,
277 false /* useHWAA */);
robertphillipsea461502015-05-26 11:38:03 -0700278 }
279}
280
robertphillipsea461502015-05-26 11:38:03 -0700281static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
282 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
283 point.fY >= rect.fTop && point.fY <= rect.fBottom;
284}
285
bsalomonc55271f2015-11-09 11:55:57 -0800286static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
287 return viewMatrix.preservesRightAngles();
288}
289
csmartdaltonecbc12b2016-06-08 10:08:43 -0700290static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt,
291 bool* useHWAA = nullptr) {
292 if (!paint.isAntiAlias()) {
293 if (useHWAA) {
294 *useHWAA = false;
295 }
296 return false;
297 } else {
298 if (useHWAA) {
bsalomonbb243832016-07-22 07:10:19 -0700299 *useHWAA = rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700300 }
bsalomonbb243832016-07-22 07:10:19 -0700301 return !rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700302 }
bsalomonc55271f2015-11-09 11:55:57 -0800303}
304
csmartdalton97f6cd52016-07-13 13:37:08 -0700305// Attempts to crop a rect and optional local rect to the clip boundaries.
306// Returns false if the draw can be skipped entirely.
307static bool crop_filled_rect(const GrRenderTarget* rt, const GrClip& clip,
308 const SkMatrix& viewMatrix, SkRect* rect,
309 SkRect* localRect = nullptr) {
310 if (!viewMatrix.rectStaysRect()) {
311 return true;
312 }
313
314 SkMatrix inverseViewMatrix;
315 if (!viewMatrix.invert(&inverseViewMatrix)) {
316 return false;
317 }
318
319 SkIRect clipDevBounds;
320 SkRect clipBounds;
321 SkASSERT(inverseViewMatrix.rectStaysRect());
322
323 clip.getConservativeBounds(rt->width(), rt->height(), &clipDevBounds);
324 inverseViewMatrix.mapRect(&clipBounds, SkRect::Make(clipDevBounds));
325
326 if (localRect) {
327 if (!rect->intersects(clipBounds)) {
328 return false;
329 }
330 const SkScalar dx = localRect->width() / rect->width();
331 const SkScalar dy = localRect->height() / rect->height();
332 if (clipBounds.fLeft > rect->fLeft) {
333 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
334 rect->fLeft = clipBounds.fLeft;
335 }
336 if (clipBounds.fTop > rect->fTop) {
337 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
338 rect->fTop = clipBounds.fTop;
339 }
340 if (clipBounds.fRight < rect->fRight) {
341 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
342 rect->fRight = clipBounds.fRight;
343 }
344 if (clipBounds.fBottom < rect->fBottom) {
345 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
346 rect->fBottom = clipBounds.fBottom;
347 }
348 return true;
349 }
350
351 return rect->intersect(clipBounds);
352}
353
robertphillips44302392016-07-08 14:43:03 -0700354bool GrDrawContext::drawFilledRect(const GrClip& clip,
355 const GrPaint& paint,
356 const SkMatrix& viewMatrix,
357 const SkRect& rect,
358 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700359 SkRect croppedRect = rect;
360 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect)) {
361 return true;
362 }
robertphillips44302392016-07-08 14:43:03 -0700363
364 SkAutoTUnref<GrDrawBatch> batch;
365 bool useHWAA;
366
csmartdaltone0d36292016-07-29 08:14:20 -0700367 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
368 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdalton97f6cd52016-07-13 13:37:08 -0700369 batch.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
robertphillips44302392016-07-08 14:43:03 -0700370 paint.isAntiAlias(), fInstancedPipelineInfo,
371 &useHWAA));
372 if (batch) {
373 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
374 if (ss) {
375 pipelineBuilder.setUserStencil(ss);
376 }
377 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
378 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700379 }
380 }
robertphillips391395d2016-03-02 09:26:36 -0800381
robertphillips44302392016-07-08 14:43:03 -0700382 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillips391395d2016-03-02 09:26:36 -0800383 // The fill path can handle rotation but not skew.
384 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
385 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700386 viewMatrix.mapRect(&devBoundRect, croppedRect);
robertphillips44302392016-07-08 14:43:03 -0700387
dvonbeck09e12a62016-08-12 12:50:36 -0700388 batch.reset(GrRectBatchFactory::CreateAAFill(paint, viewMatrix, rect, croppedRect,
389 devBoundRect));
robertphillips44302392016-07-08 14:43:03 -0700390 if (batch) {
391 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
392 if (ss) {
393 pipelineBuilder.setUserStencil(ss);
394 }
395 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
396 return true;
397 }
robertphillips391395d2016-03-02 09:26:36 -0800398 }
399 } else {
csmartdalton34ee0c92016-07-27 13:22:27 -0700400 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss,
401 useHWAA);
robertphillips44302392016-07-08 14:43:03 -0700402 return true;
robertphillips391395d2016-03-02 09:26:36 -0800403 }
404
robertphillips44302392016-07-08 14:43:03 -0700405 return false;
robertphillips391395d2016-03-02 09:26:36 -0800406}
407
robertphillips2e1e51f2015-10-15 08:01:48 -0700408void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700409 const GrPaint& paint,
410 const SkMatrix& viewMatrix,
411 const SkRect& rect,
bsalomon6663acf2016-05-10 09:14:17 -0700412 const GrStyle* style) {
413 if (!style) {
414 style = &GrStyle::SimpleFill();
415 }
joshualitt1de610a2016-01-06 08:26:09 -0800416 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700417 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700418 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800419 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700420
bsalomon6663acf2016-05-10 09:14:17 -0700421 // Path effects should've been devolved to a path in SkGpuDevice
422 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700423
robertphillips77a2e522015-10-17 07:43:27 -0700424 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700425
bsalomon6663acf2016-05-10 09:14:17 -0700426 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700427 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
428
429 if (!fContext->caps()->useDrawInsteadOfClear()) {
430 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
431 // checking cases where the RT is fully inside a stroke.
432 SkRect rtRect;
433 fRenderTarget->getBoundsRect(&rtRect);
434 // Does the clip contain the entire RT?
435 if (clip.quickContains(rtRect)) {
436 SkMatrix invM;
437 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700438 return;
439 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700440 // Does the rect bound the RT?
441 SkPoint srcSpaceRTQuad[4];
442 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
443 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
444 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
445 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
446 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
447 // Will it blend?
448 GrColor clearColor;
449 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700450 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700451 return;
452 }
453 }
robertphillipsea461502015-05-26 11:38:03 -0700454 }
455 }
robertphillips44302392016-07-08 14:43:03 -0700456
457 if (this->drawFilledRect(clip, paint, viewMatrix, rect, nullptr)) {
458 return;
459 }
bsalomona7d85ba2016-07-06 11:54:59 -0700460 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
461 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
462 if ((!rect.width() || !rect.height()) &&
463 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
464 SkScalar r = stroke.getWidth() / 2;
465 // TODO: Move these stroke->fill fallbacks to GrShape?
466 switch (stroke.getJoin()) {
467 case SkPaint::kMiter_Join:
468 this->drawRect(clip, paint, viewMatrix,
469 {rect.fLeft - r, rect.fTop - r,
470 rect.fRight + r, rect.fBottom + r},
471 &GrStyle::SimpleFill());
472 return;
473 case SkPaint::kRound_Join:
474 // Raster draws nothing when both dimensions are empty.
475 if (rect.width() || rect.height()){
476 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
477 this->drawRRect(clip, paint, viewMatrix, rrect, GrStyle::SimpleFill());
478 return;
479 }
480 case SkPaint::kBevel_Join:
481 if (!rect.width()) {
482 this->drawRect(clip, paint, viewMatrix,
483 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
484 &GrStyle::SimpleFill());
485 } else {
486 this->drawRect(clip, paint, viewMatrix,
487 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
488 &GrStyle::SimpleFill());
489 }
490 return;
491 }
492 }
robertphillips44302392016-07-08 14:43:03 -0700493
494 bool useHWAA;
495 bool snapToPixelCenters = false;
496 SkAutoTUnref<GrDrawBatch> batch;
497
robertphillips391395d2016-03-02 09:26:36 -0800498 GrColor color = paint.getColor();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700499 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
cdaltonbb539482016-01-04 09:48:25 -0800500 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
501 if (viewMatrix.rectStaysRect()) {
bsalomona7d85ba2016-07-06 11:54:59 -0700502 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke));
cdaltonbb539482016-01-04 09:48:25 -0800503 }
robertphillipsea461502015-05-26 11:38:03 -0700504 } else {
robertphillips391395d2016-03-02 09:26:36 -0800505 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700506 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800507 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700508 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
509 !fRenderTarget->isUnifiedMultisampled();
510 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
511 stroke, snapToPixelCenters));
robertphillips391395d2016-03-02 09:26:36 -0800512 }
robertphillips4bc31812016-03-01 12:22:49 -0800513
robertphillips44302392016-07-08 14:43:03 -0700514 if (batch) {
515 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips4bc31812016-03-01 12:22:49 -0800516
robertphillips44302392016-07-08 14:43:03 -0700517 if (snapToPixelCenters) {
518 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
519 snapToPixelCenters);
520 }
521
522 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
523 return;
robertphillips4bc31812016-03-01 12:22:49 -0800524 }
robertphillips4bc31812016-03-01 12:22:49 -0800525 }
halcanary9d524f22016-03-29 09:03:52 -0700526
robertphillips4bc31812016-03-01 12:22:49 -0800527 SkPath path;
528 path.setIsVolatile(true);
529 path.addRect(rect);
bsalomon6663acf2016-05-10 09:14:17 -0700530 this->internalDrawPath(clip, paint, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700531}
532
robertphillips976f5f02016-06-03 10:59:20 -0700533void GrDrawContextPriv::clearStencilClip(const SkIRect& rect, bool insideClip) {
534 ASSERT_SINGLE_OWNER_PRIV
535 RETURN_IF_ABANDONED_PRIV
536 SkDEBUGCODE(fDrawContext->validate();)
537 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
538
539 AutoCheckFlush acf(fDrawContext->fDrawingManager);
540 fDrawContext->getDrawTarget()->clearStencilClip(rect, insideClip,
541 fDrawContext->accessRenderTarget());
542}
543
robertphillips59cf61a2016-07-13 09:18:21 -0700544void GrDrawContextPriv::stencilPath(const GrClip& clip,
robertphillips59cf61a2016-07-13 09:18:21 -0700545 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700546 const SkMatrix& viewMatrix,
robertphillips59cf61a2016-07-13 09:18:21 -0700547 const GrPath* path) {
csmartdalton5c6fc4f2016-08-12 15:11:51 -0700548 fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
robertphillips976f5f02016-06-03 10:59:20 -0700549}
550
551void GrDrawContextPriv::stencilRect(const GrFixedClip& clip,
552 const GrUserStencilSettings* ss,
csmartdalton656dbe42016-06-10 12:32:57 -0700553 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700554 const SkMatrix& viewMatrix,
555 const SkRect& rect) {
556 ASSERT_SINGLE_OWNER_PRIV
557 RETURN_IF_ABANDONED_PRIV
558 SkDEBUGCODE(fDrawContext->validate();)
559 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::stencilRect");
560
561 AutoCheckFlush acf(fDrawContext->fDrawingManager);
562
563 GrPaint paint;
csmartdalton656dbe42016-06-10 12:32:57 -0700564 paint.setAntiAlias(useHWAA);
bungeman06ca8ec2016-06-09 08:01:03 -0700565 paint.setXPFactory(GrDisableColorXPFactory::Make());
robertphillips976f5f02016-06-03 10:59:20 -0700566
csmartdalton34ee0c92016-07-27 13:22:27 -0700567 fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700568}
569
cdalton846c0512016-05-13 10:25:00 -0700570bool GrDrawContextPriv::drawAndStencilRect(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -0700571 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -0800572 SkRegion::Op op,
573 bool invert,
574 bool doAA,
575 const SkMatrix& viewMatrix,
576 const SkRect& rect) {
577 ASSERT_SINGLE_OWNER_PRIV
578 RETURN_FALSE_IF_ABANDONED_PRIV
579 SkDEBUGCODE(fDrawContext->validate();)
robertphillips55fdccc2016-06-06 06:16:20 -0700580 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800581
582 AutoCheckFlush acf(fDrawContext->fDrawingManager);
583
584 GrPaint paint;
585 paint.setAntiAlias(doAA);
586 paint.setCoverageSetOpXPFactory(op, invert);
587
robertphillips44302392016-07-08 14:43:03 -0700588 if (fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800589 return true;
590 }
591
592 SkPath path;
593 path.setIsVolatile(true);
594 path.addRect(rect);
cdalton862cff32016-05-12 15:09:48 -0700595 return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800596}
597
bsalomona2e69fc2015-11-05 10:41:43 -0800598void GrDrawContext::fillRectToRect(const GrClip& clip,
599 const GrPaint& paint,
600 const SkMatrix& viewMatrix,
601 const SkRect& rectToDraw,
602 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800603 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700604 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700605 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800606 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700607
csmartdalton97f6cd52016-07-13 13:37:08 -0700608 SkRect croppedRect = rectToDraw;
609 SkRect croppedLocalRect = localRect;
610 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect, &croppedLocalRect)) {
611 return;
612 }
613
robertphillips77a2e522015-10-17 07:43:27 -0700614 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700615 bool useHWAA;
616
csmartdaltone0d36292016-07-29 08:14:20 -0700617 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
618 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltonfc49d562016-07-26 17:05:47 -0700619 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
620 croppedLocalRect, paint.isAntiAlias(),
621 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700622 if (batch) {
bsalomonbb243832016-07-22 07:10:19 -0700623 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
624 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700625 return;
626 }
627 }
628
csmartdaltonfc49d562016-07-26 17:05:47 -0700629 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700630 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect,
csmartdalton34ee0c92016-07-27 13:22:27 -0700631 nullptr, nullptr, useHWAA);
csmartdaltonfc49d562016-07-26 17:05:47 -0700632 return;
joshualitt04194f32016-01-13 10:08:27 -0800633 }
bsalomonbb243832016-07-22 07:10:19 -0700634
csmartdaltonfc49d562016-07-26 17:05:47 -0700635 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
636 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(),
637 viewMatrix,
638 croppedRect,
639 croppedLocalRect));
640 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
641 this->drawBatch(pipelineBuilder, clip, batch);
642 return;
643 }
644
645 SkMatrix viewAndUnLocalMatrix;
646 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
647 SkDebugf("fillRectToRect called with empty local matrix.\n");
648 return;
649 }
650 viewAndUnLocalMatrix.postConcat(viewMatrix);
651
652 SkPath path;
653 path.setIsVolatile(true);
654 path.addRect(localRect);
655 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700656}
657
bsalomona2e69fc2015-11-05 10:41:43 -0800658void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
659 const GrPaint& paint,
660 const SkMatrix& viewMatrix,
661 const SkRect& rectToDraw,
662 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800663 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700664 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700665 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800666 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700667
csmartdalton97f6cd52016-07-13 13:37:08 -0700668 SkRect croppedRect = rectToDraw;
669 if (!crop_filled_rect(fRenderTarget.get(), clip, viewMatrix, &croppedRect)) {
670 return;
671 }
672
robertphillips77a2e522015-10-17 07:43:27 -0700673 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700674 bool useHWAA;
675
csmartdaltone0d36292016-07-29 08:14:20 -0700676 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
677 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltonfc49d562016-07-26 17:05:47 -0700678 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
679 localMatrix, paint.isAntiAlias(),
680 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700681 if (batch) {
682 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
683 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
684 return;
685 }
686 }
687
csmartdaltonfc49d562016-07-26 17:05:47 -0700688 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700689 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr,
csmartdalton34ee0c92016-07-27 13:22:27 -0700690 &localMatrix, nullptr, useHWAA);
csmartdaltonfc49d562016-07-26 17:05:47 -0700691 return;
bsalomonc55271f2015-11-09 11:55:57 -0800692 }
robertphillips4bc31812016-03-01 12:22:49 -0800693
csmartdaltonfc49d562016-07-26 17:05:47 -0700694 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
695 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix,
696 localMatrix, croppedRect));
697 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
698 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
699 return;
700 }
701
702 SkMatrix viewAndUnLocalMatrix;
703 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
704 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
705 return;
706 }
707 viewAndUnLocalMatrix.postConcat(viewMatrix);
708
709 SkPath path;
710 path.setIsVolatile(true);
711 path.addRect(rectToDraw);
712 path.transform(localMatrix);
713 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700714}
715
robertphillips2e1e51f2015-10-15 08:01:48 -0700716void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700717 const GrPaint& paint,
718 const SkMatrix& viewMatrix,
719 GrPrimitiveType primitiveType,
720 int vertexCount,
721 const SkPoint positions[],
722 const SkPoint texCoords[],
723 const GrColor colors[],
724 const uint16_t indices[],
725 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800726 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700727 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700728 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800729 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700730
robertphillips77a2e522015-10-17 07:43:27 -0700731 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700732
robertphillipsea461502015-05-26 11:38:03 -0700733 // TODO clients should give us bounds
734 SkRect bounds;
735 if (!bounds.setBoundsCheck(positions, vertexCount)) {
736 SkDebugf("drawVertices call empty bounds\n");
737 return;
738 }
739
740 viewMatrix.mapRect(&bounds);
741
742 // 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 -0800743 // snapping. We also do this for the "hair" primitive types: lines and points since they have
744 // a 1 pixel thickness in device space.
745 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
746 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700747 bounds.outset(0.5f, 0.5f);
748 }
749
bsalomond92b4192016-06-30 07:59:23 -0700750 SkAutoTUnref<GrDrawBatch> batch(new GrDrawVerticesBatch(paint.getColor(),
751 primitiveType, viewMatrix, positions,
752 vertexCount, indices, indexCount,
753 colors, texCoords, bounds));
robertphillipsea461502015-05-26 11:38:03 -0700754
csmartdaltonecbc12b2016-06-08 10:08:43 -0700755 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700756 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700757}
758
759///////////////////////////////////////////////////////////////////////////////
760
robertphillips2e1e51f2015-10-15 08:01:48 -0700761void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700762 const GrPaint& paint,
763 const SkMatrix& viewMatrix,
764 int spriteCount,
765 const SkRSXform xform[],
766 const SkRect texRect[],
767 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800768 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700769 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700770 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800771 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700772
robertphillips77a2e522015-10-17 07:43:27 -0700773 AutoCheckFlush acf(fDrawingManager);
halcanary9d524f22016-03-29 09:03:52 -0700774
bsalomon0432dd62016-06-30 07:19:27 -0700775 SkAutoTUnref<GrDrawBatch> batch(new GrDrawAtlasBatch(paint.getColor(), viewMatrix, spriteCount,
776 xform, texRect, colors));
halcanary9d524f22016-03-29 09:03:52 -0700777
csmartdaltonecbc12b2016-06-08 10:08:43 -0700778 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700779 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700780}
781
782///////////////////////////////////////////////////////////////////////////////
783
robertphillips2e1e51f2015-10-15 08:01:48 -0700784void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700785 const GrPaint& paint,
786 const SkMatrix& viewMatrix,
787 const SkRRect& rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700788 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800789 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700790 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700791 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800792 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700793
robertphillipsea461502015-05-26 11:38:03 -0700794 if (rrect.isEmpty()) {
795 return;
796 }
797
bsalomon6663acf2016-05-10 09:14:17 -0700798 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700799
csmartdaltona7f29642016-07-07 08:49:11 -0700800 AutoCheckFlush acf(fDrawingManager);
801 const SkStrokeRec stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700802 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -0700803
csmartdaltone0d36292016-07-29 08:14:20 -0700804 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
805 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700806 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
807 SkAutoTUnref<GrDrawBatch> batch(ir->recordRRect(rrect, viewMatrix, paint.getColor(),
808 paint.isAntiAlias(), fInstancedPipelineInfo,
809 &useHWAA));
810 if (batch) {
811 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
812 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
813 return;
814 }
815 }
816
csmartdaltonecbc12b2016-06-08 10:08:43 -0700817 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800818 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800819 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800820 viewMatrix,
821 rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700822 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800823 shaderCaps));
824 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700825 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700826 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800827 return;
828 }
robertphillipsea461502015-05-26 11:38:03 -0700829 }
robertphillipsb56f9272016-02-25 11:03:52 -0800830
831 SkPath path;
832 path.setIsVolatile(true);
833 path.addRRect(rrect);
bsalomon6663acf2016-05-10 09:14:17 -0700834 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700835}
836
robertphillips00095892016-02-29 13:50:40 -0800837bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
838 const GrPaint& paintIn,
839 const SkMatrix& viewMatrix,
840 const SkRRect& origOuter,
841 const SkRRect& origInner) {
842 SkASSERT(!origInner.isEmpty());
843 SkASSERT(!origOuter.isEmpty());
844
csmartdaltone0d36292016-07-29 08:14:20 -0700845 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700846 bool useHWAA;
csmartdaltone0d36292016-07-29 08:14:20 -0700847 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltona7f29642016-07-07 08:49:11 -0700848 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
csmartdaltone0d36292016-07-29 08:14:20 -0700957 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
958 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700959 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
960 SkAutoTUnref<GrDrawBatch> batch(ir->recordOval(oval, viewMatrix, paint.getColor(),
961 paint.isAntiAlias(), fInstancedPipelineInfo,
962 &useHWAA));
963 if (batch) {
964 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
965 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
966 return;
967 }
968 }
969
csmartdaltonecbc12b2016-06-08 10:08:43 -0700970 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800971 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800972 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800973 viewMatrix,
974 oval,
bsalomon6663acf2016-05-10 09:14:17 -0700975 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800976 shaderCaps));
977 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700978 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700979 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800980 return;
981 }
robertphillipsea461502015-05-26 11:38:03 -0700982 }
robertphillipsb56f9272016-02-25 11:03:52 -0800983
984 SkPath path;
985 path.setIsVolatile(true);
986 path.addOval(oval);
bsalomon6663acf2016-05-10 09:14:17 -0700987 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700988}
989
joshualitt33a5fce2015-11-18 13:28:51 -0800990void GrDrawContext::drawImageNine(const GrClip& clip,
991 const GrPaint& paint,
992 const SkMatrix& viewMatrix,
993 int imageWidth,
994 int imageHeight,
995 const SkIRect& center,
996 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -0800997 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -0800998 RETURN_IF_ABANDONED
999 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001000 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageNine");
joshualitt33a5fce2015-11-18 13:28:51 -08001001
1002 AutoCheckFlush acf(fDrawingManager);
1003
1004 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
1005 imageWidth, imageHeight,
1006 center, dst));
1007
csmartdaltonecbc12b2016-06-08 10:08:43 -07001008 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -07001009 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
joshualitt33a5fce2015-11-18 13:28:51 -08001010}
1011
robertphillips8c523e02016-07-26 07:41:00 -07001012void GrDrawContext::prepareForExternalIO() {
1013 ASSERT_SINGLE_OWNER
1014 RETURN_IF_ABANDONED
1015 SkDEBUGCODE(this->validate();)
1016 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::prepareForExternalIO");
1017
1018 ASSERT_OWNED_RESOURCE(fRenderTarget);
1019
1020 fDrawingManager->getContext()->prepareSurfaceForExternalIO(fRenderTarget.get());
1021}
joshualitt33a5fce2015-11-18 13:28:51 -08001022
robertphillips44302392016-07-08 14:43:03 -07001023void GrDrawContext::drawNonAAFilledRect(const GrClip& clip,
1024 const GrPaint& paint,
1025 const SkMatrix& viewMatrix,
1026 const SkRect& rect,
1027 const SkRect* localRect,
1028 const SkMatrix* localMatrix,
csmartdalton34ee0c92016-07-27 13:22:27 -07001029 const GrUserStencilSettings* ss,
1030 bool useHWAA) {
1031 SkASSERT(!useHWAA || this->isStencilBufferMultisampled());
robertphillips44302392016-07-08 14:43:03 -07001032 SkAutoTUnref<GrDrawBatch> batch(
1033 GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, localRect,
1034 localMatrix));
csmartdalton34ee0c92016-07-27 13:22:27 -07001035 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips44302392016-07-08 14:43:03 -07001036 if (ss) {
1037 pipelineBuilder.setUserStencil(ss);
1038 }
1039 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1040}
1041
robertphillipsea461502015-05-26 11:38:03 -07001042// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001043static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001044
1045 if (path.isInverseFillType()) {
1046 return false;
1047 }
1048
1049 // TODO: this restriction could be lifted if we were willing to apply
1050 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001051 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001052 return false;
1053 }
1054
1055 SkPath::Direction dirs[2];
1056 if (!path.isNestedFillRects(rects, dirs)) {
1057 return false;
1058 }
1059
1060 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1061 // The two rects need to be wound opposite to each other
1062 return false;
1063 }
1064
1065 // Right now, nested rects where the margin is not the same width
1066 // all around do not render correctly
1067 const SkScalar* outer = rects[0].asScalars();
1068 const SkScalar* inner = rects[1].asScalars();
1069
1070 bool allEq = true;
1071
1072 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1073 bool allGoE1 = margin >= SK_Scalar1;
1074
1075 for (int i = 1; i < 4; ++i) {
1076 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1077 if (temp < SK_Scalar1) {
1078 allGoE1 = false;
1079 }
1080 if (!SkScalarNearlyEqual(margin, temp)) {
1081 allEq = false;
1082 }
1083 }
1084
1085 return allEq || allGoE1;
1086}
1087
robertphillips2e1e51f2015-10-15 08:01:48 -07001088void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -07001089 const GrPaint& paint,
1090 const SkMatrix& viewMatrix,
1091 const SkPath& path,
bsalomon6663acf2016-05-10 09:14:17 -07001092 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001093 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001094 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001095 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001096 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001097
robertphillipsea461502015-05-26 11:38:03 -07001098 if (path.isEmpty()) {
1099 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -07001100 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001101 }
1102 return;
1103 }
1104
robertphillips77a2e522015-10-17 07:43:27 -07001105 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -07001106
csmartdaltonecbc12b2016-06-08 10:08:43 -07001107 bool useHWAA;
1108 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA) && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001109 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001110 // Concave AA paths are expensive - try to avoid them for special cases
1111 SkRect rects[2];
1112
bsalomon6663acf2016-05-10 09:14:17 -07001113 if (fills_as_nested_rects(viewMatrix, path, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -07001114 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
robertphillips4bc31812016-03-01 12:22:49 -08001115 paint.getColor(), viewMatrix, rects));
bsalomon40ef4852016-05-02 13:22:13 -07001116 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001117 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001118 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
bsalomon40ef4852016-05-02 13:22:13 -07001119 }
robertphillipsea461502015-05-26 11:38:03 -07001120 return;
1121 }
1122 }
1123 SkRect ovalRect;
1124 bool isOval = path.isOval(&ovalRect);
1125
1126 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -08001127 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -08001128 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillips0cc2f852016-02-24 13:36:56 -08001129 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -08001130 ovalRect,
bsalomon6663acf2016-05-10 09:14:17 -07001131 style.strokeRec(),
robertphillips0cc2f852016-02-24 13:36:56 -08001132 shaderCaps));
1133 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001134 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001135 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -07001136 return;
1137 }
1138 }
1139 }
robertphillips4bc31812016-03-01 12:22:49 -08001140
1141 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1142 // Scratch textures can be recycled after they are returned to the texture
1143 // cache. This presents a potential hazard for buffered drawing. However,
1144 // the writePixels that uploads to the scratch will perform a flush so we're
1145 // OK.
bsalomon6663acf2016-05-10 09:14:17 -07001146 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001147}
1148
cdalton846c0512016-05-13 10:25:00 -07001149bool GrDrawContextPriv::drawAndStencilPath(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -07001150 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -08001151 SkRegion::Op op,
1152 bool invert,
1153 bool doAA,
1154 const SkMatrix& viewMatrix,
1155 const SkPath& path) {
1156 ASSERT_SINGLE_OWNER_PRIV
1157 RETURN_FALSE_IF_ABANDONED_PRIV
1158 SkDEBUGCODE(fDrawContext->validate();)
1159 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath");
1160
1161 if (path.isEmpty() && path.isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -07001162 this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
robertphillips6c7e3252016-04-27 10:47:51 -07001163 SkRect::MakeIWH(fDrawContext->width(),
1164 fDrawContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001165 return true;
1166 }
1167
1168 AutoCheckFlush acf(fDrawContext->fDrawingManager);
1169
1170 // An Assumption here is that path renderer would use some form of tweaking
1171 // the src color (either the input alpha or in the frag shader) to implement
1172 // aa. If we have some future driver-mojo path AA that can do the right
1173 // thing WRT to the blend then we'll need some query on the PR.
1174 bool useCoverageAA = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled();
robertphillips976f5f02016-06-03 10:59:20 -07001175 bool hasUserStencilSettings = !ss->isUnused();
robertphillips391395d2016-03-02 09:26:36 -08001176 bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled();
1177
1178 const GrPathRendererChain::DrawType type =
1179 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1180 : GrPathRendererChain::kColor_DrawType;
1181
bsalomon8acedde2016-06-24 10:42:16 -07001182 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001183 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1184 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
1185 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001186 canDrawArgs.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001187 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001188 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001189 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1190
1191 // Don't allow the SW renderer
1192 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1193 if (!pr) {
1194 return false;
1195 }
1196
1197 GrPaint paint;
1198 paint.setCoverageSetOpXPFactory(op, invert);
1199
robertphillips391395d2016-03-02 09:26:36 -08001200 GrPathRenderer::DrawPathArgs args;
robertphillips391395d2016-03-02 09:26:36 -08001201 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001202 args.fPaint = &paint;
1203 args.fUserStencilSettings = ss;
1204 args.fDrawContext = fDrawContext;
cdalton862cff32016-05-12 15:09:48 -07001205 args.fClip = &clip;
robertphillips391395d2016-03-02 09:26:36 -08001206 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001207 args.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001208 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001209 args.fGammaCorrect = fDrawContext->isGammaCorrect();
robertphillips391395d2016-03-02 09:26:36 -08001210 pr->drawPath(args);
1211 return true;
1212}
1213
robertphillips714712b2016-08-04 06:20:45 -07001214SkBudgeted GrDrawContextPriv::isBudgeted() const {
1215 ASSERT_SINGLE_OWNER_PRIV
1216
1217 if (fDrawContext->wasAbandoned()) {
1218 return SkBudgeted::kNo;
1219 }
1220
1221 SkDEBUGCODE(fDrawContext->validate();)
1222
1223 return fDrawContext->fRenderTarget->resourcePriv().isBudgeted();
1224}
1225
robertphillips4bc31812016-03-01 12:22:49 -08001226void GrDrawContext::internalDrawPath(const GrClip& clip,
1227 const GrPaint& paint,
robertphillipsea461502015-05-26 11:38:03 -07001228 const SkMatrix& viewMatrix,
bsalomon8acedde2016-06-24 10:42:16 -07001229 const SkPath& path,
1230 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001231 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001232 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001233 SkASSERT(!path.isEmpty());
robertphillipsea461502015-05-26 11:38:03 -07001234
robertphillips6c7e3252016-04-27 10:47:51 -07001235 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
cdalton93a379b2016-05-11 13:58:08 -07001236 constexpr bool kHasUserStencilSettings = false;
robertphillips4bc31812016-03-01 12:22:49 -08001237 bool isStencilBufferMSAA = fRenderTarget->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -07001238
robertphillips68737822015-10-29 12:12:21 -07001239 const GrPathRendererChain::DrawType type =
1240 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1241 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -07001242
bsalomon8acedde2016-06-24 10:42:16 -07001243 GrShape shape(path, style);
bsalomon0a0f67e2016-06-28 11:56:42 -07001244 if (shape.isEmpty()) {
1245 return;
1246 }
robertphillips68737822015-10-29 12:12:21 -07001247 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1248 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1249 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001250 canDrawArgs.fShape = &shape;
robertphillips68737822015-10-29 12:12:21 -07001251 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001252 canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
robertphillips68737822015-10-29 12:12:21 -07001253 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1254
bsalomon6663acf2016-05-10 09:14:17 -07001255 // Try a 1st time without applying any of the style to the geometry (and barring sw)
robertphillips68737822015-10-29 12:12:21 -07001256 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
bsalomon6663acf2016-05-10 09:14:17 -07001257 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001258
bsalomon8acedde2016-06-24 10:42:16 -07001259 if (!pr && shape.style().pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001260 // It didn't work above, so try again with the path effect applied.
bsalomon8acedde2016-06-24 10:42:16 -07001261 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1262 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001263 return;
1264 }
robertphillips68737822015-10-29 12:12:21 -07001265 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -07001266 }
bsalomon6663acf2016-05-10 09:14:17 -07001267 if (!pr) {
bsalomon8acedde2016-06-24 10:42:16 -07001268 if (shape.style().applies()) {
1269 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1270 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001271 return;
1272 }
bsalomon6663acf2016-05-10 09:14:17 -07001273 }
robertphillipsea461502015-05-26 11:38:03 -07001274 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -07001275 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -07001276 }
1277
bsalomon8acedde2016-06-24 10:42:16 -07001278 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001279#ifdef SK_DEBUG
1280 SkDebugf("Unable to find path renderer compatible with path.\n");
1281#endif
1282 return;
1283 }
1284
bsalomon0aff2fa2015-07-31 06:48:27 -07001285 GrPathRenderer::DrawPathArgs args;
robertphillips77a2e522015-10-17 07:43:27 -07001286 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001287 args.fPaint = &paint;
1288 args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
1289 args.fDrawContext = this;
cdalton862cff32016-05-12 15:09:48 -07001290 args.fClip = &clip;
bsalomon0aff2fa2015-07-31 06:48:27 -07001291 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001292 args.fShape = canDrawArgs.fShape;
bsalomon0aff2fa2015-07-31 06:48:27 -07001293 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001294 args.fGammaCorrect = this->isGammaCorrect();
bsalomon0aff2fa2015-07-31 06:48:27 -07001295 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001296}
1297
bsalomonbb243832016-07-22 07:10:19 -07001298void GrDrawContext::drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
1299 GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -08001300 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001301 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001302 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001303 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -07001304
robertphillips976f5f02016-06-03 10:59:20 -07001305 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillips2334fb62015-06-17 05:43:33 -07001306}