| /* | |
| * Copyright 2023 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_graphite_Image_DEFINED | |
| #define skgpu_graphite_Image_DEFINED | |
| #include "include/core/SkColorSpace.h" | |
| #include "include/core/SkImage.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkSpan.h" | |
| #include "include/gpu/GpuTypes.h" | |
| #include <string_view> | |
| #include <tuple> | |
| class SkYUVAInfo; | |
| class SkYUVAPixmaps; | |
| struct SkIRect; | |
| namespace skgpu::graphite { | |
| class BackendTexture; | |
| class Recorder; | |
| class TextureInfo; | |
| class YUVABackendTextureInfo; | |
| class YUVABackendTextures; | |
| enum class Volatile : bool; | |
| } | |
| namespace SkImages { | |
| enum class GenerateMipmapsFromBase : bool { kNo, kYes }; | |
| using TextureReleaseProc = void (*)(ReleaseContext); | |
| // Passed to imageRelease | |
| using GraphitePromiseImageContext = void*; | |
| // Passed to fulfill; for non-YUVA promise images, the image context is used as the fulfill context, | |
| // while YUVA promise images have a per-plane fulfill context. | |
| using GraphitePromiseTextureFulfillContext = void*; | |
| // Returned from fulfill and passed into textureRelease | |
| using GraphitePromiseTextureReleaseContext = void*; | |
| using GraphitePromiseTextureFulfillProc = | |
| std::tuple<skgpu::graphite::BackendTexture, GraphitePromiseTextureReleaseContext> (*)( | |
| GraphitePromiseTextureFulfillContext); | |
| using GraphitePromiseImageReleaseProc = void (*)(GraphitePromiseImageContext); | |
| using GraphitePromiseTextureReleaseProc = void (*)(GraphitePromiseTextureReleaseContext); | |
| /** Creates an SkImage from a GPU texture associated with the recorder. The client is still | |
| responsible for managing the backend texture's lifetime. | |
| SkImage is returned if the format of backendTexture is recognized and supported. Recognized | |
| formats vary by GPU back-end. | |
| The provided `alphaType` determines how the wrapped texture is sampled: | |
| - kUnknown_SkAlphaType: Sampled as RGB1, ignoring any alpha data. G and B are automatically | |
| treated as 0 if the format does not provide them. Single channel | |
| texture formats are interpretd as the "red" SkColorTypes instead of | |
| the "alpha-only" SkColorTypes. | |
| - kOpaque_SkAlphaType: Sampled as RGBA but higher-level logic *assumes* that all A values are | |
| equal to 1. Single channel texture formats are interpeted as "red" | |
| instead of "alpha-only" for disambiguating SkColorTypes. | |
| - kPremul_SkAlphaType: Sampled as RGBA and higher-level logic assumes the RGB values have | |
| been premultiplied with the A value. Single channel texture formats | |
| are interpreted as "alpha-only" color types (e.g. 000A or 000R | |
| swizzles depending on the texture format). | |
| - kUnpremul_SkAlphaType: Sampled as RGBA and higher-level logic assumes the RGB values have not | |
| been multiplied with A yet. Single channel texture formats are | |
| interpreted as "alpha-only" color types the same as | |
| kPremul_SkAlphaType. | |
| The SkColorType of the returned SkImage is selected to best match the bit depth and | |
| representation of the texture format of the backend texture. This is not necessarily an exact | |
| match since texture formats may have more options than SkColorType. Any mismatch between the | |
| format and the SkColorType is handled automatically for read/write operations on the image (the | |
| SkColorType represents how the image data will be made available on the CPU). | |
| If possible, the color type will also take into account the behavior of `alphaType`, such as | |
| using kRGB_888x_SkColorType for an RGBA8 texture with kUnknown_SkAlphaType. For single-channel | |
| textures with kUnknown|kOpaque_SkAlphaType, the best "red-only" color type is chosen, e.g. | |
| kR8_unorm_SkColorType. For single-channel textures with kPremul|kUnpremul_SkAlphaType, the best | |
| "alpha-only" color type is chosen, e.g. kAlpha_8_SkColorType. This preserves the semantic | |
| behaviors in Skia's high-level shading logic that treats red formats as color data, and | |
| automatically colorizes alpha formats based on the paint's color or shader. | |
| When using such a single-channel texture in a runtime effect, this semantic distinction defines | |
| which channel of the float4 shader value has the interesting data (R001 vs 000A). When combining | |
| multiple single-channel textures into a multiplaner YUV[A] SkImage, either colortype behaves the | |
| same. The most significant distinction occurs when the SkImage is used in | |
| SkCanvas::drawImageRect() or combined into a non-runtime SkShader. | |
| @param recorder The recorder | |
| @param backendTexture texture residing on GPU | |
| @param alphaType The nature of alpha channel data provided in the texture. | |
| @param colorSpace This describes the color space of this image's contents, as seen | |
| after sampling. In general, if the format of the backend texture | |
| is SRGB, some linear colorSpace should be supplied (e.g., | |
| SkColorSpace::MakeSRGBLinear()). If the format of the backend | |
| texture is linear, then the colorSpace should include a | |
| description of the transfer function as well (e.g., | |
| SkColorSpace::MakeSRGB()). | |
| @param origin Whether the Texture logically treats the origin as TopLeft or | |
| BottomLeft | |
| @param generateMipmapsFromBase If kYes then the pixel contents of the textures upper mipmap | |
| levels are generated by successive downsampling of the base | |
| level. If the texture is not mipmapped or isn't renderable then | |
| image creation will fail. If kNo and the texture is mipmapped | |
| then the contents of upper levels are assumed to already be | |
| valid. | |
| @return created SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, | |
| const skgpu::graphite::BackendTexture&, | |
| SkAlphaType alphaType, | |
| sk_sp<SkColorSpace> colorSpace, | |
| skgpu::Origin origin, | |
| GenerateMipmapsFromBase genMipmaps, | |
| TextureReleaseProc = nullptr, | |
| ReleaseContext = nullptr, | |
| std::string_view label = {}); | |
| SK_API inline sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder* recorder, | |
| const skgpu::graphite::BackendTexture& backendTex, | |
| SkAlphaType alphaType, | |
| sk_sp<SkColorSpace> colorSpace, | |
| skgpu::Origin origin, | |
| TextureReleaseProc releaseP = nullptr, | |
| ReleaseContext releaseC = nullptr, | |
| std::string_view label = {}) { | |
| return WrapTexture(recorder, backendTex, alphaType, std::move(colorSpace), origin, | |
| GenerateMipmapsFromBase::kNo, releaseP, releaseC, label); | |
| } | |
| SK_API inline sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder* recorder, | |
| const skgpu::graphite::BackendTexture& backendTex, | |
| SkAlphaType alphaType, | |
| sk_sp<SkColorSpace> colorSpace, | |
| TextureReleaseProc releaseP = nullptr, | |
| ReleaseContext releaseC = nullptr, | |
| std::string_view label = {}) { | |
| return WrapTexture(recorder, backendTex, alphaType, std::move(colorSpace), | |
| skgpu::Origin::kTopLeft, releaseP, releaseC, label); | |
| } | |
| // DEPRECATED: The WrapTexture calls that take an SkColorType are deprecated. Use the new versions | |
| // that automatically pick a compatible color type from the texture's format. | |
| SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, | |
| const skgpu::graphite::BackendTexture&, | |
| SkColorType colorType, | |
| SkAlphaType alphaType, | |
| sk_sp<SkColorSpace> colorSpace, | |
| skgpu::Origin origin, | |
| GenerateMipmapsFromBase generateMipmapsFromBase, | |
| TextureReleaseProc = nullptr, | |
| ReleaseContext = nullptr, | |
| std::string_view label = {}); | |
| SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, | |
| const skgpu::graphite::BackendTexture&, | |
| SkColorType colorType, | |
| SkAlphaType alphaType, | |
| sk_sp<SkColorSpace> colorSpace, | |
| skgpu::Origin origin, | |
| TextureReleaseProc = nullptr, | |
| ReleaseContext = nullptr, | |
| std::string_view label = {}); | |
| SK_API sk_sp<SkImage> WrapTexture(skgpu::graphite::Recorder*, | |
| const skgpu::graphite::BackendTexture&, | |
| SkColorType colorType, | |
| SkAlphaType alphaType, | |
| sk_sp<SkColorSpace> colorSpace, | |
| TextureReleaseProc = nullptr, | |
| ReleaseContext = nullptr, | |
| std::string_view label = {}); | |
| /** Create a new SkImage that is very similar to an SkImage created by WrapTexture. The difference | |
| is that the caller need not have created the backend texture nor populated it with data when | |
| creating the image. Instead of passing a BackendTexture to the factory the client supplies a | |
| description of the texture consisting of dimensions, TextureInfo, SkColorInfo and Volatility. | |
| In general, 'fulfill' must return a BackendTexture that matches the properties provided at | |
| SkImage creation time. The BackendTexture must refer to a valid existing texture in the backend | |
| API context/device, and already be populated with data. The texture cannot be deleted until | |
| 'textureRelease' is called. 'textureRelease' will be called with the textureReleaseContext | |
| returned by 'fulfill'. | |
| Wrt when and how often the fulfill, imageRelease, and textureRelease callbacks will be called: | |
| For non-volatile promise images, 'fulfill' will be called at Context::insertRecording time. | |
| Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be called only | |
| once - when Skia will no longer try calling 'fulfill' to get a backend texture. If 'fulfill' | |
| failed (i.e., it didn't return a valid backend texture) then 'textureRelease' will never be | |
| called. If 'fulfill' was successful then 'textureRelease' will be called only once when the GPU | |
| is done with the contents of the promise image. This will usually occur during a Context::submit | |
| call but it could occur earlier due to error conditions. 'fulfill' can be called multiple times | |
| if the promise image is used in multiple recordings. If 'fulfill' fails, the insertRecording | |
| itself will fail. Subsequent insertRecording calls (with Recordings that use the promise image) | |
| will keep calling 'fulfill' until it succeeds. | |
| For volatile promise images, 'fulfill' will be called each time the Recording is inserted into a | |
| Context. Regardless of whether 'fulfill' succeeded or failed, 'imageRelease' will always be | |
| called only once just like the non-volatile case. If 'fulfill' fails at insertRecording-time, | |
| 'textureRelease' will never be called. If 'fulfill' was successful then a 'textureRelease' | |
| matching that 'fulfill' will be called when the GPU is done with the contents of the promise | |
| image. This will usually occur during a Context::submit call but it could occur earlier due to | |
| error conditions. | |
| @param recorder the recorder that will capture the commands creating the image | |
| @param dimensions width & height of promised gpu texture | |
| @param textureInfo structural information for the promised gpu texture | |
| @param colorInfo color type, alpha type and colorSpace information for the image | |
| @param origin Whether the Texture logically treats the origin as TopLeft or BottomLeft | |
| @param isVolatile volatility of the promise image | |
| @param fulfill function called to get the actual backend texture, | |
| and the instance for the GraphitePromiseTextureReleaseProc | |
| @param imageRelease function called when any image-centric data can be deleted | |
| @param textureRelease function called when the backend texture can be deleted | |
| @param imageContext state passed to fulfill and imageRelease | |
| @return created SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, | |
| SkISize dimensions, | |
| const skgpu::graphite::TextureInfo&, | |
| const SkColorInfo&, | |
| skgpu::Origin origin, | |
| skgpu::graphite::Volatile, | |
| GraphitePromiseTextureFulfillProc, | |
| GraphitePromiseImageReleaseProc, | |
| GraphitePromiseTextureReleaseProc, | |
| GraphitePromiseImageContext, | |
| std::string_view label = {}); | |
| SK_API sk_sp<SkImage> PromiseTextureFrom(skgpu::graphite::Recorder*, | |
| SkISize dimensions, | |
| const skgpu::graphite::TextureInfo&, | |
| const SkColorInfo&, | |
| skgpu::graphite::Volatile, | |
| GraphitePromiseTextureFulfillProc, | |
| GraphitePromiseImageReleaseProc, | |
| GraphitePromiseTextureReleaseProc, | |
| GraphitePromiseImageContext); | |
| /** This is similar to 'PromiseTextureFrom' but it creates a GPU-backed SkImage from YUV[A] data. | |
| The source data may be planar (i.e. spread across multiple textures). In the extreme Y, U, V, | |
| and A are all in different planes and thus the image is specified by four textures. | |
| 'backendTextureInfo' describes the planar arrangement, texture formats, and conversion to RGB. | |
| Separate 'fulfill' and 'textureRelease' calls are made for each texture. Each texture has its | |
| own GraphitePromiseFulfillContext. The GraphitePromiseImageReleaseProc will be made even on | |
| failure. 'planeContexts' has one entry for each of the up to four textures, as indicated by | |
| 'backendTextureInfo'. Currently the mipmapped property of 'backendTextureInfo' is ignored. | |
| However, in the near future it will be required that if it is kYes then the fulfillProc must | |
| return a mip mapped texture for each plane in order to successfully draw the image. | |
| @param recorder the recorder that will capture the commands creating the image | |
| @param backendTextureInfo info about the promised yuva gpu texture(s) | |
| @param imageColorSpace range of colors; may be nullptr | |
| @param isVolatile volatility of the promise image | |
| @param fulfill function called to get the actual backend texture for | |
| a given GraphitePromiseTextureContext, and the instance | |
| for the GraphitePromiseTextureReleaseProc | |
| @param imageRelease function called when any image-centric data can be deleted | |
| @param textureRelease function called when the backend texture can be deleted | |
| @param imageContext state passed to imageRelease | |
| @param planeContexts states passed to fulfill for each plane | |
| @return created SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> PromiseTextureFromYUVA(skgpu::graphite::Recorder*, | |
| const skgpu::graphite::YUVABackendTextureInfo&, | |
| sk_sp<SkColorSpace> imageColorSpace, | |
| skgpu::graphite::Volatile, | |
| GraphitePromiseTextureFulfillProc, | |
| GraphitePromiseImageReleaseProc, | |
| GraphitePromiseTextureReleaseProc, | |
| GraphitePromiseImageContext imageContext, | |
| GraphitePromiseTextureFulfillContext planeContexts[], | |
| std::string_view label = {}); | |
| /** Returns an SkImage backed by a Graphite texture, using the provided Recorder for creation and | |
| uploads if necessary. The returned SkImage respects the required image properties' mipmap | |
| setting for non-Graphite SkImages; i.e., if mipmapping is required, the backing Graphite texture | |
| will have allocated mip map levels. | |
| It is assumed that MIP maps are always supported by the GPU. | |
| Returns original SkImage if the image is already Graphite-backed and the required mipmapping is | |
| compatible with the backing Graphite texture. If the required mipmapping is not compatible, | |
| nullptr will be returned. | |
| Returns nullptr if no Recorder is provided, or if SkImage was created with another Recorder and | |
| work on that Recorder has not been submitted. | |
| @param Recorder the Recorder to use for storing commands | |
| @param RequiredProperties properties the returned SkImage must possess (e.g. mipmaps) | |
| @return created SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder*, | |
| const SkImage*, | |
| SkImage::RequiredProperties = {}); | |
| inline sk_sp<SkImage> TextureFromImage(skgpu::graphite::Recorder* r, | |
| const sk_sp<const SkImage>& img, | |
| SkImage::RequiredProperties props = {}) { | |
| return TextureFromImage(r, img.get(), props); | |
| } | |
| /** Creates SkImage from SkYUVAPixmaps. | |
| The image will remain planar with each plane converted to a texture using the passed Recorder. | |
| SkYUVAPixmaps has a SkYUVAInfo which specifies the transformation from YUV to RGB. The | |
| SkColorSpace of the resulting RGB values is specified by imgColorSpace. This will be the | |
| SkColorSpace reported by the image and when drawn the RGB values will be converted from this | |
| space into the destination space (if the destination is tagged). | |
| This is only supported using the GPU backend and will fail if recorder is nullptr. | |
| SkYUVAPixmaps does not need to remain valid after this returns. | |
| @param Recorder The Recorder to use for storing commands | |
| @param pixmaps The planes as pixmaps with supported SkYUVAInfo that | |
| specifies conversion to RGB. | |
| @param RequiredProperties Properties the returned SkImage must possess (e.g. mipmaps) | |
| @param limitToMaxTextureSize Downscale image to GPU maximum texture size, if necessary | |
| @param imgColorSpace Range of colors of the resulting image; may be nullptr | |
| @return Created SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> TextureFromYUVAPixmaps(skgpu::graphite::Recorder*, | |
| const SkYUVAPixmaps& pixmaps, | |
| SkImage::RequiredProperties = {}, | |
| bool limitToMaxTextureSize = false, | |
| sk_sp<SkColorSpace> imgColorSpace = nullptr, | |
| std::string_view label = {}); | |
| /** Creates an SkImage from YUV[A] planar textures associated with the recorder. | |
| @param recorder The recorder. | |
| @param yuvaBackendTextures A set of textures containing YUVA data and a description of the | |
| data and transformation to RGBA. | |
| @param imageColorSpace range of colors of the resulting image after conversion to RGB; | |
| may be nullptr | |
| @param TextureReleaseProc called when the backend textures can be released | |
| @param ReleaseContext state passed to TextureReleaseProc | |
| @return created SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> TextureFromYUVATextures( | |
| skgpu::graphite::Recorder* recorder, | |
| const skgpu::graphite::YUVABackendTextures& yuvaBackendTextures, | |
| sk_sp<SkColorSpace> imageColorSpace, | |
| TextureReleaseProc = nullptr, | |
| ReleaseContext = nullptr, | |
| std::string_view label = {}); | |
| /** Creates an SkImage from YUV[A] planar SkImages associated with the recorder. | |
| The images should have kGraphite type, and the result will be nullptr if any are not. The | |
| resulting SkImage will not take a ref on the given SkImages but will take a ref on the | |
| underlying TextureProxies. The releaseProcs, if any, for those Textures will be the ones set | |
| when the given SkImages were created. | |
| @param recorder The recorder. | |
| @param yuvaInfo Structure describing the YUVA format | |
| @param images A set of SkImages containing YUVA data | |
| @param imageColorSpace Range of colors of the resulting image after conversion to RGB; | |
| may be nullptr | |
| @return created SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> TextureFromYUVAImages( | |
| skgpu::graphite::Recorder* recorder, | |
| const SkYUVAInfo& yuvaInfo, | |
| SkSpan<const sk_sp<SkImage>> images, | |
| sk_sp<SkColorSpace> imageColorSpace); | |
| /** Returns subset of this image as a texture-backed image. | |
| Returns nullptr if any of the following are true: | |
| - Subset is empty | |
| - Subset is not contained inside the image's bounds | |
| - Pixels in the source image could not be read or copied | |
| - The source image is texture-backed and context does not match the source image's context. | |
| @param recorder the non-null recorder in which to create the new image. | |
| @param img Source image | |
| @param subset bounds of returned SkImage | |
| @param props properties the returned SkImage must possess (e.g. mipmaps) | |
| @return the subsetted image, uploaded as a texture, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> SubsetTextureFrom(skgpu::graphite::Recorder* recorder, | |
| const SkImage* img, | |
| const SkIRect& subset, | |
| SkImage::RequiredProperties props = {}); | |
| /** Creates a filtered SkImage on the GPU. filter processes the src image, potentially changing | |
| color, position, and size. subset is the bounds of src that are processed by filter. clipBounds | |
| is the expected bounds of the filtered SkImage. outSubset is required storage for the actual | |
| bounds of the filtered SkImage. offset is required storage for translation of returned SkImage. | |
| Returns nullptr if SkImage could not be created. If nullptr is returned, outSubset and offset | |
| are undefined. | |
| Useful for animation of SkImageFilter that varies size from frame to frame. Returned SkImage is | |
| created larger than required by filter so that GPU texture can be reused with different sized | |
| effects. outSubset describes the valid bounds of GPU texture returned. offset translates the | |
| returned SkImage to keep subsequent animation frames aligned with respect to each other. | |
| @param recorder the recorder in which the filtering operation is to be performed | |
| @param filter how SkImage is sampled when transformed | |
| @param subset bounds of SkImage processed by filter | |
| @param clipBounds expected bounds of filtered SkImage | |
| @param outSubset storage for returned SkImage bounds | |
| @param offset storage for returned SkImage translation | |
| @return filtered SkImage, or nullptr | |
| */ | |
| SK_API sk_sp<SkImage> MakeWithFilter(skgpu::graphite::Recorder* recorder, | |
| sk_sp<SkImage> src, | |
| const SkImageFilter* filter, | |
| const SkIRect& subset, | |
| const SkIRect& clipBounds, | |
| SkIRect* outSubset, | |
| SkIPoint* offset); | |
| } // namespace SkImages | |
| #endif // skgpu_graphite_Image_DEFINED |