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