blob: f31e0b23b090917d5148fb1a8fbaa86876bda30a [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()))
joshualitt96880d92016-02-16 10:36:53 -080062 , fAtlasTextContext(nullptr)
joshualitt1b39f432016-02-11 06:46:52 -080063 , fContext(context)
joshualittde8dc7e2016-01-08 10:09:13 -080064 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080065 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080066#ifdef SK_DEBUG
67 , fSingleOwner(singleOwner)
68#endif
69{
robertphillips2e1e51f2015-10-15 08:01:48 -070070 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070071}
72
robertphillips2e1e51f2015-10-15 08:01:48 -070073#ifdef SK_DEBUG
74void GrDrawContext::validate() const {
75 SkASSERT(fRenderTarget);
76 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070077
78 if (fDrawTarget && !fDrawTarget->isClosed()) {
79 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
80 }
robertphillips2e1e51f2015-10-15 08:01:48 -070081}
82#endif
83
robertphillipsa106c622015-10-16 09:07:06 -070084GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -080085 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070086 SkSafeUnref(fDrawTarget);
87}
88
89GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -080090 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070091 SkDEBUGCODE(this->validate();)
92
93 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips77a2e522015-10-17 07:43:27 -070094 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070095 }
96
97 return fDrawTarget;
98}
99
bsalomonb8fea972016-02-16 07:34:17 -0800100bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800101 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800102 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700103 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800104 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700105
bsalomonb8fea972016-02-16 07:34:17 -0800106 return this->getDrawTarget()->copySurface(fRenderTarget, src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700107}
108
robertphillips2e1e51f2015-10-15 08:01:48 -0700109void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700110 const SkPaint& skPaint,
111 const SkMatrix& viewMatrix,
112 const char text[], size_t byteLength,
113 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800114 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700115 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700116 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800117 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700118
joshualitt96880d92016-02-16 10:36:53 -0800119 if (!fAtlasTextContext) {
120 fAtlasTextContext = GrAtlasTextContext::Create();
robertphillips2334fb62015-06-17 05:43:33 -0700121 }
122
joshualitt96880d92016-02-16 10:36:53 -0800123 fAtlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
124 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700125}
robertphillipscaef3452015-11-11 13:18:11 -0800126
robertphillips2e1e51f2015-10-15 08:01:48 -0700127void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700128 const SkPaint& skPaint,
129 const SkMatrix& viewMatrix,
130 const char text[], size_t byteLength,
131 const SkScalar pos[], int scalarsPerPosition,
132 const SkPoint& offset, 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::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700137
joshualitt96880d92016-02-16 10:36:53 -0800138 if (!fAtlasTextContext) {
139 fAtlasTextContext = GrAtlasTextContext::Create();
robertphillips2334fb62015-06-17 05:43:33 -0700140 }
141
joshualitt96880d92016-02-16 10:36:53 -0800142 fAtlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
143 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
144 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700145
146}
robertphillipscaef3452015-11-11 13:18:11 -0800147
robertphillips2e1e51f2015-10-15 08:01:48 -0700148void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700149 const SkMatrix& viewMatrix, const SkTextBlob* blob,
150 SkScalar x, SkScalar y,
151 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800152 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700153 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700154 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800155 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700156
joshualitt96880d92016-02-16 10:36:53 -0800157 if (!fAtlasTextContext) {
158 fAtlasTextContext = GrAtlasTextContext::Create();
robertphillips2334fb62015-06-17 05:43:33 -0700159 }
160
joshualitt96880d92016-02-16 10:36:53 -0800161 fAtlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
162 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700163}
164
robertphillips2e1e51f2015-10-15 08:01:48 -0700165void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800166 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700167 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700168 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800169 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700170
robertphillips77a2e522015-10-17 07:43:27 -0700171 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700172 this->getDrawTarget()->discard(fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700173}
174
robertphillips2e1e51f2015-10-15 08:01:48 -0700175void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700176 const GrColor color,
177 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800178 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700179 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700180 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800181 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700182
robertphillips77a2e522015-10-17 07:43:27 -0700183 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700184 this->getDrawTarget()->clear(rect, color, canIgnoreRect, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700185}
186
187
robertphillips2e1e51f2015-10-15 08:01:48 -0700188void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700189 const GrPaint& origPaint,
190 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800191 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700192 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700193 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800194 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700195
robertphillipsea461502015-05-26 11:38:03 -0700196 // set rect to be big enough to fill the space, but not super-huge, so we
197 // don't overflow fixed-point implementations
198 SkRect r;
199 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700200 SkIntToScalar(fRenderTarget->width()),
201 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700202 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
203
204 // by definition this fills the entire clip, no need for AA
205 if (paint->isAntiAlias()) {
206 paint.writable()->setAntiAlias(false);
207 }
208
209 bool isPerspective = viewMatrix.hasPerspective();
210
211 // We attempt to map r by the inverse matrix and draw that. mapRect will
212 // map the four corners and bound them with a new rect. This will not
213 // produce a correct result for some perspective matrices.
214 if (!isPerspective) {
215 SkMatrix inverse;
216 if (!viewMatrix.invert(&inverse)) {
217 SkDebugf("Could not invert matrix\n");
218 return;
219 }
220 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700221 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700222 } else {
223 SkMatrix localMatrix;
224 if (!viewMatrix.invert(&localMatrix)) {
225 SkDebugf("Could not invert matrix\n");
226 return;
227 }
228
robertphillips77a2e522015-10-17 07:43:27 -0700229 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700230
robertphillips2e1e51f2015-10-15 08:01:48 -0700231 GrPipelineBuilder pipelineBuilder(*paint, fRenderTarget, clip);
joshualitt04194f32016-01-13 10:08:27 -0800232 SkAutoTUnref<GrDrawBatch> batch(
233 GrRectBatchFactory::CreateNonAAFill(paint->getColor(), SkMatrix::I(), r, nullptr,
234 &localMatrix));
235 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700236 }
237}
238
robertphillipsea461502015-05-26 11:38:03 -0700239static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
240 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
241 point.fY >= rect.fTop && point.fY <= rect.fBottom;
242}
243
bsalomonc55271f2015-11-09 11:55:57 -0800244static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
245 return viewMatrix.preservesRightAngles();
246}
247
248static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) {
249 return paint.isAntiAlias() && !rt->isUnifiedMultisampled();
250}
251
robertphillips2e1e51f2015-10-15 08:01:48 -0700252void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700253 const GrPaint& paint,
254 const SkMatrix& viewMatrix,
255 const SkRect& rect,
256 const GrStrokeInfo* strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800257 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700258 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700259 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800260 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700261
robertphillipsff55b492015-11-24 07:56:59 -0800262 // Dashing should've been devolved to a path in SkGpuDevice
263 SkASSERT(!strokeInfo || !strokeInfo->isDashed());
robertphillipsea461502015-05-26 11:38:03 -0700264
robertphillips77a2e522015-10-17 07:43:27 -0700265 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700266
halcanary96fcdcc2015-08-27 07:41:13 -0700267 SkScalar width = nullptr == strokeInfo ? -1 : strokeInfo->getWidth();
robertphillipsea461502015-05-26 11:38:03 -0700268
269 // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
270 // cases where the RT is fully inside a stroke.
271 if (width < 0) {
272 SkRect rtRect;
robertphillips954cbc12015-12-02 10:33:46 -0800273 fRenderTarget->getBoundsRect(&rtRect);
robertphillipsea461502015-05-26 11:38:03 -0700274 SkRect clipSpaceRTRect = rtRect;
275 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
276 if (checkClip) {
277 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
278 SkIntToScalar(clip.origin().fY));
279 }
280 // Does the clip contain the entire RT?
281 if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
282 SkMatrix invM;
283 if (!viewMatrix.invert(&invM)) {
284 return;
285 }
286 // Does the rect bound the RT?
287 SkPoint srcSpaceRTQuad[4];
288 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
289 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
290 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
291 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
292 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
293 // Will it blend?
294 GrColor clearColor;
cdalton1fa45722015-06-02 10:43:39 -0700295 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillipsa106c622015-10-16 09:07:06 -0700296 this->getDrawTarget()->clear(nullptr, clearColor, true, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700297 return;
298 }
299 }
300 }
301 }
302
robertphillips954cbc12015-12-02 10:33:46 -0800303 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
cdaltonbb539482016-01-04 09:48:25 -0800304 GrColor color = paint.getColor();
robertphillips954cbc12015-12-02 10:33:46 -0800305
joshualitt04194f32016-01-13 10:08:27 -0800306 SkAutoTUnref<GrDrawBatch> batch;
cdaltonbb539482016-01-04 09:48:25 -0800307 if (should_apply_coverage_aa(paint, fRenderTarget)) {
robertphillipsea461502015-05-26 11:38:03 -0700308 if (width >= 0) {
cdaltonbb539482016-01-04 09:48:25 -0800309 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
310 if (viewMatrix.rectStaysRect()) {
311 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect,
312 *strokeInfo));
313 }
robertphillipsea461502015-05-26 11:38:03 -0700314 } else {
cdaltonbb539482016-01-04 09:48:25 -0800315 // The fill path can handle rotation but not skew.
316 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
317 SkRect devBoundRect;
318 viewMatrix.mapRect(&devBoundRect, rect);
319 batch.reset(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect,
320 devBoundRect));
321 }
robertphillipsea461502015-05-26 11:38:03 -0700322 }
joshualitt04194f32016-01-13 10:08:27 -0800323 if (!batch) {
cdaltonbb539482016-01-04 09:48:25 -0800324 SkPath path;
325 path.setIsVolatile(true);
326 path.addRect(rect);
327 this->internalDrawPath(&pipelineBuilder, viewMatrix, color, true, path, *strokeInfo);
328 SkASSERT(paint.isAntiAlias());
joshualitt04194f32016-01-13 10:08:27 -0800329 return;
cdaltonbb539482016-01-04 09:48:25 -0800330 }
joshualitt04194f32016-01-13 10:08:27 -0800331 } else if (width >= 0) {
robertphillipsea461502015-05-26 11:38:03 -0700332 // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
robertphillips2e1e51f2015-10-15 08:01:48 -0700333 bool snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled());
joshualitt04194f32016-01-13 10:08:27 -0800334 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect, width,
335 snapToPixelCenters));
robertphillipsea461502015-05-26 11:38:03 -0700336
337 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
338 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA
339 // is enabled because it can cause ugly artifacts.
340 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
341 snapToPixelCenters);
robertphillipsea461502015-05-26 11:38:03 -0700342 } else {
343 // filled BW rect
joshualitt04194f32016-01-13 10:08:27 -0800344 batch.reset(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect, nullptr, nullptr));
robertphillipsea461502015-05-26 11:38:03 -0700345 }
joshualitt04194f32016-01-13 10:08:27 -0800346 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700347}
348
bsalomona2e69fc2015-11-05 10:41:43 -0800349void GrDrawContext::fillRectToRect(const GrClip& clip,
350 const GrPaint& paint,
351 const SkMatrix& viewMatrix,
352 const SkRect& rectToDraw,
353 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800354 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700355 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700356 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800357 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700358
robertphillips77a2e522015-10-17 07:43:27 -0700359 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700360
361 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt04194f32016-01-13 10:08:27 -0800362 SkAutoTUnref<GrDrawBatch> batch;
bsalomonc55271f2015-11-09 11:55:57 -0800363 if (should_apply_coverage_aa(paint, fRenderTarget) &&
364 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800365 batch.reset(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(), viewMatrix, rectToDraw,
366 localRect));
bsalomonc55271f2015-11-09 11:55:57 -0800367 } else {
joshualitt04194f32016-01-13 10:08:27 -0800368 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
369 &localRect, nullptr));
370 }
371
372 if (batch) {
373 this->drawBatch(&pipelineBuilder, batch);
bsalomonc55271f2015-11-09 11:55:57 -0800374 }
joshualittb6b513b2015-08-21 10:25:18 -0700375}
376
bsalomona2e69fc2015-11-05 10:41:43 -0800377void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
378 const GrPaint& paint,
379 const SkMatrix& viewMatrix,
380 const SkRect& rectToDraw,
381 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800382 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700383 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700384 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800385 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700386
robertphillips77a2e522015-10-17 07:43:27 -0700387 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700388
389 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillips954cbc12015-12-02 10:33:46 -0800390
joshualitt04194f32016-01-13 10:08:27 -0800391 SkAutoTUnref<GrDrawBatch> batch;
robertphillips954cbc12015-12-02 10:33:46 -0800392 if (should_apply_coverage_aa(paint, fRenderTarget) &&
bsalomonc55271f2015-11-09 11:55:57 -0800393 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800394 batch.reset(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix, localMatrix,
395 rectToDraw));
bsalomonc55271f2015-11-09 11:55:57 -0800396 } else {
joshualitt04194f32016-01-13 10:08:27 -0800397 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
398 nullptr, &localMatrix));
bsalomonc55271f2015-11-09 11:55:57 -0800399 }
joshualitt04194f32016-01-13 10:08:27 -0800400 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700401}
402
robertphillips2e1e51f2015-10-15 08:01:48 -0700403void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700404 const GrPaint& paint,
405 const SkMatrix& viewMatrix,
406 GrPrimitiveType primitiveType,
407 int vertexCount,
408 const SkPoint positions[],
409 const SkPoint texCoords[],
410 const GrColor colors[],
411 const uint16_t indices[],
412 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800413 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700414 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700415 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800416 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700417
robertphillips77a2e522015-10-17 07:43:27 -0700418 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700419
420 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt7b670db2015-07-09 13:25:02 -0700421
robertphillipsea461502015-05-26 11:38:03 -0700422 // TODO clients should give us bounds
423 SkRect bounds;
424 if (!bounds.setBoundsCheck(positions, vertexCount)) {
425 SkDebugf("drawVertices call empty bounds\n");
426 return;
427 }
428
429 viewMatrix.mapRect(&bounds);
430
431 // 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 -0800432 // snapping. We also do this for the "hair" primitive types: lines and points since they have
433 // a 1 pixel thickness in device space.
434 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
435 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700436 bounds.outset(0.5f, 0.5f);
437 }
438
joshualitt2771b562015-08-07 12:46:26 -0700439 GrDrawVerticesBatch::Geometry geometry;
robertphillipsea461502015-05-26 11:38:03 -0700440 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700441 SkAutoTUnref<GrDrawBatch> batch(GrDrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
442 positions, vertexCount, indices,
443 indexCount, colors, texCoords,
444 bounds));
robertphillipsea461502015-05-26 11:38:03 -0700445
robertphillipsa106c622015-10-16 09:07:06 -0700446 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700447}
448
449///////////////////////////////////////////////////////////////////////////////
450
robertphillips2e1e51f2015-10-15 08:01:48 -0700451void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700452 const GrPaint& paint,
453 const SkMatrix& viewMatrix,
454 int spriteCount,
455 const SkRSXform xform[],
456 const SkRect texRect[],
457 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800458 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700459 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700460 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800461 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700462
robertphillips77a2e522015-10-17 07:43:27 -0700463 AutoCheckFlush acf(fDrawingManager);
jvanverth31ff7622015-08-07 10:09:28 -0700464
robertphillips2e1e51f2015-10-15 08:01:48 -0700465 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
jvanverth31ff7622015-08-07 10:09:28 -0700466
jvanverth14b88032015-08-07 12:18:54 -0700467 GrDrawAtlasBatch::Geometry geometry;
jvanverth31ff7622015-08-07 10:09:28 -0700468 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700469 SkAutoTUnref<GrDrawBatch> batch(GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount,
470 xform, texRect, colors));
jvanverth31ff7622015-08-07 10:09:28 -0700471
robertphillipsa106c622015-10-16 09:07:06 -0700472 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700473}
474
475///////////////////////////////////////////////////////////////////////////////
476
robertphillips2e1e51f2015-10-15 08:01:48 -0700477void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700478 const GrPaint& paint,
479 const SkMatrix& viewMatrix,
480 const SkRRect& rrect,
481 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800482 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700483 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700484 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800485 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700486
robertphillipsea461502015-05-26 11:38:03 -0700487 if (rrect.isEmpty()) {
488 return;
489 }
490
robertphillips514450c2015-11-24 05:36:02 -0800491 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700492
robertphillips77a2e522015-10-17 07:43:27 -0700493 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700494
robertphillips2e1e51f2015-10-15 08:01:48 -0700495 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700496 GrColor color = paint.getColor();
robertphillips2e1e51f2015-10-15 08:01:48 -0700497
robertphillipsa106c622015-10-16 09:07:06 -0700498 if (!GrOvalRenderer::DrawRRect(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700499 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700500 color,
501 viewMatrix,
502 paint.isAntiAlias(),
503 rrect,
504 strokeInfo)) {
505 SkPath path;
506 path.setIsVolatile(true);
507 path.addRRect(rrect);
robertphillipsb83bec52015-10-23 09:38:03 -0700508 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700509 paint.isAntiAlias(), path, strokeInfo);
510 }
511}
512
513///////////////////////////////////////////////////////////////////////////////
514
robertphillips2e1e51f2015-10-15 08:01:48 -0700515void GrDrawContext::drawDRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700516 const GrPaint& paint,
517 const SkMatrix& viewMatrix,
518 const SkRRect& outer,
519 const SkRRect& inner) {
joshualitt1de610a2016-01-06 08:26:09 -0800520 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700521 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700522 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800523 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700524
robertphillipsea461502015-05-26 11:38:03 -0700525 if (outer.isEmpty()) {
526 return;
527 }
528
robertphillips77a2e522015-10-17 07:43:27 -0700529 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700530
robertphillips2e1e51f2015-10-15 08:01:48 -0700531 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700532 GrColor color = paint.getColor();
robertphillipsa106c622015-10-16 09:07:06 -0700533 if (!GrOvalRenderer::DrawDRRect(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700534 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700535 color,
536 viewMatrix,
537 paint.isAntiAlias(),
538 outer,
539 inner)) {
540 SkPath path;
541 path.setIsVolatile(true);
542 path.addRRect(inner);
543 path.addRRect(outer);
544 path.setFillType(SkPath::kEvenOdd_FillType);
545
546 GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
robertphillipsb83bec52015-10-23 09:38:03 -0700547 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700548 paint.isAntiAlias(), path, fillRec);
549 }
550}
551
552///////////////////////////////////////////////////////////////////////////////
553
robertphillips2e1e51f2015-10-15 08:01:48 -0700554void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700555 const GrPaint& paint,
556 const SkMatrix& viewMatrix,
557 const SkRect& oval,
558 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800559 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700560 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700561 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800562 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -0700563
robertphillipsea461502015-05-26 11:38:03 -0700564 if (oval.isEmpty()) {
565 return;
566 }
567
robertphillips514450c2015-11-24 05:36:02 -0800568 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700569
robertphillips77a2e522015-10-17 07:43:27 -0700570 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700571
robertphillips2e1e51f2015-10-15 08:01:48 -0700572 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700573 GrColor color = paint.getColor();
robertphillips2e1e51f2015-10-15 08:01:48 -0700574
robertphillipsa106c622015-10-16 09:07:06 -0700575 if (!GrOvalRenderer::DrawOval(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700576 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700577 color,
578 viewMatrix,
579 paint.isAntiAlias(),
580 oval,
581 strokeInfo)) {
582 SkPath path;
583 path.setIsVolatile(true);
584 path.addOval(oval);
robertphillipsb83bec52015-10-23 09:38:03 -0700585 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700586 paint.isAntiAlias(), path, strokeInfo);
587 }
588}
589
joshualitt33a5fce2015-11-18 13:28:51 -0800590void GrDrawContext::drawImageNine(const GrClip& clip,
591 const GrPaint& paint,
592 const SkMatrix& viewMatrix,
593 int imageWidth,
594 int imageHeight,
595 const SkIRect& center,
596 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -0800597 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -0800598 RETURN_IF_ABANDONED
599 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800600 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageNine");
joshualitt33a5fce2015-11-18 13:28:51 -0800601
602 AutoCheckFlush acf(fDrawingManager);
603
604 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
605 imageWidth, imageHeight,
606 center, dst));
607
608 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
609 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
610}
611
612
robertphillipsea461502015-05-26 11:38:03 -0700613// Can 'path' be drawn as a pair of filled nested rectangles?
joshualittf9c5db22015-07-10 11:31:01 -0700614static bool is_nested_rects(const SkMatrix& viewMatrix,
robertphillipsea461502015-05-26 11:38:03 -0700615 const SkPath& path,
616 const SkStrokeRec& stroke,
617 SkRect rects[2]) {
618 SkASSERT(stroke.isFillStyle());
619
620 if (path.isInverseFillType()) {
621 return false;
622 }
623
624 // TODO: this restriction could be lifted if we were willing to apply
625 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -0800626 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -0700627 return false;
628 }
629
630 SkPath::Direction dirs[2];
631 if (!path.isNestedFillRects(rects, dirs)) {
632 return false;
633 }
634
635 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
636 // The two rects need to be wound opposite to each other
637 return false;
638 }
639
640 // Right now, nested rects where the margin is not the same width
641 // all around do not render correctly
642 const SkScalar* outer = rects[0].asScalars();
643 const SkScalar* inner = rects[1].asScalars();
644
645 bool allEq = true;
646
647 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
648 bool allGoE1 = margin >= SK_Scalar1;
649
650 for (int i = 1; i < 4; ++i) {
651 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
652 if (temp < SK_Scalar1) {
653 allGoE1 = false;
654 }
655 if (!SkScalarNearlyEqual(margin, temp)) {
656 allEq = false;
657 }
658 }
659
660 return allEq || allGoE1;
661}
662
robertphillips2e1e51f2015-10-15 08:01:48 -0700663void GrDrawContext::drawBatch(const GrClip& clip,
bsalomonabd30f52015-08-13 13:34:48 -0700664 const GrPaint& paint, GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800665 ASSERT_SINGLE_OWNER
joshualittb7ee1bf2015-08-10 11:59:02 -0700666 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700667 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800668 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
joshualittb7ee1bf2015-08-10 11:59:02 -0700669
robertphillips77a2e522015-10-17 07:43:27 -0700670 AutoCheckFlush acf(fDrawingManager);
joshualittb7ee1bf2015-08-10 11:59:02 -0700671
robertphillips2e1e51f2015-10-15 08:01:48 -0700672 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700673 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
joshualittb7ee1bf2015-08-10 11:59:02 -0700674}
675
cdalton8ff8d242015-12-08 10:20:32 -0800676void GrDrawContext::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
677 GrDrawPathBatchBase* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800678 ASSERT_SINGLE_OWNER
cdalton8ff8d242015-12-08 10:20:32 -0800679 RETURN_IF_ABANDONED
680 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800681 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPathBatch");
cdalton8ff8d242015-12-08 10:20:32 -0800682
683 AutoCheckFlush acf(fDrawingManager);
684
685 this->getDrawTarget()->drawPathBatch(pipelineBuilder, batch);
686}
687
robertphillips2e1e51f2015-10-15 08:01:48 -0700688void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700689 const GrPaint& paint,
690 const SkMatrix& viewMatrix,
691 const SkPath& path,
692 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800693 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700694 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700695 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800696 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -0700697
robertphillipsea461502015-05-26 11:38:03 -0700698 if (path.isEmpty()) {
699 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700700 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700701 }
702 return;
703 }
704
705 GrColor color = paint.getColor();
706
707 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
708 // Scratch textures can be recycled after they are returned to the texture
709 // cache. This presents a potential hazard for buffered drawing. However,
710 // the writePixels that uploads to the scratch will perform a flush so we're
711 // OK.
robertphillips77a2e522015-10-17 07:43:27 -0700712 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700713
robertphillips2e1e51f2015-10-15 08:01:48 -0700714 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700715 if (!strokeInfo.isDashed()) {
bsalomonc55271f2015-11-09 11:55:57 -0800716 bool useCoverageAA = should_apply_coverage_aa(paint, pipelineBuilder.getRenderTarget());
robertphillipsea461502015-05-26 11:38:03 -0700717
718 if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) {
719 // Concave AA paths are expensive - try to avoid them for special cases
720 SkRect rects[2];
721
joshualittf9c5db22015-07-10 11:31:01 -0700722 if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -0700723 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
bsalomonabd30f52015-08-13 13:34:48 -0700724 color, viewMatrix, rects));
robertphillipsa106c622015-10-16 09:07:06 -0700725 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700726 return;
727 }
728 }
729 SkRect ovalRect;
730 bool isOval = path.isOval(&ovalRect);
731
732 if (isOval && !path.isInverseFillType()) {
robertphillipsa106c622015-10-16 09:07:06 -0700733 if (GrOvalRenderer::DrawOval(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700734 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700735 color,
736 viewMatrix,
737 paint.isAntiAlias(),
738 ovalRect,
739 strokeInfo)) {
740 return;
741 }
742 }
743 }
robertphillipsb83bec52015-10-23 09:38:03 -0700744 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsa106c622015-10-16 09:07:06 -0700745 paint.isAntiAlias(), path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700746}
747
robertphillipsb83bec52015-10-23 09:38:03 -0700748void GrDrawContext::internalDrawPath(GrPipelineBuilder* pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700749 const SkMatrix& viewMatrix,
750 GrColor color,
751 bool useAA,
752 const SkPath& path,
753 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800754 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700755 RETURN_IF_ABANDONED
756 SkASSERT(!path.isEmpty());
757
robertphillipsea461502015-05-26 11:38:03 -0700758 // An Assumption here is that path renderer would use some form of tweaking
759 // the src color (either the input alpha or in the frag shader) to implement
760 // aa. If we have some future driver-mojo path AA that can do the right
761 // thing WRT to the blend then we'll need some query on the PR.
762 bool useCoverageAA = useAA &&
vbuzinovdded6962015-06-12 08:59:45 -0700763 !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
robertphillips68737822015-10-29 12:12:21 -0700764 bool isStencilDisabled = pipelineBuilder->getStencil().isDisabled();
765 bool isStencilBufferMSAA = pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -0700766
robertphillips68737822015-10-29 12:12:21 -0700767 const GrPathRendererChain::DrawType type =
768 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
769 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -0700770
771 const SkPath* pathPtr = &path;
772 SkTLazy<SkPath> tmpPath;
773 const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
774
robertphillips68737822015-10-29 12:12:21 -0700775 GrPathRenderer::CanDrawPathArgs canDrawArgs;
776 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
777 canDrawArgs.fViewMatrix = &viewMatrix;
778 canDrawArgs.fPath = pathPtr;
779 canDrawArgs.fStroke = strokeInfoPtr;
780 canDrawArgs.fAntiAlias = useCoverageAA;
781 canDrawArgs.fIsStencilDisabled = isStencilDisabled;
782 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
783
robertphillipsea461502015-05-26 11:38:03 -0700784 // Try a 1st time without stroking the path and without allowing the SW renderer
robertphillips68737822015-10-29 12:12:21 -0700785 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700786
787 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
halcanary96fcdcc2015-08-27 07:41:13 -0700788 if (nullptr == pr && strokeInfo.isDashed()) {
robertphillipsea461502015-05-26 11:38:03 -0700789 // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
790 if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
791 return;
792 }
793 pathPtr = tmpPath.get();
794 if (pathPtr->isEmpty()) {
795 return;
796 }
797 strokeInfoPtr = &dashlessStrokeInfo;
robertphillips68737822015-10-29 12:12:21 -0700798
799 canDrawArgs.fPath = pathPtr;
800 canDrawArgs.fStroke = strokeInfoPtr;
801
802 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700803 }
804
halcanary96fcdcc2015-08-27 07:41:13 -0700805 if (nullptr == pr) {
806 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, nullptr) &&
robertphillipsea461502015-05-26 11:38:03 -0700807 !strokeInfoPtr->isFillStyle()) {
808 // It didn't work above, so try again with stroke converted to a fill.
809 if (!tmpPath.isValid()) {
810 tmpPath.init();
811 }
812 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
813 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
814 return;
815 }
816 pathPtr = tmpPath.get();
817 if (pathPtr->isEmpty()) {
818 return;
819 }
820 dashlessStrokeInfo.setFillStyle();
821 strokeInfoPtr = &dashlessStrokeInfo;
822 }
823
robertphillips68737822015-10-29 12:12:21 -0700824 canDrawArgs.fPath = pathPtr;
825 canDrawArgs.fStroke = strokeInfoPtr;
826
robertphillipsea461502015-05-26 11:38:03 -0700827 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -0700828 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -0700829 }
830
halcanary96fcdcc2015-08-27 07:41:13 -0700831 if (nullptr == pr) {
robertphillipsea461502015-05-26 11:38:03 -0700832#ifdef SK_DEBUG
833 SkDebugf("Unable to find path renderer compatible with path.\n");
834#endif
835 return;
836 }
837
bsalomon0aff2fa2015-07-31 06:48:27 -0700838 GrPathRenderer::DrawPathArgs args;
robertphillipsb83bec52015-10-23 09:38:03 -0700839 args.fTarget = this->getDrawTarget();
robertphillips77a2e522015-10-17 07:43:27 -0700840 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
bsalomon0aff2fa2015-07-31 06:48:27 -0700841 args.fPipelineBuilder = pipelineBuilder;
842 args.fColor = color;
843 args.fViewMatrix = &viewMatrix;
844 args.fPath = pathPtr;
845 args.fStroke = strokeInfoPtr;
846 args.fAntiAlias = useCoverageAA;
847 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -0700848}
849
bsalomonabd30f52015-08-13 13:34:48 -0700850void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800851 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700852 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700853 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800854 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -0700855
robertphillipsa106c622015-10-16 09:07:06 -0700856 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch);
robertphillips2334fb62015-06-17 05:43:33 -0700857}