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