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