blob: 1137c57bc474a4f7035f5f607351469d93e0a260 [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,
146 int /*GrPathRendering::FillType*/ fill) {
robertphillips2d70dcb2015-10-06 07:38:23 -0700147 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700148 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -0700149
robertphillipsa106c622015-10-16 09:07:06 -0700150 this->getDrawTarget()->drawPathsFromRange(*pipelineBuilder, viewMatrix, localMatrix, color,
151 range, draw, (GrPathRendering::FillType) fill);
robertphillipsea461502015-05-26 11:38:03 -0700152}
153
robertphillips2e1e51f2015-10-15 08:01:48 -0700154void GrDrawContext::discard() {
robertphillipsea461502015-05-26 11:38:03 -0700155 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700156 SkDEBUGCODE(this->validate();)
157
robertphillips77a2e522015-10-17 07:43:27 -0700158 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700159 this->getDrawTarget()->discard(fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700160}
161
robertphillips2e1e51f2015-10-15 08:01:48 -0700162void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700163 const GrColor color,
164 bool canIgnoreRect) {
165 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700166 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700167
robertphillips77a2e522015-10-17 07:43:27 -0700168 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700169 this->getDrawTarget()->clear(rect, color, canIgnoreRect, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700170}
171
172
robertphillips2e1e51f2015-10-15 08:01:48 -0700173void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700174 const GrPaint& origPaint,
175 const SkMatrix& viewMatrix) {
176 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700177 SkDEBUGCODE(this->validate();)
178
robertphillipsea461502015-05-26 11:38:03 -0700179 // set rect to be big enough to fill the space, but not super-huge, so we
180 // don't overflow fixed-point implementations
181 SkRect r;
182 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700183 SkIntToScalar(fRenderTarget->width()),
184 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700185 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
186
187 // by definition this fills the entire clip, no need for AA
188 if (paint->isAntiAlias()) {
189 paint.writable()->setAntiAlias(false);
190 }
191
192 bool isPerspective = viewMatrix.hasPerspective();
193
194 // We attempt to map r by the inverse matrix and draw that. mapRect will
195 // map the four corners and bound them with a new rect. This will not
196 // produce a correct result for some perspective matrices.
197 if (!isPerspective) {
198 SkMatrix inverse;
199 if (!viewMatrix.invert(&inverse)) {
200 SkDebugf("Could not invert matrix\n");
201 return;
202 }
203 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700204 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700205 } else {
206 SkMatrix localMatrix;
207 if (!viewMatrix.invert(&localMatrix)) {
208 SkDebugf("Could not invert matrix\n");
209 return;
210 }
211
robertphillips77a2e522015-10-17 07:43:27 -0700212 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700213
robertphillips2e1e51f2015-10-15 08:01:48 -0700214 GrPipelineBuilder pipelineBuilder(*paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700215 this->getDrawTarget()->drawNonAARect(pipelineBuilder,
216 paint->getColor(),
217 SkMatrix::I(),
218 r,
219 localMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700220 }
221}
222
robertphillipsea461502015-05-26 11:38:03 -0700223static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
224 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
225 point.fY >= rect.fTop && point.fY <= rect.fBottom;
226}
227
bsalomonc55271f2015-11-09 11:55:57 -0800228static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
229 return viewMatrix.preservesRightAngles();
230}
231
232static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) {
233 return paint.isAntiAlias() && !rt->isUnifiedMultisampled();
234}
235
robertphillips2e1e51f2015-10-15 08:01:48 -0700236void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700237 const GrPaint& paint,
238 const SkMatrix& viewMatrix,
239 const SkRect& rect,
240 const GrStrokeInfo* strokeInfo) {
241 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700242 SkDEBUGCODE(this->validate();)
243
robertphillipsea461502015-05-26 11:38:03 -0700244 if (strokeInfo && strokeInfo->isDashed()) {
245 SkPath path;
246 path.setIsVolatile(true);
247 path.addRect(rect);
robertphillips2e1e51f2015-10-15 08:01:48 -0700248 this->drawPath(clip, paint, viewMatrix, path, *strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700249 return;
250 }
251
robertphillips77a2e522015-10-17 07:43:27 -0700252 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700253
robertphillips2e1e51f2015-10-15 08:01:48 -0700254 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt7b670db2015-07-09 13:25:02 -0700255
halcanary96fcdcc2015-08-27 07:41:13 -0700256 SkScalar width = nullptr == strokeInfo ? -1 : strokeInfo->getWidth();
robertphillipsea461502015-05-26 11:38:03 -0700257
258 // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
259 // cases where the RT is fully inside a stroke.
260 if (width < 0) {
261 SkRect rtRect;
262 pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect);
263 SkRect clipSpaceRTRect = rtRect;
264 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
265 if (checkClip) {
266 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
267 SkIntToScalar(clip.origin().fY));
268 }
269 // Does the clip contain the entire RT?
270 if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
271 SkMatrix invM;
272 if (!viewMatrix.invert(&invM)) {
273 return;
274 }
275 // Does the rect bound the RT?
276 SkPoint srcSpaceRTQuad[4];
277 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
278 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
279 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
280 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
281 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
282 // Will it blend?
283 GrColor clearColor;
cdalton1fa45722015-06-02 10:43:39 -0700284 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillipsa106c622015-10-16 09:07:06 -0700285 this->getDrawTarget()->clear(nullptr, clearColor, true, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700286 return;
287 }
288 }
289 }
290 }
291
292 GrColor color = paint.getColor();
bsalomonc55271f2015-11-09 11:55:57 -0800293 bool needAA = should_apply_coverage_aa(paint, pipelineBuilder.getRenderTarget());
robertphillipsea461502015-05-26 11:38:03 -0700294
joshualitt9be0b002015-08-19 11:50:51 -0700295 // The fill path can handle rotation but not skew
296 // The stroke path needs the rect to remain axis aligned (no rotation or skew)
robertphillipsfac9ceb2015-09-03 08:32:08 -0700297 // None of our AA draw rect calls can handle perspective yet
bsalomonc55271f2015-11-09 11:55:57 -0800298 bool canApplyAA = width >=0 ? viewMatrix.rectStaysRect() :
299 view_matrix_ok_for_aa_fill_rect(viewMatrix);
joshualitt9be0b002015-08-19 11:50:51 -0700300
301 if (needAA && canApplyAA) {
robertphillipsfac9ceb2015-09-03 08:32:08 -0700302 SkASSERT(!viewMatrix.hasPerspective());
bsalomonabd30f52015-08-13 13:34:48 -0700303 SkAutoTUnref<GrDrawBatch> batch;
robertphillipsea461502015-05-26 11:38:03 -0700304 if (width >= 0) {
joshualitt10cae832015-09-22 12:50:33 -0700305 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, *strokeInfo));
robertphillipsea461502015-05-26 11:38:03 -0700306 } else {
joshualitt10cae832015-09-22 12:50:33 -0700307 SkRect devBoundRect;
308 viewMatrix.mapRect(&devBoundRect, rect);
joshualittd2b23e02015-08-21 10:53:34 -0700309 batch.reset(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect, devBoundRect));
robertphillipsea461502015-05-26 11:38:03 -0700310 }
robertphillipsa106c622015-10-16 09:07:06 -0700311 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700312 return;
313 }
314
315 if (width >= 0) {
robertphillipsea461502015-05-26 11:38:03 -0700316 // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
robertphillips2e1e51f2015-10-15 08:01:48 -0700317 bool snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled());
joshualittd2b23e02015-08-21 10:53:34 -0700318 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAStroke(
bsalomonabd30f52015-08-13 13:34:48 -0700319 color, viewMatrix, rect, width, snapToPixelCenters));
robertphillipsea461502015-05-26 11:38:03 -0700320
321 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
322 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA
323 // is enabled because it can cause ugly artifacts.
324 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
325 snapToPixelCenters);
robertphillipsa106c622015-10-16 09:07:06 -0700326 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700327 } else {
328 // filled BW rect
robertphillipsa106c622015-10-16 09:07:06 -0700329 this->getDrawTarget()->drawNonAARect(pipelineBuilder, color, viewMatrix, rect);
robertphillipsea461502015-05-26 11:38:03 -0700330 }
331}
332
bsalomona2e69fc2015-11-05 10:41:43 -0800333void GrDrawContext::fillRectToRect(const GrClip& clip,
334 const GrPaint& paint,
335 const SkMatrix& viewMatrix,
336 const SkRect& rectToDraw,
337 const SkRect& localRect) {
robertphillipsea461502015-05-26 11:38:03 -0700338 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700339 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700340
robertphillips77a2e522015-10-17 07:43:27 -0700341 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700342
343 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
bsalomonc55271f2015-11-09 11:55:57 -0800344 if (should_apply_coverage_aa(paint, fRenderTarget) &&
345 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
346 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(
347 paint.getColor(), viewMatrix, rectToDraw, localRect));
348 if (batch) {
349 this->drawBatch(&pipelineBuilder, batch);
350 }
351 } else {
352 this->getDrawTarget()->drawNonAARect(pipelineBuilder,
353 paint.getColor(),
354 viewMatrix,
355 rectToDraw,
356 localRect);
357 }
joshualittb6b513b2015-08-21 10:25:18 -0700358}
359
bsalomona2e69fc2015-11-05 10:41:43 -0800360void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
361 const GrPaint& paint,
362 const SkMatrix& viewMatrix,
363 const SkRect& rectToDraw,
364 const SkMatrix& localMatrix) {
joshualittb6b513b2015-08-21 10:25:18 -0700365 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700366 SkDEBUGCODE(this->validate();)
joshualittb6b513b2015-08-21 10:25:18 -0700367
robertphillips77a2e522015-10-17 07:43:27 -0700368 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700369
370 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
bsalomonc55271f2015-11-09 11:55:57 -0800371 if (should_apply_coverage_aa(paint, pipelineBuilder.getRenderTarget()) &&
372 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
373 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(
374 paint.getColor(), viewMatrix, localMatrix, rectToDraw));
375 this->drawBatch(&pipelineBuilder, batch);
376 } else {
377 this->getDrawTarget()->drawNonAARect(pipelineBuilder,
378 paint.getColor(),
379 viewMatrix,
380 rectToDraw,
381 localMatrix);
382 }
robertphillipsea461502015-05-26 11:38:03 -0700383}
384
robertphillips2e1e51f2015-10-15 08:01:48 -0700385void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700386 const GrPaint& paint,
387 const SkMatrix& viewMatrix,
388 GrPrimitiveType primitiveType,
389 int vertexCount,
390 const SkPoint positions[],
391 const SkPoint texCoords[],
392 const GrColor colors[],
393 const uint16_t indices[],
394 int indexCount) {
395 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700396 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700397
robertphillips77a2e522015-10-17 07:43:27 -0700398 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700399
400 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt7b670db2015-07-09 13:25:02 -0700401
robertphillipsea461502015-05-26 11:38:03 -0700402 // TODO clients should give us bounds
403 SkRect bounds;
404 if (!bounds.setBoundsCheck(positions, vertexCount)) {
405 SkDebugf("drawVertices call empty bounds\n");
406 return;
407 }
408
409 viewMatrix.mapRect(&bounds);
410
411 // 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 -0800412 // snapping. We also do this for the "hair" primitive types: lines and points since they have
413 // a 1 pixel thickness in device space.
414 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
415 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700416 bounds.outset(0.5f, 0.5f);
417 }
418
joshualitt2771b562015-08-07 12:46:26 -0700419 GrDrawVerticesBatch::Geometry geometry;
robertphillipsea461502015-05-26 11:38:03 -0700420 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700421 SkAutoTUnref<GrDrawBatch> batch(GrDrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
422 positions, vertexCount, indices,
423 indexCount, colors, texCoords,
424 bounds));
robertphillipsea461502015-05-26 11:38:03 -0700425
robertphillipsa106c622015-10-16 09:07:06 -0700426 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700427}
428
429///////////////////////////////////////////////////////////////////////////////
430
robertphillips2e1e51f2015-10-15 08:01:48 -0700431void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700432 const GrPaint& paint,
433 const SkMatrix& viewMatrix,
434 int spriteCount,
435 const SkRSXform xform[],
436 const SkRect texRect[],
437 const SkColor colors[]) {
438 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700439 SkDEBUGCODE(this->validate();)
440
robertphillips77a2e522015-10-17 07:43:27 -0700441 AutoCheckFlush acf(fDrawingManager);
jvanverth31ff7622015-08-07 10:09:28 -0700442
robertphillips2e1e51f2015-10-15 08:01:48 -0700443 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
jvanverth31ff7622015-08-07 10:09:28 -0700444
jvanverth14b88032015-08-07 12:18:54 -0700445 GrDrawAtlasBatch::Geometry geometry;
jvanverth31ff7622015-08-07 10:09:28 -0700446 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700447 SkAutoTUnref<GrDrawBatch> batch(GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount,
448 xform, texRect, colors));
jvanverth31ff7622015-08-07 10:09:28 -0700449
robertphillipsa106c622015-10-16 09:07:06 -0700450 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700451}
452
453///////////////////////////////////////////////////////////////////////////////
454
robertphillips2e1e51f2015-10-15 08:01:48 -0700455void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700456 const GrPaint& paint,
457 const SkMatrix& viewMatrix,
458 const SkRRect& rrect,
459 const GrStrokeInfo& strokeInfo) {
460 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700461 SkDEBUGCODE(this->validate();)
462
robertphillipsea461502015-05-26 11:38:03 -0700463 if (rrect.isEmpty()) {
464 return;
465 }
466
467 if (strokeInfo.isDashed()) {
468 SkPath path;
469 path.setIsVolatile(true);
470 path.addRRect(rrect);
robertphillips2e1e51f2015-10-15 08:01:48 -0700471 this->drawPath(clip, paint, viewMatrix, path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700472 return;
473 }
474
robertphillips77a2e522015-10-17 07:43:27 -0700475 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700476
robertphillips2e1e51f2015-10-15 08:01:48 -0700477 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700478 GrColor color = paint.getColor();
robertphillips2e1e51f2015-10-15 08:01:48 -0700479
robertphillipsa106c622015-10-16 09:07:06 -0700480 if (!GrOvalRenderer::DrawRRect(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700481 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700482 color,
483 viewMatrix,
484 paint.isAntiAlias(),
485 rrect,
486 strokeInfo)) {
487 SkPath path;
488 path.setIsVolatile(true);
489 path.addRRect(rrect);
robertphillipsb83bec52015-10-23 09:38:03 -0700490 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700491 paint.isAntiAlias(), path, strokeInfo);
492 }
493}
494
495///////////////////////////////////////////////////////////////////////////////
496
robertphillips2e1e51f2015-10-15 08:01:48 -0700497void GrDrawContext::drawDRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700498 const GrPaint& paint,
499 const SkMatrix& viewMatrix,
500 const SkRRect& outer,
501 const SkRRect& inner) {
502 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700503 SkDEBUGCODE(this->validate();)
504
robertphillipsea461502015-05-26 11:38:03 -0700505 if (outer.isEmpty()) {
506 return;
507 }
508
robertphillips77a2e522015-10-17 07:43:27 -0700509 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700510
robertphillips2e1e51f2015-10-15 08:01:48 -0700511 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700512 GrColor color = paint.getColor();
robertphillipsa106c622015-10-16 09:07:06 -0700513 if (!GrOvalRenderer::DrawDRRect(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700514 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700515 color,
516 viewMatrix,
517 paint.isAntiAlias(),
518 outer,
519 inner)) {
520 SkPath path;
521 path.setIsVolatile(true);
522 path.addRRect(inner);
523 path.addRRect(outer);
524 path.setFillType(SkPath::kEvenOdd_FillType);
525
526 GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
robertphillipsb83bec52015-10-23 09:38:03 -0700527 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700528 paint.isAntiAlias(), path, fillRec);
529 }
530}
531
532///////////////////////////////////////////////////////////////////////////////
533
robertphillips2e1e51f2015-10-15 08:01:48 -0700534void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700535 const GrPaint& paint,
536 const SkMatrix& viewMatrix,
537 const SkRect& oval,
538 const GrStrokeInfo& strokeInfo) {
539 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700540 SkDEBUGCODE(this->validate();)
541
robertphillipsea461502015-05-26 11:38:03 -0700542 if (oval.isEmpty()) {
543 return;
544 }
545
546 if (strokeInfo.isDashed()) {
547 SkPath path;
548 path.setIsVolatile(true);
549 path.addOval(oval);
robertphillips2e1e51f2015-10-15 08:01:48 -0700550 this->drawPath(clip, paint, viewMatrix, path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700551 return;
552 }
553
robertphillips77a2e522015-10-17 07:43:27 -0700554 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700555
robertphillips2e1e51f2015-10-15 08:01:48 -0700556 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700557 GrColor color = paint.getColor();
robertphillips2e1e51f2015-10-15 08:01:48 -0700558
robertphillipsa106c622015-10-16 09:07:06 -0700559 if (!GrOvalRenderer::DrawOval(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700560 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700561 color,
562 viewMatrix,
563 paint.isAntiAlias(),
564 oval,
565 strokeInfo)) {
566 SkPath path;
567 path.setIsVolatile(true);
568 path.addOval(oval);
robertphillipsb83bec52015-10-23 09:38:03 -0700569 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsea461502015-05-26 11:38:03 -0700570 paint.isAntiAlias(), path, strokeInfo);
571 }
572}
573
joshualitt33a5fce2015-11-18 13:28:51 -0800574void GrDrawContext::drawImageNine(const GrClip& clip,
575 const GrPaint& paint,
576 const SkMatrix& viewMatrix,
577 int imageWidth,
578 int imageHeight,
579 const SkIRect& center,
580 const SkRect& dst) {
581 RETURN_IF_ABANDONED
582 SkDEBUGCODE(this->validate();)
583
584 AutoCheckFlush acf(fDrawingManager);
585
586 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
587 imageWidth, imageHeight,
588 center, dst));
589
590 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
591 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
592}
593
594
robertphillipsea461502015-05-26 11:38:03 -0700595// Can 'path' be drawn as a pair of filled nested rectangles?
joshualittf9c5db22015-07-10 11:31:01 -0700596static bool is_nested_rects(const SkMatrix& viewMatrix,
robertphillipsea461502015-05-26 11:38:03 -0700597 const SkPath& path,
598 const SkStrokeRec& stroke,
599 SkRect rects[2]) {
600 SkASSERT(stroke.isFillStyle());
601
602 if (path.isInverseFillType()) {
603 return false;
604 }
605
606 // TODO: this restriction could be lifted if we were willing to apply
607 // the matrix to all the points individually rather than just to the rect
608 if (!viewMatrix.preservesAxisAlignment()) {
609 return false;
610 }
611
612 SkPath::Direction dirs[2];
613 if (!path.isNestedFillRects(rects, dirs)) {
614 return false;
615 }
616
617 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
618 // The two rects need to be wound opposite to each other
619 return false;
620 }
621
622 // Right now, nested rects where the margin is not the same width
623 // all around do not render correctly
624 const SkScalar* outer = rects[0].asScalars();
625 const SkScalar* inner = rects[1].asScalars();
626
627 bool allEq = true;
628
629 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
630 bool allGoE1 = margin >= SK_Scalar1;
631
632 for (int i = 1; i < 4; ++i) {
633 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
634 if (temp < SK_Scalar1) {
635 allGoE1 = false;
636 }
637 if (!SkScalarNearlyEqual(margin, temp)) {
638 allEq = false;
639 }
640 }
641
642 return allEq || allGoE1;
643}
644
robertphillips2e1e51f2015-10-15 08:01:48 -0700645void GrDrawContext::drawBatch(const GrClip& clip,
bsalomonabd30f52015-08-13 13:34:48 -0700646 const GrPaint& paint, GrDrawBatch* batch) {
joshualittb7ee1bf2015-08-10 11:59:02 -0700647 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700648 SkDEBUGCODE(this->validate();)
joshualittb7ee1bf2015-08-10 11:59:02 -0700649
robertphillips77a2e522015-10-17 07:43:27 -0700650 AutoCheckFlush acf(fDrawingManager);
joshualittb7ee1bf2015-08-10 11:59:02 -0700651
robertphillips2e1e51f2015-10-15 08:01:48 -0700652 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700653 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
joshualittb7ee1bf2015-08-10 11:59:02 -0700654}
655
robertphillips2e1e51f2015-10-15 08:01:48 -0700656void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700657 const GrPaint& paint,
658 const SkMatrix& viewMatrix,
659 const SkPath& path,
660 const GrStrokeInfo& strokeInfo) {
661 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700662 SkDEBUGCODE(this->validate();)
663
robertphillipsea461502015-05-26 11:38:03 -0700664 if (path.isEmpty()) {
665 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700666 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700667 }
668 return;
669 }
670
671 GrColor color = paint.getColor();
672
673 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
674 // Scratch textures can be recycled after they are returned to the texture
675 // cache. This presents a potential hazard for buffered drawing. However,
676 // the writePixels that uploads to the scratch will perform a flush so we're
677 // OK.
robertphillips77a2e522015-10-17 07:43:27 -0700678 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700679
robertphillips2e1e51f2015-10-15 08:01:48 -0700680 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsea461502015-05-26 11:38:03 -0700681 if (!strokeInfo.isDashed()) {
bsalomonc55271f2015-11-09 11:55:57 -0800682 bool useCoverageAA = should_apply_coverage_aa(paint, pipelineBuilder.getRenderTarget());
robertphillipsea461502015-05-26 11:38:03 -0700683
684 if (useCoverageAA && strokeInfo.getWidth() < 0 && !path.isConvex()) {
685 // Concave AA paths are expensive - try to avoid them for special cases
686 SkRect rects[2];
687
joshualittf9c5db22015-07-10 11:31:01 -0700688 if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -0700689 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
bsalomonabd30f52015-08-13 13:34:48 -0700690 color, viewMatrix, rects));
robertphillipsa106c622015-10-16 09:07:06 -0700691 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700692 return;
693 }
694 }
695 SkRect ovalRect;
696 bool isOval = path.isOval(&ovalRect);
697
698 if (isOval && !path.isInverseFillType()) {
robertphillipsa106c622015-10-16 09:07:06 -0700699 if (GrOvalRenderer::DrawOval(this->getDrawTarget(),
joshualittae3d63a2015-07-13 08:44:06 -0700700 pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700701 color,
702 viewMatrix,
703 paint.isAntiAlias(),
704 ovalRect,
705 strokeInfo)) {
706 return;
707 }
708 }
709 }
robertphillipsb83bec52015-10-23 09:38:03 -0700710 this->internalDrawPath(&pipelineBuilder, viewMatrix, color,
robertphillipsa106c622015-10-16 09:07:06 -0700711 paint.isAntiAlias(), path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700712}
713
robertphillipsb83bec52015-10-23 09:38:03 -0700714void GrDrawContext::internalDrawPath(GrPipelineBuilder* pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700715 const SkMatrix& viewMatrix,
716 GrColor color,
717 bool useAA,
718 const SkPath& path,
719 const GrStrokeInfo& strokeInfo) {
720 RETURN_IF_ABANDONED
721 SkASSERT(!path.isEmpty());
722
robertphillipsea461502015-05-26 11:38:03 -0700723 // An Assumption here is that path renderer would use some form of tweaking
724 // the src color (either the input alpha or in the frag shader) to implement
725 // aa. If we have some future driver-mojo path AA that can do the right
726 // thing WRT to the blend then we'll need some query on the PR.
727 bool useCoverageAA = useAA &&
vbuzinovdded6962015-06-12 08:59:45 -0700728 !pipelineBuilder->getRenderTarget()->isUnifiedMultisampled();
robertphillips68737822015-10-29 12:12:21 -0700729 bool isStencilDisabled = pipelineBuilder->getStencil().isDisabled();
730 bool isStencilBufferMSAA = pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -0700731
robertphillips68737822015-10-29 12:12:21 -0700732 const GrPathRendererChain::DrawType type =
733 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
734 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -0700735
736 const SkPath* pathPtr = &path;
737 SkTLazy<SkPath> tmpPath;
738 const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
739
robertphillips68737822015-10-29 12:12:21 -0700740 GrPathRenderer::CanDrawPathArgs canDrawArgs;
741 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
742 canDrawArgs.fViewMatrix = &viewMatrix;
743 canDrawArgs.fPath = pathPtr;
744 canDrawArgs.fStroke = strokeInfoPtr;
745 canDrawArgs.fAntiAlias = useCoverageAA;
746 canDrawArgs.fIsStencilDisabled = isStencilDisabled;
747 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
748
robertphillipsea461502015-05-26 11:38:03 -0700749 // Try a 1st time without stroking the path and without allowing the SW renderer
robertphillips68737822015-10-29 12:12:21 -0700750 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700751
752 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
halcanary96fcdcc2015-08-27 07:41:13 -0700753 if (nullptr == pr && strokeInfo.isDashed()) {
robertphillipsea461502015-05-26 11:38:03 -0700754 // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
755 if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
756 return;
757 }
758 pathPtr = tmpPath.get();
759 if (pathPtr->isEmpty()) {
760 return;
761 }
762 strokeInfoPtr = &dashlessStrokeInfo;
robertphillips68737822015-10-29 12:12:21 -0700763
764 canDrawArgs.fPath = pathPtr;
765 canDrawArgs.fStroke = strokeInfoPtr;
766
767 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700768 }
769
halcanary96fcdcc2015-08-27 07:41:13 -0700770 if (nullptr == pr) {
771 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, nullptr) &&
robertphillipsea461502015-05-26 11:38:03 -0700772 !strokeInfoPtr->isFillStyle()) {
773 // It didn't work above, so try again with stroke converted to a fill.
774 if (!tmpPath.isValid()) {
775 tmpPath.init();
776 }
777 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
778 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
779 return;
780 }
781 pathPtr = tmpPath.get();
782 if (pathPtr->isEmpty()) {
783 return;
784 }
785 dashlessStrokeInfo.setFillStyle();
786 strokeInfoPtr = &dashlessStrokeInfo;
787 }
788
robertphillips68737822015-10-29 12:12:21 -0700789 canDrawArgs.fPath = pathPtr;
790 canDrawArgs.fStroke = strokeInfoPtr;
791
robertphillipsea461502015-05-26 11:38:03 -0700792 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -0700793 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -0700794 }
795
halcanary96fcdcc2015-08-27 07:41:13 -0700796 if (nullptr == pr) {
robertphillipsea461502015-05-26 11:38:03 -0700797#ifdef SK_DEBUG
798 SkDebugf("Unable to find path renderer compatible with path.\n");
799#endif
800 return;
801 }
802
bsalomon0aff2fa2015-07-31 06:48:27 -0700803 GrPathRenderer::DrawPathArgs args;
robertphillipsb83bec52015-10-23 09:38:03 -0700804 args.fTarget = this->getDrawTarget();
robertphillips77a2e522015-10-17 07:43:27 -0700805 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
bsalomon0aff2fa2015-07-31 06:48:27 -0700806 args.fPipelineBuilder = pipelineBuilder;
807 args.fColor = color;
808 args.fViewMatrix = &viewMatrix;
809 args.fPath = pathPtr;
810 args.fStroke = strokeInfoPtr;
811 args.fAntiAlias = useCoverageAA;
812 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -0700813}
814
bsalomonabd30f52015-08-13 13:34:48 -0700815void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* batch) {
robertphillips2d70dcb2015-10-06 07:38:23 -0700816 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700817 SkDEBUGCODE(this->validate();)
robertphillips2d70dcb2015-10-06 07:38:23 -0700818
robertphillipsa106c622015-10-16 09:07:06 -0700819 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch);
robertphillips2334fb62015-06-17 05:43:33 -0700820}