blob: 5b5428ac0df11c0b63510b138e5d04979677e541 [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 }
bsalomonb77a9072016-09-07 10:02:04 -070062 ~AutoCheckFlush() { fDrawingManager->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))
brianosman5a7ae7e2016-09-12 12:07:25 -070089 , fColorXformFromSRGB(nullptr)
joshualittde8dc7e2016-01-08 10:09:13 -080090 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
joshualittbc907352016-01-13 06:45:40 -080091 , fAuditTrail(auditTrail)
joshualitt6d0872d2016-01-11 08:27:48 -080092#ifdef SK_DEBUG
93 , fSingleOwner(singleOwner)
94#endif
95{
brianosman5a7ae7e2016-09-12 12:07:25 -070096 if (fColorSpace) {
97 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
98 auto srgbColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
msarettc71a9b72016-09-16 11:01:27 -070099 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
brianosman5a7ae7e2016-09-12 12:07:25 -0700100 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700101 SkDEBUGCODE(this->validate();)
robertphillipsea461502015-05-26 11:38:03 -0700102}
103
robertphillips2e1e51f2015-10-15 08:01:48 -0700104#ifdef SK_DEBUG
105void GrDrawContext::validate() const {
106 SkASSERT(fRenderTarget);
107 ASSERT_OWNED_RESOURCE(fRenderTarget);
robertphillipsa106c622015-10-16 09:07:06 -0700108
109 if (fDrawTarget && !fDrawTarget->isClosed()) {
110 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
111 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700112}
113#endif
114
robertphillipsa106c622015-10-16 09:07:06 -0700115GrDrawContext::~GrDrawContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800116 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700117 SkSafeUnref(fDrawTarget);
118}
119
120GrDrawTarget* GrDrawContext::getDrawTarget() {
joshualitt1de610a2016-01-06 08:26:09 -0800121 ASSERT_SINGLE_OWNER
robertphillipsa106c622015-10-16 09:07:06 -0700122 SkDEBUGCODE(this->validate();)
123
124 if (!fDrawTarget || fDrawTarget->isClosed()) {
robertphillips6c7e3252016-04-27 10:47:51 -0700125 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
robertphillipsa106c622015-10-16 09:07:06 -0700126 }
127
128 return fDrawTarget;
129}
130
bsalomonb8fea972016-02-16 07:34:17 -0800131bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800132 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800133 RETURN_FALSE_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700134 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800135 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
robertphillips2d70dcb2015-10-06 07:38:23 -0700136
robertphillips6c7e3252016-04-27 10:47:51 -0700137 return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700138}
139
robertphillips2e1e51f2015-10-15 08:01:48 -0700140void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700141 const SkPaint& skPaint,
142 const SkMatrix& viewMatrix,
143 const char text[], size_t byteLength,
144 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800145 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700146 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700147 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800148 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700149
brianosman86e76262016-08-11 12:17:31 -0700150 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
151 atlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
152 text, byteLength, x, y, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700153}
robertphillipscaef3452015-11-11 13:18:11 -0800154
robertphillips2e1e51f2015-10-15 08:01:48 -0700155void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700156 const SkPaint& skPaint,
157 const SkMatrix& viewMatrix,
158 const char text[], size_t byteLength,
159 const SkScalar pos[], int scalarsPerPosition,
160 const SkPoint& offset, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800161 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700162 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700163 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800164 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
robertphillips2d70dcb2015-10-06 07:38:23 -0700165
brianosman86e76262016-08-11 12:17:31 -0700166 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
167 atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
168 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
169 offset, clipBounds);
robertphillips2334fb62015-06-17 05:43:33 -0700170
171}
robertphillipscaef3452015-11-11 13:18:11 -0800172
robertphillips2e1e51f2015-10-15 08:01:48 -0700173void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
robertphillips2334fb62015-06-17 05:43:33 -0700174 const SkMatrix& viewMatrix, const SkTextBlob* blob,
175 SkScalar x, SkScalar y,
176 SkDrawFilter* filter, const SkIRect& clipBounds) {
joshualitt1de610a2016-01-06 08:26:09 -0800177 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -0700178 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700179 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800180 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
robertphillips2d70dcb2015-10-06 07:38:23 -0700181
brianosman86e76262016-08-11 12:17:31 -0700182 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
183 atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
184 x, y, filter, clipBounds);
robertphillipsea461502015-05-26 11:38:03 -0700185}
186
robertphillips2e1e51f2015-10-15 08:01:48 -0700187void GrDrawContext::discard() {
joshualitt1de610a2016-01-06 08:26:09 -0800188 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700189 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700190 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800191 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
robertphillips2e1e51f2015-10-15 08:01:48 -0700192
robertphillips77a2e522015-10-17 07:43:27 -0700193 AutoCheckFlush acf(fDrawingManager);
robertphillips6c7e3252016-04-27 10:47:51 -0700194 this->getDrawTarget()->discard(fRenderTarget.get());
robertphillipsea461502015-05-26 11:38:03 -0700195}
196
robertphillips2e1e51f2015-10-15 08:01:48 -0700197void GrDrawContext::clear(const SkIRect* rect,
robertphillipsea461502015-05-26 11:38:03 -0700198 const GrColor color,
199 bool canIgnoreRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800200 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700201 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700202 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800203 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
robertphillipsea461502015-05-26 11:38:03 -0700204
robertphillips77a2e522015-10-17 07:43:27 -0700205 AutoCheckFlush acf(fDrawingManager);
csmartdalton29df7602016-08-31 11:55:52 -0700206 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
207}
robertphillips9199a9f2016-07-13 07:48:43 -0700208
csmartdalton29df7602016-08-31 11:55:52 -0700209void GrDrawContextPriv::clear(const GrFixedClip& clip,
210 const GrColor color,
211 bool canIgnoreClip) {
212 ASSERT_SINGLE_OWNER_PRIV
213 RETURN_IF_ABANDONED_PRIV
214 SkDEBUGCODE(fDrawContext->validate();)
215 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clear");
216
217 AutoCheckFlush acf(fDrawContext->fDrawingManager);
218 fDrawContext->internalClear(clip, color, canIgnoreClip);
219}
220
221void GrDrawContext::internalClear(const GrFixedClip& clip,
222 const GrColor color,
223 bool canIgnoreClip) {
csmartdaltonbf4a8f92016-09-06 10:01:06 -0700224 bool isFull = false;
225 if (!clip.hasWindowRectangles()) {
226 isFull = !clip.scissorEnabled() ||
227 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
228 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
229 }
robertphillips9199a9f2016-07-13 07:48:43 -0700230
231 if (fContext->caps()->useDrawInsteadOfClear()) {
232 // This works around a driver bug with clear by drawing a rect instead.
233 // The driver will ignore a clear if it is the only thing rendered to a
234 // target before the target is read.
csmartdalton29df7602016-08-31 11:55:52 -0700235 SkRect clearRect = SkRect::MakeIWH(this->width(), this->height());
236 if (isFull) {
robertphillips9199a9f2016-07-13 07:48:43 -0700237 this->discard();
csmartdalton29df7602016-08-31 11:55:52 -0700238 } else if (!clearRect.intersect(SkRect::Make(clip.scissorRect()))) {
239 return;
robertphillips9199a9f2016-07-13 07:48:43 -0700240 }
241
242 GrPaint paint;
243 paint.setColor4f(GrColor4f::FromGrColor(color));
reed374772b2016-10-05 17:33:02 -0700244 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::Mode::kSrc_Mode));
robertphillips9199a9f2016-07-13 07:48:43 -0700245
csmartdalton29df7602016-08-31 11:55:52 -0700246 this->drawRect(clip, paint, SkMatrix::I(), clearRect);
bsalomon9f129de2016-08-10 16:31:05 -0700247 } else if (isFull) {
248 this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
robertphillips9199a9f2016-07-13 07:48:43 -0700249 } else {
csmartdalton29df7602016-08-31 11:55:52 -0700250 sk_sp<GrBatch> batch(GrClearBatch::Make(clip, color, this->accessRenderTarget()));
251 if (!batch) {
252 return;
253 }
robertphillips9199a9f2016-07-13 07:48:43 -0700254 this->getDrawTarget()->addBatch(std::move(batch));
255 }
robertphillipsea461502015-05-26 11:38:03 -0700256}
257
robertphillips2e1e51f2015-10-15 08:01:48 -0700258void GrDrawContext::drawPaint(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700259 const GrPaint& origPaint,
260 const SkMatrix& viewMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800261 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700262 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700263 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800264 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
robertphillips2e1e51f2015-10-15 08:01:48 -0700265
robertphillipsea461502015-05-26 11:38:03 -0700266 // set rect to be big enough to fill the space, but not super-huge, so we
267 // don't overflow fixed-point implementations
robertphillips13a7eee2016-08-31 15:06:24 -0700268
269 SkRect r = fRenderTarget->getBoundsRect();
robertphillipsea461502015-05-26 11:38:03 -0700270 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
271
bsalomoncb31e512016-08-26 10:48:19 -0700272 SkRRect rrect;
273 bool aaRRect;
274 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
275 // transformation for non-rect rrects. Rects caused a performance regression on an Android
276 // test that needs investigation. We also skip cases where there are fragment processors
277 // because they may depend on having correct local coords and this path draws in device space
278 // without a local matrix.
279 if (!paint->numTotalFragmentProcessors() &&
280 clip.isRRect(r, &rrect, &aaRRect) && !rrect.isRect()) {
281 paint.writable()->setAntiAlias(aaRRect);
282 this->drawRRect(GrNoClip(), *paint, SkMatrix::I(), rrect, GrStyle::SimpleFill());
283 return;
284 }
285
robertphillipsea461502015-05-26 11:38:03 -0700286 // by definition this fills the entire clip, no need for AA
287 if (paint->isAntiAlias()) {
288 paint.writable()->setAntiAlias(false);
289 }
290
291 bool isPerspective = viewMatrix.hasPerspective();
292
293 // We attempt to map r by the inverse matrix and draw that. mapRect will
294 // map the four corners and bound them with a new rect. This will not
295 // produce a correct result for some perspective matrices.
296 if (!isPerspective) {
reeda39667c2016-08-22 06:39:49 -0700297 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
robertphillipsea461502015-05-26 11:38:03 -0700298 SkDebugf("Could not invert matrix\n");
299 return;
300 }
robertphillips2e1e51f2015-10-15 08:01:48 -0700301 this->drawRect(clip, *paint, viewMatrix, r);
robertphillipsea461502015-05-26 11:38:03 -0700302 } else {
303 SkMatrix localMatrix;
304 if (!viewMatrix.invert(&localMatrix)) {
305 SkDebugf("Could not invert matrix\n");
306 return;
307 }
308
robertphillips77a2e522015-10-17 07:43:27 -0700309 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700310
csmartdalton34ee0c92016-07-27 13:22:27 -0700311 this->drawNonAAFilledRect(clip, *paint, SkMatrix::I(), r, nullptr, &localMatrix, nullptr,
312 false /* useHWAA */);
robertphillipsea461502015-05-26 11:38:03 -0700313 }
314}
315
robertphillipsea461502015-05-26 11:38:03 -0700316static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
317 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
318 point.fY >= rect.fTop && point.fY <= rect.fBottom;
319}
320
bsalomonc55271f2015-11-09 11:55:57 -0800321static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
322 return viewMatrix.preservesRightAngles();
323}
324
csmartdaltonecbc12b2016-06-08 10:08:43 -0700325static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt,
326 bool* useHWAA = nullptr) {
327 if (!paint.isAntiAlias()) {
328 if (useHWAA) {
329 *useHWAA = false;
330 }
331 return false;
332 } else {
333 if (useHWAA) {
bsalomonbb243832016-07-22 07:10:19 -0700334 *useHWAA = rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700335 }
bsalomonbb243832016-07-22 07:10:19 -0700336 return !rt->isUnifiedMultisampled();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700337 }
bsalomonc55271f2015-11-09 11:55:57 -0800338}
339
csmartdalton97f6cd52016-07-13 13:37:08 -0700340// Attempts to crop a rect and optional local rect to the clip boundaries.
341// Returns false if the draw can be skipped entirely.
robertphillips13a7eee2016-08-31 15:06:24 -0700342static bool crop_filled_rect(int width, int height, const GrClip& clip,
csmartdalton97f6cd52016-07-13 13:37:08 -0700343 const SkMatrix& viewMatrix, SkRect* rect,
344 SkRect* localRect = nullptr) {
345 if (!viewMatrix.rectStaysRect()) {
346 return true;
347 }
348
csmartdalton97f6cd52016-07-13 13:37:08 -0700349 SkIRect clipDevBounds;
350 SkRect clipBounds;
csmartdalton97f6cd52016-07-13 13:37:08 -0700351
robertphillips13a7eee2016-08-31 15:06:24 -0700352 clip.getConservativeBounds(width, height, &clipDevBounds);
reeda39667c2016-08-22 06:39:49 -0700353 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
354 return false;
355 }
csmartdalton97f6cd52016-07-13 13:37:08 -0700356
357 if (localRect) {
358 if (!rect->intersects(clipBounds)) {
359 return false;
360 }
361 const SkScalar dx = localRect->width() / rect->width();
362 const SkScalar dy = localRect->height() / rect->height();
363 if (clipBounds.fLeft > rect->fLeft) {
364 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
365 rect->fLeft = clipBounds.fLeft;
366 }
367 if (clipBounds.fTop > rect->fTop) {
368 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
369 rect->fTop = clipBounds.fTop;
370 }
371 if (clipBounds.fRight < rect->fRight) {
372 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
373 rect->fRight = clipBounds.fRight;
374 }
375 if (clipBounds.fBottom < rect->fBottom) {
376 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
377 rect->fBottom = clipBounds.fBottom;
378 }
379 return true;
380 }
381
382 return rect->intersect(clipBounds);
383}
384
robertphillips44302392016-07-08 14:43:03 -0700385bool GrDrawContext::drawFilledRect(const GrClip& clip,
386 const GrPaint& paint,
387 const SkMatrix& viewMatrix,
388 const SkRect& rect,
389 const GrUserStencilSettings* ss) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700390 SkRect croppedRect = rect;
robertphillips13a7eee2016-08-31 15:06:24 -0700391 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700392 return true;
393 }
robertphillips44302392016-07-08 14:43:03 -0700394
395 SkAutoTUnref<GrDrawBatch> batch;
396 bool useHWAA;
397
csmartdaltone0d36292016-07-29 08:14:20 -0700398 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
399 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdalton97f6cd52016-07-13 13:37:08 -0700400 batch.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
robertphillips44302392016-07-08 14:43:03 -0700401 paint.isAntiAlias(), fInstancedPipelineInfo,
402 &useHWAA));
403 if (batch) {
404 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
405 if (ss) {
406 pipelineBuilder.setUserStencil(ss);
407 }
408 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
409 return true;
csmartdaltona7f29642016-07-07 08:49:11 -0700410 }
411 }
robertphillips391395d2016-03-02 09:26:36 -0800412
robertphillips44302392016-07-08 14:43:03 -0700413 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillips391395d2016-03-02 09:26:36 -0800414 // The fill path can handle rotation but not skew.
415 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
416 SkRect devBoundRect;
csmartdalton97f6cd52016-07-13 13:37:08 -0700417 viewMatrix.mapRect(&devBoundRect, croppedRect);
robertphillips44302392016-07-08 14:43:03 -0700418
dvonbeck09e12a62016-08-12 12:50:36 -0700419 batch.reset(GrRectBatchFactory::CreateAAFill(paint, viewMatrix, rect, croppedRect,
420 devBoundRect));
robertphillips44302392016-07-08 14:43:03 -0700421 if (batch) {
422 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
423 if (ss) {
424 pipelineBuilder.setUserStencil(ss);
425 }
426 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
427 return true;
428 }
robertphillips391395d2016-03-02 09:26:36 -0800429 }
430 } else {
csmartdalton34ee0c92016-07-27 13:22:27 -0700431 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss,
432 useHWAA);
robertphillips44302392016-07-08 14:43:03 -0700433 return true;
robertphillips391395d2016-03-02 09:26:36 -0800434 }
435
robertphillips44302392016-07-08 14:43:03 -0700436 return false;
robertphillips391395d2016-03-02 09:26:36 -0800437}
438
robertphillips2e1e51f2015-10-15 08:01:48 -0700439void GrDrawContext::drawRect(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700440 const GrPaint& paint,
441 const SkMatrix& viewMatrix,
442 const SkRect& rect,
bsalomon6663acf2016-05-10 09:14:17 -0700443 const GrStyle* style) {
444 if (!style) {
445 style = &GrStyle::SimpleFill();
446 }
joshualitt1de610a2016-01-06 08:26:09 -0800447 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700448 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700449 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800450 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
robertphillips2e1e51f2015-10-15 08:01:48 -0700451
bsalomon6663acf2016-05-10 09:14:17 -0700452 // Path effects should've been devolved to a path in SkGpuDevice
453 SkASSERT(!style->pathEffect());
robertphillipsea461502015-05-26 11:38:03 -0700454
robertphillips77a2e522015-10-17 07:43:27 -0700455 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -0700456
bsalomon6663acf2016-05-10 09:14:17 -0700457 const SkStrokeRec& stroke = style->strokeRec();
robertphillips3ab14ca2016-07-10 11:49:39 -0700458 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
459
460 if (!fContext->caps()->useDrawInsteadOfClear()) {
461 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
462 // checking cases where the RT is fully inside a stroke.
robertphillips13a7eee2016-08-31 15:06:24 -0700463 SkRect rtRect = fRenderTarget->getBoundsRect();
robertphillips3ab14ca2016-07-10 11:49:39 -0700464 // Does the clip contain the entire RT?
465 if (clip.quickContains(rtRect)) {
466 SkMatrix invM;
467 if (!viewMatrix.invert(&invM)) {
robertphillipsea461502015-05-26 11:38:03 -0700468 return;
469 }
robertphillips3ab14ca2016-07-10 11:49:39 -0700470 // Does the rect bound the RT?
471 SkPoint srcSpaceRTQuad[4];
472 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
473 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
474 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
475 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
476 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
477 // Will it blend?
478 GrColor clearColor;
479 if (paint.isConstantBlendedColor(&clearColor)) {
robertphillips9199a9f2016-07-13 07:48:43 -0700480 this->clear(nullptr, clearColor, true);
robertphillips3ab14ca2016-07-10 11:49:39 -0700481 return;
482 }
483 }
robertphillipsea461502015-05-26 11:38:03 -0700484 }
485 }
robertphillips44302392016-07-08 14:43:03 -0700486
487 if (this->drawFilledRect(clip, paint, viewMatrix, rect, nullptr)) {
488 return;
489 }
bsalomona7d85ba2016-07-06 11:54:59 -0700490 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
491 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
492 if ((!rect.width() || !rect.height()) &&
493 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
494 SkScalar r = stroke.getWidth() / 2;
495 // TODO: Move these stroke->fill fallbacks to GrShape?
496 switch (stroke.getJoin()) {
497 case SkPaint::kMiter_Join:
498 this->drawRect(clip, paint, viewMatrix,
499 {rect.fLeft - r, rect.fTop - r,
500 rect.fRight + r, rect.fBottom + r},
501 &GrStyle::SimpleFill());
502 return;
503 case SkPaint::kRound_Join:
504 // Raster draws nothing when both dimensions are empty.
505 if (rect.width() || rect.height()){
506 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
507 this->drawRRect(clip, paint, viewMatrix, rrect, GrStyle::SimpleFill());
508 return;
509 }
510 case SkPaint::kBevel_Join:
511 if (!rect.width()) {
512 this->drawRect(clip, paint, viewMatrix,
513 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
514 &GrStyle::SimpleFill());
515 } else {
516 this->drawRect(clip, paint, viewMatrix,
517 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
518 &GrStyle::SimpleFill());
519 }
520 return;
521 }
522 }
robertphillips44302392016-07-08 14:43:03 -0700523
524 bool useHWAA;
525 bool snapToPixelCenters = false;
526 SkAutoTUnref<GrDrawBatch> batch;
527
robertphillips391395d2016-03-02 09:26:36 -0800528 GrColor color = paint.getColor();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700529 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
cdaltonbb539482016-01-04 09:48:25 -0800530 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
531 if (viewMatrix.rectStaysRect()) {
bsalomona7d85ba2016-07-06 11:54:59 -0700532 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke));
cdaltonbb539482016-01-04 09:48:25 -0800533 }
robertphillipsea461502015-05-26 11:38:03 -0700534 } else {
robertphillips391395d2016-03-02 09:26:36 -0800535 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
halcanary9d524f22016-03-29 09:03:52 -0700536 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
robertphillips391395d2016-03-02 09:26:36 -0800537 // when MSAA is enabled because it can cause ugly artifacts.
bsalomona7d85ba2016-07-06 11:54:59 -0700538 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
539 !fRenderTarget->isUnifiedMultisampled();
540 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
541 stroke, snapToPixelCenters));
robertphillips391395d2016-03-02 09:26:36 -0800542 }
robertphillips4bc31812016-03-01 12:22:49 -0800543
robertphillips44302392016-07-08 14:43:03 -0700544 if (batch) {
545 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips4bc31812016-03-01 12:22:49 -0800546
robertphillips44302392016-07-08 14:43:03 -0700547 if (snapToPixelCenters) {
548 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
549 snapToPixelCenters);
550 }
551
552 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
553 return;
robertphillips4bc31812016-03-01 12:22:49 -0800554 }
robertphillips4bc31812016-03-01 12:22:49 -0800555 }
halcanary9d524f22016-03-29 09:03:52 -0700556
robertphillips4bc31812016-03-01 12:22:49 -0800557 SkPath path;
558 path.setIsVolatile(true);
559 path.addRect(rect);
bsalomon6663acf2016-05-10 09:14:17 -0700560 this->internalDrawPath(clip, paint, viewMatrix, path, *style);
robertphillipsea461502015-05-26 11:38:03 -0700561}
562
csmartdalton29df7602016-08-31 11:55:52 -0700563void GrDrawContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
robertphillips976f5f02016-06-03 10:59:20 -0700564 ASSERT_SINGLE_OWNER_PRIV
565 RETURN_IF_ABANDONED_PRIV
566 SkDEBUGCODE(fDrawContext->validate();)
567 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
568
569 AutoCheckFlush acf(fDrawContext->fDrawingManager);
csmartdalton29df7602016-08-31 11:55:52 -0700570 fDrawContext->getDrawTarget()->clearStencilClip(clip, insideStencilMask,
robertphillips976f5f02016-06-03 10:59:20 -0700571 fDrawContext->accessRenderTarget());
572}
573
robertphillips59cf61a2016-07-13 09:18:21 -0700574void GrDrawContextPriv::stencilPath(const GrClip& clip,
robertphillips59cf61a2016-07-13 09:18:21 -0700575 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700576 const SkMatrix& viewMatrix,
robertphillips59cf61a2016-07-13 09:18:21 -0700577 const GrPath* path) {
csmartdalton5c6fc4f2016-08-12 15:11:51 -0700578 fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
robertphillips976f5f02016-06-03 10:59:20 -0700579}
580
csmartdalton29df7602016-08-31 11:55:52 -0700581void GrDrawContextPriv::stencilRect(const GrClip& clip,
robertphillips976f5f02016-06-03 10:59:20 -0700582 const GrUserStencilSettings* ss,
csmartdalton656dbe42016-06-10 12:32:57 -0700583 bool useHWAA,
robertphillips976f5f02016-06-03 10:59:20 -0700584 const SkMatrix& viewMatrix,
585 const SkRect& rect) {
586 ASSERT_SINGLE_OWNER_PRIV
587 RETURN_IF_ABANDONED_PRIV
588 SkDEBUGCODE(fDrawContext->validate();)
589 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::stencilRect");
590
591 AutoCheckFlush acf(fDrawContext->fDrawingManager);
592
593 GrPaint paint;
csmartdalton656dbe42016-06-10 12:32:57 -0700594 paint.setAntiAlias(useHWAA);
bungeman06ca8ec2016-06-09 08:01:03 -0700595 paint.setXPFactory(GrDisableColorXPFactory::Make());
robertphillips976f5f02016-06-03 10:59:20 -0700596
csmartdalton34ee0c92016-07-27 13:22:27 -0700597 fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -0700598}
599
csmartdalton29df7602016-08-31 11:55:52 -0700600bool GrDrawContextPriv::drawAndStencilRect(const GrClip& clip,
cdalton93a379b2016-05-11 13:58:08 -0700601 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -0800602 SkRegion::Op op,
603 bool invert,
604 bool doAA,
605 const SkMatrix& viewMatrix,
606 const SkRect& rect) {
607 ASSERT_SINGLE_OWNER_PRIV
608 RETURN_FALSE_IF_ABANDONED_PRIV
609 SkDEBUGCODE(fDrawContext->validate();)
robertphillips55fdccc2016-06-06 06:16:20 -0700610 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawAndStencilRect");
robertphillips391395d2016-03-02 09:26:36 -0800611
612 AutoCheckFlush acf(fDrawContext->fDrawingManager);
613
614 GrPaint paint;
615 paint.setAntiAlias(doAA);
616 paint.setCoverageSetOpXPFactory(op, invert);
617
robertphillips44302392016-07-08 14:43:03 -0700618 if (fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss)) {
robertphillips391395d2016-03-02 09:26:36 -0800619 return true;
620 }
621
622 SkPath path;
623 path.setIsVolatile(true);
624 path.addRect(rect);
cdalton862cff32016-05-12 15:09:48 -0700625 return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
robertphillips391395d2016-03-02 09:26:36 -0800626}
627
bsalomona2e69fc2015-11-05 10:41:43 -0800628void GrDrawContext::fillRectToRect(const GrClip& clip,
629 const GrPaint& paint,
630 const SkMatrix& viewMatrix,
631 const SkRect& rectToDraw,
632 const SkRect& localRect) {
joshualitt1de610a2016-01-06 08:26:09 -0800633 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700634 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700635 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800636 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
robertphillipsea461502015-05-26 11:38:03 -0700637
csmartdalton97f6cd52016-07-13 13:37:08 -0700638 SkRect croppedRect = rectToDraw;
639 SkRect croppedLocalRect = localRect;
robertphillips13a7eee2016-08-31 15:06:24 -0700640 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
641 &croppedRect, &croppedLocalRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700642 return;
643 }
644
robertphillips77a2e522015-10-17 07:43:27 -0700645 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700646 bool useHWAA;
647
csmartdaltone0d36292016-07-29 08:14:20 -0700648 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
649 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltonfc49d562016-07-26 17:05:47 -0700650 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
651 croppedLocalRect, paint.isAntiAlias(),
652 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700653 if (batch) {
bsalomonbb243832016-07-22 07:10:19 -0700654 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
655 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700656 return;
657 }
658 }
659
csmartdaltonfc49d562016-07-26 17:05:47 -0700660 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700661 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect,
csmartdalton34ee0c92016-07-27 13:22:27 -0700662 nullptr, nullptr, useHWAA);
csmartdaltonfc49d562016-07-26 17:05:47 -0700663 return;
joshualitt04194f32016-01-13 10:08:27 -0800664 }
bsalomonbb243832016-07-22 07:10:19 -0700665
csmartdaltonfc49d562016-07-26 17:05:47 -0700666 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
667 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(),
668 viewMatrix,
669 croppedRect,
670 croppedLocalRect));
671 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
672 this->drawBatch(pipelineBuilder, clip, batch);
673 return;
674 }
675
676 SkMatrix viewAndUnLocalMatrix;
677 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
678 SkDebugf("fillRectToRect called with empty local matrix.\n");
679 return;
680 }
681 viewAndUnLocalMatrix.postConcat(viewMatrix);
682
683 SkPath path;
684 path.setIsVolatile(true);
685 path.addRect(localRect);
686 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
joshualittb6b513b2015-08-21 10:25:18 -0700687}
688
bsalomona2e69fc2015-11-05 10:41:43 -0800689void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
690 const GrPaint& paint,
691 const SkMatrix& viewMatrix,
692 const SkRect& rectToDraw,
693 const SkMatrix& localMatrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800694 ASSERT_SINGLE_OWNER
joshualittb6b513b2015-08-21 10:25:18 -0700695 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700696 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800697 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
joshualittb6b513b2015-08-21 10:25:18 -0700698
csmartdalton97f6cd52016-07-13 13:37:08 -0700699 SkRect croppedRect = rectToDraw;
robertphillips13a7eee2016-08-31 15:06:24 -0700700 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700701 return;
702 }
703
robertphillips77a2e522015-10-17 07:43:27 -0700704 AutoCheckFlush acf(fDrawingManager);
csmartdaltona7f29642016-07-07 08:49:11 -0700705 bool useHWAA;
706
csmartdaltone0d36292016-07-29 08:14:20 -0700707 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
708 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltonfc49d562016-07-26 17:05:47 -0700709 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
710 localMatrix, paint.isAntiAlias(),
711 fInstancedPipelineInfo, &useHWAA));
csmartdaltona7f29642016-07-07 08:49:11 -0700712 if (batch) {
713 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
714 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
715 return;
716 }
717 }
718
csmartdaltonfc49d562016-07-26 17:05:47 -0700719 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
csmartdalton97f6cd52016-07-13 13:37:08 -0700720 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr,
csmartdalton34ee0c92016-07-27 13:22:27 -0700721 &localMatrix, nullptr, useHWAA);
csmartdaltonfc49d562016-07-26 17:05:47 -0700722 return;
bsalomonc55271f2015-11-09 11:55:57 -0800723 }
robertphillips4bc31812016-03-01 12:22:49 -0800724
csmartdaltonfc49d562016-07-26 17:05:47 -0700725 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
726 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix,
727 localMatrix, croppedRect));
728 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
729 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
730 return;
731 }
732
733 SkMatrix viewAndUnLocalMatrix;
734 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
735 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
736 return;
737 }
738 viewAndUnLocalMatrix.postConcat(viewMatrix);
739
740 SkPath path;
741 path.setIsVolatile(true);
742 path.addRect(rectToDraw);
743 path.transform(localMatrix);
744 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
robertphillipsea461502015-05-26 11:38:03 -0700745}
746
robertphillips2e1e51f2015-10-15 08:01:48 -0700747void GrDrawContext::drawVertices(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -0700748 const GrPaint& paint,
749 const SkMatrix& viewMatrix,
750 GrPrimitiveType primitiveType,
751 int vertexCount,
752 const SkPoint positions[],
753 const SkPoint texCoords[],
754 const GrColor colors[],
755 const uint16_t indices[],
756 int indexCount) {
joshualitt1de610a2016-01-06 08:26:09 -0800757 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700758 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700759 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800760 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
robertphillipsea461502015-05-26 11:38:03 -0700761
robertphillips77a2e522015-10-17 07:43:27 -0700762 AutoCheckFlush acf(fDrawingManager);
robertphillips2e1e51f2015-10-15 08:01:48 -0700763
robertphillipsea461502015-05-26 11:38:03 -0700764 // TODO clients should give us bounds
765 SkRect bounds;
766 if (!bounds.setBoundsCheck(positions, vertexCount)) {
767 SkDebugf("drawVertices call empty bounds\n");
768 return;
769 }
770
771 viewMatrix.mapRect(&bounds);
772
bsalomond92b4192016-06-30 07:59:23 -0700773 SkAutoTUnref<GrDrawBatch> batch(new GrDrawVerticesBatch(paint.getColor(),
774 primitiveType, viewMatrix, positions,
775 vertexCount, indices, indexCount,
776 colors, texCoords, bounds));
robertphillipsea461502015-05-26 11:38:03 -0700777
csmartdaltonecbc12b2016-06-08 10:08:43 -0700778 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700779 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -0700780}
781
782///////////////////////////////////////////////////////////////////////////////
783
robertphillips2e1e51f2015-10-15 08:01:48 -0700784void GrDrawContext::drawAtlas(const GrClip& clip,
jvanverth31ff7622015-08-07 10:09:28 -0700785 const GrPaint& paint,
786 const SkMatrix& viewMatrix,
787 int spriteCount,
788 const SkRSXform xform[],
789 const SkRect texRect[],
790 const SkColor colors[]) {
joshualitt1de610a2016-01-06 08:26:09 -0800791 ASSERT_SINGLE_OWNER
jvanverth31ff7622015-08-07 10:09:28 -0700792 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700793 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800794 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
robertphillips2e1e51f2015-10-15 08:01:48 -0700795
robertphillips77a2e522015-10-17 07:43:27 -0700796 AutoCheckFlush acf(fDrawingManager);
halcanary9d524f22016-03-29 09:03:52 -0700797
bsalomon0432dd62016-06-30 07:19:27 -0700798 SkAutoTUnref<GrDrawBatch> batch(new GrDrawAtlasBatch(paint.getColor(), viewMatrix, spriteCount,
799 xform, texRect, colors));
halcanary9d524f22016-03-29 09:03:52 -0700800
csmartdaltonecbc12b2016-06-08 10:08:43 -0700801 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -0700802 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
jvanverth31ff7622015-08-07 10:09:28 -0700803}
804
805///////////////////////////////////////////////////////////////////////////////
806
bsalomon7f0d9f32016-08-15 14:49:10 -0700807void GrDrawContext::drawRRect(const GrClip& origClip,
robertphillipsea461502015-05-26 11:38:03 -0700808 const GrPaint& paint,
809 const SkMatrix& viewMatrix,
810 const SkRRect& rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700811 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -0800812 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700813 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -0700814 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -0800815 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
robertphillipsea461502015-05-26 11:38:03 -0700816 if (rrect.isEmpty()) {
817 return;
818 }
819
bsalomon7f0d9f32016-08-15 14:49:10 -0700820 GrNoClip noclip;
821 const GrClip* clip = &origClip;
822#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
823 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
824 // draw is aa. Since our lower level clip code works from batch bounds, which are SkRects, it
825 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
826 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
827 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
828 SkRRect devRRect;
829 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
830 clip = &noclip;
831 }
832#endif
bsalomon6663acf2016-05-10 09:14:17 -0700833 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
ksakamotoec7f2ac2016-07-05 03:54:53 -0700834
csmartdaltona7f29642016-07-07 08:49:11 -0700835 AutoCheckFlush acf(fDrawingManager);
836 const SkStrokeRec stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -0700837 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -0700838
csmartdaltone0d36292016-07-29 08:14:20 -0700839 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
840 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700841 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
842 SkAutoTUnref<GrDrawBatch> batch(ir->recordRRect(rrect, viewMatrix, paint.getColor(),
843 paint.isAntiAlias(), fInstancedPipelineInfo,
844 &useHWAA));
845 if (batch) {
846 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
bsalomon7f0d9f32016-08-15 14:49:10 -0700847 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
csmartdaltona7f29642016-07-07 08:49:11 -0700848 return;
849 }
850 }
851
csmartdaltonecbc12b2016-06-08 10:08:43 -0700852 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -0800853 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
Robert Phillips79839d42016-10-06 15:03:34 -0400854 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(
855 paint.getColor(),
856 paint.usesDistanceVectorField(),
857 viewMatrix,
858 rrect,
859 stroke,
860 shaderCaps));
robertphillipsb56f9272016-02-25 11:03:52 -0800861 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
bsalomon6a2b1942016-09-08 11:28:59 -07001118 fDrawingManager->prepareSurfaceForExternalIO(fRenderTarget.get());
robertphillips8c523e02016-07-26 07:41:00 -07001119}
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}