blob: 43ef760d82a9e1bcae630cf48e366a094e68674c [file] [log] [blame]
robertphillipsea461502015-05-26 11:38:03 -07001
2/*
3 * Copyright 2015 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
robertphillipsea461502015-05-26 11:38:03 -07009#include "GrBatchTest.h"
jvanverth31ff7622015-08-07 10:09:28 -070010#include "GrColor.h"
robertphillipsea461502015-05-26 11:38:03 -070011#include "GrDrawContext.h"
robertphillips86c60752016-03-02 08:43:13 -080012#include "GrDrawContextPriv.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"
robertphillips2d70dcb2015-10-06 07:38:23 -070019#include "SkSurfacePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070020
joshualitt74417822015-08-07 11:42:16 -070021#include "batches/GrBatch.h"
jvanverth14b88032015-08-07 12:18:54 -070022#include "batches/GrDrawAtlasBatch.h"
joshualitt2771b562015-08-07 12:46:26 -070023#include "batches/GrDrawVerticesBatch.h"
joshualitt7fc2a262015-08-10 10:30:14 -070024#include "batches/GrRectBatchFactory.h"
joshualitt33a5fce2015-11-18 13:28:51 -080025#include "batches/GrNinePatch.h" // TODO Factory
joshualitt74417822015-08-07 11:42:16 -070026
robertphillips00095892016-02-29 13:50:40 -080027#include "effects/GrRRectEffect.h"
28
joshualitte8042922015-12-11 06:11:21 -080029#include "text/GrAtlasTextContext.h"
30#include "text/GrStencilAndCoverTextContext.h"
31
joshualittbc907352016-01-13 06:45:40 -080032#include "../private/GrAuditTrail.h"
33
robertphillips77a2e522015-10-17 07:43:27 -070034#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080035#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080036 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips86c60752016-03-02 08:43:13 -080037#define ASSERT_SINGLE_OWNER_PRIV \
38 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
robertphillips77a2e522015-10-17 07:43:27 -070039#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
40#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; }
robertphillips86c60752016-03-02 08:43:13 -080041#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->abandoned()) { return false; }
robertphillips77a2e522015-10-17 07:43:27 -070042#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070043
44class AutoCheckFlush {
45public:
robertphillips77a2e522015-10-17 07:43:27 -070046 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
47 SkASSERT(fDrawingManager);
48 }
49 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070050
51private:
robertphillips77a2e522015-10-17 07:43:27 -070052 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070053};
54
robertphillipsa106c622015-10-16 09:07:06 -070055// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
56// drawTargets to be picked up and added to by drawContexts lower in the call
57// stack. When this occurs with a closed drawTarget, a new one will be allocated
58// when the drawContext attempts to use it (via getDrawTarget).
joshualitt1b39f432016-02-11 06:46:52 -080059GrDrawContext::GrDrawContext(GrContext* context,
60 GrDrawingManager* drawingMgr,
robertphillips2e1e51f2015-10-15 08:01:48 -070061 GrRenderTarget* rt,
joshualittde8dc7e2016-01-08 10:09:13 -080062 const SkSurfaceProps* surfaceProps,
joshualittbc907352016-01-13 06:45:40 -080063 GrAuditTrail* auditTrail,
joshualittde8dc7e2016-01-08 10:09:13 -080064 GrSingleOwner* singleOwner)
robertphillips77a2e522015-10-17 07:43:27 -070065 : fDrawingManager(drawingMgr)
robertphillips2e1e51f2015-10-15 08:01:48 -070066 , fRenderTarget(rt)
robertphillipsa106c622015-10-16 09:07:06 -070067 , fDrawTarget(SkSafeRef(rt->getLastDrawTarget()))
joshualitt1b39f432016-02-11 06:46:52 -080068 , fContext(context)
joshualittde8dc7e2016-01-08 10:09:13 -080069 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080070 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080071#ifdef SK_DEBUG
72 , fSingleOwner(singleOwner)
73#endif
74{
robertphillips2e1e51f2015-10-15 08:01:48 -070075 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070076}
77
robertphillips2e1e51f2015-10-15 08:01:48 -070078#ifdef SK_DEBUG
79void GrDrawContext::validate() const {
80 SkASSERT(fRenderTarget);
81 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -070082
83 if (fDrawTarget && !fDrawTarget->isClosed()) {
84 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
85 }
robertphillips2e1e51f2015-10-15 08:01:48 -070086}
87#endif
88
robertphillipsa106c622015-10-16 09:07:06 -070089GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -080090 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070091 SkSafeUnref(fDrawTarget);
92}
93
94GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -080095 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -070096 SkDEBUGCODE(this->validate();)
97
98 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips77a2e522015-10-17 07:43:27 -070099 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -0700100 }
101
102 return fDrawTarget;
103}
104
bsalomonb8fea972016-02-16 07:34:17 -0800105bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800106 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800107 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700108 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800109 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700110
bsalomonb8fea972016-02-16 07:34:17 -0800111 return this->getDrawTarget()->copySurface(fRenderTarget, src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700112}
113
robertphillips2e1e51f2015-10-15 08:01:48 -0700114void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700115 const SkPaint& skPaint,
116 const SkMatrix& viewMatrix,
117 const char text[], size_t byteLength,
118 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800119 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700120 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700121 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800122 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700123
joshualitt96880d92016-02-16 10:36:53 -0800124 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800125 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700126 }
127
joshualitt96880d92016-02-16 10:36:53 -0800128 fAtlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
129 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700130}
robertphillipscaef3452015-11-11 13:18:11 -0800131
robertphillips2e1e51f2015-10-15 08:01:48 -0700132void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700133 const SkPaint& skPaint,
134 const SkMatrix& viewMatrix,
135 const char text[], size_t byteLength,
136 const SkScalar pos[], int scalarsPerPosition,
137 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800138 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700139 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700140 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800141 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700142
joshualitt96880d92016-02-16 10:36:53 -0800143 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800144 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700145 }
146
joshualitt96880d92016-02-16 10:36:53 -0800147 fAtlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
148 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
149 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700150
151}
robertphillipscaef3452015-11-11 13:18:11 -0800152
robertphillips2e1e51f2015-10-15 08:01:48 -0700153void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700154 const SkMatrix& viewMatrix, const SkTextBlob* blob,
155 SkScalar x, SkScalar y,
156 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800157 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700158 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700159 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800160 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700161
joshualitt96880d92016-02-16 10:36:53 -0800162 if (!fAtlasTextContext) {
joshualitt8db86782016-02-17 05:40:00 -0800163 fAtlasTextContext.reset(GrAtlasTextContext::Create());
robertphillips2334fb62015-06-17 05:43:33 -0700164 }
165
joshualitt96880d92016-02-16 10:36:53 -0800166 fAtlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
167 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700168}
169
robertphillips2e1e51f2015-10-15 08:01:48 -0700170void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800171 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700172 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700173 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800174 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700175
robertphillips77a2e522015-10-17 07:43:27 -0700176 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700177 this->getDrawTarget()->discard(fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700178}
179
robertphillips2e1e51f2015-10-15 08:01:48 -0700180void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700181 const GrColor color,
182 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800183 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700184 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700185 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800186 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700187
robertphillips77a2e522015-10-17 07:43:27 -0700188 AutoCheckFlush acf(fDrawingManager);
robertphillipsa106c622015-10-16 09:07:06 -0700189 this->getDrawTarget()->clear(rect, color, canIgnoreRect, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700190}
191
192
robertphillips2e1e51f2015-10-15 08:01:48 -0700193void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700194 const GrPaint& origPaint,
195 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800196 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700197 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700198 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800199 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700200
robertphillipsea461502015-05-26 11:38:03 -0700201 // set rect to be big enough to fill the space, but not super-huge, so we
202 // don't overflow fixed-point implementations
203 SkRect r;
204 r.setLTRB(0, 0,
robertphillips2e1e51f2015-10-15 08:01:48 -0700205 SkIntToScalar(fRenderTarget->width()),
206 SkIntToScalar(fRenderTarget->height()));
robertphillipsea461502015-05-26 11:38:03 -0700207 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
208
209 // by definition this fills the entire clip, no need for AA
210 if (paint->isAntiAlias()) {
211 paint.writable()->setAntiAlias(false);
212 }
213
214 bool isPerspective = viewMatrix.hasPerspective();
215
216 // We attempt to map r by the inverse matrix and draw that. mapRect will
217 // map the four corners and bound them with a new rect. This will not
218 // produce a correct result for some perspective matrices.
219 if (!isPerspective) {
220 SkMatrix inverse;
221 if (!viewMatrix.invert(&inverse)) {
222 SkDebugf("Could not invert matrix\n");
223 return;
224 }
225 inverse.mapRect(&r);
robertphillips2e1e51f2015-10-15 08:01:48 -0700226 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700227 } else {
228 SkMatrix localMatrix;
229 if (!viewMatrix.invert(&localMatrix)) {
230 SkDebugf("Could not invert matrix\n");
231 return;
232 }
233
robertphillips77a2e522015-10-17 07:43:27 -0700234 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700235
joshualitt04194f32016-01-13 10:08:27 -0800236 SkAutoTUnref<GrDrawBatch> batch(
237 GrRectBatchFactory::CreateNonAAFill(paint->getColor(), SkMatrix::I(), r, nullptr,
238 &localMatrix));
robertphillips4bc31812016-03-01 12:22:49 -0800239 GrPipelineBuilder pipelineBuilder(*paint, fRenderTarget, clip);
joshualitt04194f32016-01-13 10:08:27 -0800240 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700241 }
242}
243
robertphillipsea461502015-05-26 11:38:03 -0700244static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
245 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
246 point.fY >= rect.fTop && point.fY <= rect.fBottom;
247}
248
bsalomonc55271f2015-11-09 11:55:57 -0800249static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
250 return viewMatrix.preservesRightAngles();
251}
252
253static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt) {
254 return paint.isAntiAlias() && !rt->isUnifiedMultisampled();
255}
256
robertphillips86c60752016-03-02 08:43:13 -0800257GrDrawBatch* GrDrawContext::getFillRectBatch(const GrPaint& paint,
258 const SkMatrix& viewMatrix,
259 const SkRect& rect) {
260
261 GrDrawBatch* batch = nullptr;
262 if (should_apply_coverage_aa(paint, fRenderTarget)) {
263 // The fill path can handle rotation but not skew.
264 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
265 SkRect devBoundRect;
266 viewMatrix.mapRect(&devBoundRect, rect);
267 batch = GrRectBatchFactory::CreateAAFill(paint.getColor(), viewMatrix,
268 rect, devBoundRect);
269 }
270 } else {
271 // filled BW rect
272 batch = GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect,
273 nullptr, nullptr);
274 }
275
276 return batch;
277}
278
robertphillips2e1e51f2015-10-15 08:01:48 -0700279void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700280 const GrPaint& paint,
281 const SkMatrix& viewMatrix,
282 const SkRect& rect,
283 const GrStrokeInfo* strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800284 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700285 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700286 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800287 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700288
robertphillipsff55b492015-11-24 07:56:59 -0800289 // Dashing should've been devolved to a path in SkGpuDevice
290 SkASSERT(!strokeInfo || !strokeInfo->isDashed());
robertphillipsea461502015-05-26 11:38:03 -0700291
robertphillips77a2e522015-10-17 07:43:27 -0700292 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700293
robertphillips4bc31812016-03-01 12:22:49 -0800294 SkScalar width = !strokeInfo ? -1 : strokeInfo->getWidth();
robertphillipsea461502015-05-26 11:38:03 -0700295
296 // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
297 // cases where the RT is fully inside a stroke.
298 if (width < 0) {
299 SkRect rtRect;
robertphillips954cbc12015-12-02 10:33:46 -0800300 fRenderTarget->getBoundsRect(&rtRect);
robertphillipsea461502015-05-26 11:38:03 -0700301 SkRect clipSpaceRTRect = rtRect;
302 bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
303 if (checkClip) {
304 clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
305 SkIntToScalar(clip.origin().fY));
306 }
307 // Does the clip contain the entire RT?
308 if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
309 SkMatrix invM;
310 if (!viewMatrix.invert(&invM)) {
311 return;
312 }
313 // Does the rect bound the RT?
314 SkPoint srcSpaceRTQuad[4];
315 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
316 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
317 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
318 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
319 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
320 // Will it blend?
321 GrColor clearColor;
cdalton1fa45722015-06-02 10:43:39 -0700322 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillipsa106c622015-10-16 09:07:06 -0700323 this->getDrawTarget()->clear(nullptr, clearColor, true, fRenderTarget);
robertphillipsea461502015-05-26 11:38:03 -0700324 return;
325 }
326 }
327 }
328 }
329
robertphillips4bc31812016-03-01 12:22:49 -0800330 bool snapToPixelCenters = false;
joshualitt04194f32016-01-13 10:08:27 -0800331 SkAutoTUnref<GrDrawBatch> batch;
robertphillips86c60752016-03-02 08:43:13 -0800332 if (width < 0) {
333 batch.reset(this->getFillRectBatch(paint, viewMatrix, rect));
334 } else {
335 GrColor color = paint.getColor();
336
337 if (should_apply_coverage_aa(paint, fRenderTarget)) {
cdaltonbb539482016-01-04 09:48:25 -0800338 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
339 if (viewMatrix.rectStaysRect()) {
robertphillips86c60752016-03-02 08:43:13 -0800340 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect,
cdaltonbb539482016-01-04 09:48:25 -0800341 *strokeInfo));
342 }
robertphillipsea461502015-05-26 11:38:03 -0700343 } else {
robertphillips86c60752016-03-02 08:43:13 -0800344 // Non-AA hairlines are snapped to pixel centers to make which pixels are hit
345 // deterministic
346 snapToPixelCenters = (0 == width && !fRenderTarget->isUnifiedMultisampled());
347 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
348 width, snapToPixelCenters));
robertphillipsea461502015-05-26 11:38:03 -0700349
robertphillips86c60752016-03-02 08:43:13 -0800350 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
351 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
352 // when MSAA is enabled because it can cause ugly artifacts.
353 }
robertphillipsea461502015-05-26 11:38:03 -0700354 }
robertphillips4bc31812016-03-01 12:22:49 -0800355
356 if (batch) {
357 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
358
359 if (snapToPixelCenters) {
360 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
361 snapToPixelCenters);
362 }
363
364 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
365 return;
366 }
367
368 SkPath path;
369 path.setIsVolatile(true);
370 path.addRect(rect);
371 this->internalDrawPath(clip, paint, viewMatrix, path,
372 strokeInfo ? *strokeInfo : GrStrokeInfo::FillInfo());
robertphillipsea461502015-05-26 11:38:03 -0700373}
374
robertphillips86c60752016-03-02 08:43:13 -0800375bool GrDrawContextPriv::drawAndStencilRect(const SkIRect* scissorRect,
376 const GrStencilSettings& ss,
377 SkRegion::Op op,
378 bool invert,
379 bool doAA,
380 const SkMatrix& viewMatrix,
381 const SkRect& rect) {
382 ASSERT_SINGLE_OWNER_PRIV
383 RETURN_FALSE_IF_ABANDONED_PRIV
384 SkDEBUGCODE(fDrawContext->validate();)
385 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::stencilRect");
386
387 AutoCheckFlush acf(fDrawContext->fDrawingManager);
388
389 GrPaint paint;
390 paint.setAntiAlias(doAA);
391 paint.setCoverageSetOpXPFactory(op, invert);
392
393 SkAutoTUnref<GrDrawBatch> batch(fDrawContext->getFillRectBatch(paint, viewMatrix, rect));
394 if (batch) {
395 GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, GrClip::WideOpen());
396 pipelineBuilder.setStencil(ss);
397
398 fDrawContext->getDrawTarget()->drawBatch(pipelineBuilder, batch, scissorRect);
399 return true;
400 }
401
402 SkPath path;
403 path.setIsVolatile(true);
404 path.addRect(rect);
405 return this->drawAndStencilPath(scissorRect, ss, op, invert, doAA, viewMatrix, path);
406}
407
bsalomona2e69fc2015-11-05 10:41:43 -0800408void GrDrawContext::fillRectToRect(const GrClip& clip,
409 const GrPaint& paint,
410 const SkMatrix& viewMatrix,
411 const SkRect& rectToDraw,
412 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800413 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700414 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700415 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800416 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700417
robertphillips77a2e522015-10-17 07:43:27 -0700418 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700419
joshualitt04194f32016-01-13 10:08:27 -0800420 SkAutoTUnref<GrDrawBatch> batch;
bsalomonc55271f2015-11-09 11:55:57 -0800421 if (should_apply_coverage_aa(paint, fRenderTarget) &&
422 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800423 batch.reset(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(), viewMatrix, rectToDraw,
424 localRect));
bsalomonc55271f2015-11-09 11:55:57 -0800425 } else {
joshualitt04194f32016-01-13 10:08:27 -0800426 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
427 &localRect, nullptr));
428 }
429
430 if (batch) {
robertphillips4bc31812016-03-01 12:22:49 -0800431 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt04194f32016-01-13 10:08:27 -0800432 this->drawBatch(&pipelineBuilder, batch);
bsalomonc55271f2015-11-09 11:55:57 -0800433 }
joshualittb6b513b2015-08-21 10:25:18 -0700434}
435
bsalomona2e69fc2015-11-05 10:41:43 -0800436void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
437 const GrPaint& paint,
438 const SkMatrix& viewMatrix,
439 const SkRect& rectToDraw,
440 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800441 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700442 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700443 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800444 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700445
robertphillips77a2e522015-10-17 07:43:27 -0700446 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700447
joshualitt04194f32016-01-13 10:08:27 -0800448 SkAutoTUnref<GrDrawBatch> batch;
robertphillips954cbc12015-12-02 10:33:46 -0800449 if (should_apply_coverage_aa(paint, fRenderTarget) &&
bsalomonc55271f2015-11-09 11:55:57 -0800450 view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
joshualitt04194f32016-01-13 10:08:27 -0800451 batch.reset(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix, localMatrix,
452 rectToDraw));
bsalomonc55271f2015-11-09 11:55:57 -0800453 } else {
joshualitt04194f32016-01-13 10:08:27 -0800454 batch.reset(GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rectToDraw,
455 nullptr, &localMatrix));
bsalomonc55271f2015-11-09 11:55:57 -0800456 }
robertphillips4bc31812016-03-01 12:22:49 -0800457
458 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
joshualitt04194f32016-01-13 10:08:27 -0800459 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700460}
461
robertphillips2e1e51f2015-10-15 08:01:48 -0700462void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700463 const GrPaint& paint,
464 const SkMatrix& viewMatrix,
465 GrPrimitiveType primitiveType,
466 int vertexCount,
467 const SkPoint positions[],
468 const SkPoint texCoords[],
469 const GrColor colors[],
470 const uint16_t indices[],
471 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800472 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700473 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700474 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800475 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700476
robertphillips77a2e522015-10-17 07:43:27 -0700477 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700478
robertphillipsea461502015-05-26 11:38:03 -0700479 // TODO clients should give us bounds
480 SkRect bounds;
481 if (!bounds.setBoundsCheck(positions, vertexCount)) {
482 SkDebugf("drawVertices call empty bounds\n");
483 return;
484 }
485
486 viewMatrix.mapRect(&bounds);
487
488 // 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 -0800489 // snapping. We also do this for the "hair" primitive types: lines and points since they have
490 // a 1 pixel thickness in device space.
491 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
492 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700493 bounds.outset(0.5f, 0.5f);
494 }
495
joshualitt2771b562015-08-07 12:46:26 -0700496 GrDrawVerticesBatch::Geometry geometry;
robertphillipsea461502015-05-26 11:38:03 -0700497 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700498 SkAutoTUnref<GrDrawBatch> batch(GrDrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
499 positions, vertexCount, indices,
500 indexCount, colors, texCoords,
501 bounds));
robertphillipsea461502015-05-26 11:38:03 -0700502
robertphillips4bc31812016-03-01 12:22:49 -0800503 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700504 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700505}
506
507///////////////////////////////////////////////////////////////////////////////
508
robertphillips2e1e51f2015-10-15 08:01:48 -0700509void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700510 const GrPaint& paint,
511 const SkMatrix& viewMatrix,
512 int spriteCount,
513 const SkRSXform xform[],
514 const SkRect texRect[],
515 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800516 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700517 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700518 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800519 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700520
robertphillips77a2e522015-10-17 07:43:27 -0700521 AutoCheckFlush acf(fDrawingManager);
robertphillips4bc31812016-03-01 12:22:49 -0800522
jvanverth14b88032015-08-07 12:18:54 -0700523 GrDrawAtlasBatch::Geometry geometry;
jvanverth31ff7622015-08-07 10:09:28 -0700524 geometry.fColor = paint.getColor();
bsalomonabd30f52015-08-13 13:34:48 -0700525 SkAutoTUnref<GrDrawBatch> batch(GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount,
526 xform, texRect, colors));
jvanverth31ff7622015-08-07 10:09:28 -0700527
robertphillips4bc31812016-03-01 12:22:49 -0800528 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700529 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700530}
531
532///////////////////////////////////////////////////////////////////////////////
533
robertphillips2e1e51f2015-10-15 08:01:48 -0700534void GrDrawContext::drawRRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700535 const GrPaint& paint,
536 const SkMatrix& viewMatrix,
537 const SkRRect& rrect,
538 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800539 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700540 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700541 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800542 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700543
robertphillipsea461502015-05-26 11:38:03 -0700544 if (rrect.isEmpty()) {
545 return;
546 }
547
robertphillips514450c2015-11-24 05:36:02 -0800548 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700549
robertphillips77a2e522015-10-17 07:43:27 -0700550 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700551
robertphillipsb56f9272016-02-25 11:03:52 -0800552 if (should_apply_coverage_aa(paint, fRenderTarget)) {
553 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
554
robertphillips4bc31812016-03-01 12:22:49 -0800555 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800556 viewMatrix,
557 rrect,
558 strokeInfo,
559 shaderCaps));
560 if (batch) {
robertphillips4bc31812016-03-01 12:22:49 -0800561 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsb56f9272016-02-25 11:03:52 -0800562 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
563 return;
564 }
robertphillipsea461502015-05-26 11:38:03 -0700565 }
robertphillipsb56f9272016-02-25 11:03:52 -0800566
567 SkPath path;
568 path.setIsVolatile(true);
569 path.addRRect(rrect);
robertphillips4bc31812016-03-01 12:22:49 -0800570 this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700571}
572
robertphillips00095892016-02-29 13:50:40 -0800573bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
574 const GrPaint& paintIn,
575 const SkMatrix& viewMatrix,
576 const SkRRect& origOuter,
577 const SkRRect& origInner) {
578 SkASSERT(!origInner.isEmpty());
579 SkASSERT(!origOuter.isEmpty());
580
581 bool applyAA = paintIn.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
582
583 GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
584 kInverseFillBW_GrProcessorEdgeType;
585 GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
586 kFillBW_GrProcessorEdgeType;
587
588 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
589 SkMatrix inverseVM;
590 if (!viewMatrix.isIdentity()) {
591 if (!origInner.transform(viewMatrix, inner.writable())) {
592 return false;
593 }
594 if (!origOuter.transform(viewMatrix, outer.writable())) {
595 return false;
596 }
597 if (!viewMatrix.invert(&inverseVM)) {
598 return false;
599 }
600 } else {
601 inverseVM.reset();
602 }
603
604 GrPaint grPaint(paintIn);
605 grPaint.setAntiAlias(false);
606
607 // TODO these need to be a geometry processors
608 SkAutoTUnref<GrFragmentProcessor> innerEffect(GrRRectEffect::Create(innerEdgeType, *inner));
609 if (!innerEffect) {
610 return false;
611 }
612
613 SkAutoTUnref<GrFragmentProcessor> outerEffect(GrRRectEffect::Create(outerEdgeType, *outer));
614 if (!outerEffect) {
615 return false;
616 }
617
618 grPaint.addCoverageFragmentProcessor(innerEffect);
619 grPaint.addCoverageFragmentProcessor(outerEffect);
620
621 SkRect bounds = outer->getBounds();
622 if (applyAA) {
623 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
624 }
625
626 this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
627 return true;
628}
629
630void GrDrawContext::drawDRRect(const GrClip& clip,
631 const GrPaint& paint,
632 const SkMatrix& viewMatrix,
633 const SkRRect& outer,
634 const SkRRect& inner) {
635 ASSERT_SINGLE_OWNER
636 RETURN_IF_ABANDONED
637 SkDEBUGCODE(this->validate();)
638 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
639
640 SkASSERT(!outer.isEmpty());
641 SkASSERT(!inner.isEmpty());
642
643 AutoCheckFlush acf(fDrawingManager);
644
645 if (this->drawFilledDRRect(clip, paint, viewMatrix, outer, inner)) {
646 return;
647 }
648
649 SkPath path;
650 path.setIsVolatile(true);
651 path.addRRect(inner);
652 path.addRRect(outer);
653 path.setFillType(SkPath::kEvenOdd_FillType);
654
655 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillips4bc31812016-03-01 12:22:49 -0800656 this->internalDrawPath(clip, paint, viewMatrix, path, GrStrokeInfo::FillInfo());
robertphillips00095892016-02-29 13:50:40 -0800657}
658
robertphillipsea461502015-05-26 11:38:03 -0700659///////////////////////////////////////////////////////////////////////////////
660
robertphillips2e1e51f2015-10-15 08:01:48 -0700661void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700662 const GrPaint& paint,
663 const SkMatrix& viewMatrix,
664 const SkRect& oval,
665 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800666 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700667 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700668 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800669 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -0700670
robertphillipsea461502015-05-26 11:38:03 -0700671 if (oval.isEmpty()) {
672 return;
673 }
674
robertphillips514450c2015-11-24 05:36:02 -0800675 SkASSERT(!strokeInfo.isDashed()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -0700676
robertphillips77a2e522015-10-17 07:43:27 -0700677 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700678
robertphillipsb56f9272016-02-25 11:03:52 -0800679 if (should_apply_coverage_aa(paint, fRenderTarget)) {
680 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800681 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800682 viewMatrix,
683 oval,
684 strokeInfo,
685 shaderCaps));
686 if (batch) {
robertphillips4bc31812016-03-01 12:22:49 -0800687 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsb56f9272016-02-25 11:03:52 -0800688 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
689 return;
690 }
robertphillipsea461502015-05-26 11:38:03 -0700691 }
robertphillipsb56f9272016-02-25 11:03:52 -0800692
693 SkPath path;
694 path.setIsVolatile(true);
695 path.addOval(oval);
robertphillips4bc31812016-03-01 12:22:49 -0800696 this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700697}
698
joshualitt33a5fce2015-11-18 13:28:51 -0800699void GrDrawContext::drawImageNine(const GrClip& clip,
700 const GrPaint& paint,
701 const SkMatrix& viewMatrix,
702 int imageWidth,
703 int imageHeight,
704 const SkIRect& center,
705 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -0800706 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -0800707 RETURN_IF_ABANDONED
708 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800709 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageNine");
joshualitt33a5fce2015-11-18 13:28:51 -0800710
711 AutoCheckFlush acf(fDrawingManager);
712
713 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
714 imageWidth, imageHeight,
715 center, dst));
716
717 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
718 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
719}
720
721
robertphillipsea461502015-05-26 11:38:03 -0700722// Can 'path' be drawn as a pair of filled nested rectangles?
joshualittf9c5db22015-07-10 11:31:01 -0700723static bool is_nested_rects(const SkMatrix& viewMatrix,
robertphillipsea461502015-05-26 11:38:03 -0700724 const SkPath& path,
725 const SkStrokeRec& stroke,
726 SkRect rects[2]) {
727 SkASSERT(stroke.isFillStyle());
728
729 if (path.isInverseFillType()) {
730 return false;
731 }
732
733 // TODO: this restriction could be lifted if we were willing to apply
734 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -0800735 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -0700736 return false;
737 }
738
739 SkPath::Direction dirs[2];
740 if (!path.isNestedFillRects(rects, dirs)) {
741 return false;
742 }
743
744 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
745 // The two rects need to be wound opposite to each other
746 return false;
747 }
748
749 // Right now, nested rects where the margin is not the same width
750 // all around do not render correctly
751 const SkScalar* outer = rects[0].asScalars();
752 const SkScalar* inner = rects[1].asScalars();
753
754 bool allEq = true;
755
756 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
757 bool allGoE1 = margin >= SK_Scalar1;
758
759 for (int i = 1; i < 4; ++i) {
760 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
761 if (temp < SK_Scalar1) {
762 allGoE1 = false;
763 }
764 if (!SkScalarNearlyEqual(margin, temp)) {
765 allEq = false;
766 }
767 }
768
769 return allEq || allGoE1;
770}
771
robertphillips2e1e51f2015-10-15 08:01:48 -0700772void GrDrawContext::drawBatch(const GrClip& clip,
bsalomonabd30f52015-08-13 13:34:48 -0700773 const GrPaint& paint, GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800774 ASSERT_SINGLE_OWNER
joshualittb7ee1bf2015-08-10 11:59:02 -0700775 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700776 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800777 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
joshualittb7ee1bf2015-08-10 11:59:02 -0700778
robertphillips77a2e522015-10-17 07:43:27 -0700779 AutoCheckFlush acf(fDrawingManager);
joshualittb7ee1bf2015-08-10 11:59:02 -0700780
robertphillips2e1e51f2015-10-15 08:01:48 -0700781 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700782 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
joshualittb7ee1bf2015-08-10 11:59:02 -0700783}
784
cdalton8ff8d242015-12-08 10:20:32 -0800785void GrDrawContext::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
786 GrDrawPathBatchBase* batch) {
joshualitt1de610a2016-01-06 08:26:09 -0800787 ASSERT_SINGLE_OWNER
cdalton8ff8d242015-12-08 10:20:32 -0800788 RETURN_IF_ABANDONED
789 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800790 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPathBatch");
cdalton8ff8d242015-12-08 10:20:32 -0800791
792 AutoCheckFlush acf(fDrawingManager);
793
794 this->getDrawTarget()->drawPathBatch(pipelineBuilder, batch);
795}
796
robertphillips2e1e51f2015-10-15 08:01:48 -0700797void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700798 const GrPaint& paint,
799 const SkMatrix& viewMatrix,
800 const SkPath& path,
801 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800802 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700803 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700804 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800805 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -0700806
robertphillipsea461502015-05-26 11:38:03 -0700807 if (path.isEmpty()) {
808 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -0700809 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -0700810 }
811 return;
812 }
813
robertphillips77a2e522015-10-17 07:43:27 -0700814 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700815
robertphillipsb56f9272016-02-25 11:03:52 -0800816 if (should_apply_coverage_aa(paint, fRenderTarget) && !strokeInfo.isDashed()) {
817 if (strokeInfo.getWidth() < 0 && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -0700818 // Concave AA paths are expensive - try to avoid them for special cases
819 SkRect rects[2];
820
joshualittf9c5db22015-07-10 11:31:01 -0700821 if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -0700822 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
robertphillips4bc31812016-03-01 12:22:49 -0800823 paint.getColor(), viewMatrix, rects));
824
825 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillipsa106c622015-10-16 09:07:06 -0700826 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700827 return;
828 }
829 }
830 SkRect ovalRect;
831 bool isOval = path.isOval(&ovalRect);
832
833 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -0800834 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800835 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillips0cc2f852016-02-24 13:36:56 -0800836 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -0800837 ovalRect,
838 strokeInfo,
839 shaderCaps));
840 if (batch) {
robertphillips4bc31812016-03-01 12:22:49 -0800841 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
robertphillips0cc2f852016-02-24 13:36:56 -0800842 this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700843 return;
844 }
845 }
846 }
robertphillips4bc31812016-03-01 12:22:49 -0800847
848 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
849 // Scratch textures can be recycled after they are returned to the texture
850 // cache. This presents a potential hazard for buffered drawing. However,
851 // the writePixels that uploads to the scratch will perform a flush so we're
852 // OK.
853 this->internalDrawPath(clip, paint, viewMatrix, path, strokeInfo);
robertphillipsea461502015-05-26 11:38:03 -0700854}
855
robertphillips86c60752016-03-02 08:43:13 -0800856bool GrDrawContextPriv::drawAndStencilPath(const SkIRect* scissorRect,
857 const GrStencilSettings& ss,
858 SkRegion::Op op,
859 bool invert,
860 bool doAA,
861 const SkMatrix& viewMatrix,
862 const SkPath& path) {
863 ASSERT_SINGLE_OWNER_PRIV
864 RETURN_FALSE_IF_ABANDONED_PRIV
865 SkDEBUGCODE(fDrawContext->validate();)
866 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
867
868 if (path.isEmpty() && path.isInverseFillType()) {
869 this->drawAndStencilRect(scissorRect, ss, op, invert, false, SkMatrix::I(),
870 SkRect::MakeIWH(fDrawContext->fRenderTarget->width(),
871 fDrawContext->fRenderTarget->height()));
872 return true;
873 }
874
875 AutoCheckFlush acf(fDrawContext->fDrawingManager);
876
877 // An Assumption here is that path renderer would use some form of tweaking
878 // the src color (either the input alpha or in the frag shader) to implement
879 // aa. If we have some future driver-mojo path AA that can do the right
880 // thing WRT to the blend then we'll need some query on the PR.
881 bool useCoverageAA = doAA && !fDrawContext->fRenderTarget->isUnifiedMultisampled();
882 bool isStencilDisabled = true;
883 bool isStencilBufferMSAA = fDrawContext->fRenderTarget->isStencilBufferMultisampled();
884
885 const GrPathRendererChain::DrawType type =
886 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
887 : GrPathRendererChain::kColor_DrawType;
888
889 GrPathRenderer::CanDrawPathArgs canDrawArgs;
890 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
891 canDrawArgs.fViewMatrix = &viewMatrix;
892 canDrawArgs.fPath = &path;
893 canDrawArgs.fStroke = &GrStrokeInfo::FillInfo();
894 canDrawArgs.fAntiAlias = useCoverageAA;
895 canDrawArgs.fIsStencilDisabled = isStencilDisabled;
896 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
897
898 // Don't allow the SW renderer
899 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
900 if (!pr) {
901 return false;
902 }
903
904 GrPaint paint;
905 paint.setCoverageSetOpXPFactory(op, invert);
906
907 // TODO: it is unfortunate that we have to convert this to a GrClip to
908 // call drawPath.
909 GrClip clip;
910 if (scissorRect) {
911 clip.setIRect(*scissorRect);
912 }
913
914 GrPipelineBuilder pipelineBuilder(paint, fDrawContext->fRenderTarget, clip);
915 pipelineBuilder.setStencil(ss);
916
917 GrPathRenderer::DrawPathArgs args;
918 args.fTarget = fDrawContext->getDrawTarget();
919 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
920 args.fPipelineBuilder = &pipelineBuilder;
921 args.fColor = GrColor_WHITE;
922 args.fViewMatrix = &viewMatrix;
923 args.fPath = &path;
924 args.fStroke = &GrStrokeInfo::FillInfo();
925 args.fAntiAlias = useCoverageAA;
926 pr->drawPath(args);
927 return true;
928}
929
robertphillips4bc31812016-03-01 12:22:49 -0800930void GrDrawContext::internalDrawPath(const GrClip& clip,
931 const GrPaint& paint,
robertphillipsea461502015-05-26 11:38:03 -0700932 const SkMatrix& viewMatrix,
robertphillipsea461502015-05-26 11:38:03 -0700933 const SkPath& path,
934 const GrStrokeInfo& strokeInfo) {
joshualitt1de610a2016-01-06 08:26:09 -0800935 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700936 RETURN_IF_ABANDONED
937 SkASSERT(!path.isEmpty());
938
robertphillipsea461502015-05-26 11:38:03 -0700939 // An Assumption here is that path renderer would use some form of tweaking
940 // the src color (either the input alpha or in the frag shader) to implement
941 // aa. If we have some future driver-mojo path AA that can do the right
942 // thing WRT to the blend then we'll need some query on the PR.
robertphillips4bc31812016-03-01 12:22:49 -0800943 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget);
944 const bool isStencilDisabled = true;
945 bool isStencilBufferMSAA = fRenderTarget->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -0700946
robertphillips68737822015-10-29 12:12:21 -0700947 const GrPathRendererChain::DrawType type =
948 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
949 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -0700950
951 const SkPath* pathPtr = &path;
952 SkTLazy<SkPath> tmpPath;
953 const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
954
robertphillips68737822015-10-29 12:12:21 -0700955 GrPathRenderer::CanDrawPathArgs canDrawArgs;
956 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
957 canDrawArgs.fViewMatrix = &viewMatrix;
958 canDrawArgs.fPath = pathPtr;
959 canDrawArgs.fStroke = strokeInfoPtr;
960 canDrawArgs.fAntiAlias = useCoverageAA;
961 canDrawArgs.fIsStencilDisabled = isStencilDisabled;
962 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
963
robertphillipsea461502015-05-26 11:38:03 -0700964 // Try a 1st time without stroking the path and without allowing the SW renderer
robertphillips68737822015-10-29 12:12:21 -0700965 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700966
967 GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
halcanary96fcdcc2015-08-27 07:41:13 -0700968 if (nullptr == pr && strokeInfo.isDashed()) {
robertphillipsea461502015-05-26 11:38:03 -0700969 // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
970 if (!strokeInfo.applyDashToPath(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
971 return;
972 }
973 pathPtr = tmpPath.get();
974 if (pathPtr->isEmpty()) {
975 return;
976 }
977 strokeInfoPtr = &dashlessStrokeInfo;
robertphillips68737822015-10-29 12:12:21 -0700978
979 canDrawArgs.fPath = pathPtr;
980 canDrawArgs.fStroke = strokeInfoPtr;
981
982 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -0700983 }
984
halcanary96fcdcc2015-08-27 07:41:13 -0700985 if (nullptr == pr) {
986 if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, nullptr) &&
robertphillipsea461502015-05-26 11:38:03 -0700987 !strokeInfoPtr->isFillStyle()) {
988 // It didn't work above, so try again with stroke converted to a fill.
989 if (!tmpPath.isValid()) {
990 tmpPath.init();
991 }
992 dashlessStrokeInfo.setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
993 if (!dashlessStrokeInfo.applyToPath(tmpPath.get(), *pathPtr)) {
994 return;
995 }
996 pathPtr = tmpPath.get();
997 if (pathPtr->isEmpty()) {
998 return;
999 }
1000 dashlessStrokeInfo.setFillStyle();
1001 strokeInfoPtr = &dashlessStrokeInfo;
1002 }
1003
robertphillips68737822015-10-29 12:12:21 -07001004 canDrawArgs.fPath = pathPtr;
1005 canDrawArgs.fStroke = strokeInfoPtr;
1006
robertphillipsea461502015-05-26 11:38:03 -07001007 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -07001008 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -07001009 }
1010
halcanary96fcdcc2015-08-27 07:41:13 -07001011 if (nullptr == pr) {
robertphillipsea461502015-05-26 11:38:03 -07001012#ifdef SK_DEBUG
1013 SkDebugf("Unable to find path renderer compatible with path.\n");
1014#endif
1015 return;
1016 }
1017
robertphillips4bc31812016-03-01 12:22:49 -08001018 GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
1019
bsalomon0aff2fa2015-07-31 06:48:27 -07001020 GrPathRenderer::DrawPathArgs args;
robertphillipsb83bec52015-10-23 09:38:03 -07001021 args.fTarget = this->getDrawTarget();
robertphillips77a2e522015-10-17 07:43:27 -07001022 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips4bc31812016-03-01 12:22:49 -08001023 args.fPipelineBuilder = &pipelineBuilder;
1024 args.fColor = paint.getColor();
bsalomon0aff2fa2015-07-31 06:48:27 -07001025 args.fViewMatrix = &viewMatrix;
1026 args.fPath = pathPtr;
1027 args.fStroke = strokeInfoPtr;
1028 args.fAntiAlias = useCoverageAA;
1029 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001030}
1031
bsalomonabd30f52015-08-13 13:34:48 -07001032void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -08001033 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001034 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001035 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001036 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -07001037
robertphillipsa106c622015-10-16 09:07:06 -07001038 this->getDrawTarget()->drawBatch(*pipelineBuilder, batch);
robertphillips2334fb62015-06-17 05:43:33 -07001039}