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 #if !defined(SK_DISABLE_LEGACY_GRAPHITE_IMAGES) 107 inline sk_sp<SkImage> AdoptTextureFrom(skgpu::graphite::Recorder* recorder, 108 const skgpu::graphite::BackendTexture& tex, 109 SkColorType colorType, 110 SkAlphaType alphaType, 111 sk_sp<SkColorSpace> colorSpace, 112 skgpu::Origin origin, 113 TextureReleaseProc trProc = nullptr, 114 ReleaseContext ctx = nullptr) { 115 return WrapTexture(recorder, tex, colorType, alphaType, colorSpace, origin, trProc, ctx); 116 } 117 118 inline sk_sp<SkImage> AdoptTextureFrom(skgpu::graphite::Recorder* recorder, 119 const skgpu::graphite::BackendTexture& tex, 120 SkColorType colorType, 121 SkAlphaType alphaType, 122 sk_sp<SkColorSpace> colorSpace, 123 TextureReleaseProc trProc = nullptr, 124 ReleaseContext ctx = nullptr) { 125 return WrapTexture(recorder, tex, colorType, alphaType, colorSpace, trProc, ctx); 126 } 127 #endif 128 129 /** Create a new SkImage that is very similar to an SkImage created by WrapTexture. The difference 130 is that the caller need not have created the backend texture nor populated it with data when 131 creating the image. Instead of passing a BackendTexture to the factory the client supplies a 132 description of the texture consisting of dimensions, TextureInfo, SkColorInfo and Volatility. 133 134 In general, 'fulfill' must return a BackendTexture that matches the properties provided at 135 SkImage creation time. The BackendTexture must refer to a valid existing texture in the backend 136 API context/device, and already be populated with data. The texture cannot be deleted until 137 'textureRelease' is called. 'textureRelease' will be called with the textureReleaseContext 138 returned by 'fulfill'. 139 140 Wrt when and how often the fulfill, imageRelease, and textureRelease callbacks will be called: 141 142 For non-volatile promise images, 'fulfill' will be called at Context::insertRecording time. 143 Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be called only 144 once - when Skia will no longer try calling 'fulfill' to get a backend texture. If 'fulfill' 145 failed (i.e., it didn't return a valid backend texture) then 'textureRelease' will never be 146 called. If 'fulfill' was successful then 'textureRelease' will be called only once when the GPU 147 is done with the contents of the promise image. This will usually occur during a Context::submit 148 call but it could occur earlier due to error conditions. 'fulfill' can be called multiple times 149 if the promise image is used in multiple recordings. If 'fulfill' fails, the insertRecording 150 itself will fail. Subsequent insertRecording calls (with Recordings that use the promise image) 151 will keep calling 'fulfill' until it succeeds. 152 153 For volatile promise images, 'fulfill' will be called each time the Recording is inserted into a 154 Context. Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be 155 called only once just like the non-volatile case. If 'fulfill' fails at insertRecording-time, 156 'textureRelease' will never be called. If 'fulfill' was successful then a 'textureRelease' 157 matching that 'fulfill' will be called when the GPU is done with the contents of the promise 158 image. This will usually occur during a Context::submit call but it could occur earlier due to 159 error conditions. 160 161 @param recorder the recorder that will capture the commands creating the image 162 @param dimensions width & height of promised gpu texture 163 @param textureInfo structural information for the promised gpu texture 164 @param colorInfo color type, alpha type and colorSpace information for the image 165 @param origin Whether the Texture logically treats the origin as TopLeft or BottomLeft 166 @param isVolatile volatility of the promise image 167 @param fulfill function called to get the actual backend texture, 168 and the instance for the GraphitePromiseTextureReleaseProc 169 @param imageRelease function called when any image-centric data can be deleted 170 @param textureRelease function called when the backend texture can be deleted 171 @param imageContext state passed to fulfill and imageRelease 172 @return created SkImage, or nullptr 173 */ 174 SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, 175 SkISize dimensions, 176 const skgpu::graphite::TextureInfo&, 177 const SkColorInfo&, 178 skgpu::Origin origin, 179 skgpu::graphite::Volatile, 180 GraphitePromiseTextureFulfillProc, 181 GraphitePromiseImageReleaseProc, 182 GraphitePromiseTextureReleaseProc, 183 GraphitePromiseImageContext, 184 std::string_view label = {}); 185 186 SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, 187 SkISize dimensions, 188 const skgpu::graphite::TextureInfo&, 189 const SkColorInfo&, 190 skgpu::graphite::Volatile, 191 GraphitePromiseTextureFulfillProc, 192 GraphitePromiseImageReleaseProc, 193 GraphitePromiseTextureReleaseProc, 194 GraphitePromiseImageContext); 195 196 /** This is similar to 'PromiseTextureFrom' but it creates a GPU-backed SkImage from YUV[A] data. 197 The source data may be planar (i.e. spread across multiple textures). In the extreme Y, U, V, 198 and A are all in different planes and thus the image is specified by four textures. 199 'backendTextureInfo' describes the planar arrangement, texture formats, and conversion to RGB. 200 Separate 'fulfill' and 'textureRelease' calls are made for each texture. Each texture has its 201 own GraphitePromiseFulfillContext. The GraphitePromiseImageReleaseProc will be made even on 202 failure. 'planeContexts' has one entry for each of the up to four textures, as indicated by 203 'backendTextureInfo'. Currently the mipmapped property of 'backendTextureInfo' is ignored. 204 However, in the near future it will be required that if it is kYes then the fulfillProc must 205 return a mip mapped texture for each plane in order to successfully draw the image. 206 207 @param recorder the recorder that will capture the commands creating the image 208 @param backendTextureInfo info about the promised yuva gpu texture(s) 209 @param imageColorSpace range of colors; may be nullptr 210 @param isVolatile volatility of the promise image 211 @param fulfill function called to get the actual backend texture for 212 a given GraphitePromiseTextureContext, and the instance 213 for the GraphitePromiseTextureReleaseProc 214 @param imageRelease function called when any image-centric data can be deleted 215 @param textureRelease function called when the backend texture can be deleted 216 @param imageContext state passed to imageRelease 217 @param planeContexts states passed to fulfill for each plane 218 @return created SkImage, or nullptr 219 */ 220 SK_API sk_sp<SkImage> PromiseTextureFromYUVA(skgpu::graphite::Recorder*, 221 const skgpu::graphite::YUVABackendTextureInfo&, 222 sk_sp<SkColorSpace> imageColorSpace, 223 skgpu::graphite::Volatile, 224 GraphitePromiseTextureFulfillProc, 225 GraphitePromiseImageReleaseProc, 226 GraphitePromiseTextureReleaseProc, 227 GraphitePromiseImageContext imageContext, 228 GraphitePromiseTextureFulfillContext planeContexts[], 229 std::string_view label = {}); 230 231 232 /** Returns an SkImage backed by a Graphite texture, using the provided Recorder for creation and 233 uploads if necessary. The returned SkImage respects the required image properties' mipmap 234 setting for non-Graphite SkImages; i.e., if mipmapping is required, the backing Graphite texture 235 will have allocated mip map levels. 236 237 It is assumed that MIP maps are always supported by the GPU. 238 239 Returns original SkImage if the image is already Graphite-backed and the required mipmapping is 240 compatible with the backing Graphite texture. If the required mipmapping is not compatible, 241 nullptr will be returned. 242 243 Returns nullptr if no Recorder is provided, or if SkImage was created with another Recorder and 244 work on that Recorder has not been submitted. 245 246 @param Recorder the Recorder to use for storing commands 247 @param RequiredProperties properties the returned SkImage must possess (e.g. mipmaps) 248 @return created SkImage, or nullptr 249 */ 250 SK_API sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder*, 251 const SkImage*, 252 SkImage::RequiredProperties = {}); 253 254 inline sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder* r, 255 const sk_sp<const SkImage>& img, 256 SkImage::RequiredProperties props = {}) { 257 return TextureFromImage(r, img.get(), props); 258 } 259 260 /** Creates SkImage from SkYUVAPixmaps. 261 262 The image will remain planar with each plane converted to a texture using the passed Recorder. 263 264 SkYUVAPixmaps has a SkYUVAInfo which specifies the transformation from YUV to RGB. The 265 SkColorSpace of the resulting RGB values is specified by imgColorSpace. This will be the 266 SkColorSpace reported by the image and when drawn the RGB values will be converted from this 267 space into the destination space (if the destination is tagged). 268 269 This is only supported using the GPU backend and will fail if recorder is nullptr. 270 271 SkYUVAPixmaps does not need to remain valid after this returns. 272 273 @param Recorder The Recorder to use for storing commands 274 @param pixmaps The planes as pixmaps with supported SkYUVAInfo that 275 specifies conversion to RGB. 276 @param RequiredProperties Properties the returned SkImage must possess (e.g. mipmaps) 277 @param limitToMaxTextureSize Downscale image to GPU maximum texture size, if necessary 278 @param imgColorSpace Range of colors of the resulting image; may be nullptr 279 @return Created SkImage, or nullptr 280 */ 281 SK_API sk_sp<SkImage> TextureFromYUVAPixmaps(skgpu::graphite::Recorder*, 282 const SkYUVAPixmaps& pixmaps, 283 SkImage::RequiredProperties = {}, 284 bool limitToMaxTextureSize = false, 285 sk_sp<SkColorSpace> imgColorSpace = nullptr, 286 std::string_view label = {}); 287 288 /** Creates an SkImage from YUV[A] planar textures associated with the recorder. 289 @param recorder The recorder. 290 @param yuvaBackendTextures A set of textures containing YUVA data and a description of the 291 data and transformation to RGBA. 292 @param imageColorSpace range of colors of the resulting image after conversion to RGB; 293 may be nullptr 294 @param TextureReleaseProc called when the backend textures can be released 295 @param ReleaseContext state passed to TextureReleaseProc 296 @return created SkImage, or nullptr 297 */ 298 SK_API sk_sp<SkImage> TextureFromYUVATextures( 299 skgpu::graphite::Recorder* recorder, 300 const skgpu::graphite::YUVABackendTextures& yuvaBackendTextures, 301 sk_sp<SkColorSpace> imageColorSpace, 302 TextureReleaseProc = nullptr, 303 ReleaseContext = nullptr, 304 std::string_view label = {}); 305 306 /** Creates an SkImage from YUV[A] planar SkImages associated with the recorder. 307 308 The images should have kGraphite type, and the result will be nullptr if any are not. The 309 resulting SkImage will not take a ref on the given SkImages but will take a ref on the 310 underlying TextureProxies. The releaseProcs, if any, for those Textures will be the ones set 311 when the given SkImages were created. 312 313 @param recorder The recorder. 314 @param yuvaInfo Structure describing the YUVA format 315 @param images A set of SkImages containing YUVA data 316 @param imageColorSpace Range of colors of the resulting image after conversion to RGB; 317 may be nullptr 318 @return created SkImage, or nullptr 319 */ 320 SK_API sk_sp<SkImage> TextureFromYUVAImages( 321 skgpu::graphite::Recorder* recorder, 322 const SkYUVAInfo& yuvaInfo, 323 SkSpan<const sk_sp<SkImage>> images, 324 sk_sp<SkColorSpace> imageColorSpace); 325 326 /** Returns subset of this image as a texture-backed image. 327 328 Returns nullptr if any of the following are true: 329 - Subset is empty 330 - Subset is not contained inside the image's bounds 331 - Pixels in the source image could not be read or copied 332 - The source image is texture-backed and context does not match the source image's context. 333 334 @param recorder the non-null recorder in which to create the new image. 335 @param img Source image 336 @param subset bounds of returned SkImage 337 @param props properties the returned SkImage must possess (e.g. mipmaps) 338 @return the subsetted image, uploaded as a texture, or nullptr 339 */ 340 SK_API sk_sp<SkImage> SubsetTextureFrom(skgpu::graphite::Recorder* recorder, 341 const SkImage* img, 342 const SkIRect& subset, 343 SkImage::RequiredProperties props = {}); 344 345 /** Creates a filtered SkImage on the GPU. filter processes the src image, potentially changing 346 color, position, and size. subset is the bounds of src that are processed by filter. clipBounds 347 is the expected bounds of the filtered SkImage. outSubset is required storage for the actual 348 bounds of the filtered SkImage. offset is required storage for translation of returned SkImage. 349 350 Returns nullptr if SkImage could not be created. If nullptr is returned, outSubset and offset 351 are undefined. 352 353 Useful for animation of SkImageFilter that varies size from frame to frame. Returned SkImage is 354 created larger than required by filter so that GPU texture can be reused with different sized 355 effects. outSubset describes the valid bounds of GPU texture returned. offset translates the 356 returned SkImage to keep subsequent animation frames aligned with respect to each other. 357 358 @param recorder the recorder in which the filtering operation is to be performed 359 @param filter how SkImage is sampled when transformed 360 @param subset bounds of SkImage processed by filter 361 @param clipBounds expected bounds of filtered SkImage 362 @param outSubset storage for returned SkImage bounds 363 @param offset storage for returned SkImage translation 364 @return filtered SkImage, or nullptr 365 */ 366 SK_API sk_sp<SkImage> MakeWithFilter(skgpu::graphite::Recorder* recorder, 367 sk_sp<SkImage> src, 368 const SkImageFilter* filter, 369 const SkIRect& subset, 370 const SkIRect& clipBounds, 371 SkIRect* outSubset, 372 SkIPoint* offset); 373 374 } // namespace SkImages 375 376 377 #endif // skgpu_graphite_Image_DEFINED 378