xref: /aosp_15_r20/external/skia/include/gpu/graphite/Image.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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