• 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 
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