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 "include/core/SkImageInfo.h" 12 #include "include/core/SkRefCnt.h" 13 #include "include/core/SkSurfaceCharacterization.h" 14 #include "include/core/SkTypes.h" 15 #include "include/private/SkDeferredDisplayList.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 characterization()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 enum class PromiseImageApiVersion { kLegacy, kNew }; 62 63 /** 64 Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The 65 difference is that the caller need not have created the texture nor populated it with the 66 image pixel data. Moreover, the SkImage may be created on a thread as the creation of the 67 image does not require access to the backend API or GrContext. Instead of passing a 68 GrBackendTexture the client supplies a description of the texture consisting of 69 GrBackendFormat, width, height, and GrMipMapped state. The resulting SkImage can be drawn 70 to a SkDeferredDisplayListRecorder or directly to a GPU-backed SkSurface. 71 72 When the actual texture is required to perform a backend API draw, textureFulfillProc will 73 be called to receive a GrBackendTexture. The properties of the GrBackendTexture must match 74 those set during the SkImage creation, and it must refer to a valid existing texture in the 75 backend API context/device, and be populated with the image pixel data. The texture contents 76 cannot be modified until textureReleaseProc is called. The texture cannot be deleted until 77 textureDoneProc is called. 78 79 When all the following are true: 80 * the promise SkImage is deleted, 81 * any SkDeferredDisplayLists that recorded draws referencing the image are deleted, 82 * and all draws referencing the texture have been flushed (via GrContext::flush or 83 SkSurface::flush) 84 the textureReleaseProc is called. When the following additional constraint is met 85 * the texture is safe to delete in the underlying API 86 the textureDoneProc is called. For some APIs (e.g. GL) the two states are equivalent. 87 However, for others (e.g. Vulkan) they are not as it is not legal to delete a texture until 88 the GPU work referencing it has completed. 89 90 There is at most one call to each of textureFulfillProc, textureReleaseProc, and 91 textureDoneProc. textureDoneProc is always called even if image creation fails or if the 92 image is never fulfilled (e.g. it is never drawn or all draws are clipped out). If 93 textureFulfillProc is called then textureReleaseProc will always be called even if 94 textureFulfillProc failed. 95 96 If 'version' is set to kLegacy then the textureReleaseProc call is delayed until the 97 conditions for textureDoneProc are met and then they are both called. 98 99 This call is only valid if the SkDeferredDisplayListRecorder is backed by a GPU context. 100 101 @param backendFormat format of promised gpu texture 102 @param width width of promised gpu texture 103 @param height height of promised gpu texture 104 @param mipMapped mip mapped state of promised gpu texture 105 @param origin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin 106 @param colorType one of: kUnknown_SkColorType, kAlpha_8_SkColorType, 107 kRGB_565_SkColorType, kARGB_4444_SkColorType, 108 kRGBA_8888_SkColorType, kBGRA_8888_SkColorType, 109 kGray_8_SkColorType, kRGBA_F16_SkColorType 110 @param alphaType one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType, 111 kPremul_SkAlphaType, kUnpremul_SkAlphaType 112 @param colorSpace range of colors; may be nullptr 113 @param textureFulfillProc function called to get actual gpu texture 114 @param textureReleaseProc function called when texture can be released 115 @param textureDoneProc function called when we will no longer call textureFulfillProc 116 @param textureContext state passed to textureFulfillProc and textureReleaseProc 117 @param version controls when textureReleaseProc is called 118 @return created SkImage, or nullptr 119 */ 120 sk_sp<SkImage> makePromiseTexture( 121 const GrBackendFormat& backendFormat, 122 int width, 123 int height, 124 GrMipMapped mipMapped, 125 GrSurfaceOrigin origin, 126 SkColorType colorType, 127 SkAlphaType alphaType, 128 sk_sp<SkColorSpace> colorSpace, 129 PromiseImageTextureFulfillProc textureFulfillProc, 130 PromiseImageTextureReleaseProc textureReleaseProc, 131 PromiseImageTextureDoneProc textureDoneProc, 132 PromiseImageTextureContext textureContext, 133 PromiseImageApiVersion version = PromiseImageApiVersion::kLegacy); 134 135 /** 136 This entry point operates like 'makePromiseTexture' but it is used to construct a SkImage 137 from YUV[A] data. The source data may be planar (i.e. spread across multiple textures). In 138 the extreme Y, U, V, and A are all in different planes and thus the image is specified by 139 four textures. 'yuvaIndices' specifies the mapping from texture color channels to Y, U, V, 140 and possibly A components. It therefore indicates how many unique textures compose the full 141 image. Separate textureFulfillProc, textureReleaseProc, and textureDoneProc calls are made 142 for each texture and each texture has its own PromiseImageTextureContext. 'yuvFormats', 143 'yuvaSizes', and 'textureContexts' have one entry for each of the up to four textures, as 144 indicated by 'yuvaIndices'. 145 */ 146 sk_sp<SkImage> makeYUVAPromiseTexture( 147 SkYUVColorSpace yuvColorSpace, 148 const GrBackendFormat yuvaFormats[], 149 const SkISize yuvaSizes[], 150 const SkYUVAIndex yuvaIndices[4], 151 int imageWidth, 152 int imageHeight, 153 GrSurfaceOrigin imageOrigin, 154 sk_sp<SkColorSpace> imageColorSpace, 155 PromiseImageTextureFulfillProc textureFulfillProc, 156 PromiseImageTextureReleaseProc textureReleaseProc, 157 PromiseImageTextureDoneProc textureDoneProc, 158 PromiseImageTextureContext textureContexts[], 159 PromiseImageApiVersion version = PromiseImageApiVersion::kLegacy); 160 161 private: 162 bool init(); 163 164 const SkSurfaceCharacterization fCharacterization; 165 166 #if SK_SUPPORT_GPU 167 sk_sp<GrContext> fContext; 168 sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData; 169 sk_sp<SkSurface> fSurface; 170 #endif 171 }; 172 173 #endif 174