429 lines
25 KiB
C++
429 lines
25 KiB
C++
/*
|
|
* 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
|