summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/core/SkMeshPriv.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/src/core/SkMeshPriv.h')
-rw-r--r--gfx/skia/skia/src/core/SkMeshPriv.h250
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