Coverage Report

Created: 2024-05-20 07:14

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