blob: e9a9619da587742237d7e8b9e007ff681916fefb [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));
244 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
245
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();
robertphillips4bc31812016-03-01 12:22:49 -0800854 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -0800855 viewMatrix,
856 rrect,
bsalomon6663acf2016-05-10 09:14:17 -0700857 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -0800858 shaderCaps));
859 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -0700860 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
bsalomon7f0d9f32016-08-15 14:49:10 -0700861 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -0800862 return;
863 }
robertphillipsea461502015-05-26 11:38:03 -0700864 }
robertphillipsb56f9272016-02-25 11:03:52 -0800865
866 SkPath path;
867 path.setIsVolatile(true);
868 path.addRRect(rrect);
bsalomon7f0d9f32016-08-15 14:49:10 -0700869 this->internalDrawPath(*clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -0700870}
871
robertphillips00095892016-02-29 13:50:40 -0800872bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
873 const GrPaint& paintIn,
874 const SkMatrix& viewMatrix,
875 const SkRRect& origOuter,
876 const SkRRect& origInner) {
877 SkASSERT(!origInner.isEmpty());
878 SkASSERT(!origOuter.isEmpty());
879
csmartdaltone0d36292016-07-29 08:14:20 -0700880 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
csmartdaltona7f29642016-07-07 08:49:11 -0700881 bool useHWAA;
csmartdaltone0d36292016-07-29 08:14:20 -0700882 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
csmartdaltona7f29642016-07-07 08:49:11 -0700883 SkAutoTUnref<GrDrawBatch> batch(ir->recordDRRect(origOuter, origInner, viewMatrix,
884 paintIn.getColor(), paintIn.isAntiAlias(),
885 fInstancedPipelineInfo, &useHWAA));
886 if (batch) {
887 GrPipelineBuilder pipelineBuilder(paintIn, useHWAA);
888 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
889 return true;
890 }
891 }
892
robertphillips00095892016-02-29 13:50:40 -0800893 bool applyAA = paintIn.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
894
895 GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
896 kInverseFillBW_GrProcessorEdgeType;
897 GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
898 kFillBW_GrProcessorEdgeType;
899
900 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
901 SkMatrix inverseVM;
902 if (!viewMatrix.isIdentity()) {
903 if (!origInner.transform(viewMatrix, inner.writable())) {
904 return false;
905 }
906 if (!origOuter.transform(viewMatrix, outer.writable())) {
907 return false;
908 }
909 if (!viewMatrix.invert(&inverseVM)) {
910 return false;
911 }
912 } else {
913 inverseVM.reset();
halcanary9d524f22016-03-29 09:03:52 -0700914 }
robertphillips00095892016-02-29 13:50:40 -0800915
916 GrPaint grPaint(paintIn);
917 grPaint.setAntiAlias(false);
918
919 // TODO these need to be a geometry processors
bungeman06ca8ec2016-06-09 08:01:03 -0700920 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
robertphillips00095892016-02-29 13:50:40 -0800921 if (!innerEffect) {
922 return false;
923 }
924
bungeman06ca8ec2016-06-09 08:01:03 -0700925 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
robertphillips00095892016-02-29 13:50:40 -0800926 if (!outerEffect) {
927 return false;
928 }
929
bungeman06ca8ec2016-06-09 08:01:03 -0700930 grPaint.addCoverageFragmentProcessor(std::move(innerEffect));
931 grPaint.addCoverageFragmentProcessor(std::move(outerEffect));
robertphillips00095892016-02-29 13:50:40 -0800932
933 SkRect bounds = outer->getBounds();
934 if (applyAA) {
935 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
936 }
halcanary9d524f22016-03-29 09:03:52 -0700937
robertphillips00095892016-02-29 13:50:40 -0800938 this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
939 return true;
940}
941
942void GrDrawContext::drawDRRect(const GrClip& clip,
943 const GrPaint& paint,
944 const SkMatrix& viewMatrix,
945 const SkRRect& outer,
946 const SkRRect& inner) {
947 ASSERT_SINGLE_OWNER
948 RETURN_IF_ABANDONED
949 SkDEBUGCODE(this->validate();)
950 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
951
952 SkASSERT(!outer.isEmpty());
953 SkASSERT(!inner.isEmpty());
954
955 AutoCheckFlush acf(fDrawingManager);
956
957 if (this->drawFilledDRRect(clip, paint, viewMatrix, outer, inner)) {
958 return;
959 }
960
961 SkPath path;
962 path.setIsVolatile(true);
963 path.addRRect(inner);
964 path.addRRect(outer);
965 path.setFillType(SkPath::kEvenOdd_FillType);
966
bsalomon6663acf2016-05-10 09:14:17 -0700967 this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
robertphillips00095892016-02-29 13:50:40 -0800968}
969
robertphillipsea461502015-05-26 11:38:03 -0700970///////////////////////////////////////////////////////////////////////////////
971
msarettcc319b92016-08-25 18:07:18 -0700972static inline bool is_int(float x) {
973 return x == (float) sk_float_round2int(x);
974}
975
976void GrDrawContext::drawRegion(const GrClip& clip,
977 const GrPaint& paint,
978 const SkMatrix& viewMatrix,
979 const SkRegion& region,
980 const GrStyle& style) {
981 ASSERT_SINGLE_OWNER
982 RETURN_IF_ABANDONED
983 SkDEBUGCODE(this->validate();)
984 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRegion");
985
986 bool isNonTranslate = SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask));
987 bool complexStyle = !style.isSimpleFill();
988 bool antiAlias = paint.isAntiAlias() && (!is_int(viewMatrix.getTranslateX()) ||
989 !is_int(viewMatrix.getTranslateY()));
990 if (isNonTranslate || complexStyle || antiAlias) {
991 SkPath path;
992 region.getBoundaryPath(&path);
993 return this->drawPath(clip, paint, viewMatrix, path, style);
994 }
995
996 SkAutoTUnref<GrDrawBatch> batch(GrRegionBatch::Create(paint.getColor(), viewMatrix, region));
997 GrPipelineBuilder pipelineBuilder(paint, false);
998 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
999}
1000
robertphillips2e1e51f2015-10-15 08:01:48 -07001001void GrDrawContext::drawOval(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -07001002 const GrPaint& paint,
1003 const SkMatrix& viewMatrix,
1004 const SkRect& oval,
bsalomon6663acf2016-05-10 09:14:17 -07001005 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001006 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001007 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001008 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001009 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
robertphillips2e1e51f2015-10-15 08:01:48 -07001010
robertphillipsea461502015-05-26 11:38:03 -07001011 if (oval.isEmpty()) {
1012 return;
1013 }
1014
bsalomon6663acf2016-05-10 09:14:17 -07001015 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
robertphillipsea461502015-05-26 11:38:03 -07001016
robertphillips77a2e522015-10-17 07:43:27 -07001017 AutoCheckFlush acf(fDrawingManager);
bsalomon6663acf2016-05-10 09:14:17 -07001018 const SkStrokeRec& stroke = style.strokeRec();
csmartdaltonecbc12b2016-06-08 10:08:43 -07001019 bool useHWAA;
csmartdaltona7f29642016-07-07 08:49:11 -07001020
csmartdaltone0d36292016-07-29 08:14:20 -07001021 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1022 stroke.isFillStyle()) {
csmartdaltona7f29642016-07-07 08:49:11 -07001023 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
1024 SkAutoTUnref<GrDrawBatch> batch(ir->recordOval(oval, viewMatrix, paint.getColor(),
1025 paint.isAntiAlias(), fInstancedPipelineInfo,
1026 &useHWAA));
1027 if (batch) {
1028 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1029 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1030 return;
1031 }
1032 }
1033
csmartdaltonecbc12b2016-06-08 10:08:43 -07001034 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
robertphillipsb56f9272016-02-25 11:03:52 -08001035 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -08001036 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillipsb56f9272016-02-25 11:03:52 -08001037 viewMatrix,
1038 oval,
bsalomon6663acf2016-05-10 09:14:17 -07001039 stroke,
robertphillipsb56f9272016-02-25 11:03:52 -08001040 shaderCaps));
1041 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001042 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001043 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsb56f9272016-02-25 11:03:52 -08001044 return;
1045 }
robertphillipsea461502015-05-26 11:38:03 -07001046 }
robertphillipsb56f9272016-02-25 11:03:52 -08001047
1048 SkPath path;
1049 path.setIsVolatile(true);
1050 path.addOval(oval);
bsalomon6663acf2016-05-10 09:14:17 -07001051 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001052}
1053
bsalomon4f3a0ca2016-08-22 13:14:26 -07001054void GrDrawContext::drawArc(const GrClip& clip,
1055 const GrPaint& paint,
1056 const SkMatrix& viewMatrix,
1057 const SkRect& oval,
1058 SkScalar startAngle,
1059 SkScalar sweepAngle,
1060 bool useCenter,
1061 const GrStyle& style) {
1062 bool useHWAA;
1063 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
1064 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1065 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateArcBatch(paint.getColor(),
1066 viewMatrix,
1067 oval,
1068 startAngle,
1069 sweepAngle,
1070 useCenter,
1071 style,
1072 shaderCaps));
1073 if (batch) {
1074 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1075 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1076 return;
1077 }
1078 }
1079 SkPath path;
bsalomon21af9ca2016-08-25 12:29:23 -07001080 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1081 style.isSimpleFill());
bsalomon4f3a0ca2016-08-22 13:14:26 -07001082 this->internalDrawPath(clip, paint, viewMatrix, path, style);
1083 return;
1084}
1085
msarett10e3d9b2016-08-18 15:46:03 -07001086void GrDrawContext::drawImageLattice(const GrClip& clip,
1087 const GrPaint& paint,
1088 const SkMatrix& viewMatrix,
1089 int imageWidth,
1090 int imageHeight,
1091 std::unique_ptr<SkLatticeIter> iter,
1092 const SkRect& dst) {
joshualitt1de610a2016-01-06 08:26:09 -08001093 ASSERT_SINGLE_OWNER
joshualitt33a5fce2015-11-18 13:28:51 -08001094 RETURN_IF_ABANDONED
1095 SkDEBUGCODE(this->validate();)
msarett10e3d9b2016-08-18 15:46:03 -07001096 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageLattice");
joshualitt33a5fce2015-11-18 13:28:51 -08001097
1098 AutoCheckFlush acf(fDrawingManager);
1099
1100 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
1101 imageWidth, imageHeight,
msarett10e3d9b2016-08-18 15:46:03 -07001102 std::move(iter), dst));
joshualitt33a5fce2015-11-18 13:28:51 -08001103
csmartdaltonecbc12b2016-06-08 10:08:43 -07001104 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
robertphillips976f5f02016-06-03 10:59:20 -07001105 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
joshualitt33a5fce2015-11-18 13:28:51 -08001106}
1107
robertphillips8c523e02016-07-26 07:41:00 -07001108void GrDrawContext::prepareForExternalIO() {
1109 ASSERT_SINGLE_OWNER
1110 RETURN_IF_ABANDONED
1111 SkDEBUGCODE(this->validate();)
1112 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::prepareForExternalIO");
1113
1114 ASSERT_OWNED_RESOURCE(fRenderTarget);
1115
bsalomon6a2b1942016-09-08 11:28:59 -07001116 fDrawingManager->prepareSurfaceForExternalIO(fRenderTarget.get());
robertphillips8c523e02016-07-26 07:41:00 -07001117}
joshualitt33a5fce2015-11-18 13:28:51 -08001118
robertphillips44302392016-07-08 14:43:03 -07001119void GrDrawContext::drawNonAAFilledRect(const GrClip& clip,
1120 const GrPaint& paint,
1121 const SkMatrix& viewMatrix,
1122 const SkRect& rect,
1123 const SkRect* localRect,
1124 const SkMatrix* localMatrix,
csmartdalton34ee0c92016-07-27 13:22:27 -07001125 const GrUserStencilSettings* ss,
1126 bool useHWAA) {
1127 SkASSERT(!useHWAA || this->isStencilBufferMultisampled());
robertphillips44302392016-07-08 14:43:03 -07001128 SkAutoTUnref<GrDrawBatch> batch(
1129 GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, localRect,
1130 localMatrix));
csmartdalton34ee0c92016-07-27 13:22:27 -07001131 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips44302392016-07-08 14:43:03 -07001132 if (ss) {
1133 pipelineBuilder.setUserStencil(ss);
1134 }
1135 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1136}
1137
robertphillips1da3ecd2016-08-31 14:54:15 -07001138bool GrDrawContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer, size_t dstRowBytes,
1139 int x, int y) {
1140 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1141 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
1142 if (kUnknown_GrPixelConfig == config) {
1143 return false;
1144 }
1145
1146 uint32_t flags = 0;
1147 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
1148 flags = GrContext::kUnpremul_PixelOpsFlag;
1149 }
1150
1151 return fRenderTarget->readPixels(x, y, dstInfo.width(), dstInfo.height(),
1152 config, dstBuffer, dstRowBytes, flags);
1153}
1154
1155bool GrDrawContext::writePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
1156 size_t srcRowBytes, int x, int y) {
1157 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1158 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
1159 if (kUnknown_GrPixelConfig == config) {
1160 return false;
1161 }
1162 uint32_t flags = 0;
1163 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
1164 flags = GrContext::kUnpremul_PixelOpsFlag;
1165 }
1166
1167 return fRenderTarget->writePixels(x, y, srcInfo.width(), srcInfo.height(),
1168 config, srcBuffer, srcRowBytes, flags);
1169}
1170
robertphillipsea461502015-05-26 11:38:03 -07001171// Can 'path' be drawn as a pair of filled nested rectangles?
bsalomon6663acf2016-05-10 09:14:17 -07001172static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
robertphillipsea461502015-05-26 11:38:03 -07001173
1174 if (path.isInverseFillType()) {
1175 return false;
1176 }
1177
1178 // TODO: this restriction could be lifted if we were willing to apply
1179 // the matrix to all the points individually rather than just to the rect
robertphillips0e7029e2015-11-30 05:45:06 -08001180 if (!viewMatrix.rectStaysRect()) {
robertphillipsea461502015-05-26 11:38:03 -07001181 return false;
1182 }
1183
1184 SkPath::Direction dirs[2];
1185 if (!path.isNestedFillRects(rects, dirs)) {
1186 return false;
1187 }
1188
1189 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1190 // The two rects need to be wound opposite to each other
1191 return false;
1192 }
1193
1194 // Right now, nested rects where the margin is not the same width
1195 // all around do not render correctly
1196 const SkScalar* outer = rects[0].asScalars();
1197 const SkScalar* inner = rects[1].asScalars();
1198
1199 bool allEq = true;
1200
1201 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1202 bool allGoE1 = margin >= SK_Scalar1;
1203
1204 for (int i = 1; i < 4; ++i) {
1205 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1206 if (temp < SK_Scalar1) {
1207 allGoE1 = false;
1208 }
1209 if (!SkScalarNearlyEqual(margin, temp)) {
1210 allEq = false;
1211 }
1212 }
1213
1214 return allEq || allGoE1;
1215}
1216
robertphillips2e1e51f2015-10-15 08:01:48 -07001217void GrDrawContext::drawPath(const GrClip& clip,
robertphillipsea461502015-05-26 11:38:03 -07001218 const GrPaint& paint,
1219 const SkMatrix& viewMatrix,
1220 const SkPath& path,
bsalomon6663acf2016-05-10 09:14:17 -07001221 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001222 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001223 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001224 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001225 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
robertphillips2e1e51f2015-10-15 08:01:48 -07001226
robertphillipsea461502015-05-26 11:38:03 -07001227 if (path.isEmpty()) {
1228 if (path.isInverseFillType()) {
robertphillips2e1e51f2015-10-15 08:01:48 -07001229 this->drawPaint(clip, paint, viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001230 }
1231 return;
1232 }
1233
robertphillips77a2e522015-10-17 07:43:27 -07001234 AutoCheckFlush acf(fDrawingManager);
robertphillipsea461502015-05-26 11:38:03 -07001235
csmartdaltonecbc12b2016-06-08 10:08:43 -07001236 bool useHWAA;
1237 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA) && !style.pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001238 if (style.isSimpleFill() && !path.isConvex()) {
robertphillipsea461502015-05-26 11:38:03 -07001239 // Concave AA paths are expensive - try to avoid them for special cases
1240 SkRect rects[2];
1241
bsalomon6663acf2016-05-10 09:14:17 -07001242 if (fills_as_nested_rects(viewMatrix, path, rects)) {
joshualittd2b23e02015-08-21 10:53:34 -07001243 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
robertphillips4bc31812016-03-01 12:22:49 -08001244 paint.getColor(), viewMatrix, rects));
bsalomon40ef4852016-05-02 13:22:13 -07001245 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001246 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001247 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
bsalomon40ef4852016-05-02 13:22:13 -07001248 }
robertphillipsea461502015-05-26 11:38:03 -07001249 return;
1250 }
1251 }
1252 SkRect ovalRect;
1253 bool isOval = path.isOval(&ovalRect);
1254
1255 if (isOval && !path.isInverseFillType()) {
robertphillips0cc2f852016-02-24 13:36:56 -08001256 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
robertphillips4bc31812016-03-01 12:22:49 -08001257 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
robertphillips0cc2f852016-02-24 13:36:56 -08001258 viewMatrix,
robertphillips0cc2f852016-02-24 13:36:56 -08001259 ovalRect,
bsalomon6663acf2016-05-10 09:14:17 -07001260 style.strokeRec(),
robertphillips0cc2f852016-02-24 13:36:56 -08001261 shaderCaps));
1262 if (batch) {
csmartdaltonecbc12b2016-06-08 10:08:43 -07001263 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
robertphillips976f5f02016-06-03 10:59:20 -07001264 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillipsea461502015-05-26 11:38:03 -07001265 return;
1266 }
1267 }
1268 }
robertphillips4bc31812016-03-01 12:22:49 -08001269
1270 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1271 // Scratch textures can be recycled after they are returned to the texture
1272 // cache. This presents a potential hazard for buffered drawing. However,
1273 // the writePixels that uploads to the scratch will perform a flush so we're
1274 // OK.
bsalomon6663acf2016-05-10 09:14:17 -07001275 this->internalDrawPath(clip, paint, viewMatrix, path, style);
robertphillipsea461502015-05-26 11:38:03 -07001276}
1277
csmartdalton29df7602016-08-31 11:55:52 -07001278bool GrDrawContextPriv::drawAndStencilPath(const GrClip& clip,
cdalton93a379b2016-05-11 13:58:08 -07001279 const GrUserStencilSettings* ss,
robertphillips391395d2016-03-02 09:26:36 -08001280 SkRegion::Op op,
1281 bool invert,
1282 bool doAA,
1283 const SkMatrix& viewMatrix,
1284 const SkPath& path) {
1285 ASSERT_SINGLE_OWNER_PRIV
1286 RETURN_FALSE_IF_ABANDONED_PRIV
1287 SkDEBUGCODE(fDrawContext->validate();)
1288 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath");
1289
1290 if (path.isEmpty() && path.isInverseFillType()) {
cdalton862cff32016-05-12 15:09:48 -07001291 this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
robertphillips6c7e3252016-04-27 10:47:51 -07001292 SkRect::MakeIWH(fDrawContext->width(),
1293 fDrawContext->height()));
robertphillips391395d2016-03-02 09:26:36 -08001294 return true;
1295 }
1296
1297 AutoCheckFlush acf(fDrawContext->fDrawingManager);
1298
1299 // An Assumption here is that path renderer would use some form of tweaking
1300 // the src color (either the input alpha or in the frag shader) to implement
1301 // aa. If we have some future driver-mojo path AA that can do the right
1302 // thing WRT to the blend then we'll need some query on the PR.
robertphillips13a7eee2016-08-31 15:06:24 -07001303 bool useCoverageAA = doAA && !fDrawContext->isUnifiedMultisampled();
robertphillips976f5f02016-06-03 10:59:20 -07001304 bool hasUserStencilSettings = !ss->isUnused();
robertphillips13a7eee2016-08-31 15:06:24 -07001305 bool isStencilBufferMSAA = fDrawContext->isStencilBufferMultisampled();
robertphillips391395d2016-03-02 09:26:36 -08001306
1307 const GrPathRendererChain::DrawType type =
1308 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1309 : GrPathRendererChain::kColor_DrawType;
1310
bsalomon8acedde2016-06-24 10:42:16 -07001311 GrShape shape(path, GrStyle::SimpleFill());
robertphillips391395d2016-03-02 09:26:36 -08001312 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1313 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
1314 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001315 canDrawArgs.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001316 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001317 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
robertphillips391395d2016-03-02 09:26:36 -08001318 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1319
1320 // Don't allow the SW renderer
1321 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1322 if (!pr) {
1323 return false;
1324 }
1325
1326 GrPaint paint;
1327 paint.setCoverageSetOpXPFactory(op, invert);
1328
robertphillips391395d2016-03-02 09:26:36 -08001329 GrPathRenderer::DrawPathArgs args;
robertphillips391395d2016-03-02 09:26:36 -08001330 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001331 args.fPaint = &paint;
1332 args.fUserStencilSettings = ss;
1333 args.fDrawContext = fDrawContext;
cdalton862cff32016-05-12 15:09:48 -07001334 args.fClip = &clip;
robertphillips391395d2016-03-02 09:26:36 -08001335 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001336 args.fShape = &shape;
robertphillips391395d2016-03-02 09:26:36 -08001337 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001338 args.fGammaCorrect = fDrawContext->isGammaCorrect();
robertphillips391395d2016-03-02 09:26:36 -08001339 pr->drawPath(args);
1340 return true;
1341}
1342
robertphillips714712b2016-08-04 06:20:45 -07001343SkBudgeted GrDrawContextPriv::isBudgeted() const {
1344 ASSERT_SINGLE_OWNER_PRIV
1345
1346 if (fDrawContext->wasAbandoned()) {
1347 return SkBudgeted::kNo;
1348 }
1349
1350 SkDEBUGCODE(fDrawContext->validate();)
1351
1352 return fDrawContext->fRenderTarget->resourcePriv().isBudgeted();
1353}
1354
robertphillips4bc31812016-03-01 12:22:49 -08001355void GrDrawContext::internalDrawPath(const GrClip& clip,
1356 const GrPaint& paint,
robertphillipsea461502015-05-26 11:38:03 -07001357 const SkMatrix& viewMatrix,
bsalomon8acedde2016-06-24 10:42:16 -07001358 const SkPath& path,
1359 const GrStyle& style) {
joshualitt1de610a2016-01-06 08:26:09 -08001360 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -07001361 RETURN_IF_ABANDONED
bsalomon8acedde2016-06-24 10:42:16 -07001362 SkASSERT(!path.isEmpty());
robertphillipsea461502015-05-26 11:38:03 -07001363
robertphillips6c7e3252016-04-27 10:47:51 -07001364 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
cdalton93a379b2016-05-11 13:58:08 -07001365 constexpr bool kHasUserStencilSettings = false;
robertphillips13a7eee2016-08-31 15:06:24 -07001366 bool isStencilBufferMSAA = this->isStencilBufferMultisampled();
robertphillipsea461502015-05-26 11:38:03 -07001367
robertphillips68737822015-10-29 12:12:21 -07001368 const GrPathRendererChain::DrawType type =
1369 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1370 : GrPathRendererChain::kColor_DrawType;
robertphillipsea461502015-05-26 11:38:03 -07001371
bsalomon8acedde2016-06-24 10:42:16 -07001372 GrShape shape(path, style);
bsalomon0a0f67e2016-06-28 11:56:42 -07001373 if (shape.isEmpty()) {
1374 return;
1375 }
robertphillips68737822015-10-29 12:12:21 -07001376 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1377 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1378 canDrawArgs.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001379 canDrawArgs.fShape = &shape;
robertphillips68737822015-10-29 12:12:21 -07001380 canDrawArgs.fAntiAlias = useCoverageAA;
cdalton93a379b2016-05-11 13:58:08 -07001381 canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
robertphillips68737822015-10-29 12:12:21 -07001382 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1383
bsalomon6663acf2016-05-10 09:14:17 -07001384 // Try a 1st time without applying any of the style to the geometry (and barring sw)
robertphillips68737822015-10-29 12:12:21 -07001385 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
bsalomon6663acf2016-05-10 09:14:17 -07001386 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
robertphillipsea461502015-05-26 11:38:03 -07001387
bsalomon8acedde2016-06-24 10:42:16 -07001388 if (!pr && shape.style().pathEffect()) {
bsalomon6663acf2016-05-10 09:14:17 -07001389 // It didn't work above, so try again with the path effect applied.
bsalomon8acedde2016-06-24 10:42:16 -07001390 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1391 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001392 return;
1393 }
robertphillips68737822015-10-29 12:12:21 -07001394 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
robertphillipsea461502015-05-26 11:38:03 -07001395 }
bsalomon6663acf2016-05-10 09:14:17 -07001396 if (!pr) {
bsalomon8acedde2016-06-24 10:42:16 -07001397 if (shape.style().applies()) {
1398 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1399 if (shape.isEmpty()) {
robertphillipsea461502015-05-26 11:38:03 -07001400 return;
1401 }
bsalomon6663acf2016-05-10 09:14:17 -07001402 }
robertphillipsea461502015-05-26 11:38:03 -07001403 // This time, allow SW renderer
robertphillips68737822015-10-29 12:12:21 -07001404 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
robertphillipsea461502015-05-26 11:38:03 -07001405 }
1406
bsalomon8acedde2016-06-24 10:42:16 -07001407 if (!pr) {
robertphillipsea461502015-05-26 11:38:03 -07001408#ifdef SK_DEBUG
1409 SkDebugf("Unable to find path renderer compatible with path.\n");
1410#endif
1411 return;
1412 }
1413
bsalomon0aff2fa2015-07-31 06:48:27 -07001414 GrPathRenderer::DrawPathArgs args;
robertphillips77a2e522015-10-17 07:43:27 -07001415 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
robertphillips976f5f02016-06-03 10:59:20 -07001416 args.fPaint = &paint;
1417 args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
1418 args.fDrawContext = this;
cdalton862cff32016-05-12 15:09:48 -07001419 args.fClip = &clip;
bsalomon0aff2fa2015-07-31 06:48:27 -07001420 args.fViewMatrix = &viewMatrix;
bsalomon8acedde2016-06-24 10:42:16 -07001421 args.fShape = canDrawArgs.fShape;
bsalomon0aff2fa2015-07-31 06:48:27 -07001422 args.fAntiAlias = useCoverageAA;
brianosman0e3c5542016-04-13 13:56:21 -07001423 args.fGammaCorrect = this->isGammaCorrect();
bsalomon0aff2fa2015-07-31 06:48:27 -07001424 pr->drawPath(args);
robertphillipsea461502015-05-26 11:38:03 -07001425}
1426
bsalomonbb243832016-07-22 07:10:19 -07001427void GrDrawContext::drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
1428 GrDrawBatch* batch) {
joshualitt1de610a2016-01-06 08:26:09 -08001429 ASSERT_SINGLE_OWNER
robertphillips2d70dcb2015-10-06 07:38:23 -07001430 RETURN_IF_ABANDONED
robertphillips2e1e51f2015-10-15 08:01:48 -07001431 SkDEBUGCODE(this->validate();)
joshualittbc907352016-01-13 06:45:40 -08001432 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
robertphillips2d70dcb2015-10-06 07:38:23 -07001433
robertphillips976f5f02016-06-03 10:59:20 -07001434 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
robertphillips2334fb62015-06-17 05:43:33 -07001435}