blob: 17cdbf3b6be825264ee2e523c0b58aa0c435f5dd [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
robertphillips2334fb62015-06-17 05:43:33 -07009#include "GrAtlasTextContext.h"
robertphillipsea461502015-05-26 11:38:03 -070010#include "GrBatchTest.h"
jvanverth31ff7622015-08-07 10:09:28 -070011#include "GrColor.h"
robertphillipsea461502015-05-26 11:38:03 -070012#include "GrDrawContext.h"
robertphillips77a2e522015-10-17 07:43:27 -070013#include "GrDrawingManager.h"
robertphillipsea461502015-05-26 11:38:03 -070014#include "GrOvalRenderer.h"
15#include "GrPathRenderer.h"
robertphillips2334fb62015-06-17 05:43:33 -070016#include "GrRenderTarget.h"
17#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070018#include "GrResourceProvider.h"
robertphillips2334fb62015-06-17 05:43:33 -070019#include "GrStencilAndCoverTextContext.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"
jvanverth14b88032015-08-07 12:18:54 -070023#include "batches/GrDrawAtlasBatch.h"
joshualitt2771b562015-08-07 12:46:26 -070024#include "batches/GrDrawVerticesBatch.h"
joshualitt7fc2a262015-08-10 10:30:14 -070025#include "batches/GrRectBatchFactory.h"
joshualitt33a5fce2015-11-18 13:28:51 -080026#include "batches/GrNinePatch.h" // TODO Factory
joshualitt74417822015-08-07 11:42:16 -070027
robertphillips77a2e522015-10-17 07:43:27 -070028#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
29#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
30#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; }
31#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070032
33class AutoCheckFlush {
34public:
robertphillips77a2e522015-10-17 07:43:27 -070035 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
36 SkASSERT(fDrawingManager);
37 }
38 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070039
40private:
robertphillips77a2e522015-10-17 07:43:27 -070041 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070042};
43
robertphillipsa106c622015-10-16 09:07:06 -070044// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
45// drawTargets to be picked up and added to by drawContexts lower in the call
46// stack. When this occurs with a closed drawTarget, a new one will be allocated
47// when the drawContext attempts to use it (via getDrawTarget).
robertphillips77a2e522015-10-17 07:43:27 -070048GrDrawContext::GrDrawContext(GrDrawingManager* drawingMgr,
robertphillips2e1e51f2015-10-15 08:01:48 -070049 GrRenderTarget* rt,
robertphillips2d70dcb2015-10-06 07:38:23 -070050 const SkSurfaceProps* surfaceProps)
robertphillips77a2e522015-10-17 07:43:27 -070051 : fDrawingManager(drawingMgr)
robertphillips2e1e51f2015-10-15 08:01:48 -070052 , fRenderTarget(rt)
robertphillipsa106c622015-10-16 09:07:06 -070053 , fDrawTarget(SkSafeRef(rt->getLastDrawTarget()))
halcanary96fcdcc2015-08-27 07:41:13 -070054 , fTextContext(nullptr)
robertphillips2d70dcb2015-10-06 07:38:23 -070055 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) {
robertphillips2e1e51f2015-10-15 08:01:48 -070056 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070057}
58
robertphillips2e1e51f2015-10-15 08:01:48 -070059#ifdef SK_DEBUG
60void GrDrawContext::validate() const {
61 SkASSERT(fRenderTarget);
62 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070063
64 if (fDrawTarget && !fDrawTarget->isClosed()) {
65 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
66 }
robertphillips2e1e51f2015-10-15 08:01:48 -070067}
68#endif
69
robertphillipsa106c622015-10-16 09:07:06 -070070GrDrawContext::~GrDrawContext() {
71 SkSafeUnref(fDrawTarget);
72}
73
74GrDrawTarget* GrDrawContext::getDrawTarget() {
75 SkDEBUGCODE(this->validate();)
76
77 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips77a2e522015-10-17 07:43:27 -070078 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070079 }
80
81 return fDrawTarget;
82}
83
robertphillips2e1e51f2015-10-15 08:01:48 -070084void GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
robertphillips2d70dcb2015-10-06 07:38:23 -070085 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -070086 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -070087
robertphillipsa106c622015-10-16 09:07:06 -070088 this->getDrawTarget()->copySurface(fRenderTarget, src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -070089}
90
robertphillips2e1e51f2015-10-15 08:01:48 -070091void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -070092 const SkPaint& skPaint,
93 const SkMatrix& viewMatrix,
94 const char text[], size_t byteLength,
95 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
robertphillips2d70dcb2015-10-06 07:38:23 -070096 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -070097 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -070098
robertphillips2334fb62015-06-17 05:43:33 -070099 if (!fTextContext) {
robertphillips77a2e522015-10-17 07:43:27 -0700100 fTextContext = fDrawingManager->textContext(fSurfaceProps, fRenderTarget);
robertphillips2334fb62015-06-17 05:43:33 -0700101 }
102
robertphillips2e1e51f2015-10-15 08:01:48 -0700103 fTextContext->drawText(this, fRenderTarget, clip, grPaint, skPaint, viewMatrix,
robertphillips2334fb62015-06-17 05:43:33 -0700104 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700105}
robertphillipscaef3452015-11-11 13:18:11 -0800106
robertphillips2e1e51f2015-10-15 08:01:48 -0700107void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700108 const SkPaint& skPaint,
109 const SkMatrix& viewMatrix,
110 const char text[], size_t byteLength,
111 const SkScalar pos[], int scalarsPerPosition,
112 const SkPoint& offset, const SkIRect& clipBounds) {
robertphillips2d70dcb2015-10-06 07:38:23 -0700113 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700114 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -0700115
robertphillips2334fb62015-06-17 05:43:33 -0700116 if (!fTextContext) {
robertphillips77a2e522015-10-17 07:43:27 -0700117 fTextContext = fDrawingManager->textContext(fSurfaceProps, fRenderTarget);
robertphillips2334fb62015-06-17 05:43:33 -0700118 }
119
robertphillips2e1e51f2015-10-15 08:01:48 -0700120 fTextContext->drawPosText(this, fRenderTarget, clip, grPaint, skPaint, viewMatrix, text, byteLength,
robertphillipsf6703fa2015-09-01 05:36:47 -0700121 pos, scalarsPerPosition, offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700122
123}
robertphillipscaef3452015-11-11 13:18:11 -0800124
robertphillips2e1e51f2015-10-15 08:01:48 -0700125void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700126 const SkMatrix& viewMatrix, const SkTextBlob* blob,
127 SkScalar x, SkScalar y,
128 SkDrawFilter* filter, const SkIRect& clipBounds) {
robertphillips2d70dcb2015-10-06 07:38:23 -0700129 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700130 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -0700131
robertphillips2334fb62015-06-17 05:43:33 -0700132 if (!fTextContext) {
robertphillips77a2e522015-10-17 07:43:27 -0700133 fTextContext = fDrawingManager->textContext(fSurfaceProps, fRenderTarget);
robertphillips2334fb62015-06-17 05:43:33 -0700134 }
135
robertphillips2e1e51f2015-10-15 08:01:48 -0700136 fTextContext->drawTextBlob(this, fRenderTarget,
robertphillipsf6703fa2015-09-01 05:36:47 -0700137 clip, skPaint, viewMatrix, blob, x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700138}
139
bsalomon1fcc01c2015-09-09 09:48:06 -0700140void GrDrawContext::drawPathsFromRange(const GrPipelineBuilder* pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700141 const SkMatrix& viewMatrix,
142 const SkMatrix& localMatrix,
143 GrColor color,
cdalton8585dd22015-10-08 08:04:09 -0700144 GrPathRange* range,
bsalomon1fcc01c2015-09-09 09:48:06 -0700145 GrPathRangeDraw* draw,
bsalomonbf074552015-11-23 14:25:19 -0800146 int /*GrPathRendering::FillType*/ fill,
147 const SkRect& bounds) {
robertphillips2d70dcb2015-10-06 07:38:23 -0700148 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700149 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -0700150
robertphillipsa106c622015-10-16 09:07:06 -0700151 this->getDrawTarget()->drawPathsFromRange(*pipelineBuilder, viewMatrix, localMatrix, color,
bsalomonbf074552015-11-23 14:25:19 -0800152 range, draw, (GrPathRendering::FillType) fill,
153 bounds);
robertphillipsea461502015-05-26 11:38:03 -0700154}
155
robertphillips2e1e51f2015-10-15 08:01:48 -0700156void GrDrawContext::discard() {
robertphillipsea461502015-05-26 11:38:03 -0700157 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700158 SkDEBUGCODE(this->validate();)
159
robertphillips77a2e522015-10-17 07:43:27 -0700160 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700161 this->getDrawTarget()->discard(fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700162}
163
robertphillips2e1e51f2015-10-15 08:01:48 -0700164void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700165 const GrColor color,
166 bool canIgnoreRect) {
167 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700168 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700169
robertphillips77a2e522015-10-17 07:43:27 -0700170 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700171 this->getDrawTarget()->clear(rect, color, canIgnoreRect, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700172}
173
174
robertphillips2e1e51f2015-10-15 08:01:48 -0700175void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700176 const GrPaint& origPaint,
177 const SkMatrix& viewMatrix) {
178 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700179 SkDEBUGCODE(this->validate();)
180
robertphillipsea461502015-05-26 11:38:03 -0700181 // set rect to be big enough to fill the space, but not super-huge, so we
182 // don't overflow fixed-point implementations
183 SkRect r;
184 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700185 SkIntToScalar(fRenderTarget->width()),
186 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700187 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
188
189 // by definition this fills the entire clip, no need for AA
190 if (paint->isAntiAlias()) {
191 paint.writable()->setAntiAlias(false);
192 }
193
194 bool isPerspective = viewMatrix.hasPerspective();
195
196 // We attempt to map r by the inverse matrix and draw that. mapRect will
197 // map the four corners and bound them with a new rect. This will not
198 // produce a correct result for some perspective matrices.
199 if (!isPerspective) {
200 SkMatrix inverse;
201 if (!viewMatrix.invert(&inverse)) {
202 SkDebugf("Could not invert matrix\n");
203 return;
204 }
205 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700206 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700207 } else {
208 SkMatrix localMatrix;
209 if (!viewMatrix.invert(&localMatrix)) {
210 SkDebugf("Could not invert matrix\n");
211 return;
212 }
213
robertphillips77a2e522015-10-17 07:43:27 -0700214 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700215
robertphillips2e1e51f2015-10-15 08:01:48 -0700216 GrPipelineBuilder pipelineBuilder(*paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700217 this->getDrawTarget()->drawNonAARect(pipelineBuilder,
218 paint->getColor(),
219 SkMatrix::I(),
220 r,
221 localMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700222 }
223}
224
robertphillipsea461502015-05-26 11:38:03 -0700225static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
226 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
227 point.fY >= rect.fTop && point.fY <= rect.fBottom;
228}
229
bsalomonc55271f2015-11-09 11:55:57 -0800230static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
231 return viewMatrix.preservesRightAngles();
232}
233
234static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) {
235 return paint.isAntiAlias() && !rt->isUnifiedMultisampled();
236}
237
robertphillips2e1e51f2015-10-15 08:01:48 -0700238void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700239 const GrPaint& paint,
240 const SkMatrix& viewMatrix,
241 const SkRect& rect,
242 const GrStrokeInfo* strokeInfo) {
243 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700244 SkDEBUGCODE(this->validate();)
245
robertphillipsff55b492015-11-24 07:56:59 -0800246 // Dashing should've been devolved to a path in SkGpuDevice
247 SkASSERT(!strokeInfo || !strokeInfo->isDashed());
robertphillipsea461502015-05-26 11:38:03 -0700248
robertphillips77a2e522015-10-17 07:43:27 -0700249 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700250
robertphillips2e1e51f2015-10-15 08:01:48 -0700251 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt7b670db2015-07-09 13:25:02 -0700252
halcanary96fcdcc2015-08-27 07:41:13 -0700253 SkScalar width = nullptr == strokeInfo ? -1 : strokeInfo->getWidth();
robertphillipsea461502015-05-26 11:38:03 -0700254
255 // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
256 // cases where the RT is fully inside a stroke.
257 if (width < 0) {
258 SkRect rtRect;
259 pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect);
260 SkRect clipSpaceRTRect = rtRect;
261 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
262 if (checkClip) {
263 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
264 SkIntToScalar(clip.origin().fY));
265 }
266 // Does the clip contain the entire RT?
267 if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
268 SkMatrix invM;
269 if (!viewMatrix.invert(&invM)) {
270 return;
271 }
272 // Does the rect bound the RT?
273 SkPoint srcSpaceRTQuad[4];
274 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
275 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
276 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
277 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
278 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
279 // Will it blend?
280 GrColor clearColor;
cdalton1fa45722015-06-02 10:43:39 -0700281 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillipsa106c622015-10-16 09:07:06 -0700282 this->getDrawTarget()->clear(nullptr, clearColor, true, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700283 return;
284 }
285 }
286 }
287 }
288
289 GrColor color = paint.getColor();
bsalomonc55271f2015-11-09 11:55:57 -0800290 bool needAA = should_apply_coverage_aa(paint, pipelineBuilder.getRenderTarget());
robertphillipsea461502015-05-26 11:38:03 -0700291
joshualitt9be0b002015-08-19 11:50:51 -0700292 // The fill path can handle rotation but not skew
293 // The stroke path needs the rect to remain axis aligned (no rotation or skew)
robertphillipsfac9ceb2015-09-03 08:32:08 -0700294 // None of our AA draw rect calls can handle perspective yet
bsalomonc55271f2015-11-09 11:55:57 -0800295 bool canApplyAA = width >=0 ? viewMatrix.rectStaysRect() :
296 view_matrix_ok_for_aa_fill_rect(viewMatrix);
joshualitt9be0b002015-08-19 11:50:51 -0700297
298 if (needAA && canApplyAA) {
robertphillipsfac9ceb2015-09-03 08:32:08 -0700299 SkASSERT(!viewMatrix.hasPerspective());
bsalomonabd30f52015-08-13 13:34:48 -0700300 SkAutoTUnref<GrDrawBatch> batch;
robertphillipsea461502015-05-26 11:38:03 -0700301 if (width >= 0) {
joshualitt10cae832015-09-22 12:50:33 -0700302 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, *strokeInfo));
robertphillipsea461502015-05-26 11:38:03 -0700303 } else {
joshualitt10cae832015-09-22 12:50:33 -0700304 SkRect devBoundRect;
305 viewMatrix.mapRect(&devBoundRect, rect);
joshualittd2b23e02015-08-21 10:53:34 -0700306 batch.reset(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect, devBoundRect));
robertphillipsea461502015-05-26 11:38:03 -0700307 }
robertphillipsa106c622015-10-16 09:07:06 -0700308 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700309 return;
310 }
311
312 if (width >= 0) {
robertphillipsea461502015-05-26 11:38:03 -0700313 // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
robertphillips2e1e51f2015-10-15 08:01:48 -0700314 bool snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled());
joshualittd2b23e02015-08-21 10:53:34 -0700315 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAStroke(
bsalomonabd30f52015-08-13 13:34:48 -0700316 color, viewMatrix, rect, width, snapToPixelCenters));
robertphillipsea461502015-05-26 11:38:03 -0700317
318 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
319 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA
320 // is enabled because it can cause ugly artifacts.
321 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
322 snapToPixelCenters);
robertphillipsa106c622015-10-16 09:07:06 -0700323 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700324 } else {
325 // filled BW rect
robertphillipsa106c622015-10-16 09:07:06 -0700326 this->getDrawTarget()->drawNonAARect(pipelineBuilder, color, viewMatrix, rect);
robertphillipsea461502015-05-26 11:38:03 -0700327 }
328}
329
bsalomona2e69fc2015-11-05 10:41:43 -0800330void GrDrawContext::fillRectToRect(const GrClip& clip,
331 const GrPaint& paint,
332 const SkMatrix& viewMatrix,
333 const SkRect& rectToDraw,
334 const SkRect& localRect) {
robertphillipsea461502015-05-26 11:38:03 -0700335 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700336 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700337
robertphillips77a2e522015-10-17 07:43:27 -0700338 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700339
340 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
bsalomonc55271f2015-11-09 11:55:57 -0800341 if (should_apply_coverage_aa(paint, fRenderTarget) &&
342 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
343 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(
344 paint.getColor(), viewMatrix, rectToDraw, localRect));
345 if (batch) {
346 this->drawBatch(&pipelineBuilder, batch);
347 }
348 } else {
349 this->getDrawTarget()->drawNonAARect(pipelineBuilder,
350 paint.getColor(),
351 viewMatrix,
352 rectToDraw,
353 localRect);
354 }
joshualittb6b513b2015-08-21 10:25:18 -0700355}
356
bsalomona2e69fc2015-11-05 10:41:43 -0800357void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
358 const GrPaint& paint,
359 const SkMatrix& viewMatrix,
360 const SkRect& rectToDraw,
361 const SkMatrix& localMatrix) {
joshualittb6b513b2015-08-21 10:25:18 -0700362 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700363 SkDEBUGCODE(this->validate();)
joshualittb6b513b2015-08-21 10:25:18 -0700364
robertphillips77a2e522015-10-17 07:43:27 -0700365 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700366
367 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
bsalomonc55271f2015-11-09 11:55:57 -0800368 if (should_apply_coverage_aa(paint, pipelineBuilder.getRenderTarget()) &&
369 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
370 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(
371 paint.getColor(), viewMatrix, localMatrix, rectToDraw));
372 this->drawBatch(&pipelineBuilder, batch);
373 } else {
374 this->getDrawTarget()->drawNonAARect(pipelineBuilder,
375 paint.getColor(),
376 viewMatrix,
377 rectToDraw,
378 localMatrix);
379 }
robertphillipsea461502015-05-26 11:38:03 -0700380}
381
robertphillips2e1e51f2015-10-15 08:01:48 -0700382void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700383 const GrPaint& paint,
384 const SkMatrix& viewMatrix,
385 GrPrimitiveType primitiveType,
386 int vertexCount,
387 const SkPoint positions[],
388 const SkPoint texCoords[],
389 const GrColor colors[],
390 const uint16_t indices[],
391 int indexCount) {
392 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700393 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700394
robertphillips77a2e522015-10-17 07:43:27 -0700395 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700396
397 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt7b670db2015-07-09 13:25:02 -0700398
robertphillipsea461502015-05-26 11:38:03 -0700399 // TODO clients should give us bounds
400 SkRect bounds;
401 if (!bounds.setBoundsCheck(positions, vertexCount)) {
402 SkDebugf("drawVertices call empty bounds\n");
403 return;
404 }
405
406 viewMatrix.mapRect(&bounds);
407
408 // 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 -0800409 // snapping. We also do this for the "hair" primitive types: lines and points since they have
410 // a 1 pixel thickness in device space.
411 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
412 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700413 bounds.outset(0.5f, 0.5f);
414 }
415
joshualitt2771b562015-08-07 12:46:26 -0700416 GrDrawVerticesBatch::Geometry geometry;
robertphillipsea461502015-05-26 11:38:03 -0700417 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700418 SkAutoTUnref<GrDrawBatch> batch(GrDrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
419 positions, vertexCount, indices,
420 indexCount, colors, texCoords,
421 bounds));
robertphillipsea461502015-05-26 11:38:03 -0700422
robertphillipsa106c622015-10-16 09:07:06 -0700423 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700424}
425
426///////////////////////////////////////////////////////////////////////////////
427
robertphillips2e1e51f2015-10-15 08:01:48 -0700428void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700429 const GrPaint& paint,
430 const SkMatrix& viewMatrix,
431 int spriteCount,
432 const SkRSXform xform[],
433 const SkRect texRect[],
434 const SkColor colors[]) {
435 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700436 SkDEBUGCODE(this->validate();)
437
robertphillips77a2e522015-10-17 07:43:27 -0700438 AutoCheckFlush acf(fDrawingManager);
jvanverth31ff7622015-08-07 10:09:28 -0700439
robertphillips2e1e51f2015-10-15 08:01:48 -0700440 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
jvanverth31ff7622015-08-07 10:09:28 -0700441
jvanverth14b88032015-08-07 12:18:54 -0700442 GrDrawAtlasBatch::Geometry geometry;
jvanverth31ff7622015-08-07 10:09:28 -0700443 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700444 SkAutoTUnref<GrDrawBatch> batch(GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount,
445 xform, texRect, colors));
jvanverth31ff7622015-08-07 10:09:28 -0700446
robertphillipsa106c622015-10-16 09:07:06 -0700447 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700448}
449
450///////////////////////////////////////////////////////////////////////////////
451
robertphillips2e1e51f2015-10-15 08:01:48 -0700452void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700453 const GrPaint& paint,
454 const SkMatrix& viewMatrix,
455 const SkRRect& rrect,
456 const GrStrokeInfo& strokeInfo) {
457 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700458 SkDEBUGCODE(this->validate();)
459
robertphillipsea461502015-05-26 11:38:03 -0700460 if (rrect.isEmpty()) {
461 return;
462 }
463
robertphillips514450c2015-11-24 05:36:02 -0800464 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700465
robertphillips77a2e522015-10-17 07:43:27 -0700466 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700467
robertphillips2e1e51f2015-10-15 08:01:48 -0700468 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700469 GrColor color = paint.getColor();
robertphillips2e1e51f2015-10-15 08:01:48 -0700470
robertphillipsa106c622015-10-16 09:07:06 -0700471 if (!GrOvalRenderer::DrawRRect(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700472 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700473 color,
474 viewMatrix,
475 paint.isAntiAlias(),
476 rrect,
477 strokeInfo)) {
478 SkPath path;
479 path.setIsVolatile(true);
480 path.addRRect(rrect);
robertphillipsb83bec52015-10-23 09:38:03 -0700481 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700482 paint.isAntiAlias(), path, strokeInfo);
483 }
484}
485
486///////////////////////////////////////////////////////////////////////////////
487
robertphillips2e1e51f2015-10-15 08:01:48 -0700488void GrDrawContext::drawDRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700489 const GrPaint& paint,
490 const SkMatrix& viewMatrix,
491 const SkRRect& outer,
492 const SkRRect& inner) {
493 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700494 SkDEBUGCODE(this->validate();)
495
robertphillipsea461502015-05-26 11:38:03 -0700496 if (outer.isEmpty()) {
497 return;
498 }
499
robertphillips77a2e522015-10-17 07:43:27 -0700500 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700501
robertphillips2e1e51f2015-10-15 08:01:48 -0700502 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700503 GrColor color = paint.getColor();
robertphillipsa106c622015-10-16 09:07:06 -0700504 if (!GrOvalRenderer::DrawDRRect(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700505 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700506 color,
507 viewMatrix,
508 paint.isAntiAlias(),
509 outer,
510 inner)) {
511 SkPath path;
512 path.setIsVolatile(true);
513 path.addRRect(inner);
514 path.addRRect(outer);
515 path.setFillType(SkPath::kEvenOdd_FillType);
516
517 GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
robertphillipsb83bec52015-10-23 09:38:03 -0700518 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700519 paint.isAntiAlias(), path, fillRec);
520 }
521}
522
523///////////////////////////////////////////////////////////////////////////////
524
robertphillips2e1e51f2015-10-15 08:01:48 -0700525void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700526 const GrPaint& paint,
527 const SkMatrix& viewMatrix,
528 const SkRect& oval,
529 const GrStrokeInfo& strokeInfo) {
530 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700531 SkDEBUGCODE(this->validate();)
532
robertphillipsea461502015-05-26 11:38:03 -0700533 if (oval.isEmpty()) {
534 return;
535 }
536
robertphillips514450c2015-11-24 05:36:02 -0800537 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700538
robertphillips77a2e522015-10-17 07:43:27 -0700539 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700540
robertphillips2e1e51f2015-10-15 08:01:48 -0700541 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700542 GrColor color = paint.getColor();
robertphillips2e1e51f2015-10-15 08:01:48 -0700543
robertphillipsa106c622015-10-16 09:07:06 -0700544 if (!GrOvalRenderer::DrawOval(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700545 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700546 color,
547 viewMatrix,
548 paint.isAntiAlias(),
549 oval,
550 strokeInfo)) {
551 SkPath path;
552 path.setIsVolatile(true);
553 path.addOval(oval);
robertphillipsb83bec52015-10-23 09:38:03 -0700554 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700555 paint.isAntiAlias(), path, strokeInfo);
556 }
557}
558
joshualitt33a5fce2015-11-18 13:28:51 -0800559void GrDrawContext::drawImageNine(const GrClip& clip,
560 const GrPaint& paint,
561 const SkMatrix& viewMatrix,
562 int imageWidth,
563 int imageHeight,
564 const SkIRect& center,
565 const SkRect& dst) {
566 RETURN_IF_ABANDONED
567 SkDEBUGCODE(this->validate();)
568
569 AutoCheckFlush acf(fDrawingManager);
570
571 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
572 imageWidth, imageHeight,
573 center, dst));
574
575 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
576 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
577}
578
579
robertphillipsea461502015-05-26 11:38:03 -0700580// Can 'path' be drawn as a pair of filled nested rectangles?
joshualittf9c5db22015-07-10 11:31:01 -0700581static bool is_nested_rects(const SkMatrix& viewMatrix,
robertphillipsea461502015-05-26 11:38:03 -0700582 const SkPath& path,
583 const SkStrokeRec& stroke,
584 SkRect rects[2]) {
585 SkASSERT(stroke.isFillStyle());
586
587 if (path.isInverseFillType()) {
588 return false;
589 }
590
591 // TODO: this restriction could be lifted if we were willing to apply
592 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -0800593 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -0700594 return false;
595 }
596
597 SkPath::Direction dirs[2];
598 if (!path.isNestedFillRects(rects, dirs)) {
599 return false;
600 }
601
602 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
603 // The two rects need to be wound opposite to each other
604 return false;
605 }
606
607 // Right now, nested rects where the margin is not the same width
608 // all around do not render correctly
609 const SkScalar* outer = rects[0].asScalars();
610 const SkScalar* inner = rects[1].asScalars();
611
612 bool allEq = true;
613
614 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
615 bool allGoE1 = margin >= SK_Scalar1;
616
617 for (int i = 1; i < 4; ++i) {
618 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
619 if (temp < SK_Scalar1) {
620 allGoE1 = false;
621 }
622 if (!SkScalarNearlyEqual(margin, temp)) {
623 allEq = false;
624 }
625 }
626
627 return allEq || allGoE1;
628}
629
robertphillips2e1e51f2015-10-15 08:01:48 -0700630void GrDrawContext::drawBatch(const GrClip& clip,
bsalomonabd30f52015-08-13 13:34:48 -0700631 const GrPaint& paint, GrDrawBatch* batch) {
joshualittb7ee1bf2015-08-10 11:59:02 -0700632 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700633 SkDEBUGCODE(this->validate();)
joshualittb7ee1bf2015-08-10 11:59:02 -0700634
robertphillips77a2e522015-10-17 07:43:27 -0700635 AutoCheckFlush acf(fDrawingManager);
joshualittb7ee1bf2015-08-10 11:59:02 -0700636
robertphillips2e1e51f2015-10-15 08:01:48 -0700637 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700638 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
joshualittb7ee1bf2015-08-10 11:59:02 -0700639}
640
robertphillips2e1e51f2015-10-15 08:01:48 -0700641void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700642 const GrPaint& paint,
643 const SkMatrix& viewMatrix,
644 const SkPath& path,
645 const GrStrokeInfo& strokeInfo) {
646 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700647 SkDEBUGCODE(this->validate();)
648
robertphillipsea461502015-05-26 11:38:03 -0700649 if (path.isEmpty()) {
650 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700651 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700652 }
653 return;
654 }
655
656 GrColor color = paint.getColor();
657
658 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
659 // Scratch textures can be recycled after they are returned to the texture
660 // cache. This presents a potential hazard for buffered drawing. However,
661 // the writePixels that uploads to the scratch will perform a flush so we're
662 // OK.
robertphillips77a2e522015-10-17 07:43:27 -0700663 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700664
robertphillips2e1e51f2015-10-15 08:01:48 -0700665 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700666 if (!strokeInfo.isDashed()) {
bsalomonc55271f2015-11-09 11:55:57 -0800667 bool useCoverageAA = should_apply_coverage_aa(paint, pipelineBuilder.getRenderTarget());
robertphillipsea461502015-05-26 11:38:03 -0700668
669 if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) {
670 // Concave AA paths are expensive - try to avoid them for special cases
671 SkRect rects[2];
672
joshualittf9c5db22015-07-10 11:31:01 -0700673 if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -0700674 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
bsalomonabd30f52015-08-13 13:34:48 -0700675 color, viewMatrix, rects));
robertphillipsa106c622015-10-16 09:07:06 -0700676 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700677 return;
678 }
679 }
680 SkRect ovalRect;
681 bool isOval = path.isOval(&ovalRect);
682
683 if (isOval && !path.isInverseFillType()) {
robertphillipsa106c622015-10-16 09:07:06 -0700684 if (GrOvalRenderer::DrawOval(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700685 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700686 color,
687 viewMatrix,
688 paint.isAntiAlias(),
689 ovalRect,
690 strokeInfo)) {
691 return;
692 }
693 }
694 }
robertphillipsb83bec52015-10-23 09:38:03 -0700695 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsa106c622015-10-16 09:07:06 -0700696 paint.isAntiAlias(), path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700697}
698
robertphillipsb83bec52015-10-23 09:38:03 -0700699void GrDrawContext::internalDrawPath(GrPipelineBuilder* pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700700 const SkMatrix& viewMatrix,
701 GrColor color,
702 bool useAA,
703 const SkPath& path,
704 const GrStrokeInfo& strokeInfo) {
705 RETURN_IF_ABANDONED
706 SkASSERT(!path.isEmpty());
707
robertphillipsea461502015-05-26 11:38:03 -0700708 // An Assumption here is that path renderer would use some form of tweaking
709 // the src color (either the input alpha or in the frag shader) to implement
710 // aa. If we have some future driver-mojo path AA that can do the right
711 // thing WRT to the blend then we'll need some query on the PR.
712 bool useCoverageAA = useAA &&
vbuzinovdded6962015-06-12 08:59:45 -0700713 !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
robertphillips68737822015-10-29 12:12:21 -0700714 bool isStencilDisabled = pipelineBuilder->getStencil().isDisabled();
715 bool isStencilBufferMSAA = pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -0700716
robertphillips68737822015-10-29 12:12:21 -0700717 const GrPathRendererChain::DrawType type =
718 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
719 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -0700720
721 const SkPath* pathPtr = &path;
722 SkTLazy<SkPath> tmpPath;
723 const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
724
robertphillips68737822015-10-29 12:12:21 -0700725 GrPathRenderer::CanDrawPathArgs canDrawArgs;
726 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
727 canDrawArgs.fViewMatrix = &viewMatrix;
728 canDrawArgs.fPath = pathPtr;
729 canDrawArgs.fStroke = strokeInfoPtr;
730 canDrawArgs.fAntiAlias = useCoverageAA;
731 canDrawArgs.fIsStencilDisabled = isStencilDisabled;
732 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
733
robertphillipsea461502015-05-26 11:38:03 -0700734 // Try a 1st time without stroking the path and without allowing the SW renderer
robertphillips68737822015-10-29 12:12:21 -0700735 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700736
737 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
halcanary96fcdcc2015-08-27 07:41:13 -0700738 if (nullptr == pr && strokeInfo.isDashed()) {
robertphillipsea461502015-05-26 11:38:03 -0700739 // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
740 if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
741 return;
742 }
743 pathPtr = tmpPath.get();
744 if (pathPtr->isEmpty()) {
745 return;
746 }
747 strokeInfoPtr = &dashlessStrokeInfo;
robertphillips68737822015-10-29 12:12:21 -0700748
749 canDrawArgs.fPath = pathPtr;
750 canDrawArgs.fStroke = strokeInfoPtr;
751
752 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700753 }
754
halcanary96fcdcc2015-08-27 07:41:13 -0700755 if (nullptr == pr) {
756 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, nullptr) &&
robertphillipsea461502015-05-26 11:38:03 -0700757 !strokeInfoPtr->isFillStyle()) {
758 // It didn't work above, so try again with stroke converted to a fill.
759 if (!tmpPath.isValid()) {
760 tmpPath.init();
761 }
762 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
763 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
764 return;
765 }
766 pathPtr = tmpPath.get();
767 if (pathPtr->isEmpty()) {
768 return;
769 }
770 dashlessStrokeInfo.setFillStyle();
771 strokeInfoPtr = &dashlessStrokeInfo;
772 }
773
robertphillips68737822015-10-29 12:12:21 -0700774 canDrawArgs.fPath = pathPtr;
775 canDrawArgs.fStroke = strokeInfoPtr;
776
robertphillipsea461502015-05-26 11:38:03 -0700777 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -0700778 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -0700779 }
780
halcanary96fcdcc2015-08-27 07:41:13 -0700781 if (nullptr == pr) {
robertphillipsea461502015-05-26 11:38:03 -0700782#ifdef SK_DEBUG
783 SkDebugf("Unable to find path renderer compatible with path.\n");
784#endif
785 return;
786 }
787
bsalomon0aff2fa2015-07-31 06:48:27 -0700788 GrPathRenderer::DrawPathArgs args;
robertphillipsb83bec52015-10-23 09:38:03 -0700789 args.fTarget = this->getDrawTarget();
robertphillips77a2e522015-10-17 07:43:27 -0700790 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
bsalomon0aff2fa2015-07-31 06:48:27 -0700791 args.fPipelineBuilder = pipelineBuilder;
792 args.fColor = color;
793 args.fViewMatrix = &viewMatrix;
794 args.fPath = pathPtr;
795 args.fStroke = strokeInfoPtr;
796 args.fAntiAlias = useCoverageAA;
797 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -0700798}
799
bsalomonabd30f52015-08-13 13:34:48 -0700800void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* batch) {
robertphillips2d70dcb2015-10-06 07:38:23 -0700801 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700802 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -0700803
robertphillipsa106c622015-10-16 09:07:06 -0700804 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch);
robertphillips2334fb62015-06-17 05:43:33 -0700805}