1 /* 2 * Copyright 2023 Google LLC 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 skgpu_graphite_Image_DEFINED 9 #define skgpu_graphite_Image_DEFINED 10 11 #include "include/core/SkColorSpace.h" 12 #include "include/core/SkImage.h" 13 #include "include/core/SkRefCnt.h" 14 #include "include/core/SkSpan.h" 15 #include "include/gpu/GpuTypes.h" 16 17 #include <string_view> 18 19 class SkYUVAInfo; 20 class SkYUVAPixmaps; 21 struct SkIRect; 22 23 namespace skgpu::graphite { 24 class BackendTexture; 25 class Recorder; 26 class TextureInfo; 27 class YUVABackendTextureInfo; 28 class YUVABackendTextures; 29 enum class Volatile : bool; 30 } 31 32 namespace SkImages { 33 enum class GenerateMipmapsFromBase : bool { kNo, kYes }; 34 35 using TextureReleaseProc = void (*)(ReleaseContext); 36 37 // Passed to imageRelease 38 using GraphitePromiseImageContext = void*; 39 // Passed to fulfill; for non-YUVA promise images, the image context is used as the fulfill context, 40 // while YUVA promise images have a per-plane fulfill context. 41 using GraphitePromiseTextureFulfillContext = void*; 42 // Returned from fulfill and passed into textureRelease 43 using GraphitePromiseTextureReleaseContext = void*; 44 45 using GraphitePromiseTextureFulfillProc = 46 std::tuple<skgpu::graphite::BackendTexture, GraphitePromiseTextureReleaseContext> (*)( 47 GraphitePromiseTextureFulfillContext); 48 using GraphitePromiseImageReleaseProc = void (*)(GraphitePromiseImageContext); 49 using GraphitePromiseTextureReleaseProc = void (*)(GraphitePromiseTextureReleaseContext); 50 51 /** Creates an SkImage from a GPU texture associated with the recorder. The client is still 52 responsible for managing the backend texture's lifetime. 53 54 SkImage is returned if the format of backendTexture is recognized and supported. 55 Recognized formats vary by GPU back-end. 56 57 @param recorder The recorder 58 @param backendTexture texture residing on GPU 59 @param colorSpace This describes the color space of this image's contents, as 60 seen after sampling. In general, if the format of the backend 61 texture is SRGB, some linear colorSpace should be supplied 62 (e.g., SkColorSpace::MakeSRGBLinear()). If the format of the 63 backend texture is linear, then the colorSpace should include 64 a description of the transfer function as 65 well (e.g., SkColorSpace::MakeSRGB()). 66 @param origin Whether the Texture logically treats the origin as TopLeft or 67 BottomLeft 68 @param generateMipmapsFromBase If kYes then the pixel contents of the textures upper mipmap 69 levels are generated by successive downsampling of the base 70 level. If the texture is not mipmapped or isn't renderable then 71 image creation will fail. If kNo and the texture is mipmapped 72 then the contents of upper levels are assumed to already be 73 valid. 74 @return created SkImage, or nullptr 75 */ 76 SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, 77 const skgpu::graphite::BackendTexture&, 78 SkColorType colorType, 79 SkAlphaType alphaType, 80 sk_sp<SkColorSpace> colorSpace, 81 skgpu::Origin origin, 82 GenerateMipmapsFromBase generateMipmapsFromBase, 83 TextureReleaseProc = nullptr, 84 ReleaseContext = nullptr, 85 std::string_view label = {}); 86 87 SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, 88 const skgpu::graphite::BackendTexture&, 89 SkColorType colorType, 90 SkAlphaType alphaType, 91 sk_sp<SkColorSpace> colorSpace, 92 skgpu::Origin origin, 93 TextureReleaseProc = nullptr, 94 ReleaseContext = nullptr, 95 std::string_view label = {}); 96 97 SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, 98 const skgpu::graphite::BackendTexture&, 99 SkColorType colorType, 100 SkAlphaType alphaType, 101 sk_sp<SkColorSpace> colorSpace, 102 TextureReleaseProc = nullptr, 103 ReleaseContext = nullptr, 104 std::string_view label = {}); 105 106 /** Create a new SkImage that is very similar to an SkImage created by WrapTexture. The difference 107 is that the caller need not have created the backend texture nor populated it with data when 108 creating the image. Instead of passing a BackendTexture to the factory the client supplies a 109 description of the texture consisting of dimensions, TextureInfo, SkColorInfo and Volatility. 110 111 In general, 'fulfill' must return a BackendTexture that matches the properties provided at 112 SkImage creation time. The BackendTexture must refer to a valid existing texture in the backend 113 API context/device, and already be populated with data. The texture cannot be deleted until 114 'textureRelease' is called. 'textureRelease' will be called with the textureReleaseContext 115 returned by 'fulfill'. 116 117 Wrt when and how often the fulfill, imageRelease, and textureRelease callbacks will be called: 118 119 For non-volatile promise images, 'fulfill' will be called at Context::insertRecording time. 120 Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be called only 121 once - when Skia will no longer try calling 'fulfill' to get a backend texture. If 'fulfill' 122 failed (i.e., it didn't return a valid backend texture) then 'textureRelease' will never be 123 called. If 'fulfill' was successful then 'textureRelease' will be called only once when the GPU 124 is done with the contents of the promise image. This will usually occur during a Context::submit 125 call but it could occur earlier due to error conditions. 'fulfill' can be called multiple times 126 if the promise image is used in multiple recordings. If 'fulfill' fails, the insertRecording 127 itself will fail. Subsequent insertRecording calls (with Recordings that use the promise image) 128 will keep calling 'fulfill' until it succeeds. 129 130 For volatile promise images, 'fulfill' will be called each time the Recording is inserted into a 131 Context. Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be 132 called only once just like the non-volatile case. If 'fulfill' fails at insertRecording-time, 133 'textureRelease' will never be called. If 'fulfill' was successful then a 'textureRelease' 134 matching that 'fulfill' will be called when the GPU is done with the contents of the promise 135 image. This will usually occur during a Context::submit call but it could occur earlier due to 136 error conditions. 137 138 @param recorder the recorder that will capture the commands creating the image 139 @param dimensions width & height of promised gpu texture 140 @param textureInfo structural information for the promised gpu texture 141 @param colorInfo color type, alpha type and colorSpace information for the image 142 @param origin Whether the Texture logically treats the origin as TopLeft or BottomLeft 143 @param isVolatile volatility of the promise image 144 @param fulfill function called to get the actual backend texture, 145 and the instance for the GraphitePromiseTextureReleaseProc 146 @param imageRelease function called when any image-centric data can be deleted 147 @param textureRelease function called when the backend texture can be deleted 148 @param imageContext state passed to fulfill and imageRelease 149 @return created SkImage, or nullptr 150 */ 151 SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, 152 SkISize dimensions, 153 const skgpu::graphite::TextureInfo&, 154 const SkColorInfo&, 155 skgpu::Origin origin, 156 skgpu::graphite::Volatile, 157 GraphitePromiseTextureFulfillProc, 158 GraphitePromiseImageReleaseProc, 159 GraphitePromiseTextureReleaseProc, 160 GraphitePromiseImageContext, 161 std::string_view label = {}); 162 163 SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, 164 SkISize dimensions, 165 const skgpu::graphite::TextureInfo&, 166 const SkColorInfo&, 167 skgpu::graphite::Volatile, 168 GraphitePromiseTextureFulfillProc, 169 GraphitePromiseImageReleaseProc, 170 GraphitePromiseTextureReleaseProc, 171 GraphitePromiseImageContext); 172 173 /** This is similar to 'PromiseTextureFrom' but it creates a GPU-backed SkImage from YUV[A] data. 174 The source data may be planar (i.e. spread across multiple textures). In the extreme Y, U, V, 175 and A are all in different planes and thus the image is specified by four textures. 176 'backendTextureInfo' describes the planar arrangement, texture formats, and conversion to RGB. 177 Separate 'fulfill' and 'textureRelease' calls are made for each texture. Each texture has its 178 own GraphitePromiseFulfillContext. The GraphitePromiseImageReleaseProc will be made even on 179 failure. 'planeContexts' has one entry for each of the up to four textures, as indicated by 180 'backendTextureInfo'. Currently the mipmapped property of 'backendTextureInfo' is ignored. 181 However, in the near future it will be required that if it is kYes then the fulfillProc must 182 return a mip mapped texture for each plane in order to successfully draw the image. 183 184 @param recorder the recorder that will capture the commands creating the image 185 @param backendTextureInfo info about the promised yuva gpu texture(s) 186 @param imageColorSpace range of colors; may be nullptr 187 @param isVolatile volatility of the promise image 188 @param fulfill function called to get the actual backend texture for 189 a given GraphitePromiseTextureContext, and the instance 190 for the GraphitePromiseTextureReleaseProc 191 @param imageRelease function called when any image-centric data can be deleted 192 @param textureRelease function called when the backend texture can be deleted 193 @param imageContext state passed to imageRelease 194 @param planeContexts states passed to fulfill for each plane 195 @return created SkImage, or nullptr 196 */ 197 SK_API sk_sp<SkImage> PromiseTextureFromYUVA(skgpu::graphite::Recorder*, 198 const skgpu::graphite::YUVABackendTextureInfo&, 199 sk_sp<SkColorSpace> imageColorSpace, 200 skgpu::graphite::Volatile, 201 GraphitePromiseTextureFulfillProc, 202 GraphitePromiseImageReleaseProc, 203 GraphitePromiseTextureReleaseProc, 204 GraphitePromiseImageContext imageContext, 205 GraphitePromiseTextureFulfillContext planeContexts[], 206 std::string_view label = {}); 207 208 209 /** Returns an SkImage backed by a Graphite texture, using the provided Recorder for creation and 210 uploads if necessary. The returned SkImage respects the required image properties' mipmap 211 setting for non-Graphite SkImages; i.e., if mipmapping is required, the backing Graphite texture 212 will have allocated mip map levels. 213 214 It is assumed that MIP maps are always supported by the GPU. 215 216 Returns original SkImage if the image is already Graphite-backed and the required mipmapping is 217 compatible with the backing Graphite texture. If the required mipmapping is not compatible, 218 nullptr will be returned. 219 220 Returns nullptr if no Recorder is provided, or if SkImage was created with another Recorder and 221 work on that Recorder has not been submitted. 222 223 @param Recorder the Recorder to use for storing commands 224 @param RequiredProperties properties the returned SkImage must possess (e.g. mipmaps) 225 @return created SkImage, or nullptr 226 */ 227 SK_API sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder*, 228 const SkImage*, 229 SkImage::RequiredProperties = {}); 230 231 inline sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder* r, 232 const sk_sp<const SkImage>& img, 233 SkImage::RequiredProperties props = {}) { 234 return TextureFromImage(r, img.get(), props); 235 } 236 237 /** Creates SkImage from SkYUVAPixmaps. 238 239 The image will remain planar with each plane converted to a texture using the passed Recorder. 240 241 SkYUVAPixmaps has a SkYUVAInfo which specifies the transformation from YUV to RGB. The 242 SkColorSpace of the resulting RGB values is specified by imgColorSpace. This will be the 243 SkColorSpace reported by the image and when drawn the RGB values will be converted from this 244 space into the destination space (if the destination is tagged). 245 246 This is only supported using the GPU backend and will fail if recorder is nullptr. 247 248 SkYUVAPixmaps does not need to remain valid after this returns. 249 250 @param Recorder The Recorder to use for storing commands 251 @param pixmaps The planes as pixmaps with supported SkYUVAInfo that 252 specifies conversion to RGB. 253 @param RequiredProperties Properties the returned SkImage must possess (e.g. mipmaps) 254 @param limitToMaxTextureSize Downscale image to GPU maximum texture size, if necessary 255 @param imgColorSpace Range of colors of the resulting image; may be nullptr 256 @return Created SkImage, or nullptr 257 */ 258 SK_API sk_sp<SkImage> TextureFromYUVAPixmaps(skgpu::graphite::Recorder*, 259 const SkYUVAPixmaps& pixmaps, 260 SkImage::RequiredProperties = {}, 261 bool limitToMaxTextureSize = false, 262 sk_sp<SkColorSpace> imgColorSpace = nullptr, 263 std::string_view label = {}); 264 265 /** Creates an SkImage from YUV[A] planar textures associated with the recorder. 266 @param recorder The recorder. 267 @param yuvaBackendTextures A set of textures containing YUVA data and a description of the 268 data and transformation to RGBA. 269 @param imageColorSpace range of colors of the resulting image after conversion to RGB; 270 may be nullptr 271 @param TextureReleaseProc called when the backend textures can be released 272 @param ReleaseContext state passed to TextureReleaseProc 273 @return created SkImage, or nullptr 274 */ 275 SK_API sk_sp<SkImage> TextureFromYUVATextures( 276 skgpu::graphite::Recorder* recorder, 277 const skgpu::graphite::YUVABackendTextures& yuvaBackendTextures, 278 sk_sp<SkColorSpace> imageColorSpace, 279 TextureReleaseProc = nullptr, 280 ReleaseContext = nullptr, 281 std::string_view label = {}); 282 283 /** Creates an SkImage from YUV[A] planar SkImages associated with the recorder. 284 285 The images should have kGraphite type, and the result will be nullptr if any are not. The 286 resulting SkImage will not take a ref on the given SkImages but will take a ref on the 287 underlying TextureProxies. The releaseProcs, if any, for those Textures will be the ones set 288 when the given SkImages were created. 289 290 @param recorder The recorder. 291 @param yuvaInfo Structure describing the YUVA format 292 @param images A set of SkImages containing YUVA data 293 @param imageColorSpace Range of colors of the resulting image after conversion to RGB; 294 may be nullptr 295 @return created SkImage, or nullptr 296 */ 297 SK_API sk_sp<SkImage> TextureFromYUVAImages( 298 skgpu::graphite::Recorder* recorder, 299 const SkYUVAInfo& yuvaInfo, 300 SkSpan<const sk_sp<SkImage>> images, 301 sk_sp<SkColorSpace> imageColorSpace); 302 303 /** Returns subset of this image as a texture-backed image. 304 305 Returns nullptr if any of the following are true: 306 - Subset is empty 307 - Subset is not contained inside the image's bounds 308 - Pixels in the source image could not be read or copied 309 - The source image is texture-backed and context does not match the source image's context. 310 311 @param recorder the non-null recorder in which to create the new image. 312 @param img Source image 313 @param subset bounds of returned SkImage 314 @param props properties the returned SkImage must possess (e.g. mipmaps) 315 @return the subsetted image, uploaded as a texture, or nullptr 316 */ 317 SK_API sk_sp<SkImage> SubsetTextureFrom(skgpu::graphite::Recorder* recorder, 318 const SkImage* img, 319 const SkIRect& subset, 320 SkImage::RequiredProperties props = {}); 321 322 /** Creates a filtered SkImage on the GPU. filter processes the src image, potentially changing 323 color, position, and size. subset is the bounds of src that are processed by filter. clipBounds 324 is the expected bounds of the filtered SkImage. outSubset is required storage for the actual 325 bounds of the filtered SkImage. offset is required storage for translation of returned SkImage. 326 327 Returns nullptr if SkImage could not be created. If nullptr is returned, outSubset and offset 328 are undefined. 329 330 Useful for animation of SkImageFilter that varies size from frame to frame. Returned SkImage is 331 created larger than required by filter so that GPU texture can be reused with different sized 332 effects. outSubset describes the valid bounds of GPU texture returned. offset translates the 333 returned SkImage to keep subsequent animation frames aligned with respect to each other. 334 335 @param recorder the recorder in which the filtering operation is to be performed 336 @param filter how SkImage is sampled when transformed 337 @param subset bounds of SkImage processed by filter 338 @param clipBounds expected bounds of filtered SkImage 339 @param outSubset storage for returned SkImage bounds 340 @param offset storage for returned SkImage translation 341 @return filtered SkImage, or nullptr 342 */ 343 SK_API sk_sp<SkImage> MakeWithFilter(skgpu::graphite::Recorder* recorder, 344 sk_sp<SkImage> src, 345 const SkImageFilter* filter, 346 const SkIRect& subset, 347 const SkIRect& clipBounds, 348 SkIRect* outSubset, 349 SkIPoint* offset); 350 351 } // namespace SkImages 352 353 354 #endif // skgpu_graphite_Image_DEFINED 355