1 /*
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 
8 #include "GrBatchTest.h"
9 #include "GrColor.h"
10 #include "GrDrawContext.h"
11 #include "GrDrawContextPriv.h"
12 #include "GrDrawingManager.h"
13 #include "GrFixedClip.h"
14 #include "GrGpuResourcePriv.h"
15 #include "GrOvalRenderer.h"
16 #include "GrPathRenderer.h"
17 #include "GrPipelineBuilder.h"
18 #include "GrRenderTarget.h"
19 #include "GrRenderTargetPriv.h"
20 #include "GrResourceProvider.h"
21 #include "SkSurfacePriv.h"
22 
23 #include "batches/GrBatch.h"
24 #include "batches/GrClearBatch.h"
25 #include "batches/GrDrawAtlasBatch.h"
26 #include "batches/GrDrawVerticesBatch.h"
27 #include "batches/GrRectBatchFactory.h"
28 #include "batches/GrNinePatch.h" // TODO Factory
29 #include "batches/GrRegionBatch.h"
30 
31 #include "effects/GrRRectEffect.h"
32 
33 #include "instanced/InstancedRendering.h"
34 
35 #include "text/GrAtlasTextContext.h"
36 #include "text/GrStencilAndCoverTextContext.h"
37 
38 #include "../private/GrAuditTrail.h"
39 
40 #include "SkGr.h"
41 #include "SkLatticeIter.h"
42 #include "SkMatrixPriv.h"
43 
44 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
45 #define ASSERT_SINGLE_OWNER \
46     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
47 #define ASSERT_SINGLE_OWNER_PRIV \
48     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
49 #define RETURN_IF_ABANDONED        if (fDrawingManager->wasAbandoned()) { return; }
50 #define RETURN_IF_ABANDONED_PRIV   if (fDrawContext->fDrawingManager->wasAbandoned()) { return; }
51 #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; }
54 
55 using gr_instanced::InstancedRendering;
56 
57 class AutoCheckFlush {
58 public:
AutoCheckFlush(GrDrawingManager * drawingManager)59     AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
60         SkASSERT(fDrawingManager);
61     }
~AutoCheckFlush()62     ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
63 
64 private:
65     GrDrawingManager* fDrawingManager;
66 };
67 
wasAbandoned() const68 bool GrDrawContext::wasAbandoned() const {
69     return fDrawingManager->wasAbandoned();
70 }
71 
72 // 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).
GrDrawContext(GrContext * context,GrDrawingManager * drawingMgr,sk_sp<GrRenderTarget> rt,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * surfaceProps,GrAuditTrail * auditTrail,GrSingleOwner * singleOwner)76 GrDrawContext::GrDrawContext(GrContext* context,
77                              GrDrawingManager* drawingMgr,
78                              sk_sp<GrRenderTarget> rt,
79                              sk_sp<SkColorSpace> colorSpace,
80                              const SkSurfaceProps* surfaceProps,
81                              GrAuditTrail* auditTrail,
82                              GrSingleOwner* singleOwner)
83     : fDrawingManager(drawingMgr)
84     , fRenderTarget(std::move(rt))
85     , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
86     , fContext(context)
87     , fInstancedPipelineInfo(fRenderTarget.get())
88     , fColorSpace(std::move(colorSpace))
89     , fColorXformFromSRGB(nullptr)
90     , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
91     , fAuditTrail(auditTrail)
92 #ifdef SK_DEBUG
93     , fSingleOwner(singleOwner)
94 #endif
95 {
96     if (fColorSpace) {
97         // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
98         auto srgbColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
99         fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
100     }
101     SkDEBUGCODE(this->validate();)
102 }
103 
104 #ifdef SK_DEBUG
validate() const105 void GrDrawContext::validate() const {
106     SkASSERT(fRenderTarget);
107     ASSERT_OWNED_RESOURCE(fRenderTarget);
108 
109     if (fDrawTarget && !fDrawTarget->isClosed()) {
110         SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
111     }
112 }
113 #endif
114 
~GrDrawContext()115 GrDrawContext::~GrDrawContext() {
116     ASSERT_SINGLE_OWNER
117     SkSafeUnref(fDrawTarget);
118 }
119 
getDrawTarget()120 GrDrawTarget* GrDrawContext::getDrawTarget() {
121     ASSERT_SINGLE_OWNER
122     SkDEBUGCODE(this->validate();)
123 
124     if (!fDrawTarget || fDrawTarget->isClosed()) {
125         fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
126     }
127 
128     return fDrawTarget;
129 }
130 
copySurface(GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint)131 bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
132     ASSERT_SINGLE_OWNER
133     RETURN_FALSE_IF_ABANDONED
134     SkDEBUGCODE(this->validate();)
135     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
136 
137     return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
138 }
139 
drawText(const GrClip & clip,const GrPaint & grPaint,const SkPaint & skPaint,const SkMatrix & viewMatrix,const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkIRect & clipBounds)140 void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
141                              const SkPaint& skPaint,
142                              const SkMatrix& viewMatrix,
143                              const char text[], size_t byteLength,
144                              SkScalar x, SkScalar y, const SkIRect& clipBounds) {
145     ASSERT_SINGLE_OWNER
146     RETURN_IF_ABANDONED
147     SkDEBUGCODE(this->validate();)
148     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
149 
150     GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
151     atlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
152                                text, byteLength, x, y, clipBounds);
153 }
154 
drawPosText(const GrClip & clip,const GrPaint & grPaint,const SkPaint & skPaint,const SkMatrix & viewMatrix,const char text[],size_t byteLength,const SkScalar pos[],int scalarsPerPosition,const SkPoint & offset,const SkIRect & clipBounds)155 void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
156                                 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) {
161     ASSERT_SINGLE_OWNER
162     RETURN_IF_ABANDONED
163     SkDEBUGCODE(this->validate();)
164     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
165 
166     GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
167     atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
168                                   fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
169                                   offset, clipBounds);
170 
171 }
172 
drawTextBlob(const GrClip & clip,const SkPaint & skPaint,const SkMatrix & viewMatrix,const SkTextBlob * blob,SkScalar x,SkScalar y,SkDrawFilter * filter,const SkIRect & clipBounds)173 void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
174                                  const SkMatrix& viewMatrix, const SkTextBlob* blob,
175                                  SkScalar x, SkScalar y,
176                                  SkDrawFilter* filter, const SkIRect& clipBounds) {
177     ASSERT_SINGLE_OWNER
178     RETURN_IF_ABANDONED
179     SkDEBUGCODE(this->validate();)
180     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
181 
182     GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
183     atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
184                                    x, y, filter, clipBounds);
185 }
186 
discard()187 void GrDrawContext::discard() {
188     ASSERT_SINGLE_OWNER
189     RETURN_IF_ABANDONED
190     SkDEBUGCODE(this->validate();)
191     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
192 
193     AutoCheckFlush acf(fDrawingManager);
194     this->getDrawTarget()->discard(fRenderTarget.get());
195 }
196 
clear(const SkIRect * rect,const GrColor color,bool canIgnoreRect)197 void GrDrawContext::clear(const SkIRect* rect,
198                           const GrColor color,
199                           bool canIgnoreRect) {
200     ASSERT_SINGLE_OWNER
201     RETURN_IF_ABANDONED
202     SkDEBUGCODE(this->validate();)
203     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
204 
205     AutoCheckFlush acf(fDrawingManager);
206     this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
207 }
208 
clear(const GrFixedClip & clip,const GrColor color,bool canIgnoreClip)209 void 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 
internalClear(const GrFixedClip & clip,const GrColor color,bool canIgnoreClip)221 void GrDrawContext::internalClear(const GrFixedClip& clip,
222                                   const GrColor color,
223                                   bool canIgnoreClip) {
224     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     }
230 
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.
235         SkRect clearRect = SkRect::MakeIWH(this->width(), this->height());
236         if (isFull) {
237             this->discard();
238         } else if (!clearRect.intersect(SkRect::Make(clip.scissorRect()))) {
239             return;
240         }
241 
242         GrPaint paint;
243         paint.setColor4f(GrColor4f::FromGrColor(color));
244         paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::Mode::kSrc_Mode));
245 
246         this->drawRect(clip, paint, SkMatrix::I(), clearRect);
247     } else if (isFull) {
248         this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
249     } else {
250         sk_sp<GrBatch> batch(GrClearBatch::Make(clip, color, this->accessRenderTarget()));
251         if (!batch) {
252             return;
253         }
254         this->getDrawTarget()->addBatch(std::move(batch));
255     }
256 }
257 
drawPaint(const GrClip & clip,const GrPaint & origPaint,const SkMatrix & viewMatrix)258 void GrDrawContext::drawPaint(const GrClip& clip,
259                               const GrPaint& origPaint,
260                               const SkMatrix& viewMatrix) {
261     ASSERT_SINGLE_OWNER
262     RETURN_IF_ABANDONED
263     SkDEBUGCODE(this->validate();)
264     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
265 
266     // set rect to be big enough to fill the space, but not super-huge, so we
267     // don't overflow fixed-point implementations
268 
269     SkRect r = fRenderTarget->getBoundsRect();
270     SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
271 
272     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 
286     // 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) {
297         if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
298             SkDebugf("Could not invert matrix\n");
299             return;
300         }
301         this->drawRect(clip, *paint, viewMatrix, r);
302     } else {
303         SkMatrix localMatrix;
304         if (!viewMatrix.invert(&localMatrix)) {
305             SkDebugf("Could not invert matrix\n");
306             return;
307         }
308 
309         AutoCheckFlush acf(fDrawingManager);
310 
311         this->drawNonAAFilledRect(clip, *paint, SkMatrix::I(), r, nullptr, &localMatrix, nullptr,
312                                   false /* useHWAA */);
313     }
314 }
315 
rect_contains_inclusive(const SkRect & rect,const SkPoint & point)316 static 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 
view_matrix_ok_for_aa_fill_rect(const SkMatrix & viewMatrix)321 static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
322     return viewMatrix.preservesRightAngles();
323 }
324 
should_apply_coverage_aa(const GrPaint & paint,GrRenderTarget * rt,bool * useHWAA=nullptr)325 static 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) {
334             *useHWAA = rt->isUnifiedMultisampled();
335         }
336         return !rt->isUnifiedMultisampled();
337     }
338 }
339 
340 // Attempts to crop a rect and optional local rect to the clip boundaries.
341 // Returns false if the draw can be skipped entirely.
crop_filled_rect(int width,int height,const GrClip & clip,const SkMatrix & viewMatrix,SkRect * rect,SkRect * localRect=nullptr)342 static bool crop_filled_rect(int width, int height, const GrClip& clip,
343                              const SkMatrix& viewMatrix, SkRect* rect,
344                              SkRect* localRect = nullptr) {
345     if (!viewMatrix.rectStaysRect()) {
346         return true;
347     }
348 
349     SkIRect clipDevBounds;
350     SkRect clipBounds;
351 
352     clip.getConservativeBounds(width, height, &clipDevBounds);
353     if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
354         return false;
355     }
356 
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 
drawFilledRect(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRect & rect,const GrUserStencilSettings * ss)385 bool GrDrawContext::drawFilledRect(const GrClip& clip,
386                                    const GrPaint& paint,
387                                    const SkMatrix& viewMatrix,
388                                    const SkRect& rect,
389                                    const GrUserStencilSettings* ss) {
390     SkRect croppedRect = rect;
391     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
392         return true;
393     }
394 
395     SkAutoTUnref<GrDrawBatch> batch;
396     bool useHWAA;
397 
398     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
399         InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
400         batch.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
401                                    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;
410         }
411     }
412 
413     if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
414         // The fill path can handle rotation but not skew.
415         if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
416             SkRect devBoundRect;
417             viewMatrix.mapRect(&devBoundRect, croppedRect);
418 
419             batch.reset(GrRectBatchFactory::CreateAAFill(paint, viewMatrix, rect, croppedRect,
420                                                          devBoundRect));
421             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             }
429         }
430     } else {
431         this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss,
432                                   useHWAA);
433         return true;
434     }
435 
436     return false;
437 }
438 
drawRect(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRect & rect,const GrStyle * style)439 void GrDrawContext::drawRect(const GrClip& clip,
440                              const GrPaint& paint,
441                              const SkMatrix& viewMatrix,
442                              const SkRect& rect,
443                              const GrStyle* style) {
444     if (!style) {
445         style = &GrStyle::SimpleFill();
446     }
447     ASSERT_SINGLE_OWNER
448     RETURN_IF_ABANDONED
449     SkDEBUGCODE(this->validate();)
450     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
451 
452     // Path effects should've been devolved to a path in SkGpuDevice
453     SkASSERT(!style->pathEffect());
454 
455     AutoCheckFlush acf(fDrawingManager);
456 
457     const SkStrokeRec& stroke = style->strokeRec();
458     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.
463             SkRect rtRect = fRenderTarget->getBoundsRect();
464             // Does the clip contain the entire RT?
465             if (clip.quickContains(rtRect)) {
466                 SkMatrix invM;
467                 if (!viewMatrix.invert(&invM)) {
468                     return;
469                 }
470                 // 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)) {
480                         this->clear(nullptr, clearColor, true);
481                         return;
482                     }
483                 }
484             }
485         }
486 
487         if (this->drawFilledRect(clip, paint, viewMatrix, rect, nullptr)) {
488             return;
489         }
490     } 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         }
523 
524         bool useHWAA;
525         bool snapToPixelCenters = false;
526         SkAutoTUnref<GrDrawBatch> batch;
527 
528         GrColor color = paint.getColor();
529         if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
530             // The stroke path needs the rect to remain axis aligned (no rotation or skew).
531             if (viewMatrix.rectStaysRect()) {
532                 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke));
533             }
534         } else {
535             // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
536             // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
537             // when MSAA is enabled because it can cause ugly artifacts.
538             snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
539                                  !fRenderTarget->isUnifiedMultisampled();
540             batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
541                                                               stroke, snapToPixelCenters));
542         }
543 
544         if (batch) {
545             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
546 
547             if (snapToPixelCenters) {
548                 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
549                                          snapToPixelCenters);
550             }
551 
552             this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
553             return;
554         }
555     }
556 
557     SkPath path;
558     path.setIsVolatile(true);
559     path.addRect(rect);
560     this->internalDrawPath(clip, paint, viewMatrix, path, *style);
561 }
562 
clearStencilClip(const GrFixedClip & clip,bool insideStencilMask)563 void GrDrawContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
564     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);
570     fDrawContext->getDrawTarget()->clearStencilClip(clip, insideStencilMask,
571                                                     fDrawContext->accessRenderTarget());
572 }
573 
stencilPath(const GrClip & clip,bool useHWAA,const SkMatrix & viewMatrix,const GrPath * path)574 void GrDrawContextPriv::stencilPath(const GrClip& clip,
575                                     bool useHWAA,
576                                     const SkMatrix& viewMatrix,
577                                     const GrPath* path) {
578     fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
579 }
580 
stencilRect(const GrClip & clip,const GrUserStencilSettings * ss,bool useHWAA,const SkMatrix & viewMatrix,const SkRect & rect)581 void GrDrawContextPriv::stencilRect(const GrClip& clip,
582                                     const GrUserStencilSettings* ss,
583                                     bool useHWAA,
584                                     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;
594     paint.setAntiAlias(useHWAA);
595     paint.setXPFactory(GrDisableColorXPFactory::Make());
596 
597     fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA);
598 }
599 
drawAndStencilRect(const GrClip & clip,const GrUserStencilSettings * ss,SkRegion::Op op,bool invert,bool doAA,const SkMatrix & viewMatrix,const SkRect & rect)600 bool GrDrawContextPriv::drawAndStencilRect(const GrClip& clip,
601                                            const GrUserStencilSettings* ss,
602                                            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();)
610     GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawAndStencilRect");
611 
612     AutoCheckFlush acf(fDrawContext->fDrawingManager);
613 
614     GrPaint paint;
615     paint.setAntiAlias(doAA);
616     paint.setCoverageSetOpXPFactory(op, invert);
617 
618     if (fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss)) {
619         return true;
620     }
621 
622     SkPath path;
623     path.setIsVolatile(true);
624     path.addRect(rect);
625     return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
626 }
627 
fillRectToRect(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRect & rectToDraw,const SkRect & localRect)628 void GrDrawContext::fillRectToRect(const GrClip& clip,
629                                    const GrPaint& paint,
630                                    const SkMatrix& viewMatrix,
631                                    const SkRect& rectToDraw,
632                                    const SkRect& localRect) {
633     ASSERT_SINGLE_OWNER
634     RETURN_IF_ABANDONED
635     SkDEBUGCODE(this->validate();)
636     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
637 
638     SkRect croppedRect = rectToDraw;
639     SkRect croppedLocalRect = localRect;
640     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
641                           &croppedRect, &croppedLocalRect)) {
642         return;
643     }
644 
645     AutoCheckFlush acf(fDrawingManager);
646     bool useHWAA;
647 
648     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
649         InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
650         SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
651                                                        croppedLocalRect, paint.isAntiAlias(),
652                                                        fInstancedPipelineInfo, &useHWAA));
653         if (batch) {
654             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
655             this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
656             return;
657         }
658     }
659 
660     if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
661         this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect,
662                                   nullptr, nullptr, useHWAA);
663         return;
664     }
665 
666     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());
687 }
688 
fillRectWithLocalMatrix(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRect & rectToDraw,const SkMatrix & localMatrix)689 void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
690                                             const GrPaint& paint,
691                                             const SkMatrix& viewMatrix,
692                                             const SkRect& rectToDraw,
693                                             const SkMatrix& localMatrix) {
694     ASSERT_SINGLE_OWNER
695     RETURN_IF_ABANDONED
696     SkDEBUGCODE(this->validate();)
697     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
698 
699     SkRect croppedRect = rectToDraw;
700     if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
701         return;
702     }
703 
704     AutoCheckFlush acf(fDrawingManager);
705     bool useHWAA;
706 
707     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
708         InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
709         SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
710                                                        localMatrix, paint.isAntiAlias(),
711                                                        fInstancedPipelineInfo, &useHWAA));
712         if (batch) {
713             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
714             this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
715             return;
716         }
717     }
718 
719     if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
720         this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr,
721                                   &localMatrix, nullptr, useHWAA);
722         return;
723     }
724 
725     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());
745 }
746 
drawVertices(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,GrPrimitiveType primitiveType,int vertexCount,const SkPoint positions[],const SkPoint texCoords[],const GrColor colors[],const uint16_t indices[],int indexCount)747 void GrDrawContext::drawVertices(const GrClip& clip,
748                                  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) {
757     ASSERT_SINGLE_OWNER
758     RETURN_IF_ABANDONED
759     SkDEBUGCODE(this->validate();)
760     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
761 
762     AutoCheckFlush acf(fDrawingManager);
763 
764     // 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 
773     SkAutoTUnref<GrDrawBatch> batch(new GrDrawVerticesBatch(paint.getColor(),
774                                                             primitiveType, viewMatrix, positions,
775                                                             vertexCount, indices, indexCount,
776                                                             colors, texCoords, bounds));
777 
778     GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
779     this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
780 }
781 
782 ///////////////////////////////////////////////////////////////////////////////
783 
drawAtlas(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,int spriteCount,const SkRSXform xform[],const SkRect texRect[],const SkColor colors[])784 void GrDrawContext::drawAtlas(const GrClip& clip,
785                               const GrPaint& paint,
786                               const SkMatrix& viewMatrix,
787                               int spriteCount,
788                               const SkRSXform xform[],
789                               const SkRect texRect[],
790                               const SkColor colors[]) {
791     ASSERT_SINGLE_OWNER
792     RETURN_IF_ABANDONED
793     SkDEBUGCODE(this->validate();)
794     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
795 
796     AutoCheckFlush acf(fDrawingManager);
797 
798     SkAutoTUnref<GrDrawBatch> batch(new GrDrawAtlasBatch(paint.getColor(), viewMatrix, spriteCount,
799                                                          xform, texRect, colors));
800 
801     GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
802     this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
803 }
804 
805 ///////////////////////////////////////////////////////////////////////////////
806 
drawRRect(const GrClip & origClip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRRect & rrect,const GrStyle & style)807 void GrDrawContext::drawRRect(const GrClip& origClip,
808                               const GrPaint& paint,
809                               const SkMatrix& viewMatrix,
810                               const SkRRect& rrect,
811                               const GrStyle& style) {
812     ASSERT_SINGLE_OWNER
813     RETURN_IF_ABANDONED
814     SkDEBUGCODE(this->validate();)
815     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
816     if (rrect.isEmpty()) {
817        return;
818     }
819 
820     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
833     SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
834 
835     AutoCheckFlush acf(fDrawingManager);
836     const SkStrokeRec stroke = style.strokeRec();
837     bool useHWAA;
838 
839     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
840         stroke.isFillStyle()) {
841         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);
847             this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
848             return;
849         }
850     }
851 
852     if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
853         GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
854         SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
855                                                                          viewMatrix,
856                                                                          rrect,
857                                                                          stroke,
858                                                                          shaderCaps));
859         if (batch) {
860             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
861             this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
862             return;
863         }
864     }
865 
866     SkPath path;
867     path.setIsVolatile(true);
868     path.addRRect(rrect);
869     this->internalDrawPath(*clip, paint, viewMatrix, path, style);
870 }
871 
drawFilledDRRect(const GrClip & clip,const GrPaint & paintIn,const SkMatrix & viewMatrix,const SkRRect & origOuter,const SkRRect & origInner)872 bool 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 
880     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
881         bool useHWAA;
882         InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
883         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 
893     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();
914     }
915 
916     GrPaint grPaint(paintIn);
917     grPaint.setAntiAlias(false);
918 
919     // TODO these need to be a geometry processors
920     sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
921     if (!innerEffect) {
922         return false;
923     }
924 
925     sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
926     if (!outerEffect) {
927         return false;
928     }
929 
930     grPaint.addCoverageFragmentProcessor(std::move(innerEffect));
931     grPaint.addCoverageFragmentProcessor(std::move(outerEffect));
932 
933     SkRect bounds = outer->getBounds();
934     if (applyAA) {
935         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
936     }
937 
938     this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
939     return true;
940 }
941 
drawDRRect(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRRect & outer,const SkRRect & inner)942 void 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 
967     this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
968 }
969 
970 ///////////////////////////////////////////////////////////////////////////////
971 
is_int(float x)972 static inline bool is_int(float x) {
973     return x == (float) sk_float_round2int(x);
974 }
975 
drawRegion(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRegion & region,const GrStyle & style)976 void 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 
drawOval(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRect & oval,const GrStyle & style)1001 void GrDrawContext::drawOval(const GrClip& clip,
1002                              const GrPaint& paint,
1003                              const SkMatrix& viewMatrix,
1004                              const SkRect& oval,
1005                              const GrStyle& style) {
1006     ASSERT_SINGLE_OWNER
1007     RETURN_IF_ABANDONED
1008     SkDEBUGCODE(this->validate();)
1009     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
1010 
1011     if (oval.isEmpty()) {
1012        return;
1013     }
1014 
1015     SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1016 
1017     AutoCheckFlush acf(fDrawingManager);
1018     const SkStrokeRec& stroke = style.strokeRec();
1019     bool useHWAA;
1020 
1021     if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1022         stroke.isFillStyle()) {
1023         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 
1034     if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
1035         GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1036         SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
1037                                                                         viewMatrix,
1038                                                                         oval,
1039                                                                         stroke,
1040                                                                         shaderCaps));
1041         if (batch) {
1042             GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1043             this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1044             return;
1045         }
1046     }
1047 
1048     SkPath path;
1049     path.setIsVolatile(true);
1050     path.addOval(oval);
1051     this->internalDrawPath(clip, paint, viewMatrix, path, style);
1052 }
1053 
drawArc(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const GrStyle & style)1054 void 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;
1080     SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1081                                   style.isSimpleFill());
1082     this->internalDrawPath(clip, paint, viewMatrix, path, style);
1083     return;
1084 }
1085 
drawImageLattice(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,int imageWidth,int imageHeight,std::unique_ptr<SkLatticeIter> iter,const SkRect & dst)1086 void 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) {
1093     ASSERT_SINGLE_OWNER
1094     RETURN_IF_ABANDONED
1095     SkDEBUGCODE(this->validate();)
1096     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageLattice");
1097 
1098     AutoCheckFlush acf(fDrawingManager);
1099 
1100     SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
1101                                                              imageWidth, imageHeight,
1102                                                              std::move(iter), dst));
1103 
1104     GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
1105     this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1106 }
1107 
prepareForExternalIO()1108 void 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 
1116     fDrawingManager->prepareSurfaceForExternalIO(fRenderTarget.get());
1117 }
1118 
drawNonAAFilledRect(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkRect & rect,const SkRect * localRect,const SkMatrix * localMatrix,const GrUserStencilSettings * ss,bool useHWAA)1119 void 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,
1125                                         const GrUserStencilSettings* ss,
1126                                         bool useHWAA) {
1127     SkASSERT(!useHWAA || this->isStencilBufferMultisampled());
1128     SkAutoTUnref<GrDrawBatch> batch(
1129             GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, localRect,
1130                                                 localMatrix));
1131     GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1132     if (ss) {
1133         pipelineBuilder.setUserStencil(ss);
1134     }
1135     this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1136 }
1137 
readPixels(const SkImageInfo & dstInfo,void * dstBuffer,size_t dstRowBytes,int x,int y)1138 bool 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 
writePixels(const SkImageInfo & srcInfo,const void * srcBuffer,size_t srcRowBytes,int x,int y)1155 bool 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 
1171 // Can 'path' be drawn as a pair of filled nested rectangles?
fills_as_nested_rects(const SkMatrix & viewMatrix,const SkPath & path,SkRect rects[2])1172 static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
1173 
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
1180     if (!viewMatrix.rectStaysRect()) {
1181         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 
drawPath(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkPath & path,const GrStyle & style)1217 void GrDrawContext::drawPath(const GrClip& clip,
1218                              const GrPaint& paint,
1219                              const SkMatrix& viewMatrix,
1220                              const SkPath& path,
1221                              const GrStyle& style) {
1222     ASSERT_SINGLE_OWNER
1223     RETURN_IF_ABANDONED
1224     SkDEBUGCODE(this->validate();)
1225     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
1226 
1227     if (path.isEmpty()) {
1228        if (path.isInverseFillType()) {
1229            this->drawPaint(clip, paint, viewMatrix);
1230        }
1231        return;
1232     }
1233 
1234     AutoCheckFlush acf(fDrawingManager);
1235 
1236     bool useHWAA;
1237     if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA) && !style.pathEffect()) {
1238         if (style.isSimpleFill() && !path.isConvex()) {
1239             // Concave AA paths are expensive - try to avoid them for special cases
1240             SkRect rects[2];
1241 
1242             if (fills_as_nested_rects(viewMatrix, path, rects)) {
1243                 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
1244                     paint.getColor(), viewMatrix, rects));
1245                 if (batch) {
1246                     GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1247                     this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1248                 }
1249                 return;
1250             }
1251         }
1252         SkRect ovalRect;
1253         bool isOval = path.isOval(&ovalRect);
1254 
1255         if (isOval && !path.isInverseFillType()) {
1256             GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1257             SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
1258                                                                             viewMatrix,
1259                                                                             ovalRect,
1260                                                                             style.strokeRec(),
1261                                                                             shaderCaps));
1262             if (batch) {
1263                 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1264                 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1265                 return;
1266             }
1267         }
1268     }
1269 
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.
1275     this->internalDrawPath(clip, paint, viewMatrix, path, style);
1276 }
1277 
drawAndStencilPath(const GrClip & clip,const GrUserStencilSettings * ss,SkRegion::Op op,bool invert,bool doAA,const SkMatrix & viewMatrix,const SkPath & path)1278 bool GrDrawContextPriv::drawAndStencilPath(const GrClip& clip,
1279                                            const GrUserStencilSettings* ss,
1280                                            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()) {
1291         this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
1292                                  SkRect::MakeIWH(fDrawContext->width(),
1293                                                  fDrawContext->height()));
1294         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.
1303     bool useCoverageAA = doAA && !fDrawContext->isUnifiedMultisampled();
1304     bool hasUserStencilSettings = !ss->isUnused();
1305     bool isStencilBufferMSAA = fDrawContext->isStencilBufferMultisampled();
1306 
1307     const GrPathRendererChain::DrawType type =
1308         useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1309                       : GrPathRendererChain::kColor_DrawType;
1310 
1311     GrShape shape(path, GrStyle::SimpleFill());
1312     GrPathRenderer::CanDrawPathArgs canDrawArgs;
1313     canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
1314     canDrawArgs.fViewMatrix = &viewMatrix;
1315     canDrawArgs.fShape = &shape;
1316     canDrawArgs.fAntiAlias = useCoverageAA;
1317     canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
1318     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 
1329     GrPathRenderer::DrawPathArgs args;
1330     args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
1331     args.fPaint = &paint;
1332     args.fUserStencilSettings = ss;
1333     args.fDrawContext = fDrawContext;
1334     args.fClip = &clip;
1335     args.fViewMatrix = &viewMatrix;
1336     args.fShape = &shape;
1337     args.fAntiAlias = useCoverageAA;
1338     args.fGammaCorrect = fDrawContext->isGammaCorrect();
1339     pr->drawPath(args);
1340     return true;
1341 }
1342 
isBudgeted() const1343 SkBudgeted 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 
internalDrawPath(const GrClip & clip,const GrPaint & paint,const SkMatrix & viewMatrix,const SkPath & path,const GrStyle & style)1355 void GrDrawContext::internalDrawPath(const GrClip& clip,
1356                                      const GrPaint& paint,
1357                                      const SkMatrix& viewMatrix,
1358                                      const SkPath& path,
1359                                      const GrStyle& style) {
1360     ASSERT_SINGLE_OWNER
1361     RETURN_IF_ABANDONED
1362     SkASSERT(!path.isEmpty());
1363 
1364     bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
1365     constexpr bool kHasUserStencilSettings = false;
1366     bool isStencilBufferMSAA = this->isStencilBufferMultisampled();
1367 
1368     const GrPathRendererChain::DrawType type =
1369         useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1370                       : GrPathRendererChain::kColor_DrawType;
1371 
1372     GrShape shape(path, style);
1373     if (shape.isEmpty()) {
1374         return;
1375     }
1376     GrPathRenderer::CanDrawPathArgs canDrawArgs;
1377     canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1378     canDrawArgs.fViewMatrix = &viewMatrix;
1379     canDrawArgs.fShape = &shape;
1380     canDrawArgs.fAntiAlias = useCoverageAA;
1381     canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
1382     canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1383 
1384     // Try a 1st time without applying any of the style to the geometry (and barring sw)
1385     GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1386     SkScalar styleScale =  GrStyle::MatrixToScaleFactor(viewMatrix);
1387 
1388     if (!pr && shape.style().pathEffect()) {
1389         // It didn't work above, so try again with the path effect applied.
1390         shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1391         if (shape.isEmpty()) {
1392             return;
1393         }
1394         pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1395     }
1396     if (!pr) {
1397         if (shape.style().applies()) {
1398             shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1399             if (shape.isEmpty()) {
1400                 return;
1401             }
1402         }
1403         // This time, allow SW renderer
1404         pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
1405     }
1406 
1407     if (!pr) {
1408 #ifdef SK_DEBUG
1409         SkDebugf("Unable to find path renderer compatible with path.\n");
1410 #endif
1411         return;
1412     }
1413 
1414     GrPathRenderer::DrawPathArgs args;
1415     args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
1416     args.fPaint = &paint;
1417     args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
1418     args.fDrawContext = this;
1419     args.fClip = &clip;
1420     args.fViewMatrix = &viewMatrix;
1421     args.fShape = canDrawArgs.fShape;
1422     args.fAntiAlias = useCoverageAA;
1423     args.fGammaCorrect = this->isGammaCorrect();
1424     pr->drawPath(args);
1425 }
1426 
drawBatch(const GrPipelineBuilder & pipelineBuilder,const GrClip & clip,GrDrawBatch * batch)1427 void GrDrawContext::drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
1428                               GrDrawBatch* batch) {
1429     ASSERT_SINGLE_OWNER
1430     RETURN_IF_ABANDONED
1431     SkDEBUGCODE(this->validate();)
1432     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
1433 
1434     this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1435 }
1436