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