• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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