xref: /aosp_15_r20/external/skia/tools/debugger/DebugCanvas.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2012 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "tools/debugger/DebugCanvas.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkClipOp.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPicture.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRSXform.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTextBlob.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkVertices.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/utils/SkPaintFilterCanvas.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkCanvasPriv.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkRectPriv.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStringUtils.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkJSONWriter.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "tools/debugger/DebugLayerManager.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "tools/debugger/DrawCommand.h"
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
34*c8dee2aaSAndroid Build Coastguard Worker #include <string>
35*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker class SkDrawable;
38*c8dee2aaSAndroid Build Coastguard Worker class SkImage;
39*c8dee2aaSAndroid Build Coastguard Worker class SkRRect;
40*c8dee2aaSAndroid Build Coastguard Worker class SkRegion;
41*c8dee2aaSAndroid Build Coastguard Worker class UrlDataManager;
42*c8dee2aaSAndroid Build Coastguard Worker struct SkDrawShadowRec;
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
45*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrAuditTrail.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCanvas.h"
49*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
50*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTargetProxy.h"
51*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
52*c8dee2aaSAndroid Build Coastguard Worker #endif
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
55*c8dee2aaSAndroid Build Coastguard Worker 
56*c8dee2aaSAndroid Build Coastguard Worker #define SKDEBUGCANVAS_VERSION 1
57*c8dee2aaSAndroid Build Coastguard Worker #define SKDEBUGCANVAS_ATTRIBUTE_VERSION "version"
58*c8dee2aaSAndroid Build Coastguard Worker #define SKDEBUGCANVAS_ATTRIBUTE_COMMANDS "commands"
59*c8dee2aaSAndroid Build Coastguard Worker #define SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL "auditTrail"
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker namespace {
62*c8dee2aaSAndroid Build Coastguard Worker     // Constants used in Annotations by Android for keeping track of layers
63*c8dee2aaSAndroid Build Coastguard Worker     static constexpr char kOffscreenLayerDraw[] = "OffscreenLayerDraw";
64*c8dee2aaSAndroid Build Coastguard Worker     static constexpr char kSurfaceID[] = "SurfaceID";
65*c8dee2aaSAndroid Build Coastguard Worker     static constexpr char kAndroidClip[] = "AndroidDeviceClipRestriction";
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker     static SkPath arrowHead = SkPath::Polygon({
68*c8dee2aaSAndroid Build Coastguard Worker         { 0,   0},
69*c8dee2aaSAndroid Build Coastguard Worker         { 6, -15},
70*c8dee2aaSAndroid Build Coastguard Worker         { 0,  -12},
71*c8dee2aaSAndroid Build Coastguard Worker         {-6, -15},
72*c8dee2aaSAndroid Build Coastguard Worker     }, true);
73*c8dee2aaSAndroid Build Coastguard Worker 
drawArrow(SkCanvas * canvas,const SkPoint & a,const SkPoint & b,const SkPaint & paint)74*c8dee2aaSAndroid Build Coastguard Worker     void drawArrow(SkCanvas* canvas, const SkPoint& a, const SkPoint& b, const SkPaint& paint) {
75*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(0.5, 0.5);
76*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawLine(a, b, paint);
77*c8dee2aaSAndroid Build Coastguard Worker         canvas->save();
78*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(b.fX, b.fY);
79*c8dee2aaSAndroid Build Coastguard Worker         SkScalar angle = SkScalarATan2((b.fY - a.fY), b.fX - a.fX);
80*c8dee2aaSAndroid Build Coastguard Worker         canvas->rotate(angle * 180 / SK_ScalarPI - 90);
81*c8dee2aaSAndroid Build Coastguard Worker         // arrow head
82*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawPath(arrowHead, paint);
83*c8dee2aaSAndroid Build Coastguard Worker         canvas->restore();
84*c8dee2aaSAndroid Build Coastguard Worker         canvas->restore();
85*c8dee2aaSAndroid Build Coastguard Worker     }
86*c8dee2aaSAndroid Build Coastguard Worker } // namespace
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker class DebugPaintFilterCanvas : public SkPaintFilterCanvas {
89*c8dee2aaSAndroid Build Coastguard Worker public:
DebugPaintFilterCanvas(SkCanvas * canvas)90*c8dee2aaSAndroid Build Coastguard Worker     DebugPaintFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) {}
91*c8dee2aaSAndroid Build Coastguard Worker 
92*c8dee2aaSAndroid Build Coastguard Worker protected:
onFilter(SkPaint & paint) const93*c8dee2aaSAndroid Build Coastguard Worker     bool onFilter(SkPaint& paint) const override {
94*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorRED);
95*c8dee2aaSAndroid Build Coastguard Worker         paint.setAlpha(0x08);
96*c8dee2aaSAndroid Build Coastguard Worker         paint.setBlendMode(SkBlendMode::kSrcOver);
97*c8dee2aaSAndroid Build Coastguard Worker         return true;
98*c8dee2aaSAndroid Build Coastguard Worker     }
99*c8dee2aaSAndroid Build Coastguard Worker 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)100*c8dee2aaSAndroid Build Coastguard Worker     void onDrawPicture(const SkPicture* picture,
101*c8dee2aaSAndroid Build Coastguard Worker                        const SkMatrix*  matrix,
102*c8dee2aaSAndroid Build Coastguard Worker                        const SkPaint*   paint) override {
103*c8dee2aaSAndroid Build Coastguard Worker         // We need to replay the picture onto this canvas in order to filter its internal paints.
104*c8dee2aaSAndroid Build Coastguard Worker         this->SkCanvas::onDrawPicture(picture, matrix, paint);
105*c8dee2aaSAndroid Build Coastguard Worker     }
106*c8dee2aaSAndroid Build Coastguard Worker 
107*c8dee2aaSAndroid Build Coastguard Worker private:
108*c8dee2aaSAndroid Build Coastguard Worker 
109*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = SkPaintFilterCanvas;
110*c8dee2aaSAndroid Build Coastguard Worker };
111*c8dee2aaSAndroid Build Coastguard Worker 
DebugCanvas(int width,int height)112*c8dee2aaSAndroid Build Coastguard Worker DebugCanvas::DebugCanvas(int width, int height)
113*c8dee2aaSAndroid Build Coastguard Worker         : INHERITED(width, height)
114*c8dee2aaSAndroid Build Coastguard Worker         , fOverdrawViz(false)
115*c8dee2aaSAndroid Build Coastguard Worker         , fClipVizColor(SK_ColorTRANSPARENT)
116*c8dee2aaSAndroid Build Coastguard Worker         , fDrawGpuOpBounds(false)
117*c8dee2aaSAndroid Build Coastguard Worker         , fShowAndroidClip(false)
118*c8dee2aaSAndroid Build Coastguard Worker         , fShowOrigin(false)
119*c8dee2aaSAndroid Build Coastguard Worker         , fnextDrawPictureLayerId(-1)
120*c8dee2aaSAndroid Build Coastguard Worker         , fnextDrawImageRectLayerId(-1)
121*c8dee2aaSAndroid Build Coastguard Worker         , fAndroidClip(SkRect::MakeEmpty()) {
122*c8dee2aaSAndroid Build Coastguard Worker     // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
123*c8dee2aaSAndroid Build Coastguard Worker     // operations. This can lead to problems in the debugger which expects all
124*c8dee2aaSAndroid Build Coastguard Worker     // the operations in the captured skp to appear in the debug canvas. To
125*c8dee2aaSAndroid Build Coastguard Worker     // circumvent this we create a wide open clip here (an empty clip rect
126*c8dee2aaSAndroid Build Coastguard Worker     // is not sufficient).
127*c8dee2aaSAndroid Build Coastguard Worker     // Internally, the SkRect passed to clipRect is converted to an SkIRect and
128*c8dee2aaSAndroid Build Coastguard Worker     // rounded out. The following code creates a nearly maximal rect that will
129*c8dee2aaSAndroid Build Coastguard Worker     // not get collapsed by the coming conversions (Due to precision loss the
130*c8dee2aaSAndroid Build Coastguard Worker     // inset has to be surprisingly large).
131*c8dee2aaSAndroid Build Coastguard Worker     SkIRect largeIRect = SkRectPriv::MakeILarge();
132*c8dee2aaSAndroid Build Coastguard Worker     largeIRect.inset(1024, 1024);
133*c8dee2aaSAndroid Build Coastguard Worker     SkRect large = SkRect::Make(largeIRect);
134*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
135*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!large.roundOut().isEmpty());
136*c8dee2aaSAndroid Build Coastguard Worker #endif
137*c8dee2aaSAndroid Build Coastguard Worker     // call the base class' version to avoid adding a draw command
138*c8dee2aaSAndroid Build Coastguard Worker     this->INHERITED::onClipRect(large, SkClipOp::kIntersect, kHard_ClipEdgeStyle);
139*c8dee2aaSAndroid Build Coastguard Worker }
140*c8dee2aaSAndroid Build Coastguard Worker 
DebugCanvas(SkIRect bounds)141*c8dee2aaSAndroid Build Coastguard Worker DebugCanvas::DebugCanvas(SkIRect bounds)
142*c8dee2aaSAndroid Build Coastguard Worker         : DebugCanvas(bounds.width(), bounds.height()) {}
143*c8dee2aaSAndroid Build Coastguard Worker 
~DebugCanvas()144*c8dee2aaSAndroid Build Coastguard Worker DebugCanvas::~DebugCanvas() {
145*c8dee2aaSAndroid Build Coastguard Worker     for (DrawCommand* p : fCommandVector) {
146*c8dee2aaSAndroid Build Coastguard Worker         delete p;
147*c8dee2aaSAndroid Build Coastguard Worker     }
148*c8dee2aaSAndroid Build Coastguard Worker     fCommandVector.reset();
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker 
addDrawCommand(DrawCommand * command)151*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::addDrawCommand(DrawCommand* command) { fCommandVector.push_back(command); }
152*c8dee2aaSAndroid Build Coastguard Worker 
draw(SkCanvas * canvas)153*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::draw(SkCanvas* canvas) {
154*c8dee2aaSAndroid Build Coastguard Worker     if (!fCommandVector.empty()) {
155*c8dee2aaSAndroid Build Coastguard Worker         this->drawTo(canvas, fCommandVector.size() - 1);
156*c8dee2aaSAndroid Build Coastguard Worker     }
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker 
drawTo(SkCanvas * originalCanvas,int index,int m)159*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
160*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!fCommandVector.empty());
161*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(index < fCommandVector.size());
162*c8dee2aaSAndroid Build Coastguard Worker 
163*c8dee2aaSAndroid Build Coastguard Worker     int saveCount = originalCanvas->save();
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     originalCanvas->resetMatrix();
166*c8dee2aaSAndroid Build Coastguard Worker     SkCanvasPriv::ResetClip(originalCanvas);
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker     DebugPaintFilterCanvas filterCanvas(originalCanvas);
169*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas* finalCanvas = fOverdrawViz ? &filterCanvas : originalCanvas;
170*c8dee2aaSAndroid Build Coastguard Worker 
171*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
172*c8dee2aaSAndroid Build Coastguard Worker     auto dContext = GrAsDirectContext(finalCanvas->recordingContext());
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker     // If we have a GPU backend we can also visualize the op information
175*c8dee2aaSAndroid Build Coastguard Worker     GrAuditTrail* at = nullptr;
176*c8dee2aaSAndroid Build Coastguard Worker     if (fDrawGpuOpBounds || m != -1) {
177*c8dee2aaSAndroid Build Coastguard Worker         // The audit trail must be obtained from the original canvas.
178*c8dee2aaSAndroid Build Coastguard Worker         at = this->getAuditTrail(originalCanvas);
179*c8dee2aaSAndroid Build Coastguard Worker     }
180*c8dee2aaSAndroid Build Coastguard Worker #endif
181*c8dee2aaSAndroid Build Coastguard Worker 
182*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i <= index; i++) {
183*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
184*c8dee2aaSAndroid Build Coastguard Worker         GrAuditTrail::AutoCollectOps* acb = nullptr;
185*c8dee2aaSAndroid Build Coastguard Worker         if (at) {
186*c8dee2aaSAndroid Build Coastguard Worker             // We need to flush any pending operations, or they might combine with commands below.
187*c8dee2aaSAndroid Build Coastguard Worker             // Previous operations were not registered with the audit trail when they were
188*c8dee2aaSAndroid Build Coastguard Worker             // created, so if we allow them to combine, the audit trail will fail to find them.
189*c8dee2aaSAndroid Build Coastguard Worker             if (dContext) {
190*c8dee2aaSAndroid Build Coastguard Worker                 dContext->flush();
191*c8dee2aaSAndroid Build Coastguard Worker             }
192*c8dee2aaSAndroid Build Coastguard Worker             acb = new GrAuditTrail::AutoCollectOps(at, i);
193*c8dee2aaSAndroid Build Coastguard Worker         }
194*c8dee2aaSAndroid Build Coastguard Worker #endif
195*c8dee2aaSAndroid Build Coastguard Worker         if (fCommandVector[i]->isVisible()) {
196*c8dee2aaSAndroid Build Coastguard Worker             fCommandVector[i]->execute(finalCanvas);
197*c8dee2aaSAndroid Build Coastguard Worker         }
198*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
199*c8dee2aaSAndroid Build Coastguard Worker         if (at && acb) {
200*c8dee2aaSAndroid Build Coastguard Worker             delete acb;
201*c8dee2aaSAndroid Build Coastguard Worker         }
202*c8dee2aaSAndroid Build Coastguard Worker #endif
203*c8dee2aaSAndroid Build Coastguard Worker     }
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker     if (SkColorGetA(fClipVizColor) != 0) {
206*c8dee2aaSAndroid Build Coastguard Worker         finalCanvas->save();
207*c8dee2aaSAndroid Build Coastguard Worker         SkPaint clipPaint;
208*c8dee2aaSAndroid Build Coastguard Worker         clipPaint.setColor(fClipVizColor);
209*c8dee2aaSAndroid Build Coastguard Worker         finalCanvas->drawPaint(clipPaint);
210*c8dee2aaSAndroid Build Coastguard Worker         finalCanvas->restore();
211*c8dee2aaSAndroid Build Coastguard Worker     }
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     fMatrix = finalCanvas->getLocalToDevice();
214*c8dee2aaSAndroid Build Coastguard Worker     fClip   = finalCanvas->getDeviceClipBounds();
215*c8dee2aaSAndroid Build Coastguard Worker     if (fShowOrigin) {
216*c8dee2aaSAndroid Build Coastguard Worker         const SkPaint originXPaint = SkPaint({1.0, 0, 0, 1.0});
217*c8dee2aaSAndroid Build Coastguard Worker         const SkPaint originYPaint = SkPaint({0, 1.0, 0, 1.0});
218*c8dee2aaSAndroid Build Coastguard Worker         // Draw an origin cross at the origin before restoring to assist in visualizing the
219*c8dee2aaSAndroid Build Coastguard Worker         // current matrix.
220*c8dee2aaSAndroid Build Coastguard Worker         drawArrow(finalCanvas, {-50, 0}, {50, 0}, originXPaint);
221*c8dee2aaSAndroid Build Coastguard Worker         drawArrow(finalCanvas, {0, -50}, {0, 50}, originYPaint);
222*c8dee2aaSAndroid Build Coastguard Worker     }
223*c8dee2aaSAndroid Build Coastguard Worker     finalCanvas->restoreToCount(saveCount);
224*c8dee2aaSAndroid Build Coastguard Worker 
225*c8dee2aaSAndroid Build Coastguard Worker     if (fShowAndroidClip) {
226*c8dee2aaSAndroid Build Coastguard Worker         // Draw visualization of android device clip restriction
227*c8dee2aaSAndroid Build Coastguard Worker         SkPaint androidClipPaint;
228*c8dee2aaSAndroid Build Coastguard Worker         androidClipPaint.setARGB(80, 255, 100, 0);
229*c8dee2aaSAndroid Build Coastguard Worker         finalCanvas->drawRect(fAndroidClip, androidClipPaint);
230*c8dee2aaSAndroid Build Coastguard Worker     }
231*c8dee2aaSAndroid Build Coastguard Worker 
232*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
233*c8dee2aaSAndroid Build Coastguard Worker     // draw any ops if required and issue a full reset onto GrAuditTrail
234*c8dee2aaSAndroid Build Coastguard Worker     if (at) {
235*c8dee2aaSAndroid Build Coastguard Worker         // just in case there is global reordering, we flush the canvas before querying
236*c8dee2aaSAndroid Build Coastguard Worker         // GrAuditTrail
237*c8dee2aaSAndroid Build Coastguard Worker         GrAuditTrail::AutoEnable ae(at);
238*c8dee2aaSAndroid Build Coastguard Worker         if (dContext) {
239*c8dee2aaSAndroid Build Coastguard Worker             dContext->flush();
240*c8dee2aaSAndroid Build Coastguard Worker         }
241*c8dee2aaSAndroid Build Coastguard Worker 
242*c8dee2aaSAndroid Build Coastguard Worker         // we pick three colorblind-safe colors, 75% alpha
243*c8dee2aaSAndroid Build Coastguard Worker         static const SkColor kTotalBounds     = SkColorSetARGB(0xC0, 0x6A, 0x3D, 0x9A);
244*c8dee2aaSAndroid Build Coastguard Worker         static const SkColor kCommandOpBounds = SkColorSetARGB(0xC0, 0xE3, 0x1A, 0x1C);
245*c8dee2aaSAndroid Build Coastguard Worker         static const SkColor kOtherOpBounds   = SkColorSetARGB(0xC0, 0xFF, 0x7F, 0x00);
246*c8dee2aaSAndroid Build Coastguard Worker 
247*c8dee2aaSAndroid Build Coastguard Worker         // get the render target of the top device (from the original canvas) so we can ignore ops
248*c8dee2aaSAndroid Build Coastguard Worker         // drawn offscreen
249*c8dee2aaSAndroid Build Coastguard Worker         GrRenderTargetProxy* rtp = skgpu::ganesh::TopDeviceTargetProxy(originalCanvas);
250*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceProxy::UniqueID proxyID = rtp->uniqueID();
251*c8dee2aaSAndroid Build Coastguard Worker 
252*c8dee2aaSAndroid Build Coastguard Worker         // get the bounding boxes to draw
253*c8dee2aaSAndroid Build Coastguard Worker         TArray<GrAuditTrail::OpInfo> childrenBounds;
254*c8dee2aaSAndroid Build Coastguard Worker         if (m == -1) {
255*c8dee2aaSAndroid Build Coastguard Worker             at->getBoundsByClientID(&childrenBounds, index);
256*c8dee2aaSAndroid Build Coastguard Worker         } else {
257*c8dee2aaSAndroid Build Coastguard Worker             // the client wants us to draw the mth op
258*c8dee2aaSAndroid Build Coastguard Worker             at->getBoundsByOpsTaskID(&childrenBounds.push_back(), m);
259*c8dee2aaSAndroid Build Coastguard Worker         }
260*c8dee2aaSAndroid Build Coastguard Worker         // Shift the rects half a pixel, so they appear as exactly 1px thick lines.
261*c8dee2aaSAndroid Build Coastguard Worker         finalCanvas->save();
262*c8dee2aaSAndroid Build Coastguard Worker         finalCanvas->translate(0.5, -0.5);
263*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
264*c8dee2aaSAndroid Build Coastguard Worker         paint.setStyle(SkPaint::kStroke_Style);
265*c8dee2aaSAndroid Build Coastguard Worker         paint.setStrokeWidth(1);
266*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < childrenBounds.size(); i++) {
267*c8dee2aaSAndroid Build Coastguard Worker             if (childrenBounds[i].fProxyUniqueID != proxyID) {
268*c8dee2aaSAndroid Build Coastguard Worker                 // offscreen draw, ignore for now
269*c8dee2aaSAndroid Build Coastguard Worker                 continue;
270*c8dee2aaSAndroid Build Coastguard Worker             }
271*c8dee2aaSAndroid Build Coastguard Worker             paint.setColor(kTotalBounds);
272*c8dee2aaSAndroid Build Coastguard Worker             finalCanvas->drawRect(childrenBounds[i].fBounds, paint);
273*c8dee2aaSAndroid Build Coastguard Worker             for (int j = 0; j < childrenBounds[i].fOps.size(); j++) {
274*c8dee2aaSAndroid Build Coastguard Worker                 const GrAuditTrail::OpInfo::Op& op = childrenBounds[i].fOps[j];
275*c8dee2aaSAndroid Build Coastguard Worker                 if (op.fClientID != index) {
276*c8dee2aaSAndroid Build Coastguard Worker                     paint.setColor(kOtherOpBounds);
277*c8dee2aaSAndroid Build Coastguard Worker                 } else {
278*c8dee2aaSAndroid Build Coastguard Worker                     paint.setColor(kCommandOpBounds);
279*c8dee2aaSAndroid Build Coastguard Worker                 }
280*c8dee2aaSAndroid Build Coastguard Worker                 finalCanvas->drawRect(op.fBounds, paint);
281*c8dee2aaSAndroid Build Coastguard Worker             }
282*c8dee2aaSAndroid Build Coastguard Worker         }
283*c8dee2aaSAndroid Build Coastguard Worker         finalCanvas->restore();
284*c8dee2aaSAndroid Build Coastguard Worker         this->cleanupAuditTrail(at);
285*c8dee2aaSAndroid Build Coastguard Worker     }
286*c8dee2aaSAndroid Build Coastguard Worker #endif
287*c8dee2aaSAndroid Build Coastguard Worker }
288*c8dee2aaSAndroid Build Coastguard Worker 
deleteDrawCommandAt(int index)289*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::deleteDrawCommandAt(int index) {
290*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(index < fCommandVector.size());
291*c8dee2aaSAndroid Build Coastguard Worker     delete fCommandVector[index];
292*c8dee2aaSAndroid Build Coastguard Worker     fCommandVector.remove(index);
293*c8dee2aaSAndroid Build Coastguard Worker }
294*c8dee2aaSAndroid Build Coastguard Worker 
getDrawCommandAt(int index) const295*c8dee2aaSAndroid Build Coastguard Worker DrawCommand* DebugCanvas::getDrawCommandAt(int index) const {
296*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(index < fCommandVector.size());
297*c8dee2aaSAndroid Build Coastguard Worker     return fCommandVector[index];
298*c8dee2aaSAndroid Build Coastguard Worker }
299*c8dee2aaSAndroid Build Coastguard Worker 
300*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
getAuditTrail(SkCanvas * canvas)301*c8dee2aaSAndroid Build Coastguard Worker GrAuditTrail* DebugCanvas::getAuditTrail(SkCanvas* canvas) {
302*c8dee2aaSAndroid Build Coastguard Worker     GrAuditTrail* at  = nullptr;
303*c8dee2aaSAndroid Build Coastguard Worker     auto ctx = canvas->recordingContext();
304*c8dee2aaSAndroid Build Coastguard Worker     if (ctx) {
305*c8dee2aaSAndroid Build Coastguard Worker         at = ctx->priv().auditTrail();
306*c8dee2aaSAndroid Build Coastguard Worker     }
307*c8dee2aaSAndroid Build Coastguard Worker     return at;
308*c8dee2aaSAndroid Build Coastguard Worker }
309*c8dee2aaSAndroid Build Coastguard Worker 
drawAndCollectOps(SkCanvas * canvas)310*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::drawAndCollectOps(SkCanvas* canvas) {
311*c8dee2aaSAndroid Build Coastguard Worker     GrAuditTrail* at = this->getAuditTrail(canvas);
312*c8dee2aaSAndroid Build Coastguard Worker     if (at) {
313*c8dee2aaSAndroid Build Coastguard Worker         // loop over all of the commands and draw them, this is to collect reordering
314*c8dee2aaSAndroid Build Coastguard Worker         // information
315*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < this->getSize(); i++) {
316*c8dee2aaSAndroid Build Coastguard Worker             GrAuditTrail::AutoCollectOps enable(at, i);
317*c8dee2aaSAndroid Build Coastguard Worker             fCommandVector[i]->execute(canvas);
318*c8dee2aaSAndroid Build Coastguard Worker         }
319*c8dee2aaSAndroid Build Coastguard Worker 
320*c8dee2aaSAndroid Build Coastguard Worker         // in case there is some kind of global reordering
321*c8dee2aaSAndroid Build Coastguard Worker         {
322*c8dee2aaSAndroid Build Coastguard Worker             GrAuditTrail::AutoEnable ae(at);
323*c8dee2aaSAndroid Build Coastguard Worker 
324*c8dee2aaSAndroid Build Coastguard Worker             auto dContext = GrAsDirectContext(canvas->recordingContext());
325*c8dee2aaSAndroid Build Coastguard Worker             if (dContext) {
326*c8dee2aaSAndroid Build Coastguard Worker                 dContext->flush();
327*c8dee2aaSAndroid Build Coastguard Worker             }
328*c8dee2aaSAndroid Build Coastguard Worker         }
329*c8dee2aaSAndroid Build Coastguard Worker     }
330*c8dee2aaSAndroid Build Coastguard Worker }
331*c8dee2aaSAndroid Build Coastguard Worker 
cleanupAuditTrail(GrAuditTrail * at)332*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::cleanupAuditTrail(GrAuditTrail* at) {
333*c8dee2aaSAndroid Build Coastguard Worker     if (at) {
334*c8dee2aaSAndroid Build Coastguard Worker         GrAuditTrail::AutoEnable ae(at);
335*c8dee2aaSAndroid Build Coastguard Worker         at->fullReset();
336*c8dee2aaSAndroid Build Coastguard Worker     }
337*c8dee2aaSAndroid Build Coastguard Worker }
338*c8dee2aaSAndroid Build Coastguard Worker #endif // defined(SK_GANESH)
339*c8dee2aaSAndroid Build Coastguard Worker 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager,SkCanvas * canvas)340*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::toJSON(SkJSONWriter&   writer,
341*c8dee2aaSAndroid Build Coastguard Worker                          UrlDataManager& urlDataManager,
342*c8dee2aaSAndroid Build Coastguard Worker                          SkCanvas*       canvas) {
343*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
344*c8dee2aaSAndroid Build Coastguard Worker     this->drawAndCollectOps(canvas);
345*c8dee2aaSAndroid Build Coastguard Worker 
346*c8dee2aaSAndroid Build Coastguard Worker     // now collect json
347*c8dee2aaSAndroid Build Coastguard Worker     GrAuditTrail* at = this->getAuditTrail(canvas);
348*c8dee2aaSAndroid Build Coastguard Worker #endif
349*c8dee2aaSAndroid Build Coastguard Worker     writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_VERSION, SKDEBUGCANVAS_VERSION);
350*c8dee2aaSAndroid Build Coastguard Worker     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_COMMANDS);
351*c8dee2aaSAndroid Build Coastguard Worker 
352*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < this->getSize(); i++) {
353*c8dee2aaSAndroid Build Coastguard Worker         writer.beginObject();  // command
354*c8dee2aaSAndroid Build Coastguard Worker         this->getDrawCommandAt(i)->toJSON(writer, urlDataManager);
355*c8dee2aaSAndroid Build Coastguard Worker 
356*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
357*c8dee2aaSAndroid Build Coastguard Worker         if (at && at->isEnabled()) {
358*c8dee2aaSAndroid Build Coastguard Worker             writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL);
359*c8dee2aaSAndroid Build Coastguard Worker             at->toJson(writer, i);
360*c8dee2aaSAndroid Build Coastguard Worker         }
361*c8dee2aaSAndroid Build Coastguard Worker #endif
362*c8dee2aaSAndroid Build Coastguard Worker         writer.endObject();  // command
363*c8dee2aaSAndroid Build Coastguard Worker     }
364*c8dee2aaSAndroid Build Coastguard Worker 
365*c8dee2aaSAndroid Build Coastguard Worker     writer.endArray();  // commands
366*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
367*c8dee2aaSAndroid Build Coastguard Worker     this->cleanupAuditTrail(at);
368*c8dee2aaSAndroid Build Coastguard Worker #endif
369*c8dee2aaSAndroid Build Coastguard Worker }
370*c8dee2aaSAndroid Build Coastguard Worker 
toJSONOpsTask(SkJSONWriter & writer,SkCanvas * canvas)371*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::toJSONOpsTask(SkJSONWriter& writer, SkCanvas* canvas) {
372*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
373*c8dee2aaSAndroid Build Coastguard Worker     this->drawAndCollectOps(canvas);
374*c8dee2aaSAndroid Build Coastguard Worker 
375*c8dee2aaSAndroid Build Coastguard Worker     GrAuditTrail* at = this->getAuditTrail(canvas);
376*c8dee2aaSAndroid Build Coastguard Worker     if (at) {
377*c8dee2aaSAndroid Build Coastguard Worker         GrAuditTrail::AutoManageOpsTask enable(at);
378*c8dee2aaSAndroid Build Coastguard Worker         at->toJson(writer);
379*c8dee2aaSAndroid Build Coastguard Worker         this->cleanupAuditTrail(at);
380*c8dee2aaSAndroid Build Coastguard Worker         return;
381*c8dee2aaSAndroid Build Coastguard Worker     }
382*c8dee2aaSAndroid Build Coastguard Worker #endif
383*c8dee2aaSAndroid Build Coastguard Worker 
384*c8dee2aaSAndroid Build Coastguard Worker     writer.beginObject();
385*c8dee2aaSAndroid Build Coastguard Worker     writer.endObject();
386*c8dee2aaSAndroid Build Coastguard Worker }
387*c8dee2aaSAndroid Build Coastguard Worker 
setOverdrawViz(bool overdrawViz)388*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::setOverdrawViz(bool overdrawViz) { fOverdrawViz = overdrawViz; }
389*c8dee2aaSAndroid Build Coastguard Worker 
onClipPath(const SkPath & path,SkClipOp op,ClipEdgeStyle edgeStyle)390*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
391*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new ClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
392*c8dee2aaSAndroid Build Coastguard Worker }
393*c8dee2aaSAndroid Build Coastguard Worker 
onClipRect(const SkRect & rect,SkClipOp op,ClipEdgeStyle edgeStyle)394*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
395*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new ClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
396*c8dee2aaSAndroid Build Coastguard Worker }
397*c8dee2aaSAndroid Build Coastguard Worker 
onClipRRect(const SkRRect & rrect,SkClipOp op,ClipEdgeStyle edgeStyle)398*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
399*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new ClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
400*c8dee2aaSAndroid Build Coastguard Worker }
401*c8dee2aaSAndroid Build Coastguard Worker 
onClipRegion(const SkRegion & region,SkClipOp op)402*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
403*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new ClipRegionCommand(region, op));
404*c8dee2aaSAndroid Build Coastguard Worker }
405*c8dee2aaSAndroid Build Coastguard Worker 
onClipShader(sk_sp<SkShader> cs,SkClipOp op)406*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onClipShader(sk_sp<SkShader> cs, SkClipOp op) {
407*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new ClipShaderCommand(std::move(cs), op));
408*c8dee2aaSAndroid Build Coastguard Worker }
409*c8dee2aaSAndroid Build Coastguard Worker 
onResetClip()410*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onResetClip() {
411*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new ResetClipCommand());
412*c8dee2aaSAndroid Build Coastguard Worker }
413*c8dee2aaSAndroid Build Coastguard Worker 
didConcat44(const SkM44 & m)414*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::didConcat44(const SkM44& m) {
415*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new Concat44Command(m));
416*c8dee2aaSAndroid Build Coastguard Worker     this->INHERITED::didConcat44(m);
417*c8dee2aaSAndroid Build Coastguard Worker }
418*c8dee2aaSAndroid Build Coastguard Worker 
didScale(SkScalar x,SkScalar y)419*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::didScale(SkScalar x, SkScalar y) {
420*c8dee2aaSAndroid Build Coastguard Worker     this->didConcat44(SkM44::Scale(x, y));
421*c8dee2aaSAndroid Build Coastguard Worker }
422*c8dee2aaSAndroid Build Coastguard Worker 
didTranslate(SkScalar x,SkScalar y)423*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::didTranslate(SkScalar x, SkScalar y) {
424*c8dee2aaSAndroid Build Coastguard Worker     this->didConcat44(SkM44::Translate(x, y));
425*c8dee2aaSAndroid Build Coastguard Worker }
426*c8dee2aaSAndroid Build Coastguard Worker 
onDrawAnnotation(const SkRect & rect,const char key[],SkData * value)427*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
428*c8dee2aaSAndroid Build Coastguard Worker     // Parse layer-releated annotations added in SkiaPipeline.cpp and RenderNodeDrawable.cpp
429*c8dee2aaSAndroid Build Coastguard Worker     // the format of the annotations is <Indicator|RenderNodeId>
430*c8dee2aaSAndroid Build Coastguard Worker     TArray<SkString> tokens;
431*c8dee2aaSAndroid Build Coastguard Worker     SkStrSplit(key, "|", kStrict_SkStrSplitMode, &tokens);
432*c8dee2aaSAndroid Build Coastguard Worker     if (tokens.size() == 2) {
433*c8dee2aaSAndroid Build Coastguard Worker         if (tokens[0].equals(kOffscreenLayerDraw)) {
434*c8dee2aaSAndroid Build Coastguard Worker             // Indicates that the next drawPicture command contains the SkPicture to render the
435*c8dee2aaSAndroid Build Coastguard Worker             // node at this id in an offscreen buffer.
436*c8dee2aaSAndroid Build Coastguard Worker             fnextDrawPictureLayerId = std::stoi(tokens[1].c_str());
437*c8dee2aaSAndroid Build Coastguard Worker             fnextDrawPictureDirtyRect = rect.roundOut();
438*c8dee2aaSAndroid Build Coastguard Worker             return; // don't record it
439*c8dee2aaSAndroid Build Coastguard Worker         } else if (tokens[0].equals(kSurfaceID)) {
440*c8dee2aaSAndroid Build Coastguard Worker             // Indicates that the following drawImageRect should draw the offscreen buffer.
441*c8dee2aaSAndroid Build Coastguard Worker             fnextDrawImageRectLayerId = std::stoi(tokens[1].c_str());
442*c8dee2aaSAndroid Build Coastguard Worker             return; // don't record it
443*c8dee2aaSAndroid Build Coastguard Worker         }
444*c8dee2aaSAndroid Build Coastguard Worker     }
445*c8dee2aaSAndroid Build Coastguard Worker     if (strcmp(kAndroidClip, key) == 0) {
446*c8dee2aaSAndroid Build Coastguard Worker         // Store this frame's android device clip restriction for visualization later.
447*c8dee2aaSAndroid Build Coastguard Worker         // This annotation stands in place of the androidFramework_setDeviceClipRestriction
448*c8dee2aaSAndroid Build Coastguard Worker         // which is unrecordable.
449*c8dee2aaSAndroid Build Coastguard Worker         fAndroidClip = rect;
450*c8dee2aaSAndroid Build Coastguard Worker     }
451*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawAnnotationCommand(rect, key, sk_ref_sp(value)));
452*c8dee2aaSAndroid Build Coastguard Worker }
453*c8dee2aaSAndroid Build Coastguard Worker 
onDrawImage2(const SkImage * image,SkScalar left,SkScalar top,const SkSamplingOptions & sampling,const SkPaint * paint)454*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawImage2(const SkImage*           image,
455*c8dee2aaSAndroid Build Coastguard Worker                                SkScalar                 left,
456*c8dee2aaSAndroid Build Coastguard Worker                                SkScalar                 top,
457*c8dee2aaSAndroid Build Coastguard Worker                                const SkSamplingOptions& sampling,
458*c8dee2aaSAndroid Build Coastguard Worker                                const SkPaint*           paint) {
459*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawImageCommand(image, left, top, sampling, paint));
460*c8dee2aaSAndroid Build Coastguard Worker }
461*c8dee2aaSAndroid Build Coastguard Worker 
onDrawImageLattice2(const SkImage * image,const Lattice & lattice,const SkRect & dst,SkFilterMode filter,const SkPaint * paint)462*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawImageLattice2(const SkImage* image,
463*c8dee2aaSAndroid Build Coastguard Worker                                       const Lattice& lattice,
464*c8dee2aaSAndroid Build Coastguard Worker                                       const SkRect&  dst,
465*c8dee2aaSAndroid Build Coastguard Worker                                       SkFilterMode filter,   // todo
466*c8dee2aaSAndroid Build Coastguard Worker                                       const SkPaint* paint) {
467*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawImageLatticeCommand(image, lattice, dst, filter, paint));
468*c8dee2aaSAndroid Build Coastguard Worker }
469*c8dee2aaSAndroid Build Coastguard Worker 
onDrawImageRect2(const SkImage * image,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SrcRectConstraint constraint)470*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawImageRect2(const SkImage*           image,
471*c8dee2aaSAndroid Build Coastguard Worker                                    const SkRect&            src,
472*c8dee2aaSAndroid Build Coastguard Worker                                    const SkRect&            dst,
473*c8dee2aaSAndroid Build Coastguard Worker                                    const SkSamplingOptions& sampling,
474*c8dee2aaSAndroid Build Coastguard Worker                                    const SkPaint*           paint,
475*c8dee2aaSAndroid Build Coastguard Worker                                    SrcRectConstraint        constraint) {
476*c8dee2aaSAndroid Build Coastguard Worker     if (fnextDrawImageRectLayerId != -1 && fLayerManager) {
477*c8dee2aaSAndroid Build Coastguard Worker         // This drawImageRect command would have drawn the offscreen buffer for a layer.
478*c8dee2aaSAndroid Build Coastguard Worker         // On Android, we recorded an SkPicture of the commands that drew to the layer.
479*c8dee2aaSAndroid Build Coastguard Worker         // To render the layer as it would have looked on the frame this DebugCanvas draws, we need
480*c8dee2aaSAndroid Build Coastguard Worker         // to call fLayerManager->getLayerAsImage(id). This must be done just before
481*c8dee2aaSAndroid Build Coastguard Worker         // drawTo(command), since it depends on the index into the layer's commands
482*c8dee2aaSAndroid Build Coastguard Worker         // (managed by fLayerManager)
483*c8dee2aaSAndroid Build Coastguard Worker         // Instead of adding a DrawImageRectCommand, we need a deferred command, that when
484*c8dee2aaSAndroid Build Coastguard Worker         // executed, will call drawImageRect(fLayerManager->getLayerAsImage())
485*c8dee2aaSAndroid Build Coastguard Worker         this->addDrawCommand(new DrawImageRectLayerCommand(
486*c8dee2aaSAndroid Build Coastguard Worker             fLayerManager, fnextDrawImageRectLayerId, fFrame, src, dst, sampling,
487*c8dee2aaSAndroid Build Coastguard Worker                                                            paint, constraint));
488*c8dee2aaSAndroid Build Coastguard Worker     } else {
489*c8dee2aaSAndroid Build Coastguard Worker         this->addDrawCommand(new DrawImageRectCommand(image, src, dst, sampling, paint, constraint));
490*c8dee2aaSAndroid Build Coastguard Worker     }
491*c8dee2aaSAndroid Build Coastguard Worker     // Reset expectation so next drawImageRect is not special.
492*c8dee2aaSAndroid Build Coastguard Worker     fnextDrawImageRectLayerId = -1;
493*c8dee2aaSAndroid Build Coastguard Worker }
494*c8dee2aaSAndroid Build Coastguard Worker 
onDrawOval(const SkRect & oval,const SkPaint & paint)495*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
496*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawOvalCommand(oval, paint));
497*c8dee2aaSAndroid Build Coastguard Worker }
498*c8dee2aaSAndroid Build Coastguard Worker 
onDrawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)499*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawArc(const SkRect&  oval,
500*c8dee2aaSAndroid Build Coastguard Worker                             SkScalar       startAngle,
501*c8dee2aaSAndroid Build Coastguard Worker                             SkScalar       sweepAngle,
502*c8dee2aaSAndroid Build Coastguard Worker                             bool           useCenter,
503*c8dee2aaSAndroid Build Coastguard Worker                             const SkPaint& paint) {
504*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawArcCommand(oval, startAngle, sweepAngle, useCenter, paint));
505*c8dee2aaSAndroid Build Coastguard Worker }
506*c8dee2aaSAndroid Build Coastguard Worker 
onDrawPaint(const SkPaint & paint)507*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawPaint(const SkPaint& paint) {
508*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawPaintCommand(paint));
509*c8dee2aaSAndroid Build Coastguard Worker }
510*c8dee2aaSAndroid Build Coastguard Worker 
onDrawBehind(const SkPaint & paint)511*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawBehind(const SkPaint& paint) {
512*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawBehindCommand(paint));
513*c8dee2aaSAndroid Build Coastguard Worker }
514*c8dee2aaSAndroid Build Coastguard Worker 
onDrawPath(const SkPath & path,const SkPaint & paint)515*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
516*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawPathCommand(path, paint));
517*c8dee2aaSAndroid Build Coastguard Worker }
518*c8dee2aaSAndroid Build Coastguard Worker 
onDrawRegion(const SkRegion & region,const SkPaint & paint)519*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
520*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawRegionCommand(region, paint));
521*c8dee2aaSAndroid Build Coastguard Worker }
522*c8dee2aaSAndroid Build Coastguard Worker 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)523*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawPicture(const SkPicture* picture,
524*c8dee2aaSAndroid Build Coastguard Worker                                 const SkMatrix*  matrix,
525*c8dee2aaSAndroid Build Coastguard Worker                                 const SkPaint*   paint) {
526*c8dee2aaSAndroid Build Coastguard Worker     if (fnextDrawPictureLayerId != -1 && fLayerManager) {
527*c8dee2aaSAndroid Build Coastguard Worker         fLayerManager->storeSkPicture(fnextDrawPictureLayerId, fFrame, sk_ref_sp(picture),
528*c8dee2aaSAndroid Build Coastguard Worker            fnextDrawPictureDirtyRect);
529*c8dee2aaSAndroid Build Coastguard Worker     } else {
530*c8dee2aaSAndroid Build Coastguard Worker         this->addDrawCommand(new BeginDrawPictureCommand(picture, matrix, paint));
531*c8dee2aaSAndroid Build Coastguard Worker         SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
532*c8dee2aaSAndroid Build Coastguard Worker         picture->playback(this);
533*c8dee2aaSAndroid Build Coastguard Worker         this->addDrawCommand(new EndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint)));
534*c8dee2aaSAndroid Build Coastguard Worker     }
535*c8dee2aaSAndroid Build Coastguard Worker     fnextDrawPictureLayerId = -1;
536*c8dee2aaSAndroid Build Coastguard Worker }
537*c8dee2aaSAndroid Build Coastguard Worker 
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)538*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawPoints(PointMode      mode,
539*c8dee2aaSAndroid Build Coastguard Worker                                size_t         count,
540*c8dee2aaSAndroid Build Coastguard Worker                                const SkPoint  pts[],
541*c8dee2aaSAndroid Build Coastguard Worker                                const SkPaint& paint) {
542*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawPointsCommand(mode, count, pts, paint));
543*c8dee2aaSAndroid Build Coastguard Worker }
544*c8dee2aaSAndroid Build Coastguard Worker 
onDrawRect(const SkRect & rect,const SkPaint & paint)545*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
546*c8dee2aaSAndroid Build Coastguard Worker     // NOTE(chudy): Messing up when renamed to DrawRect... Why?
547*c8dee2aaSAndroid Build Coastguard Worker     addDrawCommand(new DrawRectCommand(rect, paint));
548*c8dee2aaSAndroid Build Coastguard Worker }
549*c8dee2aaSAndroid Build Coastguard Worker 
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)550*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
551*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawRRectCommand(rrect, paint));
552*c8dee2aaSAndroid Build Coastguard Worker }
553*c8dee2aaSAndroid Build Coastguard Worker 
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)554*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
555*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawDRRectCommand(outer, inner, paint));
556*c8dee2aaSAndroid Build Coastguard Worker }
557*c8dee2aaSAndroid Build Coastguard Worker 
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)558*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawTextBlob(const SkTextBlob* blob,
559*c8dee2aaSAndroid Build Coastguard Worker                                  SkScalar          x,
560*c8dee2aaSAndroid Build Coastguard Worker                                  SkScalar          y,
561*c8dee2aaSAndroid Build Coastguard Worker                                  const SkPaint&    paint) {
562*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(
563*c8dee2aaSAndroid Build Coastguard Worker             new DrawTextBlobCommand(sk_ref_sp(const_cast<SkTextBlob*>(blob)), x, y, paint));
564*c8dee2aaSAndroid Build Coastguard Worker }
565*c8dee2aaSAndroid Build Coastguard Worker 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)566*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawPatch(const SkPoint  cubics[12],
567*c8dee2aaSAndroid Build Coastguard Worker                               const SkColor  colors[4],
568*c8dee2aaSAndroid Build Coastguard Worker                               const SkPoint  texCoords[4],
569*c8dee2aaSAndroid Build Coastguard Worker                               SkBlendMode    bmode,
570*c8dee2aaSAndroid Build Coastguard Worker                               const SkPaint& paint) {
571*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawPatchCommand(cubics, colors, texCoords, bmode, paint));
572*c8dee2aaSAndroid Build Coastguard Worker }
573*c8dee2aaSAndroid Build Coastguard Worker 
onDrawVerticesObject(const SkVertices * vertices,SkBlendMode bmode,const SkPaint & paint)574*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawVerticesObject(const SkVertices*      vertices,
575*c8dee2aaSAndroid Build Coastguard Worker                                        SkBlendMode            bmode,
576*c8dee2aaSAndroid Build Coastguard Worker                                        const SkPaint&         paint) {
577*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(
578*c8dee2aaSAndroid Build Coastguard Worker             new DrawVerticesCommand(sk_ref_sp(const_cast<SkVertices*>(vertices)), bmode, paint));
579*c8dee2aaSAndroid Build Coastguard Worker }
580*c8dee2aaSAndroid Build Coastguard Worker 
onDrawAtlas2(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkSamplingOptions & sampling,const SkRect * cull,const SkPaint * paint)581*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawAtlas2(const SkImage*           image,
582*c8dee2aaSAndroid Build Coastguard Worker                                const SkRSXform          xform[],
583*c8dee2aaSAndroid Build Coastguard Worker                                const SkRect             tex[],
584*c8dee2aaSAndroid Build Coastguard Worker                                const SkColor            colors[],
585*c8dee2aaSAndroid Build Coastguard Worker                                int                      count,
586*c8dee2aaSAndroid Build Coastguard Worker                                SkBlendMode              bmode,
587*c8dee2aaSAndroid Build Coastguard Worker                                const SkSamplingOptions& sampling,
588*c8dee2aaSAndroid Build Coastguard Worker                                const SkRect*            cull,
589*c8dee2aaSAndroid Build Coastguard Worker                                const SkPaint*           paint) {
590*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(
591*c8dee2aaSAndroid Build Coastguard Worker             new DrawAtlasCommand(image, xform, tex, colors, count, bmode, sampling, cull, paint));
592*c8dee2aaSAndroid Build Coastguard Worker }
593*c8dee2aaSAndroid Build Coastguard Worker 
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)594*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
595*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawShadowCommand(path, rec));
596*c8dee2aaSAndroid Build Coastguard Worker }
597*c8dee2aaSAndroid Build Coastguard Worker 
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)598*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
599*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawDrawableCommand(drawable, matrix));
600*c8dee2aaSAndroid Build Coastguard Worker }
601*c8dee2aaSAndroid Build Coastguard Worker 
onDrawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)602*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawEdgeAAQuad(const SkRect&    rect,
603*c8dee2aaSAndroid Build Coastguard Worker                                    const SkPoint    clip[4],
604*c8dee2aaSAndroid Build Coastguard Worker                                    QuadAAFlags      aa,
605*c8dee2aaSAndroid Build Coastguard Worker                                    const SkColor4f& color,
606*c8dee2aaSAndroid Build Coastguard Worker                                    SkBlendMode      mode) {
607*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawEdgeAAQuadCommand(rect, clip, aa, color, mode));
608*c8dee2aaSAndroid Build Coastguard Worker }
609*c8dee2aaSAndroid Build Coastguard Worker 
onDrawEdgeAAImageSet2(const ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkSamplingOptions & sampling,const SkPaint * paint,SrcRectConstraint constraint)610*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry set[],
611*c8dee2aaSAndroid Build Coastguard Worker                                         int                 count,
612*c8dee2aaSAndroid Build Coastguard Worker                                         const SkPoint       dstClips[],
613*c8dee2aaSAndroid Build Coastguard Worker                                         const SkMatrix      preViewMatrices[],
614*c8dee2aaSAndroid Build Coastguard Worker                                         const SkSamplingOptions& sampling,
615*c8dee2aaSAndroid Build Coastguard Worker                                         const SkPaint*      paint,
616*c8dee2aaSAndroid Build Coastguard Worker                                         SrcRectConstraint   constraint) {
617*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new DrawEdgeAAImageSetCommand(
618*c8dee2aaSAndroid Build Coastguard Worker             set, count, dstClips, preViewMatrices, sampling, paint, constraint));
619*c8dee2aaSAndroid Build Coastguard Worker }
620*c8dee2aaSAndroid Build Coastguard Worker 
willRestore()621*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::willRestore() {
622*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new RestoreCommand());
623*c8dee2aaSAndroid Build Coastguard Worker     this->INHERITED::willRestore();
624*c8dee2aaSAndroid Build Coastguard Worker }
625*c8dee2aaSAndroid Build Coastguard Worker 
willSave()626*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::willSave() {
627*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new SaveCommand());
628*c8dee2aaSAndroid Build Coastguard Worker     this->INHERITED::willSave();
629*c8dee2aaSAndroid Build Coastguard Worker }
630*c8dee2aaSAndroid Build Coastguard Worker 
getSaveLayerStrategy(const SaveLayerRec & rec)631*c8dee2aaSAndroid Build Coastguard Worker SkCanvas::SaveLayerStrategy DebugCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
632*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new SaveLayerCommand(rec));
633*c8dee2aaSAndroid Build Coastguard Worker     (void)this->INHERITED::getSaveLayerStrategy(rec);
634*c8dee2aaSAndroid Build Coastguard Worker     // No need for a full layer.
635*c8dee2aaSAndroid Build Coastguard Worker     return kNoLayer_SaveLayerStrategy;
636*c8dee2aaSAndroid Build Coastguard Worker }
637*c8dee2aaSAndroid Build Coastguard Worker 
onDoSaveBehind(const SkRect * subset)638*c8dee2aaSAndroid Build Coastguard Worker bool DebugCanvas::onDoSaveBehind(const SkRect* subset) {
639*c8dee2aaSAndroid Build Coastguard Worker     // TODO
640*c8dee2aaSAndroid Build Coastguard Worker     return false;
641*c8dee2aaSAndroid Build Coastguard Worker }
642*c8dee2aaSAndroid Build Coastguard Worker 
didSetM44(const SkM44 & matrix)643*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::didSetM44(const SkM44& matrix) {
644*c8dee2aaSAndroid Build Coastguard Worker     this->addDrawCommand(new SetM44Command(matrix));
645*c8dee2aaSAndroid Build Coastguard Worker     this->INHERITED::didSetM44(matrix);
646*c8dee2aaSAndroid Build Coastguard Worker }
647*c8dee2aaSAndroid Build Coastguard Worker 
toggleCommand(int index,bool toggle)648*c8dee2aaSAndroid Build Coastguard Worker void DebugCanvas::toggleCommand(int index, bool toggle) {
649*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(index < fCommandVector.size());
650*c8dee2aaSAndroid Build Coastguard Worker     fCommandVector[index]->setVisible(toggle);
651*c8dee2aaSAndroid Build Coastguard Worker }
652*c8dee2aaSAndroid Build Coastguard Worker 
getImageIdToCommandMap(UrlDataManager & udm) const653*c8dee2aaSAndroid Build Coastguard Worker std::map<int, std::vector<int>> DebugCanvas::getImageIdToCommandMap(UrlDataManager& udm) const {
654*c8dee2aaSAndroid Build Coastguard Worker     // map from image ids to list of commands that reference them.
655*c8dee2aaSAndroid Build Coastguard Worker     std::map<int, std::vector<int>> m;
656*c8dee2aaSAndroid Build Coastguard Worker 
657*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < this->getSize(); i++) {
658*c8dee2aaSAndroid Build Coastguard Worker         const DrawCommand* command = this->getDrawCommandAt(i);
659*c8dee2aaSAndroid Build Coastguard Worker         int imageIndex = -1;
660*c8dee2aaSAndroid Build Coastguard Worker         // this is not an exaustive list of where images can be used, they show up in paints too.
661*c8dee2aaSAndroid Build Coastguard Worker         switch (command->getOpType()) {
662*c8dee2aaSAndroid Build Coastguard Worker             case DrawCommand::OpType::kDrawImage_OpType: {
663*c8dee2aaSAndroid Build Coastguard Worker                 imageIndex = static_cast<const DrawImageCommand*>(command)->imageId(udm);
664*c8dee2aaSAndroid Build Coastguard Worker                 break;
665*c8dee2aaSAndroid Build Coastguard Worker             }
666*c8dee2aaSAndroid Build Coastguard Worker             case DrawCommand::OpType::kDrawImageRect_OpType: {
667*c8dee2aaSAndroid Build Coastguard Worker                 imageIndex = static_cast<const DrawImageRectCommand*>(command)->imageId(udm);
668*c8dee2aaSAndroid Build Coastguard Worker                 break;
669*c8dee2aaSAndroid Build Coastguard Worker             }
670*c8dee2aaSAndroid Build Coastguard Worker             case DrawCommand::OpType::kDrawImageLattice_OpType: {
671*c8dee2aaSAndroid Build Coastguard Worker                 imageIndex = static_cast<const DrawImageLatticeCommand*>(command)->imageId(udm);
672*c8dee2aaSAndroid Build Coastguard Worker                 break;
673*c8dee2aaSAndroid Build Coastguard Worker             }
674*c8dee2aaSAndroid Build Coastguard Worker             default: break;
675*c8dee2aaSAndroid Build Coastguard Worker         }
676*c8dee2aaSAndroid Build Coastguard Worker         if (imageIndex >= 0) {
677*c8dee2aaSAndroid Build Coastguard Worker             m[imageIndex].push_back(i);
678*c8dee2aaSAndroid Build Coastguard Worker         }
679*c8dee2aaSAndroid Build Coastguard Worker     }
680*c8dee2aaSAndroid Build Coastguard Worker     return m;
681*c8dee2aaSAndroid Build Coastguard Worker }
682