blob: b5c28190f2daa1b352bb6d0318db84cdba4db45f [file] [log] [blame]
robertphillipsea461502015-05-26 11:38:03 -07001
2/*
3 * Copyright 2015 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
robertphillipsea461502015-05-26 11:38:03 -07009#include "GrBatchTest.h"
jvanverth31ff7622015-08-07 10:09:28 -070010#include "GrColor.h"
robertphillipsea461502015-05-26 11:38:03 -070011#include "GrDrawContext.h"
robertphillips77a2e522015-10-17 07:43:27 -070012#include "GrDrawingManager.h"
robertphillipsea461502015-05-26 11:38:03 -070013#include "GrOvalRenderer.h"
14#include "GrPathRenderer.h"
robertphillips2334fb62015-06-17 05:43:33 -070015#include "GrRenderTarget.h"
16#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070017#include "GrResourceProvider.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070018#include "SkSurfacePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070019
joshualitt74417822015-08-07 11:42:16 -070020#include "batches/GrBatch.h"
jvanverth14b88032015-08-07 12:18:54 -070021#include "batches/GrDrawAtlasBatch.h"
joshualitt2771b562015-08-07 12:46:26 -070022#include "batches/GrDrawVerticesBatch.h"
joshualitt7fc2a262015-08-10 10:30:14 -070023#include "batches/GrRectBatchFactory.h"
joshualitt33a5fce2015-11-18 13:28:51 -080024#include "batches/GrNinePatch.h" // TODO Factory
joshualitt74417822015-08-07 11:42:16 -070025
joshualitte8042922015-12-11 06:11:21 -080026#include "text/GrAtlasTextContext.h"
27#include "text/GrStencilAndCoverTextContext.h"
28
joshualittbc907352016-01-13 06:45:40 -080029#include "../private/GrAuditTrail.h"
30
robertphillips77a2e522015-10-17 07:43:27 -070031#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080032#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080033 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips77a2e522015-10-17 07:43:27 -070034#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
35#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; }
36#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070037
38class AutoCheckFlush {
39public:
robertphillips77a2e522015-10-17 07:43:27 -070040 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
41 SkASSERT(fDrawingManager);
42 }
43 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070044
45private:
robertphillips77a2e522015-10-17 07:43:27 -070046 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070047};
48
robertphillipsa106c622015-10-16 09:07:06 -070049// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
50// drawTargets to be picked up and added to by drawContexts lower in the call
51// stack. When this occurs with a closed drawTarget, a new one will be allocated
52// when the drawContext attempts to use it (via getDrawTarget).
joshualitt1b39f432016-02-11 06:46:52 -080053GrDrawContext::GrDrawContext(GrContext* context,
54 GrDrawingManager* drawingMgr,
robertphillips2e1e51f2015-10-15 08:01:48 -070055 GrRenderTarget* rt,
joshualittde8dc7e2016-01-08 10:09:13 -080056 const SkSurfaceProps* surfaceProps,
joshualittbc907352016-01-13 06:45:40 -080057 GrAuditTrail* auditTrail,
joshualittde8dc7e2016-01-08 10:09:13 -080058 GrSingleOwner* singleOwner)
robertphillips77a2e522015-10-17 07:43:27 -070059 : fDrawingManager(drawingMgr)
robertphillips2e1e51f2015-10-15 08:01:48 -070060 , fRenderTarget(rt)
robertphillipsa106c622015-10-16 09:07:06 -070061 , fDrawTarget(SkSafeRef(rt->getLastDrawTarget()))
joshualitt1b39f432016-02-11 06:46:52 -080062 , fContext(context)
joshualittde8dc7e2016-01-08 10:09:13 -080063 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080064 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080065#ifdef SK_DEBUG
66 , fSingleOwner(singleOwner)
67#endif
68{
robertphillips2e1e51f2015-10-15 08:01:48 -070069 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070070}
71
robertphillips2e1e51f2015-10-15 08:01:48 -070072#ifdef SK_DEBUG
73void GrDrawContext::validate() const {
74 SkASSERT(fRenderTarget);
75 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070076
77 if (fDrawTarget && !fDrawTarget->isClosed()) {
78 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
79 }
robertphillips2e1e51f2015-10-15 08:01:48 -070080}
81#endif
82
robertphillipsa106c622015-10-16 09:07:06 -070083GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -080084 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070085 SkSafeUnref(fDrawTarget);
86}
87
88GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -080089 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070090 SkDEBUGCODE(this->validate();)
91
92 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips77a2e522015-10-17 07:43:27 -070093 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070094 }
95
96 return fDrawTarget;
97}
98
bsalomonb8fea972016-02-16 07:34:17 -080099bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800100 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800101 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700102 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800103 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700104
bsalomonb8fea972016-02-16 07:34:17 -0800105 return this->getDrawTarget()->copySurface(fRenderTarget, src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700106}
107
robertphillips2e1e51f2015-10-15 08:01:48 -0700108void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700109 const SkPaint& skPaint,
110 const SkMatrix& viewMatrix,
111 const char text[], size_t byteLength,
112 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800113 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700114 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700115 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800116 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700117
joshualitt96880d92016-02-16 10:36:53 -0800118 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800119 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700120 }
121
joshualitt96880d92016-02-16 10:36:53 -0800122 fAtlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
123 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700124}
robertphillipscaef3452015-11-11 13:18:11 -0800125
robertphillips2e1e51f2015-10-15 08:01:48 -0700126void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700127 const SkPaint& skPaint,
128 const SkMatrix& viewMatrix,
129 const char text[], size_t byteLength,
130 const SkScalar pos[], int scalarsPerPosition,
131 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800132 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700133 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700134 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800135 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700136
joshualitt96880d92016-02-16 10:36:53 -0800137 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800138 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700139 }
140
joshualitt96880d92016-02-16 10:36:53 -0800141 fAtlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
142 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
143 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700144
145}
robertphillipscaef3452015-11-11 13:18:11 -0800146
robertphillips2e1e51f2015-10-15 08:01:48 -0700147void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700148 const SkMatrix& viewMatrix, const SkTextBlob* blob,
149 SkScalar x, SkScalar y,
150 SkDrawFilter* filter, 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::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700155
joshualitt96880d92016-02-16 10:36:53 -0800156 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800157 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700158 }
159
joshualitt96880d92016-02-16 10:36:53 -0800160 fAtlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
161 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700162}
163
robertphillips2e1e51f2015-10-15 08:01:48 -0700164void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800165 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -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::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700169
robertphillips77a2e522015-10-17 07:43:27 -0700170 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700171 this->getDrawTarget()->discard(fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700172}
173
robertphillips2e1e51f2015-10-15 08:01:48 -0700174void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700175 const GrColor color,
176 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800177 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700178 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700179 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800180 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700181
robertphillips77a2e522015-10-17 07:43:27 -0700182 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700183 this->getDrawTarget()->clear(rect, color, canIgnoreRect, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700184}
185
186
robertphillips2e1e51f2015-10-15 08:01:48 -0700187void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700188 const GrPaint& origPaint,
189 const SkMatrix& viewMatrix) {
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::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700194
robertphillipsea461502015-05-26 11:38:03 -0700195 // set rect to be big enough to fill the space, but not super-huge, so we
196 // don't overflow fixed-point implementations
197 SkRect r;
198 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700199 SkIntToScalar(fRenderTarget->width()),
200 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700201 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
202
203 // by definition this fills the entire clip, no need for AA
204 if (paint->isAntiAlias()) {
205 paint.writable()->setAntiAlias(false);
206 }
207
208 bool isPerspective = viewMatrix.hasPerspective();
209
210 // We attempt to map r by the inverse matrix and draw that. mapRect will
211 // map the four corners and bound them with a new rect. This will not
212 // produce a correct result for some perspective matrices.
213 if (!isPerspective) {
214 SkMatrix inverse;
215 if (!viewMatrix.invert(&inverse)) {
216 SkDebugf("Could not invert matrix\n");
217 return;
218 }
219 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700220 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700221 } else {
222 SkMatrix localMatrix;
223 if (!viewMatrix.invert(&localMatrix)) {
224 SkDebugf("Could not invert matrix\n");
225 return;
226 }
227
robertphillips77a2e522015-10-17 07:43:27 -0700228 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700229
ethannicholasd2c77912016-02-25 13:43:16 -0800230 GrPipelineBuilder pipelineBuilder(*paint, fRenderTarget, clip);
joshualitt04194f32016-01-13 10:08:27 -0800231 SkAutoTUnref<GrDrawBatch> batch(
232 GrRectBatchFactory::CreateNonAAFill(paint->getColor(), SkMatrix::I(), r, nullptr,
233 &localMatrix));
234 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700235 }
236}
237
robertphillipsea461502015-05-26 11:38:03 -0700238static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
239 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
240 point.fY >= rect.fTop && point.fY <= rect.fBottom;
241}
242
bsalomonc55271f2015-11-09 11:55:57 -0800243static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
244 return viewMatrix.preservesRightAngles();
245}
246
247static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) {
248 return paint.isAntiAlias() && !rt->isUnifiedMultisampled();
249}
250
robertphillips2e1e51f2015-10-15 08:01:48 -0700251void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700252 const GrPaint& paint,
253 const SkMatrix& viewMatrix,
254 const SkRect& rect,
255 const GrStrokeInfo* strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800256 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700257 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700258 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800259 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700260
robertphillipsff55b492015-11-24 07:56:59 -0800261 // Dashing should've been devolved to a path in SkGpuDevice
262 SkASSERT(!strokeInfo || !strokeInfo->isDashed());
robertphillipsea461502015-05-26 11:38:03 -0700263
robertphillips77a2e522015-10-17 07:43:27 -0700264 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700265
ethannicholasd2c77912016-02-25 13:43:16 -0800266 SkScalar width = nullptr == strokeInfo ? -1 : strokeInfo->getWidth();
robertphillipsea461502015-05-26 11:38:03 -0700267
268 // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
269 // cases where the RT is fully inside a stroke.
270 if (width < 0) {
271 SkRect rtRect;
robertphillips954cbc12015-12-02 10:33:46 -0800272 fRenderTarget->getBoundsRect(&rtRect);
robertphillipsea461502015-05-26 11:38:03 -0700273 SkRect clipSpaceRTRect = rtRect;
274 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
275 if (checkClip) {
276 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
277 SkIntToScalar(clip.origin().fY));
278 }
279 // Does the clip contain the entire RT?
280 if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
281 SkMatrix invM;
282 if (!viewMatrix.invert(&invM)) {
283 return;
284 }
285 // Does the rect bound the RT?
286 SkPoint srcSpaceRTQuad[4];
287 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
288 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
289 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
290 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
291 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
292 // Will it blend?
293 GrColor clearColor;
cdalton1fa45722015-06-02 10:43:39 -0700294 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillipsa106c622015-10-16 09:07:06 -0700295 this->getDrawTarget()->clear(nullptr, clearColor, true, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700296 return;
297 }
298 }
299 }
300 }
301
ethannicholasd2c77912016-02-25 13:43:16 -0800302 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
303 GrColor color = paint.getColor();
304
joshualitt04194f32016-01-13 10:08:27 -0800305 SkAutoTUnref<GrDrawBatch> batch;
cdaltonbb539482016-01-04 09:48:25 -0800306 if (should_apply_coverage_aa(paint, fRenderTarget)) {
robertphillipsea461502015-05-26 11:38:03 -0700307 if (width >= 0) {
cdaltonbb539482016-01-04 09:48:25 -0800308 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
309 if (viewMatrix.rectStaysRect()) {
ethannicholasd2c77912016-02-25 13:43:16 -0800310 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect,
cdaltonbb539482016-01-04 09:48:25 -0800311 *strokeInfo));
312 }
robertphillipsea461502015-05-26 11:38:03 -0700313 } else {
cdaltonbb539482016-01-04 09:48:25 -0800314 // The fill path can handle rotation but not skew.
315 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
316 SkRect devBoundRect;
317 viewMatrix.mapRect(&devBoundRect, rect);
ethannicholasd2c77912016-02-25 13:43:16 -0800318 batch.reset(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect,
cdaltonbb539482016-01-04 09:48:25 -0800319 devBoundRect));
320 }
robertphillipsea461502015-05-26 11:38:03 -0700321 }
ethannicholasd2c77912016-02-25 13:43:16 -0800322 if (!batch) {
323 SkPath path;
324 path.setIsVolatile(true);
325 path.addRect(rect);
326 this->internalDrawPath(&pipelineBuilder, viewMatrix, color, true, path, *strokeInfo);
327 SkASSERT(paint.isAntiAlias());
328 return;
329 }
joshualitt04194f32016-01-13 10:08:27 -0800330 } else if (width >= 0) {
robertphillipsea461502015-05-26 11:38:03 -0700331 // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
ethannicholasd2c77912016-02-25 13:43:16 -0800332 bool snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled());
333 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, width,
334 snapToPixelCenters));
robertphillipsea461502015-05-26 11:38:03 -0700335
336 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
ethannicholasd2c77912016-02-25 13:43:16 -0800337 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA
338 // is enabled because it can cause ugly artifacts.
339 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
340 snapToPixelCenters);
robertphillipsea461502015-05-26 11:38:03 -0700341 } else {
342 // filled BW rect
ethannicholasd2c77912016-02-25 13:43:16 -0800343 batch.reset(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect, nullptr, nullptr));
robertphillipsea461502015-05-26 11:38:03 -0700344 }
ethannicholasd2c77912016-02-25 13:43:16 -0800345 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700346}
347
bsalomona2e69fc2015-11-05 10:41:43 -0800348void GrDrawContext::fillRectToRect(const GrClip& clip,
349 const GrPaint& paint,
350 const SkMatrix& viewMatrix,
351 const SkRect& rectToDraw,
352 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800353 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700354 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700355 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800356 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700357
robertphillips77a2e522015-10-17 07:43:27 -0700358 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700359
ethannicholasd2c77912016-02-25 13:43:16 -0800360 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt04194f32016-01-13 10:08:27 -0800361 SkAutoTUnref<GrDrawBatch> batch;
bsalomonc55271f2015-11-09 11:55:57 -0800362 if (should_apply_coverage_aa(paint, fRenderTarget) &&
363 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800364 batch.reset(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(), viewMatrix, rectToDraw,
365 localRect));
bsalomonc55271f2015-11-09 11:55:57 -0800366 } else {
joshualitt04194f32016-01-13 10:08:27 -0800367 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
368 &localRect, nullptr));
369 }
370
371 if (batch) {
372 this->drawBatch(&pipelineBuilder, batch);
bsalomonc55271f2015-11-09 11:55:57 -0800373 }
joshualittb6b513b2015-08-21 10:25:18 -0700374}
375
bsalomona2e69fc2015-11-05 10:41:43 -0800376void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
377 const GrPaint& paint,
378 const SkMatrix& viewMatrix,
379 const SkRect& rectToDraw,
380 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800381 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700382 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700383 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800384 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700385
robertphillips77a2e522015-10-17 07:43:27 -0700386 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700387
ethannicholasd2c77912016-02-25 13:43:16 -0800388 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
389
joshualitt04194f32016-01-13 10:08:27 -0800390 SkAutoTUnref<GrDrawBatch> batch;
robertphillips954cbc12015-12-02 10:33:46 -0800391 if (should_apply_coverage_aa(paint, fRenderTarget) &&
bsalomonc55271f2015-11-09 11:55:57 -0800392 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800393 batch.reset(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix, localMatrix,
394 rectToDraw));
bsalomonc55271f2015-11-09 11:55:57 -0800395 } else {
joshualitt04194f32016-01-13 10:08:27 -0800396 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
397 nullptr, &localMatrix));
bsalomonc55271f2015-11-09 11:55:57 -0800398 }
joshualitt04194f32016-01-13 10:08:27 -0800399 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700400}
401
robertphillips2e1e51f2015-10-15 08:01:48 -0700402void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700403 const GrPaint& paint,
404 const SkMatrix& viewMatrix,
405 GrPrimitiveType primitiveType,
406 int vertexCount,
407 const SkPoint positions[],
408 const SkPoint texCoords[],
409 const GrColor colors[],
410 const uint16_t indices[],
411 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800412 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700413 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700414 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800415 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700416
robertphillips77a2e522015-10-17 07:43:27 -0700417 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700418
ethannicholasd2c77912016-02-25 13:43:16 -0800419 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
420
robertphillipsea461502015-05-26 11:38:03 -0700421 // TODO clients should give us bounds
422 SkRect bounds;
423 if (!bounds.setBoundsCheck(positions, vertexCount)) {
424 SkDebugf("drawVertices call empty bounds\n");
425 return;
426 }
427
428 viewMatrix.mapRect(&bounds);
429
430 // 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 -0800431 // snapping. We also do this for the "hair" primitive types: lines and points since they have
432 // a 1 pixel thickness in device space.
433 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
434 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700435 bounds.outset(0.5f, 0.5f);
436 }
437
joshualitt2771b562015-08-07 12:46:26 -0700438 GrDrawVerticesBatch::Geometry geometry;
robertphillipsea461502015-05-26 11:38:03 -0700439 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700440 SkAutoTUnref<GrDrawBatch> batch(GrDrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
441 positions, vertexCount, indices,
442 indexCount, colors, texCoords,
443 bounds));
robertphillipsea461502015-05-26 11:38:03 -0700444
robertphillipsa106c622015-10-16 09:07:06 -0700445 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700446}
447
448///////////////////////////////////////////////////////////////////////////////
449
robertphillips2e1e51f2015-10-15 08:01:48 -0700450void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700451 const GrPaint& paint,
452 const SkMatrix& viewMatrix,
453 int spriteCount,
454 const SkRSXform xform[],
455 const SkRect texRect[],
456 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800457 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700458 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700459 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800460 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700461
robertphillips77a2e522015-10-17 07:43:27 -0700462 AutoCheckFlush acf(fDrawingManager);
ethannicholasd2c77912016-02-25 13:43:16 -0800463
464 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
465
jvanverth14b88032015-08-07 12:18:54 -0700466 GrDrawAtlasBatch::Geometry geometry;
jvanverth31ff7622015-08-07 10:09:28 -0700467 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700468 SkAutoTUnref<GrDrawBatch> batch(GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount,
469 xform, texRect, colors));
jvanverth31ff7622015-08-07 10:09:28 -0700470
robertphillipsa106c622015-10-16 09:07:06 -0700471 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700472}
473
474///////////////////////////////////////////////////////////////////////////////
475
robertphillips2e1e51f2015-10-15 08:01:48 -0700476void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700477 const GrPaint& paint,
478 const SkMatrix& viewMatrix,
479 const SkRRect& rrect,
480 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800481 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700482 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700483 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800484 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700485
robertphillipsea461502015-05-26 11:38:03 -0700486 if (rrect.isEmpty()) {
487 return;
488 }
489
robertphillips514450c2015-11-24 05:36:02 -0800490 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700491
robertphillips77a2e522015-10-17 07:43:27 -0700492 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700493
ethannicholasd2c77912016-02-25 13:43:16 -0800494 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
495 GrColor color = paint.getColor();
496
robertphillipsb56f9272016-02-25 11:03:52 -0800497 if (should_apply_coverage_aa(paint, fRenderTarget)) {
498 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
499
ethannicholasd2c77912016-02-25 13:43:16 -0800500 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(color,
robertphillipsb56f9272016-02-25 11:03:52 -0800501 viewMatrix,
502 rrect,
503 strokeInfo,
504 shaderCaps));
505 if (batch) {
506 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
507 return;
508 }
robertphillipsea461502015-05-26 11:38:03 -0700509 }
robertphillipsb56f9272016-02-25 11:03:52 -0800510
511 SkPath path;
512 path.setIsVolatile(true);
513 path.addRRect(rrect);
ethannicholasd2c77912016-02-25 13:43:16 -0800514 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
515 paint.isAntiAlias(), path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700516}
517
518///////////////////////////////////////////////////////////////////////////////
519
robertphillips2e1e51f2015-10-15 08:01:48 -0700520void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700521 const GrPaint& paint,
522 const SkMatrix& viewMatrix,
523 const SkRect& oval,
524 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800525 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700526 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700527 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800528 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -0700529
robertphillipsea461502015-05-26 11:38:03 -0700530 if (oval.isEmpty()) {
531 return;
532 }
533
robertphillips514450c2015-11-24 05:36:02 -0800534 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700535
robertphillips77a2e522015-10-17 07:43:27 -0700536 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700537
ethannicholasd2c77912016-02-25 13:43:16 -0800538 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
539 GrColor color = paint.getColor();
540
robertphillipsb56f9272016-02-25 11:03:52 -0800541 if (should_apply_coverage_aa(paint, fRenderTarget)) {
542 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
ethannicholasd2c77912016-02-25 13:43:16 -0800543 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(color,
robertphillipsb56f9272016-02-25 11:03:52 -0800544 viewMatrix,
545 oval,
546 strokeInfo,
547 shaderCaps));
548 if (batch) {
549 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
550 return;
551 }
robertphillipsea461502015-05-26 11:38:03 -0700552 }
robertphillipsb56f9272016-02-25 11:03:52 -0800553
554 SkPath path;
555 path.setIsVolatile(true);
556 path.addOval(oval);
ethannicholasd2c77912016-02-25 13:43:16 -0800557 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
558 paint.isAntiAlias(), path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700559}
560
joshualitt33a5fce2015-11-18 13:28:51 -0800561void GrDrawContext::drawImageNine(const GrClip& clip,
562 const GrPaint& paint,
563 const SkMatrix& viewMatrix,
564 int imageWidth,
565 int imageHeight,
566 const SkIRect& center,
567 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -0800568 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -0800569 RETURN_IF_ABANDONED
570 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800571 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageNine");
joshualitt33a5fce2015-11-18 13:28:51 -0800572
573 AutoCheckFlush acf(fDrawingManager);
574
575 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
576 imageWidth, imageHeight,
577 center, dst));
578
579 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
580 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
581}
582
583
robertphillipsea461502015-05-26 11:38:03 -0700584// Can 'path' be drawn as a pair of filled nested rectangles?
joshualittf9c5db22015-07-10 11:31:01 -0700585static bool is_nested_rects(const SkMatrix& viewMatrix,
robertphillipsea461502015-05-26 11:38:03 -0700586 const SkPath& path,
587 const SkStrokeRec& stroke,
588 SkRect rects[2]) {
589 SkASSERT(stroke.isFillStyle());
590
591 if (path.isInverseFillType()) {
592 return false;
593 }
594
595 // TODO: this restriction could be lifted if we were willing to apply
596 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -0800597 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -0700598 return false;
599 }
600
601 SkPath::Direction dirs[2];
602 if (!path.isNestedFillRects(rects, dirs)) {
603 return false;
604 }
605
606 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
607 // The two rects need to be wound opposite to each other
608 return false;
609 }
610
611 // Right now, nested rects where the margin is not the same width
612 // all around do not render correctly
613 const SkScalar* outer = rects[0].asScalars();
614 const SkScalar* inner = rects[1].asScalars();
615
616 bool allEq = true;
617
618 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
619 bool allGoE1 = margin >= SK_Scalar1;
620
621 for (int i = 1; i < 4; ++i) {
622 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
623 if (temp < SK_Scalar1) {
624 allGoE1 = false;
625 }
626 if (!SkScalarNearlyEqual(margin, temp)) {
627 allEq = false;
628 }
629 }
630
631 return allEq || allGoE1;
632}
633
robertphillips2e1e51f2015-10-15 08:01:48 -0700634void GrDrawContext::drawBatch(const GrClip& clip,
bsalomonabd30f52015-08-13 13:34:48 -0700635 const GrPaint& paint, GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800636 ASSERT_SINGLE_OWNER
joshualittb7ee1bf2015-08-10 11:59:02 -0700637 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700638 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800639 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
joshualittb7ee1bf2015-08-10 11:59:02 -0700640
robertphillips77a2e522015-10-17 07:43:27 -0700641 AutoCheckFlush acf(fDrawingManager);
joshualittb7ee1bf2015-08-10 11:59:02 -0700642
robertphillips2e1e51f2015-10-15 08:01:48 -0700643 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700644 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
joshualittb7ee1bf2015-08-10 11:59:02 -0700645}
646
cdalton8ff8d242015-12-08 10:20:32 -0800647void GrDrawContext::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
648 GrDrawPathBatchBase* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800649 ASSERT_SINGLE_OWNER
cdalton8ff8d242015-12-08 10:20:32 -0800650 RETURN_IF_ABANDONED
651 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800652 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPathBatch");
cdalton8ff8d242015-12-08 10:20:32 -0800653
654 AutoCheckFlush acf(fDrawingManager);
655
656 this->getDrawTarget()->drawPathBatch(pipelineBuilder, batch);
657}
658
robertphillips2e1e51f2015-10-15 08:01:48 -0700659void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700660 const GrPaint& paint,
661 const SkMatrix& viewMatrix,
662 const SkPath& path,
663 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800664 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700665 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700666 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800667 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -0700668
robertphillipsea461502015-05-26 11:38:03 -0700669 if (path.isEmpty()) {
670 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700671 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700672 }
673 return;
674 }
675
ethannicholasd2c77912016-02-25 13:43:16 -0800676 GrColor color = paint.getColor();
677
678 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
679 // Scratch textures can be recycled after they are returned to the texture
680 // cache. This presents a potential hazard for buffered drawing. However,
681 // the writePixels that uploads to the scratch will perform a flush so we're
682 // OK.
robertphillips77a2e522015-10-17 07:43:27 -0700683 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700684
ethannicholasd2c77912016-02-25 13:43:16 -0800685 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsb56f9272016-02-25 11:03:52 -0800686 if (should_apply_coverage_aa(paint, fRenderTarget) && !strokeInfo.isDashed()) {
687 if (strokeInfo.getWidth() < 0 && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -0700688 // Concave AA paths are expensive - try to avoid them for special cases
689 SkRect rects[2];
690
joshualittf9c5db22015-07-10 11:31:01 -0700691 if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -0700692 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
ethannicholasd2c77912016-02-25 13:43:16 -0800693 color, viewMatrix, rects));
robertphillipsa106c622015-10-16 09:07:06 -0700694 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700695 return;
696 }
697 }
698 SkRect ovalRect;
699 bool isOval = path.isOval(&ovalRect);
700
701 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -0800702 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
ethannicholasd2c77912016-02-25 13:43:16 -0800703 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(color,
robertphillips0cc2f852016-02-24 13:36:56 -0800704 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -0800705 ovalRect,
706 strokeInfo,
707 shaderCaps));
708 if (batch) {
709 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700710 return;
711 }
712 }
713 }
ethannicholasd2c77912016-02-25 13:43:16 -0800714 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
715 paint.isAntiAlias(), path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700716}
717
ethannicholasd2c77912016-02-25 13:43:16 -0800718void GrDrawContext::internalDrawPath(GrPipelineBuilder* pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700719 const SkMatrix& viewMatrix,
ethannicholasd2c77912016-02-25 13:43:16 -0800720 GrColor color,
721 bool useAA,
robertphillipsea461502015-05-26 11:38:03 -0700722 const SkPath& path,
723 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800724 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700725 RETURN_IF_ABANDONED
726 SkASSERT(!path.isEmpty());
727
robertphillipsea461502015-05-26 11:38:03 -0700728 // An Assumption here is that path renderer would use some form of tweaking
729 // the src color (either the input alpha or in the frag shader) to implement
730 // aa. If we have some future driver-mojo path AA that can do the right
731 // thing WRT to the blend then we'll need some query on the PR.
ethannicholasd2c77912016-02-25 13:43:16 -0800732 bool useCoverageAA = useAA &&
733 !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
734 bool isStencilDisabled = pipelineBuilder->getStencil().isDisabled();
735 bool isStencilBufferMSAA = pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -0700736
robertphillips68737822015-10-29 12:12:21 -0700737 const GrPathRendererChain::DrawType type =
738 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
739 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -0700740
741 const SkPath* pathPtr = &path;
742 SkTLazy<SkPath> tmpPath;
743 const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
744
robertphillips68737822015-10-29 12:12:21 -0700745 GrPathRenderer::CanDrawPathArgs canDrawArgs;
746 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
747 canDrawArgs.fViewMatrix = &viewMatrix;
748 canDrawArgs.fPath = pathPtr;
749 canDrawArgs.fStroke = strokeInfoPtr;
750 canDrawArgs.fAntiAlias = useCoverageAA;
751 canDrawArgs.fIsStencilDisabled = isStencilDisabled;
752 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
753
robertphillipsea461502015-05-26 11:38:03 -0700754 // Try a 1st time without stroking the path and without allowing the SW renderer
robertphillips68737822015-10-29 12:12:21 -0700755 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700756
757 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
halcanary96fcdcc2015-08-27 07:41:13 -0700758 if (nullptr == pr && strokeInfo.isDashed()) {
robertphillipsea461502015-05-26 11:38:03 -0700759 // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
760 if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
761 return;
762 }
763 pathPtr = tmpPath.get();
764 if (pathPtr->isEmpty()) {
765 return;
766 }
767 strokeInfoPtr = &dashlessStrokeInfo;
robertphillips68737822015-10-29 12:12:21 -0700768
769 canDrawArgs.fPath = pathPtr;
770 canDrawArgs.fStroke = strokeInfoPtr;
771
772 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700773 }
774
halcanary96fcdcc2015-08-27 07:41:13 -0700775 if (nullptr == pr) {
776 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, nullptr) &&
robertphillipsea461502015-05-26 11:38:03 -0700777 !strokeInfoPtr->isFillStyle()) {
778 // It didn't work above, so try again with stroke converted to a fill.
779 if (!tmpPath.isValid()) {
780 tmpPath.init();
781 }
782 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
783 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
784 return;
785 }
786 pathPtr = tmpPath.get();
787 if (pathPtr->isEmpty()) {
788 return;
789 }
790 dashlessStrokeInfo.setFillStyle();
791 strokeInfoPtr = &dashlessStrokeInfo;
792 }
793
robertphillips68737822015-10-29 12:12:21 -0700794 canDrawArgs.fPath = pathPtr;
795 canDrawArgs.fStroke = strokeInfoPtr;
796
robertphillipsea461502015-05-26 11:38:03 -0700797 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -0700798 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -0700799 }
800
halcanary96fcdcc2015-08-27 07:41:13 -0700801 if (nullptr == pr) {
robertphillipsea461502015-05-26 11:38:03 -0700802#ifdef SK_DEBUG
803 SkDebugf("Unable to find path renderer compatible with path.\n");
804#endif
805 return;
806 }
807
bsalomon0aff2fa2015-07-31 06:48:27 -0700808 GrPathRenderer::DrawPathArgs args;
robertphillipsb83bec52015-10-23 09:38:03 -0700809 args.fTarget = this->getDrawTarget();
robertphillips77a2e522015-10-17 07:43:27 -0700810 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
ethannicholasd2c77912016-02-25 13:43:16 -0800811 args.fPipelineBuilder = pipelineBuilder;
812 args.fColor = color;
bsalomon0aff2fa2015-07-31 06:48:27 -0700813 args.fViewMatrix = &viewMatrix;
814 args.fPath = pathPtr;
815 args.fStroke = strokeInfoPtr;
816 args.fAntiAlias = useCoverageAA;
817 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -0700818}
819
bsalomonabd30f52015-08-13 13:34:48 -0700820void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800821 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700822 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700823 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800824 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -0700825
robertphillipsa106c622015-10-16 09:07:06 -0700826 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch);
robertphillips2334fb62015-06-17 05:43:33 -0700827}