blob: 549e5ebf80b0efc82bf39950692df8dde15ed659 [file] [log] [blame]
robertphillipsea461502015-05-26 11:38:03 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
robertphillipsea461502015-05-26 11:38:03 -07008#include "GrBatchTest.h"
jvanverth31ff7622015-08-07 10:09:28 -07009#include "GrColor.h"
robertphillipsea461502015-05-26 11:38:03 -070010#include "GrDrawContext.h"
robertphillips391395d2016-03-02 09:26:36 -080011#include "GrDrawContextPriv.h"
robertphillips77a2e522015-10-17 07:43:27 -070012#include "GrDrawingManager.h"
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
robertphillips00095892016-02-29 13:50:40 -080026#include "effects/GrRRectEffect.h"
27
joshualitte8042922015-12-11 06:11:21 -080028#include "text/GrAtlasTextContext.h"
29#include "text/GrStencilAndCoverTextContext.h"
30
joshualittbc907352016-01-13 06:45:40 -080031#include "../private/GrAuditTrail.h"
32
robertphillips77a2e522015-10-17 07:43:27 -070033#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080034#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080035 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080036#define ASSERT_SINGLE_OWNER_PRIV \
37 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
robertphillips77a2e522015-10-17 07:43:27 -070038#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
39#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; }
robertphillips391395d2016-03-02 09:26:36 -080040#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->abandoned()) { return false; }
robertphillips77a2e522015-10-17 07:43:27 -070041#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070042
43class AutoCheckFlush {
44public:
halcanary9d524f22016-03-29 09:03:52 -070045 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070046 SkASSERT(fDrawingManager);
47 }
48 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070049
50private:
robertphillips77a2e522015-10-17 07:43:27 -070051 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070052};
53
robertphillipsa106c622015-10-16 09:07:06 -070054// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
55// drawTargets to be picked up and added to by drawContexts lower in the call
56// stack. When this occurs with a closed drawTarget, a new one will be allocated
57// when the drawContext attempts to use it (via getDrawTarget).
joshualitt1b39f432016-02-11 06:46:52 -080058GrDrawContext::GrDrawContext(GrContext* context,
59 GrDrawingManager* drawingMgr,
robertphillips6c7e3252016-04-27 10:47:51 -070060 sk_sp<GrRenderTarget> rt,
joshualittde8dc7e2016-01-08 10:09:13 -080061 const SkSurfaceProps* surfaceProps,
joshualittbc907352016-01-13 06:45:40 -080062 GrAuditTrail* auditTrail,
joshualittde8dc7e2016-01-08 10:09:13 -080063 GrSingleOwner* singleOwner)
robertphillips77a2e522015-10-17 07:43:27 -070064 : fDrawingManager(drawingMgr)
robertphillips6c7e3252016-04-27 10:47:51 -070065 , fRenderTarget(std::move(rt))
66 , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
joshualitt1b39f432016-02-11 06:46:52 -080067 , fContext(context)
joshualittde8dc7e2016-01-08 10:09:13 -080068 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080069 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080070#ifdef SK_DEBUG
71 , fSingleOwner(singleOwner)
72#endif
73{
robertphillips2e1e51f2015-10-15 08:01:48 -070074 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070075}
76
robertphillips2e1e51f2015-10-15 08:01:48 -070077#ifdef SK_DEBUG
78void GrDrawContext::validate() const {
79 SkASSERT(fRenderTarget);
80 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070081
82 if (fDrawTarget && !fDrawTarget->isClosed()) {
83 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
84 }
robertphillips2e1e51f2015-10-15 08:01:48 -070085}
86#endif
87
robertphillipsa106c622015-10-16 09:07:06 -070088GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -080089 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070090 SkSafeUnref(fDrawTarget);
91}
92
93GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -080094 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070095 SkDEBUGCODE(this->validate();)
96
97 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips6c7e3252016-04-27 10:47:51 -070098 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
robertphillipsa106c622015-10-16 09:07:06 -070099 }
100
101 return fDrawTarget;
102}
103
bsalomonb8fea972016-02-16 07:34:17 -0800104bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800105 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800106 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700107 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800108 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700109
robertphillips6c7e3252016-04-27 10:47:51 -0700110 return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700111}
112
robertphillips2e1e51f2015-10-15 08:01:48 -0700113void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700114 const SkPaint& skPaint,
115 const SkMatrix& viewMatrix,
116 const char text[], size_t byteLength,
117 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800118 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700119 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700120 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800121 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700122
joshualitt96880d92016-02-16 10:36:53 -0800123 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800124 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700125 }
126
joshualitt96880d92016-02-16 10:36:53 -0800127 fAtlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
128 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700129}
robertphillipscaef3452015-11-11 13:18:11 -0800130
robertphillips2e1e51f2015-10-15 08:01:48 -0700131void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700132 const SkPaint& skPaint,
133 const SkMatrix& viewMatrix,
134 const char text[], size_t byteLength,
135 const SkScalar pos[], int scalarsPerPosition,
136 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800137 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700138 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700139 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800140 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700141
joshualitt96880d92016-02-16 10:36:53 -0800142 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800143 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700144 }
145
joshualitt96880d92016-02-16 10:36:53 -0800146 fAtlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
147 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
148 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700149
150}
robertphillipscaef3452015-11-11 13:18:11 -0800151
robertphillips2e1e51f2015-10-15 08:01:48 -0700152void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700153 const SkMatrix& viewMatrix, const SkTextBlob* blob,
154 SkScalar x, SkScalar y,
155 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800156 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700157 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700158 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800159 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700160
joshualitt96880d92016-02-16 10:36:53 -0800161 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800162 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700163 }
164
joshualitt96880d92016-02-16 10:36:53 -0800165 fAtlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
166 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700167}
168
robertphillips2e1e51f2015-10-15 08:01:48 -0700169void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800170 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700171 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700172 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800173 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700174
robertphillips77a2e522015-10-17 07:43:27 -0700175 AutoCheckFlush acf(fDrawingManager);
robertphillips6c7e3252016-04-27 10:47:51 -0700176 this->getDrawTarget()->discard(fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700177}
178
robertphillips2e1e51f2015-10-15 08:01:48 -0700179void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700180 const GrColor color,
181 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800182 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700183 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700184 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800185 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700186
robertphillips77a2e522015-10-17 07:43:27 -0700187 AutoCheckFlush acf(fDrawingManager);
robertphillips6c7e3252016-04-27 10:47:51 -0700188 this->getDrawTarget()->clear(rect, color, canIgnoreRect, fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700189}
190
191
robertphillips2e1e51f2015-10-15 08:01:48 -0700192void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700193 const GrPaint& origPaint,
194 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800195 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700196 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700197 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800198 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700199
robertphillipsea461502015-05-26 11:38:03 -0700200 // set rect to be big enough to fill the space, but not super-huge, so we
201 // don't overflow fixed-point implementations
202 SkRect r;
203 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700204 SkIntToScalar(fRenderTarget->width()),
205 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700206 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
207
208 // by definition this fills the entire clip, no need for AA
209 if (paint->isAntiAlias()) {
210 paint.writable()->setAntiAlias(false);
211 }
212
213 bool isPerspective = viewMatrix.hasPerspective();
214
215 // We attempt to map r by the inverse matrix and draw that. mapRect will
216 // map the four corners and bound them with a new rect. This will not
217 // produce a correct result for some perspective matrices.
218 if (!isPerspective) {
219 SkMatrix inverse;
220 if (!viewMatrix.invert(&inverse)) {
221 SkDebugf("Could not invert matrix\n");
222 return;
223 }
224 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700225 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700226 } else {
227 SkMatrix localMatrix;
228 if (!viewMatrix.invert(&localMatrix)) {
229 SkDebugf("Could not invert matrix\n");
230 return;
231 }
232
robertphillips77a2e522015-10-17 07:43:27 -0700233 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700234
joshualitt04194f32016-01-13 10:08:27 -0800235 SkAutoTUnref<GrDrawBatch> batch(
236 GrRectBatchFactory::CreateNonAAFill(paint->getColor(), SkMatrix::I(), r, nullptr,
237 &localMatrix));
cdalton862cff32016-05-12 15:09:48 -0700238 GrPipelineBuilder pipelineBuilder(*paint, fRenderTarget.get());
239 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700240 }
241}
242
robertphillipsea461502015-05-26 11:38:03 -0700243static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
244 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
245 point.fY >= rect.fTop && point.fY <= rect.fBottom;
246}
247
bsalomonc55271f2015-11-09 11:55:57 -0800248static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
249 return viewMatrix.preservesRightAngles();
250}
251
252static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) {
253 return paint.isAntiAlias() && !rt->isUnifiedMultisampled();
254}
255
robertphillips391395d2016-03-02 09:26:36 -0800256GrDrawBatch* GrDrawContext::getFillRectBatch(const GrPaint& paint,
257 const SkMatrix& viewMatrix,
258 const SkRect& rect) {
259
260 GrDrawBatch* batch = nullptr;
robertphillips6c7e3252016-04-27 10:47:51 -0700261 if (should_apply_coverage_aa(paint, fRenderTarget.get())) {
robertphillips391395d2016-03-02 09:26:36 -0800262 // The fill path can handle rotation but not skew.
263 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
264 SkRect devBoundRect;
265 viewMatrix.mapRect(&devBoundRect, rect);
266 batch = GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix,
267 rect, devBoundRect);
268 }
269 } else {
270 // filled BW rect
271 batch = GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect,
halcanary9d524f22016-03-29 09:03:52 -0700272 nullptr, nullptr);
robertphillips391395d2016-03-02 09:26:36 -0800273 }
274
275 return batch;
276}
277
robertphillips2e1e51f2015-10-15 08:01:48 -0700278void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700279 const GrPaint& paint,
280 const SkMatrix& viewMatrix,
281 const SkRect& rect,
bsalomon6663acf2016-05-10 09:14:17 -0700282 const GrStyle* style) {
283 if (!style) {
284 style = &GrStyle::SimpleFill();
285 }
joshualitt1de610a2016-01-06 08:26:09 -0800286 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700287 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700288 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800289 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700290
bsalomon6663acf2016-05-10 09:14:17 -0700291 // Path effects should've been devolved to a path in SkGpuDevice
292 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700293
robertphillips77a2e522015-10-17 07:43:27 -0700294 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700295
bsalomon6663acf2016-05-10 09:14:17 -0700296 const SkStrokeRec& stroke = style->strokeRec();
297 SkScalar width = stroke.getWidth();
robertphillipsea461502015-05-26 11:38:03 -0700298
299 // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
300 // cases where the RT is fully inside a stroke.
301 if (width < 0) {
302 SkRect rtRect;
robertphillips954cbc12015-12-02 10:33:46 -0800303 fRenderTarget->getBoundsRect(&rtRect);
robertphillipsea461502015-05-26 11:38:03 -0700304 // Does the clip contain the entire RT?
cdalton846c0512016-05-13 10:25:00 -0700305 if (clip.quickContains(rtRect)) {
robertphillipsea461502015-05-26 11:38:03 -0700306 SkMatrix invM;
307 if (!viewMatrix.invert(&invM)) {
308 return;
309 }
310 // Does the rect bound the RT?
311 SkPoint srcSpaceRTQuad[4];
312 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
313 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
314 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
315 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
316 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
317 // Will it blend?
318 GrColor clearColor;
cdalton1fa45722015-06-02 10:43:39 -0700319 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips6c7e3252016-04-27 10:47:51 -0700320 this->getDrawTarget()->clear(nullptr, clearColor, true, fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700321 return;
322 }
323 }
324 }
325 }
326
robertphillips4bc31812016-03-01 12:22:49 -0800327 bool snapToPixelCenters = false;
joshualitt04194f32016-01-13 10:08:27 -0800328 SkAutoTUnref<GrDrawBatch> batch;
robertphillips391395d2016-03-02 09:26:36 -0800329 if (width < 0) {
330 batch.reset(this->getFillRectBatch(paint, viewMatrix, rect));
331 } else {
332 GrColor color = paint.getColor();
333
robertphillips6c7e3252016-04-27 10:47:51 -0700334 if (should_apply_coverage_aa(paint, fRenderTarget.get())) {
cdaltonbb539482016-01-04 09:48:25 -0800335 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
336 if (viewMatrix.rectStaysRect()) {
robertphillips391395d2016-03-02 09:26:36 -0800337 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect,
bsalomon6663acf2016-05-10 09:14:17 -0700338 stroke));
cdaltonbb539482016-01-04 09:48:25 -0800339 }
robertphillipsea461502015-05-26 11:38:03 -0700340 } else {
robertphillips391395d2016-03-02 09:26:36 -0800341 // Non-AA hairlines are snapped to pixel centers to make which pixels are hit
342 // deterministic
343 snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled());
344 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
345 width, snapToPixelCenters));
robertphillips8b8f36f2016-03-02 08:53:12 -0800346
robertphillips391395d2016-03-02 09:26:36 -0800347 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700348 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800349 // when MSAA is enabled because it can cause ugly artifacts.
350 }
robertphillipsea461502015-05-26 11:38:03 -0700351 }
robertphillips4bc31812016-03-01 12:22:49 -0800352
353 if (batch) {
cdalton862cff32016-05-12 15:09:48 -0700354 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
robertphillips4bc31812016-03-01 12:22:49 -0800355
356 if (snapToPixelCenters) {
357 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
358 snapToPixelCenters);
359 }
360
cdalton862cff32016-05-12 15:09:48 -0700361 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillips4bc31812016-03-01 12:22:49 -0800362 return;
363 }
halcanary9d524f22016-03-29 09:03:52 -0700364
robertphillips4bc31812016-03-01 12:22:49 -0800365 SkPath path;
366 path.setIsVolatile(true);
367 path.addRect(rect);
bsalomon6663acf2016-05-10 09:14:17 -0700368 this->internalDrawPath(clip, paint, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700369}
370
cdalton846c0512016-05-13 10:25:00 -0700371bool GrDrawContextPriv::drawAndStencilRect(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -0700372 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -0800373 SkRegion::Op op,
374 bool invert,
375 bool doAA,
376 const SkMatrix& viewMatrix,
377 const SkRect& rect) {
378 ASSERT_SINGLE_OWNER_PRIV
379 RETURN_FALSE_IF_ABANDONED_PRIV
380 SkDEBUGCODE(fDrawContext->validate();)
381 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::stencilRect");
382
383 AutoCheckFlush acf(fDrawContext->fDrawingManager);
384
385 GrPaint paint;
386 paint.setAntiAlias(doAA);
387 paint.setCoverageSetOpXPFactory(op, invert);
388
389 SkAutoTUnref<GrDrawBatch> batch(fDrawContext->getFillRectBatch(paint, viewMatrix, rect));
390 if (batch) {
cdalton862cff32016-05-12 15:09:48 -0700391 GrPipelineBuilder pipelineBuilder(paint, fDrawContext->accessRenderTarget());
cdalton93a379b2016-05-11 13:58:08 -0700392 pipelineBuilder.setUserStencil(ss);
robertphillips391395d2016-03-02 09:26:36 -0800393
cdalton862cff32016-05-12 15:09:48 -0700394 fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillips391395d2016-03-02 09:26:36 -0800395 return true;
396 }
397
398 SkPath path;
399 path.setIsVolatile(true);
400 path.addRect(rect);
cdalton862cff32016-05-12 15:09:48 -0700401 return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800402}
403
bsalomona2e69fc2015-11-05 10:41:43 -0800404void GrDrawContext::fillRectToRect(const GrClip& clip,
405 const GrPaint& paint,
406 const SkMatrix& viewMatrix,
407 const SkRect& rectToDraw,
408 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800409 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700410 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700411 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800412 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700413
robertphillips77a2e522015-10-17 07:43:27 -0700414 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700415
joshualitt04194f32016-01-13 10:08:27 -0800416 SkAutoTUnref<GrDrawBatch> batch;
robertphillips6c7e3252016-04-27 10:47:51 -0700417 if (should_apply_coverage_aa(paint, fRenderTarget.get()) &&
bsalomonc55271f2015-11-09 11:55:57 -0800418 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800419 batch.reset(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(), viewMatrix, rectToDraw,
420 localRect));
bsalomonc55271f2015-11-09 11:55:57 -0800421 } else {
joshualitt04194f32016-01-13 10:08:27 -0800422 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
423 &localRect, nullptr));
424 }
425
426 if (batch) {
cdalton862cff32016-05-12 15:09:48 -0700427 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
428 this->drawBatch(&pipelineBuilder, clip, batch);
bsalomonc55271f2015-11-09 11:55:57 -0800429 }
joshualittb6b513b2015-08-21 10:25:18 -0700430}
431
bsalomona2e69fc2015-11-05 10:41:43 -0800432void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
433 const GrPaint& paint,
434 const SkMatrix& viewMatrix,
435 const SkRect& rectToDraw,
436 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800437 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700438 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700439 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800440 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700441
robertphillips77a2e522015-10-17 07:43:27 -0700442 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700443
joshualitt04194f32016-01-13 10:08:27 -0800444 SkAutoTUnref<GrDrawBatch> batch;
robertphillips6c7e3252016-04-27 10:47:51 -0700445 if (should_apply_coverage_aa(paint, fRenderTarget.get()) &&
bsalomonc55271f2015-11-09 11:55:57 -0800446 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800447 batch.reset(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix, localMatrix,
448 rectToDraw));
bsalomonc55271f2015-11-09 11:55:57 -0800449 } else {
joshualitt04194f32016-01-13 10:08:27 -0800450 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
451 nullptr, &localMatrix));
bsalomonc55271f2015-11-09 11:55:57 -0800452 }
robertphillips4bc31812016-03-01 12:22:49 -0800453
cdalton862cff32016-05-12 15:09:48 -0700454 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
455 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700456}
457
robertphillips2e1e51f2015-10-15 08:01:48 -0700458void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700459 const GrPaint& paint,
460 const SkMatrix& viewMatrix,
461 GrPrimitiveType primitiveType,
462 int vertexCount,
463 const SkPoint positions[],
464 const SkPoint texCoords[],
465 const GrColor colors[],
466 const uint16_t indices[],
467 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800468 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700469 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700470 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800471 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700472
robertphillips77a2e522015-10-17 07:43:27 -0700473 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700474
robertphillipsea461502015-05-26 11:38:03 -0700475 // TODO clients should give us bounds
476 SkRect bounds;
477 if (!bounds.setBoundsCheck(positions, vertexCount)) {
478 SkDebugf("drawVertices call empty bounds\n");
479 return;
480 }
481
482 viewMatrix.mapRect(&bounds);
483
484 // 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 -0800485 // snapping. We also do this for the "hair" primitive types: lines and points since they have
486 // a 1 pixel thickness in device space.
487 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
488 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700489 bounds.outset(0.5f, 0.5f);
490 }
491
joshualitt2771b562015-08-07 12:46:26 -0700492 GrDrawVerticesBatch::Geometry geometry;
robertphillipsea461502015-05-26 11:38:03 -0700493 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700494 SkAutoTUnref<GrDrawBatch> batch(GrDrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
495 positions, vertexCount, indices,
496 indexCount, colors, texCoords,
497 bounds));
robertphillipsea461502015-05-26 11:38:03 -0700498
cdalton862cff32016-05-12 15:09:48 -0700499 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
500 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700501}
502
503///////////////////////////////////////////////////////////////////////////////
504
robertphillips2e1e51f2015-10-15 08:01:48 -0700505void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700506 const GrPaint& paint,
507 const SkMatrix& viewMatrix,
508 int spriteCount,
509 const SkRSXform xform[],
510 const SkRect texRect[],
511 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800512 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700513 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700514 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800515 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700516
robertphillips77a2e522015-10-17 07:43:27 -0700517 AutoCheckFlush acf(fDrawingManager);
halcanary9d524f22016-03-29 09:03:52 -0700518
jvanverth14b88032015-08-07 12:18:54 -0700519 GrDrawAtlasBatch::Geometry geometry;
jvanverth31ff7622015-08-07 10:09:28 -0700520 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700521 SkAutoTUnref<GrDrawBatch> batch(GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount,
522 xform, texRect, colors));
halcanary9d524f22016-03-29 09:03:52 -0700523
cdalton862cff32016-05-12 15:09:48 -0700524 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
525 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700526}
527
528///////////////////////////////////////////////////////////////////////////////
529
robertphillips2e1e51f2015-10-15 08:01:48 -0700530void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700531 const GrPaint& paint,
532 const SkMatrix& viewMatrix,
533 const SkRRect& rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700534 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800535 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700536 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700537 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800538 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700539
robertphillipsea461502015-05-26 11:38:03 -0700540 if (rrect.isEmpty()) {
541 return;
542 }
543
bsalomon6663acf2016-05-10 09:14:17 -0700544 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
545 const SkStrokeRec stroke = style.strokeRec();
robertphillips77a2e522015-10-17 07:43:27 -0700546 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700547
robertphillips6c7e3252016-04-27 10:47:51 -0700548 if (should_apply_coverage_aa(paint, fRenderTarget.get())) {
robertphillipsb56f9272016-02-25 11:03:52 -0800549 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
550
robertphillips4bc31812016-03-01 12:22:49 -0800551 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800552 viewMatrix,
553 rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700554 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800555 shaderCaps));
556 if (batch) {
cdalton862cff32016-05-12 15:09:48 -0700557 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
558 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800559 return;
560 }
robertphillipsea461502015-05-26 11:38:03 -0700561 }
robertphillipsb56f9272016-02-25 11:03:52 -0800562
563 SkPath path;
564 path.setIsVolatile(true);
565 path.addRRect(rrect);
bsalomon6663acf2016-05-10 09:14:17 -0700566 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700567}
568
robertphillips00095892016-02-29 13:50:40 -0800569bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
570 const GrPaint& paintIn,
571 const SkMatrix& viewMatrix,
572 const SkRRect& origOuter,
573 const SkRRect& origInner) {
574 SkASSERT(!origInner.isEmpty());
575 SkASSERT(!origOuter.isEmpty());
576
577 bool applyAA = paintIn.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
578
579 GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
580 kInverseFillBW_GrProcessorEdgeType;
581 GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
582 kFillBW_GrProcessorEdgeType;
583
584 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
585 SkMatrix inverseVM;
586 if (!viewMatrix.isIdentity()) {
587 if (!origInner.transform(viewMatrix, inner.writable())) {
588 return false;
589 }
590 if (!origOuter.transform(viewMatrix, outer.writable())) {
591 return false;
592 }
593 if (!viewMatrix.invert(&inverseVM)) {
594 return false;
595 }
596 } else {
597 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -0700598 }
robertphillips00095892016-02-29 13:50:40 -0800599
600 GrPaint grPaint(paintIn);
601 grPaint.setAntiAlias(false);
602
603 // TODO these need to be a geometry processors
604 SkAutoTUnref<GrFragmentProcessor> innerEffect(GrRRectEffect::Create(innerEdgeType, *inner));
605 if (!innerEffect) {
606 return false;
607 }
608
609 SkAutoTUnref<GrFragmentProcessor> outerEffect(GrRRectEffect::Create(outerEdgeType, *outer));
610 if (!outerEffect) {
611 return false;
612 }
613
614 grPaint.addCoverageFragmentProcessor(innerEffect);
615 grPaint.addCoverageFragmentProcessor(outerEffect);
616
617 SkRect bounds = outer->getBounds();
618 if (applyAA) {
619 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
620 }
halcanary9d524f22016-03-29 09:03:52 -0700621
robertphillips00095892016-02-29 13:50:40 -0800622 this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
623 return true;
624}
625
626void GrDrawContext::drawDRRect(const GrClip& clip,
627 const GrPaint& paint,
628 const SkMatrix& viewMatrix,
629 const SkRRect& outer,
630 const SkRRect& inner) {
631 ASSERT_SINGLE_OWNER
632 RETURN_IF_ABANDONED
633 SkDEBUGCODE(this->validate();)
634 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
635
636 SkASSERT(!outer.isEmpty());
637 SkASSERT(!inner.isEmpty());
638
639 AutoCheckFlush acf(fDrawingManager);
640
641 if (this->drawFilledDRRect(clip, paint, viewMatrix, outer, inner)) {
642 return;
643 }
644
645 SkPath path;
646 path.setIsVolatile(true);
647 path.addRRect(inner);
648 path.addRRect(outer);
649 path.setFillType(SkPath::kEvenOdd_FillType);
650
bsalomon6663acf2016-05-10 09:14:17 -0700651 this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -0800652}
653
robertphillipsea461502015-05-26 11:38:03 -0700654///////////////////////////////////////////////////////////////////////////////
655
robertphillips2e1e51f2015-10-15 08:01:48 -0700656void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700657 const GrPaint& paint,
658 const SkMatrix& viewMatrix,
659 const SkRect& oval,
bsalomon6663acf2016-05-10 09:14:17 -0700660 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800661 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700662 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700663 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800664 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -0700665
robertphillipsea461502015-05-26 11:38:03 -0700666 if (oval.isEmpty()) {
667 return;
668 }
669
bsalomon6663acf2016-05-10 09:14:17 -0700670 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700671
robertphillips77a2e522015-10-17 07:43:27 -0700672 AutoCheckFlush acf(fDrawingManager);
bsalomon6663acf2016-05-10 09:14:17 -0700673 const SkStrokeRec& stroke = style.strokeRec();
robertphillips6c7e3252016-04-27 10:47:51 -0700674 if (should_apply_coverage_aa(paint, fRenderTarget.get())) {
robertphillipsb56f9272016-02-25 11:03:52 -0800675 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800676 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800677 viewMatrix,
678 oval,
bsalomon6663acf2016-05-10 09:14:17 -0700679 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800680 shaderCaps));
681 if (batch) {
cdalton862cff32016-05-12 15:09:48 -0700682 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
683 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800684 return;
685 }
robertphillipsea461502015-05-26 11:38:03 -0700686 }
robertphillipsb56f9272016-02-25 11:03:52 -0800687
688 SkPath path;
689 path.setIsVolatile(true);
690 path.addOval(oval);
bsalomon6663acf2016-05-10 09:14:17 -0700691 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700692}
693
joshualitt33a5fce2015-11-18 13:28:51 -0800694void GrDrawContext::drawImageNine(const GrClip& clip,
695 const GrPaint& paint,
696 const SkMatrix& viewMatrix,
697 int imageWidth,
698 int imageHeight,
699 const SkIRect& center,
700 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -0800701 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -0800702 RETURN_IF_ABANDONED
703 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800704 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageNine");
joshualitt33a5fce2015-11-18 13:28:51 -0800705
706 AutoCheckFlush acf(fDrawingManager);
707
708 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
709 imageWidth, imageHeight,
710 center, dst));
711
cdalton862cff32016-05-12 15:09:48 -0700712 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
713 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
joshualitt33a5fce2015-11-18 13:28:51 -0800714}
715
716
robertphillipsea461502015-05-26 11:38:03 -0700717// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -0700718static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -0700719
720 if (path.isInverseFillType()) {
721 return false;
722 }
723
724 // TODO: this restriction could be lifted if we were willing to apply
725 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -0800726 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -0700727 return false;
728 }
729
730 SkPath::Direction dirs[2];
731 if (!path.isNestedFillRects(rects, dirs)) {
732 return false;
733 }
734
735 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
736 // The two rects need to be wound opposite to each other
737 return false;
738 }
739
740 // Right now, nested rects where the margin is not the same width
741 // all around do not render correctly
742 const SkScalar* outer = rects[0].asScalars();
743 const SkScalar* inner = rects[1].asScalars();
744
745 bool allEq = true;
746
747 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
748 bool allGoE1 = margin >= SK_Scalar1;
749
750 for (int i = 1; i < 4; ++i) {
751 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
752 if (temp < SK_Scalar1) {
753 allGoE1 = false;
754 }
755 if (!SkScalarNearlyEqual(margin, temp)) {
756 allEq = false;
757 }
758 }
759
760 return allEq || allGoE1;
761}
762
robertphillips2e1e51f2015-10-15 08:01:48 -0700763void GrDrawContext::drawBatch(const GrClip& clip,
bsalomonabd30f52015-08-13 13:34:48 -0700764 const GrPaint& paint, GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800765 ASSERT_SINGLE_OWNER
joshualittb7ee1bf2015-08-10 11:59:02 -0700766 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700767 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800768 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
joshualittb7ee1bf2015-08-10 11:59:02 -0700769
robertphillips77a2e522015-10-17 07:43:27 -0700770 AutoCheckFlush acf(fDrawingManager);
joshualittb7ee1bf2015-08-10 11:59:02 -0700771
cdalton862cff32016-05-12 15:09:48 -0700772 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
773 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
joshualittb7ee1bf2015-08-10 11:59:02 -0700774}
775
robertphillips2e1e51f2015-10-15 08:01:48 -0700776void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700777 const GrPaint& paint,
778 const SkMatrix& viewMatrix,
779 const SkPath& path,
bsalomon6663acf2016-05-10 09:14:17 -0700780 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800781 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700782 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700783 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800784 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -0700785
robertphillipsea461502015-05-26 11:38:03 -0700786 if (path.isEmpty()) {
787 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700788 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700789 }
790 return;
791 }
792
robertphillips77a2e522015-10-17 07:43:27 -0700793 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700794
bsalomon6663acf2016-05-10 09:14:17 -0700795 if (should_apply_coverage_aa(paint, fRenderTarget.get()) && !style.pathEffect()) {
796 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -0700797 // Concave AA paths are expensive - try to avoid them for special cases
798 SkRect rects[2];
799
bsalomon6663acf2016-05-10 09:14:17 -0700800 if (fills_as_nested_rects(viewMatrix, path, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -0700801 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
robertphillips4bc31812016-03-01 12:22:49 -0800802 paint.getColor(), viewMatrix, rects));
bsalomon40ef4852016-05-02 13:22:13 -0700803 if (batch) {
cdalton862cff32016-05-12 15:09:48 -0700804 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
805 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
bsalomon40ef4852016-05-02 13:22:13 -0700806 }
robertphillipsea461502015-05-26 11:38:03 -0700807 return;
808 }
809 }
810 SkRect ovalRect;
811 bool isOval = path.isOval(&ovalRect);
812
813 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -0800814 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800815 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillips0cc2f852016-02-24 13:36:56 -0800816 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -0800817 ovalRect,
bsalomon6663acf2016-05-10 09:14:17 -0700818 style.strokeRec(),
robertphillips0cc2f852016-02-24 13:36:56 -0800819 shaderCaps));
820 if (batch) {
cdalton862cff32016-05-12 15:09:48 -0700821 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
822 this->getDrawTarget()->drawBatch(pipelineBuilder, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700823 return;
824 }
825 }
826 }
robertphillips4bc31812016-03-01 12:22:49 -0800827
828 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
829 // Scratch textures can be recycled after they are returned to the texture
830 // cache. This presents a potential hazard for buffered drawing. However,
831 // the writePixels that uploads to the scratch will perform a flush so we're
832 // OK.
bsalomon6663acf2016-05-10 09:14:17 -0700833 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700834}
835
cdalton846c0512016-05-13 10:25:00 -0700836bool GrDrawContextPriv::drawAndStencilPath(const GrFixedClip& clip,
cdalton93a379b2016-05-11 13:58:08 -0700837 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -0800838 SkRegion::Op op,
839 bool invert,
840 bool doAA,
841 const SkMatrix& viewMatrix,
842 const SkPath& path) {
843 ASSERT_SINGLE_OWNER_PRIV
844 RETURN_FALSE_IF_ABANDONED_PRIV
845 SkDEBUGCODE(fDrawContext->validate();)
846 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath");
847
848 if (path.isEmpty() && path.isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -0700849 this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
robertphillips6c7e3252016-04-27 10:47:51 -0700850 SkRect::MakeIWH(fDrawContext->width(),
851 fDrawContext->height()));
robertphillips391395d2016-03-02 09:26:36 -0800852 return true;
853 }
854
855 AutoCheckFlush acf(fDrawContext->fDrawingManager);
856
857 // An Assumption here is that path renderer would use some form of tweaking
858 // the src color (either the input alpha or in the frag shader) to implement
859 // aa. If we have some future driver-mojo path AA that can do the right
860 // thing WRT to the blend then we'll need some query on the PR.
861 bool useCoverageAA = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled();
cdalton93a379b2016-05-11 13:58:08 -0700862 bool hasUserStencilSettings = (&GrUserStencilSettings::kUnused != ss);
robertphillips391395d2016-03-02 09:26:36 -0800863 bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled();
864
865 const GrPathRendererChain::DrawType type =
866 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
867 : GrPathRendererChain::kColor_DrawType;
868
869 GrPathRenderer::CanDrawPathArgs canDrawArgs;
870 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
871 canDrawArgs.fViewMatrix = &viewMatrix;
872 canDrawArgs.fPath = &path;
bsalomon6663acf2016-05-10 09:14:17 -0700873 canDrawArgs.fStyle = &GrStyle::SimpleFill();
robertphillips391395d2016-03-02 09:26:36 -0800874 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -0700875 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -0800876 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
877
878 // Don't allow the SW renderer
879 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
880 if (!pr) {
881 return false;
882 }
883
884 GrPaint paint;
885 paint.setCoverageSetOpXPFactory(op, invert);
886
cdalton862cff32016-05-12 15:09:48 -0700887 GrPipelineBuilder pipelineBuilder(paint, fDrawContext->accessRenderTarget());
cdalton93a379b2016-05-11 13:58:08 -0700888 pipelineBuilder.setUserStencil(ss);
robertphillips391395d2016-03-02 09:26:36 -0800889
890 GrPathRenderer::DrawPathArgs args;
891 args.fTarget = fDrawContext->getDrawTarget();
892 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
893 args.fPipelineBuilder = &pipelineBuilder;
cdalton862cff32016-05-12 15:09:48 -0700894 args.fClip = &clip;
robertphillips391395d2016-03-02 09:26:36 -0800895 args.fColor = GrColor_WHITE;
896 args.fViewMatrix = &viewMatrix;
897 args.fPath = &path;
bsalomon6663acf2016-05-10 09:14:17 -0700898 args.fStyle = &GrStyle::SimpleFill();
robertphillips391395d2016-03-02 09:26:36 -0800899 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -0700900 args.fGammaCorrect = fDrawContext->isGammaCorrect();
robertphillips391395d2016-03-02 09:26:36 -0800901 pr->drawPath(args);
902 return true;
903}
904
robertphillips4bc31812016-03-01 12:22:49 -0800905void GrDrawContext::internalDrawPath(const GrClip& clip,
906 const GrPaint& paint,
robertphillipsea461502015-05-26 11:38:03 -0700907 const SkMatrix& viewMatrix,
bsalomon6663acf2016-05-10 09:14:17 -0700908 const SkPath& origPath,
909 const GrStyle& origStyle) {
joshualitt1de610a2016-01-06 08:26:09 -0800910 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700911 RETURN_IF_ABANDONED
bsalomon6663acf2016-05-10 09:14:17 -0700912 SkASSERT(!origPath.isEmpty());
robertphillipsea461502015-05-26 11:38:03 -0700913
robertphillips6c7e3252016-04-27 10:47:51 -0700914 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
cdalton93a379b2016-05-11 13:58:08 -0700915 constexpr bool kHasUserStencilSettings = false;
robertphillips4bc31812016-03-01 12:22:49 -0800916 bool isStencilBufferMSAA = fRenderTarget->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -0700917
robertphillips68737822015-10-29 12:12:21 -0700918 const GrPathRendererChain::DrawType type =
919 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
920 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -0700921
robertphillipsea461502015-05-26 11:38:03 -0700922 SkTLazy<SkPath> tmpPath;
bsalomon6663acf2016-05-10 09:14:17 -0700923 SkTLazy<GrStyle> tmpStyle;
robertphillipsea461502015-05-26 11:38:03 -0700924
robertphillips68737822015-10-29 12:12:21 -0700925 GrPathRenderer::CanDrawPathArgs canDrawArgs;
926 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
927 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon6663acf2016-05-10 09:14:17 -0700928 canDrawArgs.fPath = &origPath;
929 canDrawArgs.fStyle = &origStyle;
robertphillips68737822015-10-29 12:12:21 -0700930 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -0700931 canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
robertphillips68737822015-10-29 12:12:21 -0700932 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
933
bsalomon6663acf2016-05-10 09:14:17 -0700934 // Try a 1st time without applying any of the style to the geometry (and barring sw)
robertphillips68737822015-10-29 12:12:21 -0700935 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
bsalomon6663acf2016-05-10 09:14:17 -0700936 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700937
bsalomon6663acf2016-05-10 09:14:17 -0700938 if (!pr && canDrawArgs.fStyle->pathEffect()) {
939 // It didn't work above, so try again with the path effect applied.
940 SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
941 if (!canDrawArgs.fStyle->applyPathEffectToPath(tmpPath.init(), &rec, *canDrawArgs.fPath,
942 styleScale)) {
943 GrStyle noPathEffect(canDrawArgs.fStyle->strokeRec(), nullptr);
944 this->internalDrawPath(clip, paint, viewMatrix, *canDrawArgs.fPath, noPathEffect);
robertphillipsea461502015-05-26 11:38:03 -0700945 return;
946 }
bsalomon6663acf2016-05-10 09:14:17 -0700947 tmpStyle.init(rec, nullptr);
948 canDrawArgs.fPath = tmpPath.get();
949 canDrawArgs.fStyle = tmpStyle.get();
950 if (canDrawArgs.fPath->isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -0700951 return;
952 }
robertphillips68737822015-10-29 12:12:21 -0700953
954 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700955 }
bsalomon6663acf2016-05-10 09:14:17 -0700956 if (!pr) {
957 SkASSERT(!canDrawArgs.fStyle->pathEffect());
958 if (canDrawArgs.fStyle->strokeRec().needToApply()) {
robertphillipsea461502015-05-26 11:38:03 -0700959 if (!tmpPath.isValid()) {
960 tmpPath.init();
961 }
bsalomon6663acf2016-05-10 09:14:17 -0700962 // It didn't work above, so try again by applying the stroke to the geometry.
963 SkStrokeRec::InitStyle fillOrHairline;
964 if (!canDrawArgs.fStyle->applyToPath(tmpPath.get(), &fillOrHairline,
965 *canDrawArgs.fPath, styleScale)) {
robertphillipsea461502015-05-26 11:38:03 -0700966 return;
967 }
bsalomon6663acf2016-05-10 09:14:17 -0700968 if (!tmpStyle.isValid()) {
969 tmpStyle.init(fillOrHairline);
970 } else {
971 tmpStyle.get()->resetToInitStyle(fillOrHairline);
972 }
973 canDrawArgs.fPath = tmpPath.get();
974 canDrawArgs.fStyle = tmpStyle.get();
975 if (canDrawArgs.fPath->isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -0700976 return;
977 }
robertphillips68737822015-10-29 12:12:21 -0700978
bsalomon6663acf2016-05-10 09:14:17 -0700979 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
980 }
bsalomon85d96672016-05-10 06:19:21 -0700981
robertphillipsea461502015-05-26 11:38:03 -0700982 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -0700983 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -0700984 }
985
halcanary96fcdcc2015-08-27 07:41:13 -0700986 if (nullptr == pr) {
robertphillipsea461502015-05-26 11:38:03 -0700987#ifdef SK_DEBUG
988 SkDebugf("Unable to find path renderer compatible with path.\n");
989#endif
990 return;
991 }
992
cdalton862cff32016-05-12 15:09:48 -0700993 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget.get());
robertphillips4bc31812016-03-01 12:22:49 -0800994
bsalomon0aff2fa2015-07-31 06:48:27 -0700995 GrPathRenderer::DrawPathArgs args;
robertphillipsb83bec52015-10-23 09:38:03 -0700996 args.fTarget = this->getDrawTarget();
robertphillips77a2e522015-10-17 07:43:27 -0700997 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips4bc31812016-03-01 12:22:49 -0800998 args.fPipelineBuilder = &pipelineBuilder;
cdalton862cff32016-05-12 15:09:48 -0700999 args.fClip = &clip;
robertphillips4bc31812016-03-01 12:22:49 -08001000 args.fColor = paint.getColor();
bsalomon0aff2fa2015-07-31 06:48:27 -07001001 args.fViewMatrix = &viewMatrix;
bsalomon6663acf2016-05-10 09:14:17 -07001002 args.fPath = canDrawArgs.fPath;
1003 args.fStyle = canDrawArgs.fStyle;
bsalomon0aff2fa2015-07-31 06:48:27 -07001004 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001005 args.fGammaCorrect = this->isGammaCorrect();
bsalomon0aff2fa2015-07-31 06:48:27 -07001006 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001007}
1008
cdalton862cff32016-05-12 15:09:48 -07001009void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, const GrClip& clip,
1010 GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -08001011 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001012 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001013 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001014 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -07001015
cdalton862cff32016-05-12 15:09:48 -07001016 this->getDrawTarget()->drawBatch(*pipelineBuilder, clip, batch);
robertphillips2334fb62015-06-17 05:43:33 -07001017}