diff options
Diffstat (limited to 'gfx/skia/skia/src/core/SkMeshPriv.h')
-rw-r--r-- | gfx/skia/skia/src/core/SkMeshPriv.h | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/core/SkMeshPriv.h b/gfx/skia/skia/src/core/SkMeshPriv.h new file mode 100644 index 0000000000..a4f50e9bc4 --- /dev/null +++ b/gfx/skia/skia/src/core/SkMeshPriv.h @@ -0,0 +1,250 @@ +/* + * Copyright 2021 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkMeshPriv_DEFINED +#define SkMeshPriv_DEFINED + +#include "include/core/SkMesh.h" + +#ifdef SK_ENABLE_SKSL +#include "include/core/SkData.h" +#include "src/core/SkSLTypeShared.h" + +#if defined(SK_GANESH) +#include "include/gpu/GrDirectContext.h" +#include "include/private/gpu/ganesh/GrTypesPriv.h" +#include "src/gpu/ganesh/GrDirectContextPriv.h" +#include "src/gpu/ganesh/GrDrawingManager.h" +#include "src/gpu/ganesh/GrGpuBuffer.h" +#include "src/gpu/ganesh/GrResourceCache.h" +#include "src/gpu/ganesh/GrResourceProvider.h" +#endif + +struct SkMeshSpecificationPriv { + using Varying = SkMeshSpecification::Varying; + using Attribute = SkMeshSpecification::Attribute; + using ColorType = SkMeshSpecification::ColorType; + + static SkSpan<const Varying> Varyings(const SkMeshSpecification& spec) { + return SkSpan(spec.fVaryings); + } + + static const SkSL::Program* VS(const SkMeshSpecification& spec) { return spec.fVS.get(); } + static const SkSL::Program* FS(const SkMeshSpecification& spec) { return spec.fFS.get(); } + + static int Hash(const SkMeshSpecification& spec) { return spec.fHash; } + + static ColorType GetColorType(const SkMeshSpecification& spec) { return spec.fColorType; } + static bool HasColors(const SkMeshSpecification& spec) { + return GetColorType(spec) != ColorType::kNone; + } + + static SkColorSpace* ColorSpace(const SkMeshSpecification& spec) { + return spec.fColorSpace.get(); + } + + static SkAlphaType AlphaType(const SkMeshSpecification& spec) { return spec.fAlphaType; } + + static SkSLType VaryingTypeAsSLType(Varying::Type type) { + switch (type) { + case Varying::Type::kFloat: return SkSLType::kFloat; + case Varying::Type::kFloat2: return SkSLType::kFloat2; + case Varying::Type::kFloat3: return SkSLType::kFloat3; + case Varying::Type::kFloat4: return SkSLType::kFloat4; + case Varying::Type::kHalf: return SkSLType::kHalf; + case Varying::Type::kHalf2: return SkSLType::kHalf2; + case Varying::Type::kHalf3: return SkSLType::kHalf3; + case Varying::Type::kHalf4: return SkSLType::kHalf4; + } + SkUNREACHABLE; + } + +#if defined(SK_GANESH) + static GrVertexAttribType AttrTypeAsVertexAttribType(Attribute::Type type) { + switch (type) { + case Attribute::Type::kFloat: return kFloat_GrVertexAttribType; + case Attribute::Type::kFloat2: return kFloat2_GrVertexAttribType; + case Attribute::Type::kFloat3: return kFloat3_GrVertexAttribType; + case Attribute::Type::kFloat4: return kFloat4_GrVertexAttribType; + case Attribute::Type::kUByte4_unorm: return kUByte4_norm_GrVertexAttribType; + } + SkUNREACHABLE; + } +#endif + + static SkSLType AttrTypeAsSLType(Attribute::Type type) { + switch (type) { + case Attribute::Type::kFloat: return SkSLType::kFloat; + case Attribute::Type::kFloat2: return SkSLType::kFloat2; + case Attribute::Type::kFloat3: return SkSLType::kFloat3; + case Attribute::Type::kFloat4: return SkSLType::kFloat4; + case Attribute::Type::kUByte4_unorm: return SkSLType::kHalf4; + } + SkUNREACHABLE; + } + + static int PassthroughLocalCoordsVaryingIndex(const SkMeshSpecification& spec) { + return spec.fPassthroughLocalCoordsVaryingIndex; + } + + /** + * A varying is dead if it is never referenced OR it is only referenced as a passthrough for + * local coordinates. In the latter case it's index will returned as + * PassthroughLocalCoordsVaryingIndex. Our analysis is not very sophisticated so this is + * determined conservatively. + */ + static bool VaryingIsDead(const SkMeshSpecification& spec, int v) { + SkASSERT(v >= 0 && SkToSizeT(v) < spec.fVaryings.size()); + return (1 << v) & spec.fDeadVaryingMask; + } +}; + +struct SkMeshPriv { + class Buffer { + public: + virtual ~Buffer() = 0; + + Buffer() = default; + Buffer(const Buffer&) = delete; + + Buffer& operator=(const Buffer&) = delete; + + virtual const void* peek() const { return nullptr; } + +#if defined(SK_GANESH) + virtual sk_sp<const GrGpuBuffer> asGpuBuffer() const { return nullptr; } +#endif + }; + + class IB : public Buffer, public SkMesh::IndexBuffer {}; + class VB : public Buffer, public SkMesh::VertexBuffer {}; + + template <typename Base> class CpuBuffer final : public Base { + public: + ~CpuBuffer() override = default; + + static sk_sp<Base> Make(const void* data, size_t size); + + const void* peek() const override { return fData->data(); } + + size_t size() const override { return fData->size(); } + + private: + CpuBuffer(sk_sp<SkData> data) : fData(std::move(data)) {} + + bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) override; + + sk_sp<SkData> fData; + }; + + using CpuIndexBuffer = CpuBuffer<IB>; + using CpuVertexBuffer = CpuBuffer<VB>; + +#if defined(SK_GANESH) + template <typename Base, GrGpuBufferType> class GpuBuffer final : public Base { + public: + GpuBuffer() = default; + + ~GpuBuffer() override; + + static sk_sp<Base> Make(GrDirectContext*, const void* data, size_t size); + + sk_sp<const GrGpuBuffer> asGpuBuffer() const override { return fBuffer; } + + size_t size() const override { return fBuffer->size(); } + + private: + bool onUpdate(GrDirectContext*, const void* data, size_t offset, size_t size) override; + + sk_sp<GrGpuBuffer> fBuffer; + GrDirectContext::DirectContextID fContextID; + }; + + using GpuIndexBuffer = GpuBuffer<IB, GrGpuBufferType::kIndex >; + using GpuVertexBuffer = GpuBuffer<VB, GrGpuBufferType::kVertex>; +#endif // defined(SK_GANESH) + +private: +#if defined(SK_GANESH) + static bool UpdateGpuBuffer(GrDirectContext*, + sk_sp<GrGpuBuffer>, + const void*, + size_t offset, + size_t size); +#endif +}; + +inline SkMeshPriv::Buffer::~Buffer() = default; + +template <typename Base> sk_sp<Base> SkMeshPriv::CpuBuffer<Base>::Make(const void* data, + size_t size) { + SkASSERT(size); + sk_sp<SkData> storage; + if (data) { + storage = SkData::MakeWithCopy(data, size); + } else { + storage = SkData::MakeZeroInitialized(size); + } + return sk_sp<Base>(new CpuBuffer<Base>(std::move(storage))); +} + +template <typename Base> bool SkMeshPriv::CpuBuffer<Base>::onUpdate(GrDirectContext* dc, + const void* data, + size_t offset, + size_t size) { + if (dc) { + return false; + } + std::memcpy(SkTAddOffset<void>(fData->writable_data(), offset), data, size); + return true; +} + +#if defined(SK_GANESH) + +template <typename Base, GrGpuBufferType Type> SkMeshPriv::GpuBuffer<Base, Type>::~GpuBuffer() { + GrResourceCache::ReturnResourceFromThread(std::move(fBuffer), fContextID); +} + +template <typename Base, GrGpuBufferType Type> +sk_sp<Base> SkMeshPriv::GpuBuffer<Base, Type>::Make(GrDirectContext* dc, + const void* data, + size_t size) { + SkASSERT(dc); + + sk_sp<GrGpuBuffer> buffer = dc->priv().resourceProvider()->createBuffer( + size, + Type, + kStatic_GrAccessPattern, + data ? GrResourceProvider::ZeroInit::kNo : GrResourceProvider::ZeroInit::kYes); + if (!buffer) { + return nullptr; + } + + if (data && !buffer->updateData(data, 0, size, /*preserve=*/false)) { + return nullptr; + } + + auto result = new GpuBuffer; + result->fBuffer = std::move(buffer); + result->fContextID = dc->directContextID(); + return sk_sp<Base>(result); +} + + +template <typename Base, GrGpuBufferType Type> +bool SkMeshPriv::GpuBuffer<Base, Type>::onUpdate(GrDirectContext* dc, + const void* data, + size_t offset, + size_t size) { + return UpdateGpuBuffer(dc, fBuffer, data, offset, size); +} + +#endif // defined(SK_GANESH) + +#endif // SK_ENABLE_SKSL + +#endif |