xref: /aosp_15_r20/external/skia/tools/DDLTileHelper.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2018 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 #ifndef DDLTileHelper_DEFINED
9 #define DDLTileHelper_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkSpan.h"
14 #include "include/private/base/SkTemplates.h"
15 #include "include/private/chromium/GrDeferredDisplayList.h"
16 #include "include/private/chromium/GrSurfaceCharacterization.h"
17 
18 class DDLPromiseImageHelper;
19 class PromiseImageCallbackContext;
20 class SkCanvas;
21 class SkData;
22 class GrDeferredDisplayListRecorder;
23 class SkImage;
24 class SkPicture;
25 class SkSurface;
26 class GrSurfaceCharacterization;
27 class SkTaskGroup;
28 
29 class DDLTileHelper {
30 public:
31     // The TileData class encapsulates the information and behavior of a single tile when
32     // rendering with DDLs.
33     class TileData {
34     public:
35         TileData();
36         ~TileData();
37 
initialized()38         bool initialized() const { return fID != -1; }
39 
40         void init(int id,
41                   GrDirectContext*,
42                   const GrSurfaceCharacterization& dstChar,
43                   const SkIRect& clip,
44                   const SkIRect& paddingOutsets);
45 
46         // Create the DDL for this tile (i.e., fill in 'fDisplayList').
47         void createDDL(const SkPicture*);
48 
dropDDL()49         void dropDDL() { fDisplayList.reset(); }
50 
51         // Precompile all the programs required to draw this tile's DDL
52         void precompile(GrDirectContext*);
53 
54         // Just draw the re-inflated per-tile SKP directly into this tile w/o going through a DDL
55         // first. This is used for determining the overhead of using DDLs (i.e., it replaces
56         // a 'createDDL' and 'draw' pair.
57         void drawSKPDirectly(GrDirectContext*, const SkPicture*);
58 
59         // Replay the recorded DDL into the tile surface - filling in 'fBackendTexture'.
60         void draw(GrDirectContext*);
61 
62         void reset();
63 
id()64         int id() const { return fID; }
clipRect()65         SkIRect clipRect() const { return fClip; }
paddedRectSize()66         SkISize paddedRectSize() const {
67             return { fClip.width() + fPaddingOutsets.fLeft + fPaddingOutsets.fRight,
68                      fClip.height() + fPaddingOutsets.fTop + fPaddingOutsets.fBottom };
69         }
padOffset()70         SkIVector padOffset() const { return { fPaddingOutsets.fLeft, fPaddingOutsets.fTop }; }
71 
ddl()72         GrDeferredDisplayList* ddl() { return fDisplayList.get(); }
73 
74         sk_sp<SkImage> makePromiseImageForDst(sk_sp<GrContextThreadSafeProxy>);
dropCallbackContext()75         void dropCallbackContext() { fCallbackContext.reset(); }
76 
77         static void CreateBackendTexture(GrDirectContext*, TileData*);
78         static void DeleteBackendTexture(GrDirectContext*, TileData*);
79 
80     private:
81         sk_sp<SkSurface> makeWrappedTileDest(GrRecordingContext* context);
82 
refCallbackContext()83         sk_sp<PromiseImageCallbackContext> refCallbackContext() { return fCallbackContext; }
84 
85         int                       fID = -1;
86         SkIRect                   fClip;             // in the device space of the final SkSurface
87         SkIRect                   fPaddingOutsets;   // random padding for the output surface
88         GrSurfaceCharacterization fPlaybackChar;     // characterization for the tile's dst surface
89 
90         // The callback context holds (via its GrPromiseImageTexture) the backend texture
91         // that is both wrapped in 'fTileSurface' and backs this tile's promise image
92         // (i.e., the one returned by 'makePromiseImage').
93         sk_sp<PromiseImageCallbackContext> fCallbackContext;
94         // 'fTileSurface' wraps the backend texture in 'fCallbackContext' and must exist until
95         // after 'fDisplayList' has been flushed (bc it owns the proxy the DDL's destination
96         // trampoline points at).
97         // TODO: fix the ref-order so we don't need 'fTileSurface' here
98         sk_sp<SkSurface>              fTileSurface;
99 
100         sk_sp<GrDeferredDisplayList>  fDisplayList;
101     };
102 
103     DDLTileHelper(GrDirectContext*,
104                   const GrSurfaceCharacterization& dstChar,
105                   const SkIRect& viewport,
106                   int numXDivisions, int numYDivisions,
107                   bool addRandomPaddingToDst);
108 
109     void kickOffThreadedWork(SkTaskGroup* recordingTaskGroup,
110                              SkTaskGroup* gpuTaskGroup,
111                              GrDirectContext*,
112                              SkPicture*);
113 
114     void createDDLsInParallel(SkPicture*);
115 
116     // Create the DDL that will compose all the tile images into a final result.
117     void createComposeDDL();
composeDDL()118     const sk_sp<GrDeferredDisplayList>& composeDDL() const { return fComposeDDL; }
119 
120     // For each tile, create its DDL and then draw it - all on a single thread. This is to allow
121     // comparison w/ just drawing the SKP directly (i.e., drawAllTilesDirectly). The
122     // DDL creations and draws are interleaved to prevent starvation of the GPU.
123     // Note: this is somewhat of a misuse/pessimistic-use of DDLs since they are supposed to
124     // be created on a separate thread.
125     void interleaveDDLCreationAndDraw(GrDirectContext*, SkPicture*);
126 
127     // This draws all the per-tile SKPs directly into all of the tiles w/o converting them to
128     // DDLs first - all on a single thread.
129     void drawAllTilesDirectly(GrDirectContext*, SkPicture*);
130 
131     void dropCallbackContexts();
132     void resetAllTiles();
133 
numTiles()134     int numTiles() const { return fNumXDivisions * fNumYDivisions; }
135 
136     void createBackendTextures(SkTaskGroup*, GrDirectContext*);
137     void deleteBackendTextures(SkTaskGroup*, GrDirectContext*);
138 
139 private:
140     int                                    fNumXDivisions; // number of tiles horizontally
141     int                                    fNumYDivisions; // number of tiles vertically
142     skia_private::AutoTArray<TileData>   fTiles;        // 'fNumXDivisions' x
143     // 'fNumYDivisions'
144 
145     sk_sp<GrDeferredDisplayList>           fComposeDDL;
146 
147     const GrSurfaceCharacterization        fDstCharacterization;
148 };
149 
150 #endif
151