1 /* 2 * Copyright 2017 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 SkDeferredDisplayListRecorder_DEFINED 9 #define SkDeferredDisplayListRecorder_DEFINED 10 11 #include "../private/SkDeferredDisplayList.h" 12 #include "SkImageInfo.h" 13 #include "SkRefCnt.h" 14 #include "SkSurfaceCharacterization.h" 15 #include "SkTypes.h" 16 17 class GrBackendFormat; 18 class GrBackendTexture; 19 class GrContext; 20 class SkCanvas; 21 class SkImage; 22 class SkPromiseImageTexture; 23 class SkSurface; 24 struct SkYUVAIndex; 25 struct SkYUVASizeInfo; 26 27 /* 28 * This class is intended to be used as: 29 * Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface 30 * Create one of these (an SkDDLMaker) on the stack 31 * Get the canvas and render into it 32 * Snap off and hold on to an SkDeferredDisplayList 33 * Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*) 34 * 35 * This class never accesses the GPU but performs all the cpu work it can. It 36 * is thread-safe (i.e., one can break a scene into tiles and perform their cpu-side 37 * work in parallel ahead of time). 38 */ 39 class SK_API SkDeferredDisplayListRecorder { 40 public: 41 SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&); 42 ~SkDeferredDisplayListRecorder(); 43 44 const SkSurfaceCharacterization& characterization() const { 45 return fCharacterization; 46 } 47 48 // The backing canvas will become invalid (and this entry point will return 49 // null) once 'detach' is called. 50 // Note: ownership of the SkCanvas is not transferred via this call. 51 SkCanvas* getCanvas(); 52 53 std::unique_ptr<SkDeferredDisplayList> detach(); 54 55 using PromiseImageTextureContext = void*; 56 using PromiseImageTextureFulfillProc = 57 sk_sp<SkPromiseImageTexture> (*)(PromiseImageTextureContext); 58 using PromiseImageTextureReleaseProc = void (*)(PromiseImageTextureContext); 59 using PromiseImageTextureDoneProc = void (*)(PromiseImageTextureContext); 60 61 // Deprecated types. To be removed. 62 using LegacyPromiseImageTextureFulfillProc = void (*)(PromiseImageTextureContext, 63 GrBackendTexture*); 64 using TextureContext = PromiseImageTextureContext; 65 66 enum class DelayReleaseCallback : bool { kNo = false, kYes = true }; 67 68 /** 69 Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The main 70 difference is that the client doesn't have the backend texture on the gpu yet but they know 71 all the properties of the texture. So instead of passing in a GrBackendTexture the client 72 supplies a GrBackendFormat, width, height, and GrMipMapped state. 73 74 When we actually send the draw calls to the GPU, we will call the textureFulfillProc and 75 the client will return a GrBackendTexture to us. The properties of the GrBackendTexture must 76 match those set during the SkImage creation, and it must have a valid backend gpu texture. 77 The gpu texture supplied by the client must stay valid until we call the textureReleaseProc. 78 79 The following applies when DelayReleaseCallback is kNo: 80 When we are done with the texture returned by the textureFulfillProc we will call the 81 textureReleaseProc passing in the textureContext. This is a signal to the client that 82 they are free to delete the underlying gpu texture. If future draws also use the same 83 promise image we will call the textureFulfillProc again if we've already called the 84 textureReleaseProc. We will always call textureFulfillProc and textureReleaseProc in 85 pairs. In other words we will never call textureFulfillProc or textureReleaseProc 86 multiple times for the same textureContext before calling the other. 87 88 We call the textureDoneProc when we will no longer call the textureFulfillProc again. We 89 pass in the textureContext as a parameter to the textureDoneProc. We also guarantee that 90 there will be no outstanding textureReleaseProcs that still need to be called when we 91 call the textureDoneProc. Thus when the textureDoneProc gets called the client is able 92 to cleanup all GPU objects and meta data needed for the textureFulfill call. 93 94 When delayReleaseCallback is kYes: 95 When all the following are true: 96 * the promise image is deleted, 97 * any SkDeferredDisplayLists that recorded draws referencing the image are deleted, 98 * and the texture is safe to delete in the underlying API with respect to drawn 99 SkDeferredDisplayLists that reference the image 100 the textureReleaseProc and then textureDoneProc are called. The texture can be deleted 101 by the client as soon as textureReleaseProc is called. In this mode there is only one 102 call to each of textureFulfillProc, textureReleaseProc, and textureDoneProc. 103 104 105 This call is only valid if the SkDeferredDisplayListRecorder is backed by a gpu context. 106 107 @param backendFormat format of promised gpu texture 108 @param width width of promised gpu texture 109 @param height height of promised gpu texture 110 @param mipMapped mip mapped state of promised gpu texture 111 @param origin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin 112 @param colorType one of: kUnknown_SkColorType, kAlpha_8_SkColorType, 113 kRGB_565_SkColorType, kARGB_4444_SkColorType, 114 kRGBA_8888_SkColorType, kBGRA_8888_SkColorType, 115 kGray_8_SkColorType, kRGBA_F16_SkColorType 116 @param alphaType one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType, 117 kPremul_SkAlphaType, kUnpremul_SkAlphaType 118 @param colorSpace range of colors; may be nullptr 119 @param textureFulfillProc function called to get actual gpu texture 120 @param textureReleaseProc function called when texture can be released 121 @param promiseDoneProc function called when we will no longer call textureFulfillProc 122 @param textureContext state passed to textureFulfillProc and textureReleaseProc 123 @return created SkImage, or nullptr 124 */ 125 sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat, 126 int width, 127 int height, 128 GrMipMapped mipMapped, 129 GrSurfaceOrigin origin, 130 SkColorType colorType, 131 SkAlphaType alphaType, 132 sk_sp<SkColorSpace> colorSpace, 133 PromiseImageTextureFulfillProc textureFulfillProc, 134 PromiseImageTextureReleaseProc textureReleaseProc, 135 PromiseImageTextureDoneProc textureDoneProc, 136 PromiseImageTextureContext textureContext, 137 DelayReleaseCallback delayReleaseCallback); 138 139 /** Deprecated version that assumes DelayReleaseCallback::kNo. */ 140 sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat, 141 int width, 142 int height, 143 GrMipMapped mipMapped, 144 GrSurfaceOrigin origin, 145 SkColorType colorType, 146 SkAlphaType alphaType, 147 sk_sp<SkColorSpace> colorSpace, 148 PromiseImageTextureFulfillProc textureFulfillProc, 149 PromiseImageTextureReleaseProc textureReleaseProc, 150 PromiseImageTextureDoneProc textureDoneProc, 151 PromiseImageTextureContext textureContext) { 152 return this->makePromiseTexture(backendFormat, width, height, mipMapped, origin, colorType, 153 alphaType, colorSpace, textureFulfillProc, 154 textureReleaseProc, textureDoneProc, textureContext, 155 DelayReleaseCallback::kNo); 156 } 157 158 /** 159 This entry point operates the same as 'makePromiseTexture' except that its 160 textureFulfillProc can be called up to four times to fetch the required YUVA 161 planes (passing a different textureContext to each call). So, if the 'yuvaIndices' 162 indicate that only the first two backend textures are used, 'textureFulfillProc' will 163 be called with the first two 'textureContexts'. 164 */ 165 sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace, 166 const GrBackendFormat yuvaFormats[], 167 const SkISize yuvaSizes[], 168 const SkYUVAIndex yuvaIndices[4], 169 int imageWidth, 170 int imageHeight, 171 GrSurfaceOrigin imageOrigin, 172 sk_sp<SkColorSpace> imageColorSpace, 173 PromiseImageTextureFulfillProc textureFulfillProc, 174 PromiseImageTextureReleaseProc textureReleaseProc, 175 PromiseImageTextureDoneProc textureDoneProc, 176 PromiseImageTextureContext textureContexts[], 177 DelayReleaseCallback delayReleaseCallback); 178 179 /** Deprecated version that assumes DelayReleaseCallback::kNo. */ 180 sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace, 181 const GrBackendFormat yuvaFormats[], 182 const SkISize yuvaSizes[], 183 const SkYUVAIndex yuvaIndices[4], 184 int imageWidth, 185 int imageHeight, 186 GrSurfaceOrigin imageOrigin, 187 sk_sp<SkColorSpace> imageColorSpace, 188 PromiseImageTextureFulfillProc textureFulfillProc, 189 PromiseImageTextureReleaseProc textureReleaseProc, 190 PromiseImageTextureDoneProc textureDoneProc, 191 PromiseImageTextureContext textureContexts[]) { 192 return this->makeYUVAPromiseTexture( 193 yuvColorSpace, yuvaFormats, yuvaSizes, yuvaIndices, imageWidth, imageHeight, 194 imageOrigin, std::move(imageColorSpace), textureFulfillProc, textureReleaseProc, 195 textureDoneProc, textureContexts, DelayReleaseCallback::kNo); 196 } 197 198 private: 199 bool init(); 200 201 const SkSurfaceCharacterization fCharacterization; 202 203 #if SK_SUPPORT_GPU 204 sk_sp<GrContext> fContext; 205 sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData; 206 sk_sp<SkSurface> fSurface; 207 #endif 208 }; 209 210 #endif 211