blob: 87252f39792ab174a2d62bb2ca127a81a9c8fd58 [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"
csmartdalton02fa32c2016-08-19 13:29:27 -070013#include "GrFixedClip.h"
robertphillips714712b2016-08-04 06:20:45 -070014#include "GrGpuResourcePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070015#include "GrOvalRenderer.h"
16#include "GrPathRenderer.h"
robertphillips5fa7f302016-07-21 09:21:04 -070017#include "GrPipelineBuilder.h"
robertphillips2334fb62015-06-17 05:43:33 -070018#include "GrRenderTarget.h"
19#include "GrRenderTargetPriv.h"
bsalomon473addf2015-10-02 07:49:05 -070020#include "GrResourceProvider.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070021#include "SkSurfacePriv.h"
robertphillipsea461502015-05-26 11:38:03 -070022
joshualitt74417822015-08-07 11:42:16 -070023#include "batches/GrBatch.h"
robertphillips9199a9f2016-07-13 07:48:43 -070024#include "batches/GrClearBatch.h"
jvanverth14b88032015-08-07 12:18:54 -070025#include "batches/GrDrawAtlasBatch.h"
joshualitt2771b562015-08-07 12:46:26 -070026#include "batches/GrDrawVerticesBatch.h"
joshualitt7fc2a262015-08-10 10:30:14 -070027#include "batches/GrRectBatchFactory.h"
joshualitt33a5fce2015-11-18 13:28:51 -080028#include "batches/GrNinePatch.h" // TODO Factory
msarettcc319b92016-08-25 18:07:18 -070029#include "batches/GrRegionBatch.h"
joshualitt74417822015-08-07 11:42:16 -070030
robertphillips00095892016-02-29 13:50:40 -080031#include "effects/GrRRectEffect.h"
32
csmartdaltona7f29642016-07-07 08:49:11 -070033#include "instanced/InstancedRendering.h"
34
joshualitte8042922015-12-11 06:11:21 -080035#include "text/GrAtlasTextContext.h"
36#include "text/GrStencilAndCoverTextContext.h"
37
joshualittbc907352016-01-13 06:45:40 -080038#include "../private/GrAuditTrail.h"
39
robertphillips1da3ecd2016-08-31 14:54:15 -070040#include "SkGr.h"
msarett10e3d9b2016-08-18 15:46:03 -070041#include "SkLatticeIter.h"
reeda39667c2016-08-22 06:39:49 -070042#include "SkMatrixPriv.h"
msarett10e3d9b2016-08-18 15:46:03 -070043
robertphillips77a2e522015-10-17 07:43:27 -070044#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
joshualitt1de610a2016-01-06 08:26:09 -080045#define ASSERT_SINGLE_OWNER \
joshualittde8dc7e2016-01-08 10:09:13 -080046 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
robertphillips391395d2016-03-02 09:26:36 -080047#define ASSERT_SINGLE_OWNER_PRIV \
48 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070049#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
robertphillips976f5f02016-06-03 10:59:20 -070050#define RETURN_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return; }
robertphillips7761d612016-05-16 09:14:53 -070051#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
52#define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return false; }
53#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
robertphillipsea461502015-05-26 11:38:03 -070054
csmartdaltona7f29642016-07-07 08:49:11 -070055using gr_instanced::InstancedRendering;
56
robertphillipsea461502015-05-26 11:38:03 -070057class AutoCheckFlush {
58public:
halcanary9d524f22016-03-29 09:03:52 -070059 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
robertphillips77a2e522015-10-17 07:43:27 -070060 SkASSERT(fDrawingManager);
61 }
62 ~AutoCheckFlush() { fDrawingManager->getContext()->flushIfNecessary(); }
robertphillipsea461502015-05-26 11:38:03 -070063
64private:
robertphillips77a2e522015-10-17 07:43:27 -070065 GrDrawingManager* fDrawingManager;
robertphillipsea461502015-05-26 11:38:03 -070066};
67
robertphillips7761d612016-05-16 09:14:53 -070068bool GrDrawContext::wasAbandoned() const {
69 return fDrawingManager->wasAbandoned();
70}
71
robertphillipsa106c622015-10-16 09:07:06 -070072// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
73// drawTargets to be picked up and added to by drawContexts lower in the call
74// stack. When this occurs with a closed drawTarget, a new one will be allocated
75// when the drawContext attempts to use it (via getDrawTarget).
joshualitt1b39f432016-02-11 06:46:52 -080076GrDrawContext::GrDrawContext(GrContext* context,
77 GrDrawingManager* drawingMgr,
robertphillips6c7e3252016-04-27 10:47:51 -070078 sk_sp<GrRenderTarget> rt,
brianosmandfe4f2e2016-07-21 13:28:36 -070079 sk_sp<SkColorSpace> colorSpace,
joshualittde8dc7e2016-01-08 10:09:13 -080080 const SkSurfaceProps* surfaceProps,
joshualittbc907352016-01-13 06:45:40 -080081 GrAuditTrail* auditTrail,
joshualittde8dc7e2016-01-08 10:09:13 -080082 GrSingleOwner* singleOwner)
robertphillips77a2e522015-10-17 07:43:27 -070083 : fDrawingManager(drawingMgr)
robertphillips6c7e3252016-04-27 10:47:51 -070084 , fRenderTarget(std::move(rt))
85 , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
joshualitt1b39f432016-02-11 06:46:52 -080086 , fContext(context)
csmartdaltona7f29642016-07-07 08:49:11 -070087 , fInstancedPipelineInfo(fRenderTarget.get())
brianosmandfe4f2e2016-07-21 13:28:36 -070088 , fColorSpace(std::move(colorSpace))
joshualittde8dc7e2016-01-08 10:09:13 -080089 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080090 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080091#ifdef SK_DEBUG
92 , fSingleOwner(singleOwner)
93#endif
94{
robertphillips2e1e51f2015-10-15 08:01:48 -070095 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -070096}
97
robertphillips2e1e51f2015-10-15 08:01:48 -070098#ifdef SK_DEBUG
99void GrDrawContext::validate() const {
100 SkASSERT(fRenderTarget);
101 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -0700102
103 if (fDrawTarget && !fDrawTarget->isClosed()) {
104 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
105 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700106}
107#endif
108
robertphillipsa106c622015-10-16 09:07:06 -0700109GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800110 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700111 SkSafeUnref(fDrawTarget);
112}
113
114GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -0800115 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700116 SkDEBUGCODE(this->validate();)
117
118 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips6c7e3252016-04-27 10:47:51 -0700119 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
robertphillipsa106c622015-10-16 09:07:06 -0700120 }
121
122 return fDrawTarget;
123}
124
bsalomonb8fea972016-02-16 07:34:17 -0800125bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800126 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800127 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700128 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800129 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700130
robertphillips6c7e3252016-04-27 10:47:51 -0700131 return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700132}
133
robertphillips2e1e51f2015-10-15 08:01:48 -0700134void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700135 const SkPaint& skPaint,
136 const SkMatrix& viewMatrix,
137 const char text[], size_t byteLength,
138 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800139 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700140 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700141 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800142 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700143
brianosman86e76262016-08-11 12:17:31 -0700144 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
145 atlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
146 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700147}
robertphillipscaef3452015-11-11 13:18:11 -0800148
robertphillips2e1e51f2015-10-15 08:01:48 -0700149void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700150 const SkPaint& skPaint,
151 const SkMatrix& viewMatrix,
152 const char text[], size_t byteLength,
153 const SkScalar pos[], int scalarsPerPosition,
154 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800155 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700156 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700157 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800158 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700159
brianosman86e76262016-08-11 12:17:31 -0700160 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
161 atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
162 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
163 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700164
165}
robertphillipscaef3452015-11-11 13:18:11 -0800166
robertphillips2e1e51f2015-10-15 08:01:48 -0700167void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700168 const SkMatrix& viewMatrix, const SkTextBlob* blob,
169 SkScalar x, SkScalar y,
170 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800171 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -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::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700175
brianosman86e76262016-08-11 12:17:31 -0700176 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
177 atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
178 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700179}
180
robertphillips2e1e51f2015-10-15 08:01:48 -0700181void GrDrawContext::discard() {
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::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700186
robertphillips77a2e522015-10-17 07:43:27 -0700187 AutoCheckFlush acf(fDrawingManager);
robertphillips6c7e3252016-04-27 10:47:51 -0700188 this->getDrawTarget()->discard(fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700189}
190
robertphillips2e1e51f2015-10-15 08:01:48 -0700191void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700192 const GrColor color,
193 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800194 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700195 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700196 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800197 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700198
robertphillips77a2e522015-10-17 07:43:27 -0700199 AutoCheckFlush acf(fDrawingManager);
csmartdalton29df7602016-08-31 11:55:52 -0700200 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
201}
robertphillips9199a9f2016-07-13 07:48:43 -0700202
csmartdalton29df7602016-08-31 11:55:52 -0700203void GrDrawContextPriv::clear(const GrFixedClip& clip,
204 const GrColor color,
205 bool canIgnoreClip) {
206 ASSERT_SINGLE_OWNER_PRIV
207 RETURN_IF_ABANDONED_PRIV
208 SkDEBUGCODE(fDrawContext->validate();)
209 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clear");
210
211 AutoCheckFlush acf(fDrawContext->fDrawingManager);
212 fDrawContext->internalClear(clip, color, canIgnoreClip);
213}
214
215void GrDrawContext::internalClear(const GrFixedClip& clip,
216 const GrColor color,
217 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700218 bool isFull = false;
219 if (!clip.hasWindowRectangles()) {
220 isFull = !clip.scissorEnabled() ||
221 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
222 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
223 }
robertphillips9199a9f2016-07-13 07:48:43 -0700224
225 if (fContext->caps()->useDrawInsteadOfClear()) {
226 // This works around a driver bug with clear by drawing a rect instead.
227 // The driver will ignore a clear if it is the only thing rendered to a
228 // target before the target is read.
csmartdalton29df7602016-08-31 11:55:52 -0700229 SkRect clearRect = SkRect::MakeIWH(this->width(), this->height());
230 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700231 this->discard();
csmartdalton29df7602016-08-31 11:55:52 -0700232 } else if (!clearRect.intersect(SkRect::Make(clip.scissorRect()))) {
233 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700234 }
235
236 GrPaint paint;
237 paint.setColor4f(GrColor4f::FromGrColor(color));
238 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
239
csmartdalton29df7602016-08-31 11:55:52 -0700240 this->drawRect(clip, paint, SkMatrix::I(), clearRect);
bsalomon9f129de2016-08-10 16:31:05 -0700241 } else if (isFull) {
242 this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
robertphillips9199a9f2016-07-13 07:48:43 -0700243 } else {
csmartdalton29df7602016-08-31 11:55:52 -0700244 sk_sp<GrBatch> batch(GrClearBatch::Make(clip, color, this->accessRenderTarget()));
245 if (!batch) {
246 return;
247 }
robertphillips9199a9f2016-07-13 07:48:43 -0700248 this->getDrawTarget()->addBatch(std::move(batch));
249 }
robertphillipsea461502015-05-26 11:38:03 -0700250}
251
robertphillips2e1e51f2015-10-15 08:01:48 -0700252void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700253 const GrPaint& origPaint,
254 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800255 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700256 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700257 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800258 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700259
robertphillipsea461502015-05-26 11:38:03 -0700260 // set rect to be big enough to fill the space, but not super-huge, so we
261 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700262
263 SkRect r = fRenderTarget->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700264 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
265
bsalomoncb31e512016-08-26 10:48:19 -0700266 SkRRect rrect;
267 bool aaRRect;
268 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
269 // transformation for non-rect rrects. Rects caused a performance regression on an Android
270 // test that needs investigation. We also skip cases where there are fragment processors
271 // because they may depend on having correct local coords and this path draws in device space
272 // without a local matrix.
273 if (!paint->numTotalFragmentProcessors() &&
274 clip.isRRect(r, &rrect, &aaRRect) && !rrect.isRect()) {
275 paint.writable()->setAntiAlias(aaRRect);
276 this->drawRRect(GrNoClip(), *paint, SkMatrix::I(), rrect, GrStyle::SimpleFill());
277 return;
278 }
279
robertphillipsea461502015-05-26 11:38:03 -0700280 // by definition this fills the entire clip, no need for AA
281 if (paint->isAntiAlias()) {
282 paint.writable()->setAntiAlias(false);
283 }
284
285 bool isPerspective = viewMatrix.hasPerspective();
286
287 // We attempt to map r by the inverse matrix and draw that. mapRect will
288 // map the four corners and bound them with a new rect. This will not
289 // produce a correct result for some perspective matrices.
290 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700291 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700292 SkDebugf("Could not invert matrix\n");
293 return;
294 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700295 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700296 } else {
297 SkMatrix localMatrix;
298 if (!viewMatrix.invert(&localMatrix)) {
299 SkDebugf("Could not invert matrix\n");
300 return;
301 }
302
robertphillips77a2e522015-10-17 07:43:27 -0700303 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700304
csmartdalton34ee0c92016-07-27 13:22:27 -0700305 this->drawNonAAFilledRect(clip, *paint, SkMatrix::I(), r, nullptr, &localMatrix, nullptr,
306 false /* useHWAA */);
robertphillipsea461502015-05-26 11:38:03 -0700307 }
308}
309
robertphillipsea461502015-05-26 11:38:03 -0700310static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
311 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
312 point.fY >= rect.fTop && point.fY <= rect.fBottom;
313}
314
bsalomonc55271f2015-11-09 11:55:57 -0800315static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
316 return viewMatrix.preservesRightAngles();
317}
318
csmartdaltonecbc12b2016-06-08 10:08:43 -0700319static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt,
320 bool* useHWAA = nullptr) {
321 if (!paint.isAntiAlias()) {
322 if (useHWAA) {
323 *useHWAA = false;
324 }
325 return false;
326 } else {
327 if (useHWAA) {
bsalomonbb243832016-07-22 07:10:19 -0700328 *useHWAA = rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700329 }
bsalomonbb243832016-07-22 07:10:19 -0700330 return !rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700331 }
bsalomonc55271f2015-11-09 11:55:57 -0800332}
333
csmartdalton97f6cd52016-07-13 13:37:08 -0700334// Attempts to crop a rect and optional local rect to the clip boundaries.
335// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700336static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700337 const SkMatrix& viewMatrix, SkRect* rect,
338 SkRect* localRect = nullptr) {
339 if (!viewMatrix.rectStaysRect()) {
340 return true;
341 }
342
csmartdalton97f6cd52016-07-13 13:37:08 -0700343 SkIRect clipDevBounds;
344 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700345
robertphillips13a7eee2016-08-31 15:06:24 -0700346 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700347 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
348 return false;
349 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700350
351 if (localRect) {
352 if (!rect->intersects(clipBounds)) {
353 return false;
354 }
355 const SkScalar dx = localRect->width() / rect->width();
356 const SkScalar dy = localRect->height() / rect->height();
357 if (clipBounds.fLeft > rect->fLeft) {
358 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
359 rect->fLeft = clipBounds.fLeft;
360 }
361 if (clipBounds.fTop > rect->fTop) {
362 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
363 rect->fTop = clipBounds.fTop;
364 }
365 if (clipBounds.fRight < rect->fRight) {
366 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
367 rect->fRight = clipBounds.fRight;
368 }
369 if (clipBounds.fBottom < rect->fBottom) {
370 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
371 rect->fBottom = clipBounds.fBottom;
372 }
373 return true;
374 }
375
376 return rect->intersect(clipBounds);
377}
378
robertphillips44302392016-07-08 14:43:03 -0700379bool GrDrawContext::drawFilledRect(const GrClip& clip,
380 const GrPaint& paint,
381 const SkMatrix& viewMatrix,
382 const SkRect& rect,
383 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700384 SkRect croppedRect = rect;
robertphillips13a7eee2016-08-31 15:06:24 -0700385 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700386 return true;
387 }
robertphillips44302392016-07-08 14:43:03 -0700388
389 SkAutoTUnref<GrDrawBatch> batch;
390 bool useHWAA;
391
csmartdaltone0d36292016-07-29 08:14:20 -0700392 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
393 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdalton97f6cd52016-07-13 13:37:08 -0700394 batch.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
robertphillips44302392016-07-08 14:43:03 -0700395 paint.isAntiAlias(), fInstancedPipelineInfo,
396 &useHWAA));
397 if (batch) {
398 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
399 if (ss) {
400 pipelineBuilder.setUserStencil(ss);
401 }
402 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
403 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700404 }
405 }
robertphillips391395d2016-03-02 09:26:36 -0800406
robertphillips44302392016-07-08 14:43:03 -0700407 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillips391395d2016-03-02 09:26:36 -0800408 // The fill path can handle rotation but not skew.
409 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
410 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700411 viewMatrix.mapRect(&devBoundRect, croppedRect);
robertphillips44302392016-07-08 14:43:03 -0700412
dvonbeck09e12a62016-08-12 12:50:36 -0700413 batch.reset(GrRectBatchFactory::CreateAAFill(paint, viewMatrix, rect, croppedRect,
414 devBoundRect));
robertphillips44302392016-07-08 14:43:03 -0700415 if (batch) {
416 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
417 if (ss) {
418 pipelineBuilder.setUserStencil(ss);
419 }
420 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
421 return true;
422 }
robertphillips391395d2016-03-02 09:26:36 -0800423 }
424 } else {
csmartdalton34ee0c92016-07-27 13:22:27 -0700425 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss,
426 useHWAA);
robertphillips44302392016-07-08 14:43:03 -0700427 return true;
robertphillips391395d2016-03-02 09:26:36 -0800428 }
429
robertphillips44302392016-07-08 14:43:03 -0700430 return false;
robertphillips391395d2016-03-02 09:26:36 -0800431}
432
robertphillips2e1e51f2015-10-15 08:01:48 -0700433void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700434 const GrPaint& paint,
435 const SkMatrix& viewMatrix,
436 const SkRect& rect,
bsalomon6663acf2016-05-10 09:14:17 -0700437 const GrStyle* style) {
438 if (!style) {
439 style = &GrStyle::SimpleFill();
440 }
joshualitt1de610a2016-01-06 08:26:09 -0800441 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -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::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700445
bsalomon6663acf2016-05-10 09:14:17 -0700446 // Path effects should've been devolved to a path in SkGpuDevice
447 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700448
robertphillips77a2e522015-10-17 07:43:27 -0700449 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700450
bsalomon6663acf2016-05-10 09:14:17 -0700451 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700452 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
453
454 if (!fContext->caps()->useDrawInsteadOfClear()) {
455 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
456 // checking cases where the RT is fully inside a stroke.
robertphillips13a7eee2016-08-31 15:06:24 -0700457 SkRect rtRect = fRenderTarget->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700458 // Does the clip contain the entire RT?
459 if (clip.quickContains(rtRect)) {
460 SkMatrix invM;
461 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700462 return;
463 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700464 // Does the rect bound the RT?
465 SkPoint srcSpaceRTQuad[4];
466 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
467 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
468 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
469 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
470 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
471 // Will it blend?
472 GrColor clearColor;
473 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700474 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700475 return;
476 }
477 }
robertphillipsea461502015-05-26 11:38:03 -0700478 }
479 }
robertphillips44302392016-07-08 14:43:03 -0700480
481 if (this->drawFilledRect(clip, paint, viewMatrix, rect, nullptr)) {
482 return;
483 }
bsalomona7d85ba2016-07-06 11:54:59 -0700484 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
485 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
486 if ((!rect.width() || !rect.height()) &&
487 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
488 SkScalar r = stroke.getWidth() / 2;
489 // TODO: Move these stroke->fill fallbacks to GrShape?
490 switch (stroke.getJoin()) {
491 case SkPaint::kMiter_Join:
492 this->drawRect(clip, paint, viewMatrix,
493 {rect.fLeft - r, rect.fTop - r,
494 rect.fRight + r, rect.fBottom + r},
495 &GrStyle::SimpleFill());
496 return;
497 case SkPaint::kRound_Join:
498 // Raster draws nothing when both dimensions are empty.
499 if (rect.width() || rect.height()){
500 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
501 this->drawRRect(clip, paint, viewMatrix, rrect, GrStyle::SimpleFill());
502 return;
503 }
504 case SkPaint::kBevel_Join:
505 if (!rect.width()) {
506 this->drawRect(clip, paint, viewMatrix,
507 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
508 &GrStyle::SimpleFill());
509 } else {
510 this->drawRect(clip, paint, viewMatrix,
511 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
512 &GrStyle::SimpleFill());
513 }
514 return;
515 }
516 }
robertphillips44302392016-07-08 14:43:03 -0700517
518 bool useHWAA;
519 bool snapToPixelCenters = false;
520 SkAutoTUnref<GrDrawBatch> batch;
521
robertphillips391395d2016-03-02 09:26:36 -0800522 GrColor color = paint.getColor();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700523 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
cdaltonbb539482016-01-04 09:48:25 -0800524 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
525 if (viewMatrix.rectStaysRect()) {
bsalomona7d85ba2016-07-06 11:54:59 -0700526 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke));
cdaltonbb539482016-01-04 09:48:25 -0800527 }
robertphillipsea461502015-05-26 11:38:03 -0700528 } else {
robertphillips391395d2016-03-02 09:26:36 -0800529 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700530 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800531 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700532 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
533 !fRenderTarget->isUnifiedMultisampled();
534 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
535 stroke, snapToPixelCenters));
robertphillips391395d2016-03-02 09:26:36 -0800536 }
robertphillips4bc31812016-03-01 12:22:49 -0800537
robertphillips44302392016-07-08 14:43:03 -0700538 if (batch) {
539 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips4bc31812016-03-01 12:22:49 -0800540
robertphillips44302392016-07-08 14:43:03 -0700541 if (snapToPixelCenters) {
542 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
543 snapToPixelCenters);
544 }
545
546 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
547 return;
robertphillips4bc31812016-03-01 12:22:49 -0800548 }
robertphillips4bc31812016-03-01 12:22:49 -0800549 }
halcanary9d524f22016-03-29 09:03:52 -0700550
robertphillips4bc31812016-03-01 12:22:49 -0800551 SkPath path;
552 path.setIsVolatile(true);
553 path.addRect(rect);
bsalomon6663acf2016-05-10 09:14:17 -0700554 this->internalDrawPath(clip, paint, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700555}
556
csmartdalton29df7602016-08-31 11:55:52 -0700557void GrDrawContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700558 ASSERT_SINGLE_OWNER_PRIV
559 RETURN_IF_ABANDONED_PRIV
560 SkDEBUGCODE(fDrawContext->validate();)
561 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
562
563 AutoCheckFlush acf(fDrawContext->fDrawingManager);
csmartdalton29df7602016-08-31 11:55:52 -0700564 fDrawContext->getDrawTarget()->clearStencilClip(clip, insideStencilMask,
robertphillips976f5f02016-06-03 10:59:20 -0700565 fDrawContext->accessRenderTarget());
566}
567
robertphillips59cf61a2016-07-13 09:18:21 -0700568void GrDrawContextPriv::stencilPath(const GrClip& clip,
robertphillips59cf61a2016-07-13 09:18:21 -0700569 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700570 const SkMatrix& viewMatrix,
robertphillips59cf61a2016-07-13 09:18:21 -0700571 const GrPath* path) {
csmartdalton5c6fc4f2016-08-12 15:11:51 -0700572 fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
robertphillips976f5f02016-06-03 10:59:20 -0700573}
574
csmartdalton29df7602016-08-31 11:55:52 -0700575void GrDrawContextPriv::stencilRect(const GrClip& clip,
robertphillips976f5f02016-06-03 10:59:20 -0700576 const GrUserStencilSettings* ss,
csmartdalton656dbe42016-06-10 12:32:57 -0700577 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700578 const SkMatrix& viewMatrix,
579 const SkRect& rect) {
580 ASSERT_SINGLE_OWNER_PRIV
581 RETURN_IF_ABANDONED_PRIV
582 SkDEBUGCODE(fDrawContext->validate();)
583 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::stencilRect");
584
585 AutoCheckFlush acf(fDrawContext->fDrawingManager);
586
587 GrPaint paint;
csmartdalton656dbe42016-06-10 12:32:57 -0700588 paint.setAntiAlias(useHWAA);
bungeman06ca8ec2016-06-09 08:01:03 -0700589 paint.setXPFactory(GrDisableColorXPFactory::Make());
robertphillips976f5f02016-06-03 10:59:20 -0700590
csmartdalton34ee0c92016-07-27 13:22:27 -0700591 fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700592}
593
csmartdalton29df7602016-08-31 11:55:52 -0700594bool GrDrawContextPriv::drawAndStencilRect(const GrClip& clip,
cdalton93a379b2016-05-11 13:58:08 -0700595 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -0800596 SkRegion::Op op,
597 bool invert,
598 bool doAA,
599 const SkMatrix& viewMatrix,
600 const SkRect& rect) {
601 ASSERT_SINGLE_OWNER_PRIV
602 RETURN_FALSE_IF_ABANDONED_PRIV
603 SkDEBUGCODE(fDrawContext->validate();)
robertphillips55fdccc2016-06-06 06:16:20 -0700604 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800605
606 AutoCheckFlush acf(fDrawContext->fDrawingManager);
607
608 GrPaint paint;
609 paint.setAntiAlias(doAA);
610 paint.setCoverageSetOpXPFactory(op, invert);
611
robertphillips44302392016-07-08 14:43:03 -0700612 if (fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800613 return true;
614 }
615
616 SkPath path;
617 path.setIsVolatile(true);
618 path.addRect(rect);
cdalton862cff32016-05-12 15:09:48 -0700619 return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800620}
621
bsalomona2e69fc2015-11-05 10:41:43 -0800622void GrDrawContext::fillRectToRect(const GrClip& clip,
623 const GrPaint& paint,
624 const SkMatrix& viewMatrix,
625 const SkRect& rectToDraw,
626 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800627 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700628 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700629 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800630 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700631
csmartdalton97f6cd52016-07-13 13:37:08 -0700632 SkRect croppedRect = rectToDraw;
633 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700634 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
635 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700636 return;
637 }
638
robertphillips77a2e522015-10-17 07:43:27 -0700639 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700640 bool useHWAA;
641
csmartdaltone0d36292016-07-29 08:14:20 -0700642 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
643 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltonfc49d562016-07-26 17:05:47 -0700644 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
645 croppedLocalRect, paint.isAntiAlias(),
646 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700647 if (batch) {
bsalomonbb243832016-07-22 07:10:19 -0700648 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
649 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700650 return;
651 }
652 }
653
csmartdaltonfc49d562016-07-26 17:05:47 -0700654 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700655 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect,
csmartdalton34ee0c92016-07-27 13:22:27 -0700656 nullptr, nullptr, useHWAA);
csmartdaltonfc49d562016-07-26 17:05:47 -0700657 return;
joshualitt04194f32016-01-13 10:08:27 -0800658 }
bsalomonbb243832016-07-22 07:10:19 -0700659
csmartdaltonfc49d562016-07-26 17:05:47 -0700660 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
661 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(),
662 viewMatrix,
663 croppedRect,
664 croppedLocalRect));
665 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
666 this->drawBatch(pipelineBuilder, clip, batch);
667 return;
668 }
669
670 SkMatrix viewAndUnLocalMatrix;
671 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
672 SkDebugf("fillRectToRect called with empty local matrix.\n");
673 return;
674 }
675 viewAndUnLocalMatrix.postConcat(viewMatrix);
676
677 SkPath path;
678 path.setIsVolatile(true);
679 path.addRect(localRect);
680 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700681}
682
bsalomona2e69fc2015-11-05 10:41:43 -0800683void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
684 const GrPaint& paint,
685 const SkMatrix& viewMatrix,
686 const SkRect& rectToDraw,
687 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800688 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700689 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700690 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800691 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700692
csmartdalton97f6cd52016-07-13 13:37:08 -0700693 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700694 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700695 return;
696 }
697
robertphillips77a2e522015-10-17 07:43:27 -0700698 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700699 bool useHWAA;
700
csmartdaltone0d36292016-07-29 08:14:20 -0700701 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
702 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltonfc49d562016-07-26 17:05:47 -0700703 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
704 localMatrix, paint.isAntiAlias(),
705 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700706 if (batch) {
707 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
708 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
709 return;
710 }
711 }
712
csmartdaltonfc49d562016-07-26 17:05:47 -0700713 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700714 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr,
csmartdalton34ee0c92016-07-27 13:22:27 -0700715 &localMatrix, nullptr, useHWAA);
csmartdaltonfc49d562016-07-26 17:05:47 -0700716 return;
bsalomonc55271f2015-11-09 11:55:57 -0800717 }
robertphillips4bc31812016-03-01 12:22:49 -0800718
csmartdaltonfc49d562016-07-26 17:05:47 -0700719 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
720 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix,
721 localMatrix, croppedRect));
722 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
723 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
724 return;
725 }
726
727 SkMatrix viewAndUnLocalMatrix;
728 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
729 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
730 return;
731 }
732 viewAndUnLocalMatrix.postConcat(viewMatrix);
733
734 SkPath path;
735 path.setIsVolatile(true);
736 path.addRect(rectToDraw);
737 path.transform(localMatrix);
738 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700739}
740
robertphillips2e1e51f2015-10-15 08:01:48 -0700741void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700742 const GrPaint& paint,
743 const SkMatrix& viewMatrix,
744 GrPrimitiveType primitiveType,
745 int vertexCount,
746 const SkPoint positions[],
747 const SkPoint texCoords[],
748 const GrColor colors[],
749 const uint16_t indices[],
750 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800751 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700752 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700753 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800754 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700755
robertphillips77a2e522015-10-17 07:43:27 -0700756 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700757
robertphillipsea461502015-05-26 11:38:03 -0700758 // TODO clients should give us bounds
759 SkRect bounds;
760 if (!bounds.setBoundsCheck(positions, vertexCount)) {
761 SkDebugf("drawVertices call empty bounds\n");
762 return;
763 }
764
765 viewMatrix.mapRect(&bounds);
766
767 // 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 -0800768 // snapping. We also do this for the "hair" primitive types: lines and points since they have
769 // a 1 pixel thickness in device space.
770 if (!paint.isAntiAlias() || GrIsPrimTypeLines(primitiveType) ||
771 kPoints_GrPrimitiveType == primitiveType) {
robertphillipsea461502015-05-26 11:38:03 -0700772 bounds.outset(0.5f, 0.5f);
773 }
774
bsalomond92b4192016-06-30 07:59:23 -0700775 SkAutoTUnref<GrDrawBatch> batch(new GrDrawVerticesBatch(paint.getColor(),
776 primitiveType, viewMatrix, positions,
777 vertexCount, indices, indexCount,
778 colors, texCoords, bounds));
robertphillipsea461502015-05-26 11:38:03 -0700779
csmartdaltonecbc12b2016-06-08 10:08:43 -0700780 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700781 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700782}
783
784///////////////////////////////////////////////////////////////////////////////
785
robertphillips2e1e51f2015-10-15 08:01:48 -0700786void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700787 const GrPaint& paint,
788 const SkMatrix& viewMatrix,
789 int spriteCount,
790 const SkRSXform xform[],
791 const SkRect texRect[],
792 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800793 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700794 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700795 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800796 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700797
robertphillips77a2e522015-10-17 07:43:27 -0700798 AutoCheckFlush acf(fDrawingManager);
halcanary9d524f22016-03-29 09:03:52 -0700799
bsalomon0432dd62016-06-30 07:19:27 -0700800 SkAutoTUnref<GrDrawBatch> batch(new GrDrawAtlasBatch(paint.getColor(), viewMatrix, spriteCount,
801 xform, texRect, colors));
halcanary9d524f22016-03-29 09:03:52 -0700802
csmartdaltonecbc12b2016-06-08 10:08:43 -0700803 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700804 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700805}
806
807///////////////////////////////////////////////////////////////////////////////
808
bsalomon7f0d9f32016-08-15 14:49:10 -0700809void GrDrawContext::drawRRect(const GrClip& origClip,
robertphillipsea461502015-05-26 11:38:03 -0700810 const GrPaint& paint,
811 const SkMatrix& viewMatrix,
812 const SkRRect& rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700813 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800814 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700815 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700816 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800817 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700818 if (rrect.isEmpty()) {
819 return;
820 }
821
bsalomon7f0d9f32016-08-15 14:49:10 -0700822 GrNoClip noclip;
823 const GrClip* clip = &origClip;
824#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
825 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
826 // draw is aa. Since our lower level clip code works from batch bounds, which are SkRects, it
827 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
828 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
829 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
830 SkRRect devRRect;
831 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
832 clip = &noclip;
833 }
834#endif
bsalomon6663acf2016-05-10 09:14:17 -0700835 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700836
csmartdaltona7f29642016-07-07 08:49:11 -0700837 AutoCheckFlush acf(fDrawingManager);
838 const SkStrokeRec stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700839 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -0700840
csmartdaltone0d36292016-07-29 08:14:20 -0700841 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
842 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700843 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
844 SkAutoTUnref<GrDrawBatch> batch(ir->recordRRect(rrect, viewMatrix, paint.getColor(),
845 paint.isAntiAlias(), fInstancedPipelineInfo,
846 &useHWAA));
847 if (batch) {
848 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
bsalomon7f0d9f32016-08-15 14:49:10 -0700849 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700850 return;
851 }
852 }
853
csmartdaltonecbc12b2016-06-08 10:08:43 -0700854 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800855 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -0800856 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800857 viewMatrix,
858 rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700859 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800860 shaderCaps));
861 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700862 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
bsalomon7f0d9f32016-08-15 14:49:10 -0700863 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800864 return;
865 }
robertphillipsea461502015-05-26 11:38:03 -0700866 }
robertphillipsb56f9272016-02-25 11:03:52 -0800867
868 SkPath path;
869 path.setIsVolatile(true);
870 path.addRRect(rrect);
bsalomon7f0d9f32016-08-15 14:49:10 -0700871 this->internalDrawPath(*clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700872}
873
robertphillips00095892016-02-29 13:50:40 -0800874bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
875 const GrPaint& paintIn,
876 const SkMatrix& viewMatrix,
877 const SkRRect& origOuter,
878 const SkRRect& origInner) {
879 SkASSERT(!origInner.isEmpty());
880 SkASSERT(!origOuter.isEmpty());
881
csmartdaltone0d36292016-07-29 08:14:20 -0700882 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700883 bool useHWAA;
csmartdaltone0d36292016-07-29 08:14:20 -0700884 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltona7f29642016-07-07 08:49:11 -0700885 SkAutoTUnref<GrDrawBatch> batch(ir->recordDRRect(origOuter, origInner, viewMatrix,
886 paintIn.getColor(), paintIn.isAntiAlias(),
887 fInstancedPipelineInfo, &useHWAA));
888 if (batch) {
889 GrPipelineBuilder pipelineBuilder(paintIn, useHWAA);
890 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
891 return true;
892 }
893 }
894
robertphillips00095892016-02-29 13:50:40 -0800895 bool applyAA = paintIn.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
896
897 GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
898 kInverseFillBW_GrProcessorEdgeType;
899 GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
900 kFillBW_GrProcessorEdgeType;
901
902 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
903 SkMatrix inverseVM;
904 if (!viewMatrix.isIdentity()) {
905 if (!origInner.transform(viewMatrix, inner.writable())) {
906 return false;
907 }
908 if (!origOuter.transform(viewMatrix, outer.writable())) {
909 return false;
910 }
911 if (!viewMatrix.invert(&inverseVM)) {
912 return false;
913 }
914 } else {
915 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -0700916 }
robertphillips00095892016-02-29 13:50:40 -0800917
918 GrPaint grPaint(paintIn);
919 grPaint.setAntiAlias(false);
920
921 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -0700922 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -0800923 if (!innerEffect) {
924 return false;
925 }
926
bungeman06ca8ec2016-06-09 08:01:03 -0700927 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -0800928 if (!outerEffect) {
929 return false;
930 }
931
bungeman06ca8ec2016-06-09 08:01:03 -0700932 grPaint.addCoverageFragmentProcessor(std::move(innerEffect));
933 grPaint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -0800934
935 SkRect bounds = outer->getBounds();
936 if (applyAA) {
937 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
938 }
halcanary9d524f22016-03-29 09:03:52 -0700939
robertphillips00095892016-02-29 13:50:40 -0800940 this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
941 return true;
942}
943
944void GrDrawContext::drawDRRect(const GrClip& clip,
945 const GrPaint& paint,
946 const SkMatrix& viewMatrix,
947 const SkRRect& outer,
948 const SkRRect& inner) {
949 ASSERT_SINGLE_OWNER
950 RETURN_IF_ABANDONED
951 SkDEBUGCODE(this->validate();)
952 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
953
954 SkASSERT(!outer.isEmpty());
955 SkASSERT(!inner.isEmpty());
956
957 AutoCheckFlush acf(fDrawingManager);
958
959 if (this->drawFilledDRRect(clip, paint, viewMatrix, outer, inner)) {
960 return;
961 }
962
963 SkPath path;
964 path.setIsVolatile(true);
965 path.addRRect(inner);
966 path.addRRect(outer);
967 path.setFillType(SkPath::kEvenOdd_FillType);
968
bsalomon6663acf2016-05-10 09:14:17 -0700969 this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -0800970}
971
robertphillipsea461502015-05-26 11:38:03 -0700972///////////////////////////////////////////////////////////////////////////////
973
msarettcc319b92016-08-25 18:07:18 -0700974static inline bool is_int(float x) {
975 return x == (float) sk_float_round2int(x);
976}
977
978void GrDrawContext::drawRegion(const GrClip& clip,
979 const GrPaint& paint,
980 const SkMatrix& viewMatrix,
981 const SkRegion& region,
982 const GrStyle& style) {
983 ASSERT_SINGLE_OWNER
984 RETURN_IF_ABANDONED
985 SkDEBUGCODE(this->validate();)
986 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRegion");
987
988 bool isNonTranslate = SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask));
989 bool complexStyle = !style.isSimpleFill();
990 bool antiAlias = paint.isAntiAlias() && (!is_int(viewMatrix.getTranslateX()) ||
991 !is_int(viewMatrix.getTranslateY()));
992 if (isNonTranslate || complexStyle || antiAlias) {
993 SkPath path;
994 region.getBoundaryPath(&path);
995 return this->drawPath(clip, paint, viewMatrix, path, style);
996 }
997
998 SkAutoTUnref<GrDrawBatch> batch(GrRegionBatch::Create(paint.getColor(), viewMatrix, region));
999 GrPipelineBuilder pipelineBuilder(paint, false);
1000 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1001}
1002
robertphillips2e1e51f2015-10-15 08:01:48 -07001003void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -07001004 const GrPaint& paint,
1005 const SkMatrix& viewMatrix,
1006 const SkRect& oval,
bsalomon6663acf2016-05-10 09:14:17 -07001007 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001008 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001009 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001010 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001011 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001012
robertphillipsea461502015-05-26 11:38:03 -07001013 if (oval.isEmpty()) {
1014 return;
1015 }
1016
bsalomon6663acf2016-05-10 09:14:17 -07001017 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001018
robertphillips77a2e522015-10-17 07:43:27 -07001019 AutoCheckFlush acf(fDrawingManager);
bsalomon6663acf2016-05-10 09:14:17 -07001020 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -07001021 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -07001022
csmartdaltone0d36292016-07-29 08:14:20 -07001023 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1024 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -07001025 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
1026 SkAutoTUnref<GrDrawBatch> batch(ir->recordOval(oval, viewMatrix, paint.getColor(),
1027 paint.isAntiAlias(), fInstancedPipelineInfo,
1028 &useHWAA));
1029 if (batch) {
1030 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1031 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1032 return;
1033 }
1034 }
1035
csmartdaltonecbc12b2016-06-08 10:08:43 -07001036 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -08001037 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -08001038 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -08001039 viewMatrix,
1040 oval,
bsalomon6663acf2016-05-10 09:14:17 -07001041 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -08001042 shaderCaps));
1043 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001044 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001045 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -08001046 return;
1047 }
robertphillipsea461502015-05-26 11:38:03 -07001048 }
robertphillipsb56f9272016-02-25 11:03:52 -08001049
1050 SkPath path;
1051 path.setIsVolatile(true);
1052 path.addOval(oval);
bsalomon6663acf2016-05-10 09:14:17 -07001053 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001054}
1055
bsalomon4f3a0ca2016-08-22 13:14:26 -07001056void GrDrawContext::drawArc(const GrClip& clip,
1057 const GrPaint& paint,
1058 const SkMatrix& viewMatrix,
1059 const SkRect& oval,
1060 SkScalar startAngle,
1061 SkScalar sweepAngle,
1062 bool useCenter,
1063 const GrStyle& style) {
1064 bool useHWAA;
1065 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
1066 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1067 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateArcBatch(paint.getColor(),
1068 viewMatrix,
1069 oval,
1070 startAngle,
1071 sweepAngle,
1072 useCenter,
1073 style,
1074 shaderCaps));
1075 if (batch) {
1076 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1077 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1078 return;
1079 }
1080 }
1081 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001082 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1083 style.isSimpleFill());
bsalomon4f3a0ca2016-08-22 13:14:26 -07001084 this->internalDrawPath(clip, paint, viewMatrix, path, style);
1085 return;
1086}
1087
msarett10e3d9b2016-08-18 15:46:03 -07001088void GrDrawContext::drawImageLattice(const GrClip& clip,
1089 const GrPaint& paint,
1090 const SkMatrix& viewMatrix,
1091 int imageWidth,
1092 int imageHeight,
1093 std::unique_ptr<SkLatticeIter> iter,
1094 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001095 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001096 RETURN_IF_ABANDONED
1097 SkDEBUGCODE(this->validate();)
msarett10e3d9b2016-08-18 15:46:03 -07001098 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001099
1100 AutoCheckFlush acf(fDrawingManager);
1101
1102 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
1103 imageWidth, imageHeight,
msarett10e3d9b2016-08-18 15:46:03 -07001104 std::move(iter), dst));
joshualitt33a5fce2015-11-18 13:28:51 -08001105
csmartdaltonecbc12b2016-06-08 10:08:43 -07001106 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -07001107 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
joshualitt33a5fce2015-11-18 13:28:51 -08001108}
1109
robertphillips8c523e02016-07-26 07:41:00 -07001110void GrDrawContext::prepareForExternalIO() {
1111 ASSERT_SINGLE_OWNER
1112 RETURN_IF_ABANDONED
1113 SkDEBUGCODE(this->validate();)
1114 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::prepareForExternalIO");
1115
1116 ASSERT_OWNED_RESOURCE(fRenderTarget);
1117
1118 fDrawingManager->getContext()->prepareSurfaceForExternalIO(fRenderTarget.get());
1119}
joshualitt33a5fce2015-11-18 13:28:51 -08001120
robertphillips44302392016-07-08 14:43:03 -07001121void GrDrawContext::drawNonAAFilledRect(const GrClip& clip,
1122 const GrPaint& paint,
1123 const SkMatrix& viewMatrix,
1124 const SkRect& rect,
1125 const SkRect* localRect,
1126 const SkMatrix* localMatrix,
csmartdalton34ee0c92016-07-27 13:22:27 -07001127 const GrUserStencilSettings* ss,
1128 bool useHWAA) {
1129 SkASSERT(!useHWAA || this->isStencilBufferMultisampled());
robertphillips44302392016-07-08 14:43:03 -07001130 SkAutoTUnref<GrDrawBatch> batch(
1131 GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, localRect,
1132 localMatrix));
csmartdalton34ee0c92016-07-27 13:22:27 -07001133 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips44302392016-07-08 14:43:03 -07001134 if (ss) {
1135 pipelineBuilder.setUserStencil(ss);
1136 }
1137 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1138}
1139
robertphillips1da3ecd2016-08-31 14:54:15 -07001140bool GrDrawContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer, size_t dstRowBytes,
1141 int x, int y) {
1142 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1143 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
1144 if (kUnknown_GrPixelConfig == config) {
1145 return false;
1146 }
1147
1148 uint32_t flags = 0;
1149 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
1150 flags = GrContext::kUnpremul_PixelOpsFlag;
1151 }
1152
1153 return fRenderTarget->readPixels(x, y, dstInfo.width(), dstInfo.height(),
1154 config, dstBuffer, dstRowBytes, flags);
1155}
1156
1157bool GrDrawContext::writePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
1158 size_t srcRowBytes, int x, int y) {
1159 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1160 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
1161 if (kUnknown_GrPixelConfig == config) {
1162 return false;
1163 }
1164 uint32_t flags = 0;
1165 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
1166 flags = GrContext::kUnpremul_PixelOpsFlag;
1167 }
1168
1169 return fRenderTarget->writePixels(x, y, srcInfo.width(), srcInfo.height(),
1170 config, srcBuffer, srcRowBytes, flags);
1171}
1172
robertphillipsea461502015-05-26 11:38:03 -07001173// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001174static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001175
1176 if (path.isInverseFillType()) {
1177 return false;
1178 }
1179
1180 // TODO: this restriction could be lifted if we were willing to apply
1181 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001182 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001183 return false;
1184 }
1185
1186 SkPath::Direction dirs[2];
1187 if (!path.isNestedFillRects(rects, dirs)) {
1188 return false;
1189 }
1190
1191 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1192 // The two rects need to be wound opposite to each other
1193 return false;
1194 }
1195
1196 // Right now, nested rects where the margin is not the same width
1197 // all around do not render correctly
1198 const SkScalar* outer = rects[0].asScalars();
1199 const SkScalar* inner = rects[1].asScalars();
1200
1201 bool allEq = true;
1202
1203 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1204 bool allGoE1 = margin >= SK_Scalar1;
1205
1206 for (int i = 1; i < 4; ++i) {
1207 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1208 if (temp < SK_Scalar1) {
1209 allGoE1 = false;
1210 }
1211 if (!SkScalarNearlyEqual(margin, temp)) {
1212 allEq = false;
1213 }
1214 }
1215
1216 return allEq || allGoE1;
1217}
1218
robertphillips2e1e51f2015-10-15 08:01:48 -07001219void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -07001220 const GrPaint& paint,
1221 const SkMatrix& viewMatrix,
1222 const SkPath& path,
bsalomon6663acf2016-05-10 09:14:17 -07001223 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001224 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001225 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001226 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001227 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001228
robertphillipsea461502015-05-26 11:38:03 -07001229 if (path.isEmpty()) {
1230 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -07001231 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001232 }
1233 return;
1234 }
1235
robertphillips77a2e522015-10-17 07:43:27 -07001236 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -07001237
csmartdaltonecbc12b2016-06-08 10:08:43 -07001238 bool useHWAA;
1239 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA) && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001240 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001241 // Concave AA paths are expensive - try to avoid them for special cases
1242 SkRect rects[2];
1243
bsalomon6663acf2016-05-10 09:14:17 -07001244 if (fills_as_nested_rects(viewMatrix, path, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -07001245 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
robertphillips4bc31812016-03-01 12:22:49 -08001246 paint.getColor(), viewMatrix, rects));
bsalomon40ef4852016-05-02 13:22:13 -07001247 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001248 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001249 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
bsalomon40ef4852016-05-02 13:22:13 -07001250 }
robertphillipsea461502015-05-26 11:38:03 -07001251 return;
1252 }
1253 }
1254 SkRect ovalRect;
1255 bool isOval = path.isOval(&ovalRect);
1256
1257 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -08001258 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -08001259 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillips0cc2f852016-02-24 13:36:56 -08001260 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -08001261 ovalRect,
bsalomon6663acf2016-05-10 09:14:17 -07001262 style.strokeRec(),
robertphillips0cc2f852016-02-24 13:36:56 -08001263 shaderCaps));
1264 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001265 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001266 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -07001267 return;
1268 }
1269 }
1270 }
robertphillips4bc31812016-03-01 12:22:49 -08001271
1272 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1273 // Scratch textures can be recycled after they are returned to the texture
1274 // cache. This presents a potential hazard for buffered drawing. However,
1275 // the writePixels that uploads to the scratch will perform a flush so we're
1276 // OK.
bsalomon6663acf2016-05-10 09:14:17 -07001277 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001278}
1279
csmartdalton29df7602016-08-31 11:55:52 -07001280bool GrDrawContextPriv::drawAndStencilPath(const GrClip& clip,
cdalton93a379b2016-05-11 13:58:08 -07001281 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -08001282 SkRegion::Op op,
1283 bool invert,
1284 bool doAA,
1285 const SkMatrix& viewMatrix,
1286 const SkPath& path) {
1287 ASSERT_SINGLE_OWNER_PRIV
1288 RETURN_FALSE_IF_ABANDONED_PRIV
1289 SkDEBUGCODE(fDrawContext->validate();)
1290 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath");
1291
1292 if (path.isEmpty() && path.isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -07001293 this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
robertphillips6c7e3252016-04-27 10:47:51 -07001294 SkRect::MakeIWH(fDrawContext->width(),
1295 fDrawContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001296 return true;
1297 }
1298
1299 AutoCheckFlush acf(fDrawContext->fDrawingManager);
1300
1301 // An Assumption here is that path renderer would use some form of tweaking
1302 // the src color (either the input alpha or in the frag shader) to implement
1303 // aa. If we have some future driver-mojo path AA that can do the right
1304 // thing WRT to the blend then we'll need some query on the PR.
robertphillips13a7eee2016-08-31 15:06:24 -07001305 bool useCoverageAA = doAA && !fDrawContext->isUnifiedMultisampled();
robertphillips976f5f02016-06-03 10:59:20 -07001306 bool hasUserStencilSettings = !ss->isUnused();
robertphillips13a7eee2016-08-31 15:06:24 -07001307 bool isStencilBufferMSAA = fDrawContext->isStencilBufferMultisampled();
robertphillips391395d2016-03-02 09:26:36 -08001308
1309 const GrPathRendererChain::DrawType type =
1310 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1311 : GrPathRendererChain::kColor_DrawType;
1312
bsalomon8acedde2016-06-24 10:42:16 -07001313 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001314 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1315 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
1316 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001317 canDrawArgs.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001318 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001319 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001320 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1321
1322 // Don't allow the SW renderer
1323 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1324 if (!pr) {
1325 return false;
1326 }
1327
1328 GrPaint paint;
1329 paint.setCoverageSetOpXPFactory(op, invert);
1330
robertphillips391395d2016-03-02 09:26:36 -08001331 GrPathRenderer::DrawPathArgs args;
robertphillips391395d2016-03-02 09:26:36 -08001332 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001333 args.fPaint = &paint;
1334 args.fUserStencilSettings = ss;
1335 args.fDrawContext = fDrawContext;
cdalton862cff32016-05-12 15:09:48 -07001336 args.fClip = &clip;
robertphillips391395d2016-03-02 09:26:36 -08001337 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001338 args.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001339 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001340 args.fGammaCorrect = fDrawContext->isGammaCorrect();
robertphillips391395d2016-03-02 09:26:36 -08001341 pr->drawPath(args);
1342 return true;
1343}
1344
robertphillips714712b2016-08-04 06:20:45 -07001345SkBudgeted GrDrawContextPriv::isBudgeted() const {
1346 ASSERT_SINGLE_OWNER_PRIV
1347
1348 if (fDrawContext->wasAbandoned()) {
1349 return SkBudgeted::kNo;
1350 }
1351
1352 SkDEBUGCODE(fDrawContext->validate();)
1353
1354 return fDrawContext->fRenderTarget->resourcePriv().isBudgeted();
1355}
1356
robertphillips4bc31812016-03-01 12:22:49 -08001357void GrDrawContext::internalDrawPath(const GrClip& clip,
1358 const GrPaint& paint,
robertphillipsea461502015-05-26 11:38:03 -07001359 const SkMatrix& viewMatrix,
bsalomon8acedde2016-06-24 10:42:16 -07001360 const SkPath& path,
1361 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001362 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001363 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001364 SkASSERT(!path.isEmpty());
robertphillipsea461502015-05-26 11:38:03 -07001365
robertphillips6c7e3252016-04-27 10:47:51 -07001366 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
cdalton93a379b2016-05-11 13:58:08 -07001367 constexpr bool kHasUserStencilSettings = false;
robertphillips13a7eee2016-08-31 15:06:24 -07001368 bool isStencilBufferMSAA = this->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -07001369
robertphillips68737822015-10-29 12:12:21 -07001370 const GrPathRendererChain::DrawType type =
1371 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1372 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -07001373
bsalomon8acedde2016-06-24 10:42:16 -07001374 GrShape shape(path, style);
bsalomon0a0f67e2016-06-28 11:56:42 -07001375 if (shape.isEmpty()) {
1376 return;
1377 }
robertphillips68737822015-10-29 12:12:21 -07001378 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1379 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1380 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001381 canDrawArgs.fShape = &shape;
robertphillips68737822015-10-29 12:12:21 -07001382 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001383 canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
robertphillips68737822015-10-29 12:12:21 -07001384 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1385
bsalomon6663acf2016-05-10 09:14:17 -07001386 // Try a 1st time without applying any of the style to the geometry (and barring sw)
robertphillips68737822015-10-29 12:12:21 -07001387 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
bsalomon6663acf2016-05-10 09:14:17 -07001388 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001389
bsalomon8acedde2016-06-24 10:42:16 -07001390 if (!pr && shape.style().pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001391 // It didn't work above, so try again with the path effect applied.
bsalomon8acedde2016-06-24 10:42:16 -07001392 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1393 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001394 return;
1395 }
robertphillips68737822015-10-29 12:12:21 -07001396 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -07001397 }
bsalomon6663acf2016-05-10 09:14:17 -07001398 if (!pr) {
bsalomon8acedde2016-06-24 10:42:16 -07001399 if (shape.style().applies()) {
1400 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1401 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001402 return;
1403 }
bsalomon6663acf2016-05-10 09:14:17 -07001404 }
robertphillipsea461502015-05-26 11:38:03 -07001405 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -07001406 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -07001407 }
1408
bsalomon8acedde2016-06-24 10:42:16 -07001409 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001410#ifdef SK_DEBUG
1411 SkDebugf("Unable to find path renderer compatible with path.\n");
1412#endif
1413 return;
1414 }
1415
bsalomon0aff2fa2015-07-31 06:48:27 -07001416 GrPathRenderer::DrawPathArgs args;
robertphillips77a2e522015-10-17 07:43:27 -07001417 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001418 args.fPaint = &paint;
1419 args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
1420 args.fDrawContext = this;
cdalton862cff32016-05-12 15:09:48 -07001421 args.fClip = &clip;
bsalomon0aff2fa2015-07-31 06:48:27 -07001422 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001423 args.fShape = canDrawArgs.fShape;
bsalomon0aff2fa2015-07-31 06:48:27 -07001424 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001425 args.fGammaCorrect = this->isGammaCorrect();
bsalomon0aff2fa2015-07-31 06:48:27 -07001426 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001427}
1428
bsalomonbb243832016-07-22 07:10:19 -07001429void GrDrawContext::drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
1430 GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -08001431 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001432 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001433 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001434 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -07001435
robertphillips976f5f02016-06-03 10:59:20 -07001436 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillips2334fb62015-06-17 05:43:33 -07001437}