[graphite] Add support for creating wrapped SkSurfaces.
Bug: skia:12633 Change-Id: Ic1598bea37bae6f53e054de98093b3c049125b38 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/479063 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
eff367ac83
commit
fec9a3027c
@ -8,16 +8,39 @@
|
||||
#ifndef SkStuff_DEFINED
|
||||
#define SkStuff_DEFINED
|
||||
|
||||
#include "include/core/SkImageInfo.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
|
||||
struct SkImageInfo;
|
||||
class SkSurface;
|
||||
class SkSurfaceProps;
|
||||
|
||||
namespace skgpu {
|
||||
class BackendTexture;
|
||||
class Recorder;
|
||||
}
|
||||
|
||||
// TODO: Should be in SkSurface.h
|
||||
sk_sp<SkSurface> MakeGraphite(sk_sp<skgpu::Recorder>, const SkImageInfo&);
|
||||
|
||||
/**
|
||||
* Wraps a GPU-backed texture into SkSurface. Depending on the backend gpu API, the caller may be
|
||||
* required to ensure the texture is valid for the lifetime of returned SkSurface. The required
|
||||
* lifetimes for the specific apis are:
|
||||
* Metal: Skia will call retain on the underlying MTLTexture so the caller can drop it once this
|
||||
* call returns.
|
||||
*
|
||||
* SkSurface is returned if all parameters are valid. BackendTexture is valid if its format agrees
|
||||
* with colorSpace and context; for instance, if backendTexture has an sRGB configuration, then
|
||||
* context must support sRGB, and colorSpace must be present. Further, backendTexture width and
|
||||
* height must not exceed context capabilities, and the context must be able to support back-end
|
||||
* textures.
|
||||
*
|
||||
* If SK_ENABLE_GRAPHITE is not defined, this has no effect and returns nullptr.
|
||||
*/
|
||||
sk_sp<SkSurface> MakeGraphiteFromBackendTexture(sk_sp<skgpu::Recorder>,
|
||||
const skgpu::BackendTexture&,
|
||||
SkColorType colorType,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
const SkSurfaceProps* props);
|
||||
|
||||
#endif // SkStuff_DEFINED
|
||||
|
@ -6,6 +6,8 @@
|
||||
*/
|
||||
|
||||
#include "experimental/graphite/src/Caps.h"
|
||||
|
||||
#include "experimental/graphite/include/TextureInfo.h"
|
||||
#include "src/sksl/SkSLUtil.h"
|
||||
|
||||
namespace skgpu {
|
||||
@ -13,6 +15,13 @@ namespace skgpu {
|
||||
Caps::Caps() {}
|
||||
Caps::~Caps() {}
|
||||
|
||||
bool Caps::isTexturable(const TextureInfo& info) const {
|
||||
if (info.numSamples() > 1) {
|
||||
return false;
|
||||
}
|
||||
return this->onIsTexturable(info);
|
||||
}
|
||||
|
||||
bool Caps::areColorTypeAndTextureInfoCompatible(SkColorType type, const TextureInfo& info) const {
|
||||
if (type == kUnknown_SkColorType) {
|
||||
return false;
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
|
||||
bool areColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo&) const;
|
||||
|
||||
virtual bool isTexturable(const TextureInfo&) const = 0;
|
||||
bool isTexturable(const TextureInfo&) const;
|
||||
virtual bool isRenderable(const TextureInfo&) const = 0;
|
||||
|
||||
int maxTextureSize() const { return fMaxTextureSize; }
|
||||
@ -59,6 +59,7 @@ protected:
|
||||
std::unique_ptr<SkSL::ShaderCaps> fShaderCaps;
|
||||
|
||||
private:
|
||||
virtual bool onIsTexturable(const TextureInfo&) const = 0;
|
||||
virtual bool onAreColorTypeAndTextureInfoCompatible(SkColorType, const TextureInfo&) const = 0;
|
||||
};
|
||||
|
||||
|
@ -48,14 +48,33 @@ bool is_opaque(const PaintParams& paint) {
|
||||
} // anonymous namespace
|
||||
|
||||
sk_sp<Device> Device::Make(sk_sp<Recorder> recorder, const SkImageInfo& ii) {
|
||||
if (!recorder) {
|
||||
return nullptr;
|
||||
}
|
||||
const Gpu* gpu = recorder->context()->priv().gpu();
|
||||
auto textureInfo = gpu->caps()->getDefaultSampledTextureInfo(ii.colorType(), /*levelCount=*/1,
|
||||
Protected::kNo, Renderable::kYes);
|
||||
auto target = sk_sp<TextureProxy>(new TextureProxy(ii.dimensions(), textureInfo));
|
||||
sk_sp<DrawContext> dc = DrawContext::Make(target,
|
||||
ii.refColorSpace(),
|
||||
ii.colorType(),
|
||||
ii.alphaType());
|
||||
sk_sp<TextureProxy> target(new TextureProxy(ii.dimensions(), textureInfo));
|
||||
return Make(std::move(recorder),
|
||||
std::move(target),
|
||||
ii.refColorSpace(),
|
||||
ii.colorType(),
|
||||
ii.alphaType());
|
||||
}
|
||||
|
||||
sk_sp<Device> Device::Make(sk_sp<Recorder> recorder,
|
||||
sk_sp<TextureProxy> target,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
SkColorType colorType,
|
||||
SkAlphaType alphaType) {
|
||||
if (!recorder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<DrawContext> dc = DrawContext::Make(std::move(target),
|
||||
std::move(colorSpace),
|
||||
colorType,
|
||||
alphaType);
|
||||
if (!dc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ class Context;
|
||||
class DrawContext;
|
||||
class Recorder;
|
||||
class Shape;
|
||||
class TextureProxy;
|
||||
class Transform;
|
||||
|
||||
class Device final : public SkBaseDevice {
|
||||
@ -31,10 +32,15 @@ public:
|
||||
~Device() override;
|
||||
|
||||
static sk_sp<Device> Make(sk_sp<Recorder>, const SkImageInfo&);
|
||||
static sk_sp<Device> Make(sk_sp<Recorder>,
|
||||
sk_sp<TextureProxy>,
|
||||
sk_sp<SkColorSpace>,
|
||||
SkColorType,
|
||||
SkAlphaType);
|
||||
|
||||
sk_sp<Recorder> refRecorder() { return fRecorder; }
|
||||
|
||||
protected:
|
||||
private:
|
||||
// Clipping
|
||||
void onSave() override {}
|
||||
void onRestore() override {}
|
||||
@ -112,7 +118,6 @@ protected:
|
||||
sk_sp<SkSpecialImage> makeSpecial(const SkImage*) override;
|
||||
sk_sp<SkSpecialImage> snapSpecial(const SkIRect& subset, bool forceCopy = false) override;
|
||||
|
||||
private:
|
||||
// DrawFlags alters the effects used by drawShape.
|
||||
enum class DrawFlags : unsigned {
|
||||
kNone = 0b00,
|
||||
|
@ -7,9 +7,17 @@
|
||||
|
||||
#include "experimental/graphite/include/SkStuff.h"
|
||||
|
||||
#include "experimental/graphite/include/BackendTexture.h"
|
||||
#include "experimental/graphite/include/Context.h"
|
||||
#include "experimental/graphite/include/Recorder.h"
|
||||
#include "experimental/graphite/src/Caps.h"
|
||||
#include "experimental/graphite/src/ContextPriv.h"
|
||||
#include "experimental/graphite/src/Device.h"
|
||||
#include "experimental/graphite/src/Gpu.h"
|
||||
#include "experimental/graphite/src/ResourceProvider.h"
|
||||
#include "experimental/graphite/src/Surface_Graphite.h"
|
||||
#include "experimental/graphite/src/Texture.h"
|
||||
#include "experimental/graphite/src/TextureProxy.h"
|
||||
|
||||
sk_sp<SkSurface> MakeGraphite(sk_sp<skgpu::Recorder> recorder, const SkImageInfo& ii) {
|
||||
sk_sp<skgpu::Device> device = skgpu::Device::Make(std::move(recorder), ii);
|
||||
@ -19,3 +27,58 @@ sk_sp<SkSurface> MakeGraphite(sk_sp<skgpu::Recorder> recorder, const SkImageInfo
|
||||
|
||||
return sk_make_sp<skgpu::Surface_Graphite>(std::move(device));
|
||||
}
|
||||
|
||||
static bool validate_backend_texture(const skgpu::Caps* caps,
|
||||
const skgpu::BackendTexture& texture,
|
||||
SkColorType ct) {
|
||||
if (!texture.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const skgpu::TextureInfo& info = texture.info();
|
||||
if (!caps->areColorTypeAndTextureInfoCompatible(ct, info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!caps->isRenderable(info)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> MakeGraphiteFromBackendTexture(sk_sp<skgpu::Recorder> recorder,
|
||||
const skgpu::BackendTexture& beTexture,
|
||||
SkColorType colorType,
|
||||
sk_sp<SkColorSpace> colorSpace,
|
||||
const SkSurfaceProps* props) {
|
||||
|
||||
if (!recorder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!validate_backend_texture(recorder->context()->priv().gpu()->caps(),
|
||||
beTexture,
|
||||
colorType)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<skgpu::Texture> texture =
|
||||
recorder->context()->priv().resourceProvider()->createWrappedTexture(beTexture);
|
||||
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<skgpu::TextureProxy> proxy(new skgpu::TextureProxy(std::move(texture)));
|
||||
|
||||
sk_sp<skgpu::Device> device = skgpu::Device::Make(std::move(recorder),
|
||||
std::move(proxy),
|
||||
std::move(colorSpace),
|
||||
colorType,
|
||||
kPremul_SkAlphaType);
|
||||
if (!device) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sk_make_sp<skgpu::Surface_Graphite>(std::move(device));
|
||||
}
|
||||
|
@ -15,6 +15,11 @@ namespace skgpu {
|
||||
TextureProxy::TextureProxy(SkISize dimensions, const TextureInfo& info)
|
||||
: fDimensions(dimensions), fInfo(info) {}
|
||||
|
||||
TextureProxy::TextureProxy(sk_sp<Texture> texture)
|
||||
: fDimensions(texture->dimensions())
|
||||
, fInfo(texture->textureInfo())
|
||||
, fTexture(std::move(texture)) {}
|
||||
|
||||
TextureProxy::~TextureProxy() {}
|
||||
|
||||
bool TextureProxy::instantiate(ResourceProvider* resourceProvider) {
|
||||
|
@ -20,6 +20,7 @@ class Texture;
|
||||
class TextureProxy : public SkRefCnt {
|
||||
public:
|
||||
TextureProxy(SkISize dimensions, const TextureInfo& info);
|
||||
TextureProxy(sk_sp<Texture>);
|
||||
|
||||
~TextureProxy() override;
|
||||
|
||||
|
@ -37,7 +37,6 @@ public:
|
||||
|
||||
size_t getMinBufferAlignment() const { return this->isMac() ? 4 : 1; }
|
||||
|
||||
bool isTexturable(const skgpu::TextureInfo&) const override;
|
||||
bool isRenderable(const skgpu::TextureInfo&) const override;
|
||||
|
||||
private:
|
||||
@ -57,6 +56,8 @@ private:
|
||||
|
||||
bool onAreColorTypeAndTextureInfoCompatible(SkColorType,
|
||||
const skgpu::TextureInfo&) const override;
|
||||
|
||||
bool onIsTexturable(const skgpu::TextureInfo&) const override;
|
||||
bool isTexturable(MTLPixelFormat) const;
|
||||
bool isRenderable(MTLPixelFormat, uint32_t numSamples) const;
|
||||
|
||||
|
@ -311,7 +311,7 @@ skgpu::TextureInfo Caps::getDefaultDepthStencilTextureInfo(Mask<DepthStencilFlag
|
||||
return info;
|
||||
}
|
||||
|
||||
bool Caps::isTexturable(const skgpu::TextureInfo& info) const {
|
||||
bool Caps::onIsTexturable(const skgpu::TextureInfo& info) const {
|
||||
return info.mtlTextureSpec().fUsage & MTLTextureUsageShaderRead &&
|
||||
this->isTexturable((MTLPixelFormat)info.mtlTextureSpec().fFormat);
|
||||
}
|
||||
|
@ -9,11 +9,15 @@
|
||||
|
||||
#include "experimental/graphite/include/BackendTexture.h"
|
||||
#include "experimental/graphite/include/Context.h"
|
||||
#include "experimental/graphite/include/Recorder.h"
|
||||
#include "experimental/graphite/include/SkStuff.h"
|
||||
#include "experimental/graphite/src/Caps.h"
|
||||
#include "experimental/graphite/src/ContextPriv.h"
|
||||
#include "experimental/graphite/src/Gpu.h"
|
||||
#include "experimental/graphite/src/ResourceTypes.h"
|
||||
|
||||
#include "include/core/SkSurface.h"
|
||||
|
||||
using namespace skgpu;
|
||||
|
||||
namespace {
|
||||
@ -61,3 +65,59 @@ DEF_GRAPHITE_TEST_FOR_CONTEXTS(BackendTextureTest, reporter, context) {
|
||||
context->deleteBackendTexture(texture1);
|
||||
context->deleteBackendTexture(texture2);
|
||||
}
|
||||
|
||||
// Tests the wrapping of a BackendTexture in an SkSurface
|
||||
DEF_GRAPHITE_TEST_FOR_CONTEXTS(SurfaceBackendTextureTest, reporter, context) {
|
||||
// TODO: Right now this just tests very basic combinations of surfaces. This should be expanded
|
||||
// to conver a much broader set of things once we add more support in Graphite for different
|
||||
// formats, color types, etc.
|
||||
|
||||
auto caps = context->priv().gpu()->caps();
|
||||
sk_sp<Recorder> recorder = context->createRecorder();
|
||||
|
||||
TextureInfo info = caps->getDefaultSampledTextureInfo(kRGBA_8888_SkColorType,
|
||||
/*levelCount=*/1,
|
||||
Protected::kNo,
|
||||
Renderable::kYes);
|
||||
|
||||
auto texture = context->createBackendTexture(kSize, info);
|
||||
REPORTER_ASSERT(reporter, texture.isValid());
|
||||
|
||||
sk_sp<SkSurface> surface = MakeGraphiteFromBackendTexture(recorder,
|
||||
texture,
|
||||
kRGBA_8888_SkColorType,
|
||||
/*colorSpace=*/nullptr,
|
||||
/*props=*/nullptr);
|
||||
REPORTER_ASSERT(reporter, surface);
|
||||
|
||||
surface.reset();
|
||||
|
||||
// We should fail when trying to wrap the same texture in a surface with a non compatible
|
||||
// color type.
|
||||
surface = MakeGraphiteFromBackendTexture(recorder,
|
||||
texture,
|
||||
kAlpha_8_SkColorType,
|
||||
/*colorSpace=*/nullptr,
|
||||
/*props=*/nullptr);
|
||||
REPORTER_ASSERT(reporter, !surface);
|
||||
|
||||
context->deleteBackendTexture(texture);
|
||||
|
||||
// We should fail to make a wrap non renderable texture in a surface.
|
||||
info = caps->getDefaultSampledTextureInfo(kRGBA_8888_SkColorType,
|
||||
/*levelCount=*/1,
|
||||
Protected::kNo,
|
||||
Renderable::kNo);
|
||||
texture = context->createBackendTexture(kSize, info);
|
||||
REPORTER_ASSERT(reporter, texture.isValid());
|
||||
|
||||
surface = MakeGraphiteFromBackendTexture(recorder,
|
||||
texture,
|
||||
kRGBA_8888_SkColorType,
|
||||
/*colorSpace=*/nullptr,
|
||||
/*props=*/nullptr);
|
||||
|
||||
REPORTER_ASSERT(reporter, !surface);
|
||||
context->deleteBackendTexture(texture);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user