Finish uniform support for SkMesh.
SkMesh now takes SkData that contains the uniform values. Change-Id: I286e7559ba692ce15925a54f59c2e829b6b5448f Reviewed-on: https://skia-review.googlesource.com/c/skia/+/546096 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
d29d446a7d
commit
3e08ec878d
173
gm/mesh.cpp
173
gm/mesh.cpp
@ -16,6 +16,7 @@
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "src/core/SkCanvasPriv.h"
|
||||
#include "src/core/SkMeshPriv.h"
|
||||
#include "tools/timer/TimeUtils.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -147,8 +148,9 @@ protected:
|
||||
mesh = SkMesh::Make(fSpecWithColor,
|
||||
SkMesh::Mode::kTriangleStrip,
|
||||
fColorVB,
|
||||
/*vertexCount= */ 4,
|
||||
/*vertexOffset=*/ 0,
|
||||
/*vertexCount= */4,
|
||||
/*vertexOffset=*/0,
|
||||
/*uniforms= */nullptr,
|
||||
kRect);
|
||||
} else {
|
||||
mesh = SkMesh::Make(fSpecWithNoColor,
|
||||
@ -156,6 +158,7 @@ protected:
|
||||
fNoColorVB,
|
||||
/*vertexCount=*/4,
|
||||
kNoColorOffset,
|
||||
/*uniforms=*/nullptr,
|
||||
kRect);
|
||||
}
|
||||
} else {
|
||||
@ -165,21 +168,23 @@ protected:
|
||||
mesh = SkMesh::MakeIndexed(fSpecWithColor,
|
||||
SkMesh::Mode::kTriangles,
|
||||
fColorIndexedVB,
|
||||
/*vertexCount=*/ 6,
|
||||
/*vertexCount=*/6,
|
||||
kColorIndexedOffset,
|
||||
std::move(ib),
|
||||
/*indexCount=*/6,
|
||||
kIndexOffset,
|
||||
/*uniforms=*/nullptr,
|
||||
kRect);
|
||||
} else {
|
||||
mesh = SkMesh::MakeIndexed(fSpecWithNoColor,
|
||||
SkMesh::Mode::kTriangles,
|
||||
fNoColorIndexedVB,
|
||||
/*vertexCount=*/ 6,
|
||||
/*vertexCount=*/6,
|
||||
/*vertexOffset=*/0,
|
||||
std::move(ib),
|
||||
/*indexCount=*/6,
|
||||
kIndexOffset,
|
||||
/*uniforms=*/nullptr,
|
||||
kRect);
|
||||
}
|
||||
}
|
||||
@ -418,8 +423,9 @@ protected:
|
||||
SkMesh mesh = SkMesh::Make(fSpecs[SpecIndex(unpremul, spin)],
|
||||
SkMesh::Mode::kTriangleStrip,
|
||||
fVB,
|
||||
/*vertexCount=*/ 4,
|
||||
/*vertexCount= */4,
|
||||
/*vertexOffset=*/0,
|
||||
/*uniforms= */nullptr,
|
||||
kRect);
|
||||
|
||||
SkPaint paint;
|
||||
@ -467,4 +473,161 @@ private:
|
||||
|
||||
DEF_GM(return new MeshColorSpaceGM;)
|
||||
|
||||
class MeshUniformsGM : public skiagm::GM {
|
||||
public:
|
||||
MeshUniformsGM() { this->onAnimate(0); }
|
||||
|
||||
protected:
|
||||
using Attribute = SkMeshSpecification::Attribute;
|
||||
using Varying = SkMeshSpecification::Varying;
|
||||
|
||||
SkISize onISize() override { return {140, 250}; }
|
||||
|
||||
void onOnceBeforeDraw() override {
|
||||
static const Attribute kAttributes[]{
|
||||
{Attribute::Type::kFloat2, 0, SkString{"pos"} },
|
||||
{Attribute::Type::kFloat2, 8, SkString{"coords"}},
|
||||
};
|
||||
static const Varying kVaryings[]{
|
||||
{Varying::Type::kFloat2, SkString{"coords"}},
|
||||
};
|
||||
// To exercise shared VS/FS uniforms we have a matrix that is applied twice, once in each
|
||||
// stage.
|
||||
static constexpr char kVS[] = R"(
|
||||
uniform float t[2];
|
||||
uniform half3x3 m;
|
||||
float2 main(in Attributes attributes, out Varyings varyings) {
|
||||
varyings.coords = (m*float3(attributes.coords + float2(t[0], t[1]), 1)).xy;
|
||||
return attributes.pos;
|
||||
}
|
||||
)";
|
||||
static constexpr char kFS[] = R"(
|
||||
uniform half3x3 m;
|
||||
layout(color) uniform half4 color;
|
||||
float2 main(Varyings varyings, out half4 c) {
|
||||
c = color;
|
||||
return (m*float3(varyings.coords, 1)).xy;
|
||||
}
|
||||
)";
|
||||
auto [spec, error] =
|
||||
SkMeshSpecification::Make(SkMakeSpan(kAttributes, SK_ARRAY_COUNT(kAttributes)),
|
||||
sizeof(Vertex),
|
||||
SkMakeSpan(kVaryings, SK_ARRAY_COUNT(kVaryings)),
|
||||
SkString(kVS),
|
||||
SkString(kFS),
|
||||
SkColorSpace::MakeSRGB(),
|
||||
kPremul_SkAlphaType);
|
||||
if (!spec) {
|
||||
SkDebugf("%s\n", error.c_str());
|
||||
}
|
||||
fSpec = std::move(spec);
|
||||
|
||||
SkColor colors[] = {SK_ColorWHITE, SK_ColorBLACK};
|
||||
fShader = SkGradientShader::MakeRadial(kGradCenter,
|
||||
.4f,
|
||||
colors,
|
||||
nullptr,
|
||||
2,
|
||||
SkTileMode::kMirror);
|
||||
|
||||
fVB = SkMesh::MakeVertexBuffer(nullptr, SkData::MakeWithoutCopy(kQuad, sizeof(kQuad)));
|
||||
}
|
||||
|
||||
SkString onShortName() override { return SkString("custommesh_uniforms"); }
|
||||
|
||||
DrawResult onDraw(SkCanvas* canvas, SkString* error) override {
|
||||
SkMatrix matrices[] {
|
||||
SkMatrix::MakeAll(-1, 0, 0, // self inverse so no effect.
|
||||
0, -1, 0,
|
||||
0, 0, 1),
|
||||
SkMatrix::RotateDeg(fDegrees/2.f, {0.5f, 0.5f}),
|
||||
};
|
||||
for (const auto& m : matrices) {
|
||||
auto unis = SkData::MakeUninitialized(fSpec->uniformSize());
|
||||
|
||||
SkPoint trans = -kCoordTrans;
|
||||
static_assert(sizeof(SkPoint) == 2*sizeof(float));
|
||||
|
||||
const SkMeshSpecification::Uniform* u = fSpec->findUniform("t");
|
||||
SkASSERT(u);
|
||||
std::memcpy(SkTAddOffset<void>(unis->writable_data(), u->offset),
|
||||
(void*)&trans,
|
||||
2*sizeof(float));
|
||||
|
||||
u = fSpec->findUniform("m");
|
||||
SkASSERT(u);
|
||||
for (size_t offset = u->offset, col = 0; col < 3; ++col) {
|
||||
for (size_t row = 0; row < 3; ++row, offset += sizeof(float)) {
|
||||
*SkTAddOffset<float>(unis->writable_data(), offset) = m.rc(row, col);
|
||||
}
|
||||
}
|
||||
|
||||
u = fSpec->findUniform("color");
|
||||
SkASSERT(u);
|
||||
std::memcpy(SkTAddOffset<void>(unis->writable_data(), u->offset),
|
||||
fColor.vec(),
|
||||
4*sizeof(float));
|
||||
|
||||
SkMesh mesh = SkMesh::Make(fSpec,
|
||||
SkMesh::Mode::kTriangleStrip,
|
||||
fVB,
|
||||
/*vertexCount= */4,
|
||||
/*vertexOffset=*/0,
|
||||
/*uniforms= */std::move(unis),
|
||||
kRect);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setShader(fShader);
|
||||
SkCanvasPriv::DrawMesh(canvas, mesh, SkBlender::Mode(SkBlendMode::kModulate), paint);
|
||||
|
||||
canvas->translate(0, kRect.height() + 10);
|
||||
}
|
||||
return DrawResult::kOk;
|
||||
}
|
||||
|
||||
bool onAnimate(double nanos) override {
|
||||
fDegrees = TimeUtils::NanosToSeconds(nanos) * 360.f/10.f + 45.f;
|
||||
// prime number periods, like locusts.
|
||||
fColor.fR = TimeUtils::SineWave(nanos, 13.f, 0.f, 0.f, 1.f);
|
||||
fColor.fG = TimeUtils::SineWave(nanos, 23.f, 5.f, 0.f, 1.f);
|
||||
fColor.fB = TimeUtils::SineWave(nanos, 11.f, 0.f, 0.f, 1.f);
|
||||
fColor.fA = 1.f;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Vertex {
|
||||
SkPoint pos;
|
||||
SkPoint tex;
|
||||
};
|
||||
|
||||
static constexpr auto kRect = SkRect::MakeLTRB(20, 20, 120, 120);
|
||||
|
||||
// Our logical tex coords are [0..1] but we insert an arbitrary translation that gets undone
|
||||
// with a uniform.
|
||||
static constexpr SkPoint kCoordTrans = {75, -37};
|
||||
static constexpr auto kCoordRect = SkRect::MakeXYWH(kCoordTrans.x(), kCoordTrans.y(), 1, 1);
|
||||
|
||||
static constexpr SkPoint kGradCenter = {0.3f, 0.2f};
|
||||
|
||||
static constexpr Vertex kQuad[] {
|
||||
{{kRect.left() , kRect.top() }, {kCoordRect.left() , kCoordRect.top()} },
|
||||
{{kRect.right(), kRect.top() }, {kCoordRect.right(), kCoordRect.top()} },
|
||||
{{kRect.left() , kRect.bottom()}, {kCoordRect.left() , kCoordRect.bottom()}},
|
||||
{{kRect.right(), kRect.bottom()}, {kCoordRect.right(), kCoordRect.bottom()}},
|
||||
};
|
||||
|
||||
float fDegrees;
|
||||
|
||||
SkColor4f fColor;
|
||||
|
||||
sk_sp<SkMesh::VertexBuffer> fVB;
|
||||
|
||||
sk_sp<SkMeshSpecification> fSpec;
|
||||
|
||||
sk_sp<SkShader> fShader;
|
||||
};
|
||||
|
||||
DEF_GM(return new MeshUniformsGM())
|
||||
|
||||
} // namespace skiagm
|
||||
|
@ -143,8 +143,17 @@ public:
|
||||
|
||||
SkSpan<const Attribute> attributes() const { return SkMakeSpan(fAttributes); }
|
||||
|
||||
/**
|
||||
* Combined size of all 'uniform' variables. When creating a SkMesh with this specification
|
||||
* provide an SkData of this size, containing values for all of those variables. Use uniforms()
|
||||
* to get the offset of each uniform within the SkData.
|
||||
*/
|
||||
size_t uniformSize() const;
|
||||
|
||||
/**
|
||||
* Provides info about individual uniforms including the offset into an SkData where each
|
||||
* uniform value should be placed.
|
||||
*/
|
||||
SkSpan<const Uniform> uniforms() const { return SkMakeSpan(fUniforms); }
|
||||
|
||||
/** Returns pointer to the named uniform variable's description, or nullptr if not found. */
|
||||
@ -215,6 +224,10 @@ private:
|
||||
*
|
||||
* If Make() is used the implicit index sequence is 0, 1, 2, 3, ... and vertexCount must be at least
|
||||
* 3.
|
||||
*
|
||||
* Both Make() and MakeIndexed() take a SkData with the uniform values. See
|
||||
* SkMeshSpecification::uniformSize() and SkMeshSpecification::uniforms() for sizing and packing
|
||||
* uniforms into the SkData.
|
||||
*/
|
||||
class SkMesh {
|
||||
public:
|
||||
@ -263,6 +276,7 @@ public:
|
||||
sk_sp<VertexBuffer>,
|
||||
size_t vertexCount,
|
||||
size_t vertexOffset,
|
||||
sk_sp<const SkData> uniforms,
|
||||
const SkRect& bounds);
|
||||
|
||||
static SkMesh MakeIndexed(sk_sp<SkMeshSpecification>,
|
||||
@ -273,6 +287,7 @@ public:
|
||||
sk_sp<IndexBuffer>,
|
||||
size_t indexCount,
|
||||
size_t indexOffset,
|
||||
sk_sp<const SkData> uniforms,
|
||||
const SkRect& bounds);
|
||||
|
||||
sk_sp<SkMeshSpecification> spec() const { return fSpec; }
|
||||
@ -289,6 +304,8 @@ public:
|
||||
size_t indexOffset() const { return fIOffset; }
|
||||
size_t indexCount() const { return fICount; }
|
||||
|
||||
sk_sp<const SkData> uniforms() const { return fUniforms; }
|
||||
|
||||
SkRect bounds() const { return fBounds; }
|
||||
|
||||
bool isValid() const;
|
||||
@ -303,6 +320,8 @@ private:
|
||||
sk_sp<VertexBuffer> fVB;
|
||||
sk_sp<IndexBuffer> fIB;
|
||||
|
||||
sk_sp<const SkData> fUniforms;
|
||||
|
||||
size_t fVOffset = 0; // Must be a multiple of spec->stride()
|
||||
size_t fVCount = 0;
|
||||
|
||||
|
@ -783,7 +783,7 @@ struct SK_API SkRect {
|
||||
|
||||
@return midpoint on x-axis
|
||||
*/
|
||||
SkScalar centerX() const {
|
||||
constexpr SkScalar centerX() const {
|
||||
// don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5
|
||||
return SkScalarHalf(fLeft) + SkScalarHalf(fRight);
|
||||
}
|
||||
@ -793,11 +793,16 @@ struct SK_API SkRect {
|
||||
|
||||
@return midpoint on y-axis
|
||||
*/
|
||||
SkScalar centerY() const {
|
||||
constexpr SkScalar centerY() const {
|
||||
// don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5
|
||||
return SkScalarHalf(fTop) + SkScalarHalf(fBottom);
|
||||
}
|
||||
|
||||
/** Returns the point this->centerX(), this->centerY().
|
||||
@return rectangle center
|
||||
*/
|
||||
constexpr SkPoint center() const { return {this->centerX(), this->centerY()}; }
|
||||
|
||||
/** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are
|
||||
equal to the corresponding members in b.
|
||||
|
||||
|
@ -501,14 +501,16 @@ SkMesh SkMesh::Make(sk_sp<SkMeshSpecification> spec,
|
||||
sk_sp<VertexBuffer> vb,
|
||||
size_t vertexCount,
|
||||
size_t vertexOffset,
|
||||
sk_sp<const SkData> uniforms,
|
||||
const SkRect& bounds) {
|
||||
SkMesh cm;
|
||||
cm.fSpec = std::move(spec);
|
||||
cm.fMode = mode;
|
||||
cm.fVB = std::move(vb);
|
||||
cm.fVCount = vertexCount;
|
||||
cm.fVOffset = vertexOffset;
|
||||
cm.fBounds = bounds;
|
||||
cm.fSpec = std::move(spec);
|
||||
cm.fMode = mode;
|
||||
cm.fVB = std::move(vb);
|
||||
cm.fUniforms = std::move(uniforms);
|
||||
cm.fVCount = vertexCount;
|
||||
cm.fVOffset = vertexOffset;
|
||||
cm.fBounds = bounds;
|
||||
return cm.validate() ? cm : SkMesh{};
|
||||
}
|
||||
|
||||
@ -520,17 +522,19 @@ SkMesh SkMesh::MakeIndexed(sk_sp<SkMeshSpecification> spec,
|
||||
sk_sp<IndexBuffer> ib,
|
||||
size_t indexCount,
|
||||
size_t indexOffset,
|
||||
sk_sp<const SkData> uniforms,
|
||||
const SkRect& bounds) {
|
||||
SkMesh cm;
|
||||
cm.fSpec = std::move(spec);
|
||||
cm.fMode = mode;
|
||||
cm.fVB = std::move(vb);
|
||||
cm.fVCount = vertexCount;
|
||||
cm.fVOffset = vertexOffset;
|
||||
cm.fIB = std::move(ib);
|
||||
cm.fICount = indexCount;
|
||||
cm.fIOffset = indexOffset;
|
||||
cm.fBounds = bounds;
|
||||
cm.fSpec = std::move(spec);
|
||||
cm.fMode = mode;
|
||||
cm.fVB = std::move(vb);
|
||||
cm.fVCount = vertexCount;
|
||||
cm.fVOffset = vertexOffset;
|
||||
cm.fIB = std::move(ib);
|
||||
cm.fUniforms = std::move(uniforms);
|
||||
cm.fICount = indexCount;
|
||||
cm.fIOffset = indexOffset;
|
||||
cm.fBounds = bounds;
|
||||
return cm.validate() ? cm : SkMesh{};
|
||||
}
|
||||
|
||||
@ -574,6 +578,12 @@ bool SkMesh::validate() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size_t uniformSize = fSpec->uniformSize()) {
|
||||
if (!fUniforms || fUniforms->size() < uniformSize) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ib) {
|
||||
if (fICount < min_vcount_for_mode(fMode)) {
|
||||
return false;
|
||||
|
@ -113,6 +113,59 @@ SkRuntimeEffect::Uniform SkRuntimeEffectPriv::VarAsUniform(const SkSL::Variable&
|
||||
SkASSERT(SkIsAlign4(*offset));
|
||||
return uni;
|
||||
}
|
||||
sk_sp<const SkData> SkRuntimeEffectPriv::TransformUniforms(
|
||||
SkSpan<const SkRuntimeEffect::Uniform> uniforms,
|
||||
sk_sp<const SkData> originalData,
|
||||
const SkColorSpace* dstCS) {
|
||||
SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
|
||||
dstCS, kUnpremul_SkAlphaType);
|
||||
return TransformUniforms(uniforms, std::move(originalData), steps);
|
||||
}
|
||||
|
||||
sk_sp<const SkData> SkRuntimeEffectPriv::TransformUniforms(
|
||||
SkSpan<const SkRuntimeEffect::Uniform> uniforms,
|
||||
sk_sp<const SkData> originalData,
|
||||
const SkColorSpaceXformSteps& steps) {
|
||||
using Flags = SkRuntimeEffect::Uniform::Flags;
|
||||
using Type = SkRuntimeEffect::Uniform::Type;
|
||||
|
||||
sk_sp<SkData> data = nullptr;
|
||||
auto writableData = [&]() {
|
||||
if (!data) {
|
||||
data = SkData::MakeWithCopy(originalData->data(), originalData->size());
|
||||
}
|
||||
return data->writable_data();
|
||||
};
|
||||
|
||||
for (const auto& u : uniforms) {
|
||||
if (u.flags & Flags::kColor_Flag) {
|
||||
SkASSERT(u.type == Type::kFloat3 || u.type == Type::kFloat4);
|
||||
if (steps.flags.mask()) {
|
||||
float* color = SkTAddOffset<float>(writableData(), u.offset);
|
||||
if (u.type == Type::kFloat4) {
|
||||
// RGBA, easy case
|
||||
for (int i = 0; i < u.count; ++i) {
|
||||
steps.apply(color);
|
||||
color += 4;
|
||||
}
|
||||
} else {
|
||||
// RGB, need to pad out to include alpha. Technically, this isn't necessary,
|
||||
// because steps shouldn't include unpremul or premul, and thus shouldn't
|
||||
// read or write the fourth element. But let's be safe.
|
||||
float rgba[4];
|
||||
for (int i = 0; i < u.count; ++i) {
|
||||
memcpy(rgba, color, 3 * sizeof(float));
|
||||
rgba[3] = 1.0f;
|
||||
steps.apply(rgba);
|
||||
memcpy(color, rgba, 3 * sizeof(float));
|
||||
color += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return data ? data : originalData;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -788,52 +841,6 @@ const SkFilterColorProgram* SkRuntimeEffect::getFilterColorProgram() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static sk_sp<const SkData> get_xformed_uniforms(const SkRuntimeEffect* effect,
|
||||
sk_sp<const SkData> baseUniforms,
|
||||
const SkColorSpace* dstCS) {
|
||||
using Flags = SkRuntimeEffect::Uniform::Flags;
|
||||
using Type = SkRuntimeEffect::Uniform::Type;
|
||||
SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
|
||||
dstCS, kUnpremul_SkAlphaType);
|
||||
|
||||
sk_sp<SkData> uniforms = nullptr;
|
||||
auto writableData = [&]() {
|
||||
if (!uniforms) {
|
||||
uniforms = SkData::MakeWithCopy(baseUniforms->data(), baseUniforms->size());
|
||||
}
|
||||
return uniforms->writable_data();
|
||||
};
|
||||
|
||||
for (const auto& v : effect->uniforms()) {
|
||||
if (v.flags & Flags::kColor_Flag) {
|
||||
SkASSERT(v.type == Type::kFloat3 || v.type == Type::kFloat4);
|
||||
if (steps.flags.mask()) {
|
||||
float* color = SkTAddOffset<float>(writableData(), v.offset);
|
||||
if (v.type == Type::kFloat4) {
|
||||
// RGBA, easy case
|
||||
for (int i = 0; i < v.count; ++i) {
|
||||
steps.apply(color);
|
||||
color += 4;
|
||||
}
|
||||
} else {
|
||||
// RGB, need to pad out to include alpha. Technically, this isn't necessary,
|
||||
// because steps shouldn't include unpremul or premul, and thus shouldn't
|
||||
// read or write the fourth element. But let's be safe.
|
||||
float rgba[4];
|
||||
for (int i = 0; i < v.count; ++i) {
|
||||
memcpy(rgba, color, 3 * sizeof(float));
|
||||
rgba[3] = 1.0f;
|
||||
steps.apply(rgba);
|
||||
memcpy(color, rgba, 3 * sizeof(float));
|
||||
color += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uniforms ? uniforms : baseUniforms;
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
static GrFPResult make_effect_fp(sk_sp<SkRuntimeEffect> effect,
|
||||
const char* name,
|
||||
@ -968,8 +975,10 @@ public:
|
||||
GrFPResult asFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
|
||||
GrRecordingContext* context,
|
||||
const GrColorInfo& colorInfo) const override {
|
||||
sk_sp<const SkData> uniforms =
|
||||
get_xformed_uniforms(fEffect.get(), fUniforms, colorInfo.colorSpace());
|
||||
sk_sp<const SkData> uniforms = SkRuntimeEffectPriv::TransformUniforms(
|
||||
fEffect->uniforms(),
|
||||
fUniforms,
|
||||
colorInfo.colorSpace());
|
||||
SkASSERT(uniforms);
|
||||
|
||||
SkOverrideDeviceMatrixProvider matrixProvider(SkMatrix::I());
|
||||
@ -991,8 +1000,10 @@ public:
|
||||
skvm::Color onProgram(skvm::Builder* p, skvm::Color c,
|
||||
const SkColorInfo& colorInfo,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
|
||||
sk_sp<const SkData> inputs =
|
||||
get_xformed_uniforms(fEffect.get(), fUniforms, colorInfo.colorSpace());
|
||||
sk_sp<const SkData> inputs = SkRuntimeEffectPriv::TransformUniforms(
|
||||
fEffect->uniforms(),
|
||||
fUniforms,
|
||||
colorInfo.colorSpace());
|
||||
SkASSERT(inputs);
|
||||
|
||||
RuntimeEffectVMCallbacks callbacks(p, uniforms, alloc, fChildren, c, colorInfo);
|
||||
@ -1017,7 +1028,10 @@ public:
|
||||
}
|
||||
|
||||
// Get our specific uniform values
|
||||
sk_sp<const SkData> inputs = get_xformed_uniforms(fEffect.get(), fUniforms, dstCS);
|
||||
sk_sp<const SkData> inputs = SkRuntimeEffectPriv::TransformUniforms(
|
||||
fEffect->uniforms(),
|
||||
fUniforms,
|
||||
dstCS);
|
||||
SkASSERT(inputs);
|
||||
|
||||
auto evalChild = [&](int index, SkPMColor4f inColor) {
|
||||
@ -1116,8 +1130,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<const SkData> uniforms =
|
||||
get_xformed_uniforms(fEffect.get(), fUniforms, args.fDstColorInfo->colorSpace());
|
||||
sk_sp<const SkData> uniforms = SkRuntimeEffectPriv::TransformUniforms(
|
||||
fEffect->uniforms(),
|
||||
fUniforms,
|
||||
args.fDstColorInfo->colorSpace());
|
||||
SkASSERT(uniforms);
|
||||
|
||||
auto [success, fp] = make_effect_fp(fEffect,
|
||||
@ -1144,8 +1160,9 @@ public:
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
const SkColorInfo& colorInfo,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
|
||||
sk_sp<const SkData> inputs =
|
||||
get_xformed_uniforms(fEffect.get(), fUniforms, colorInfo.colorSpace());
|
||||
sk_sp<const SkData> inputs = SkRuntimeEffectPriv::TransformUniforms(fEffect->uniforms(),
|
||||
fUniforms,
|
||||
colorInfo.colorSpace());
|
||||
SkASSERT(inputs);
|
||||
|
||||
SkMatrix inv;
|
||||
@ -1252,8 +1269,9 @@ public:
|
||||
skvm::Color onProgram(skvm::Builder* p, skvm::Color src, skvm::Color dst,
|
||||
const SkColorInfo& colorInfo, skvm::Uniforms* uniforms,
|
||||
SkArenaAlloc* alloc) const override {
|
||||
sk_sp<const SkData> inputs = get_xformed_uniforms(fEffect.get(), fUniforms,
|
||||
colorInfo.colorSpace());
|
||||
sk_sp<const SkData> inputs = SkRuntimeEffectPriv::TransformUniforms(fEffect->uniforms(),
|
||||
fUniforms,
|
||||
colorInfo.colorSpace());
|
||||
SkASSERT(inputs);
|
||||
|
||||
RuntimeEffectVMCallbacks callbacks(p, uniforms, alloc, fChildren, src, colorInfo);
|
||||
@ -1272,8 +1290,10 @@ public:
|
||||
std::unique_ptr<GrFragmentProcessor> srcFP,
|
||||
std::unique_ptr<GrFragmentProcessor> dstFP,
|
||||
const GrFPArgs& args) const override {
|
||||
sk_sp<const SkData> uniforms = get_xformed_uniforms(fEffect.get(), fUniforms,
|
||||
args.fDstColorInfo->colorSpace());
|
||||
sk_sp<const SkData> uniforms = SkRuntimeEffectPriv::TransformUniforms(
|
||||
fEffect->uniforms(),
|
||||
fUniforms,
|
||||
args.fDstColorInfo->colorSpace());
|
||||
SkASSERT(uniforms);
|
||||
auto [success, fp] = make_effect_fp(fEffect,
|
||||
"runtime_blender",
|
||||
@ -1380,7 +1400,9 @@ sk_sp<SkImage> SkRuntimeEffect::makeImage(GrRecordingContext* rContext,
|
||||
if (!fillContext) {
|
||||
return nullptr;
|
||||
}
|
||||
uniforms = get_xformed_uniforms(this, std::move(uniforms), resultInfo.colorSpace());
|
||||
uniforms = SkRuntimeEffectPriv::TransformUniforms(this->uniforms(),
|
||||
std::move(uniforms),
|
||||
resultInfo.colorSpace());
|
||||
SkASSERT(uniforms);
|
||||
|
||||
SkOverrideDeviceMatrixProvider matrixProvider(SkMatrix::I());
|
||||
|
@ -21,6 +21,8 @@ class Variable;
|
||||
class Context;
|
||||
}
|
||||
|
||||
struct SkColorSpaceXformSteps;
|
||||
|
||||
class SkRuntimeEffectPriv {
|
||||
public:
|
||||
// Helper function when creating an effect for a GrSkSLFP that verifies an effect will
|
||||
@ -42,6 +44,15 @@ public:
|
||||
static SkRuntimeEffect::Uniform VarAsUniform(const SkSL::Variable&,
|
||||
const SkSL::Context&,
|
||||
size_t* offset);
|
||||
|
||||
// If there are layout(color) uniforms then this performs color space transformation on the
|
||||
// color values and returns a new SkData. Otherwise, the original data is returned.
|
||||
static sk_sp<const SkData> TransformUniforms(SkSpan<const SkRuntimeEffect::Uniform> uniforms,
|
||||
sk_sp<const SkData> originalData,
|
||||
const SkColorSpaceXformSteps&);
|
||||
static sk_sp<const SkData> TransformUniforms(SkSpan<const SkRuntimeEffect::Uniform> uniforms,
|
||||
sk_sp<const SkData> originalData,
|
||||
const SkColorSpace* dstCS);
|
||||
};
|
||||
|
||||
// These internal APIs for creating runtime effects vary from the public API in two ways:
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "include/core/SkMesh.h"
|
||||
#include "src/core/SkArenaAlloc.h"
|
||||
#include "src/core/SkMeshPriv.h"
|
||||
#include "src/core/SkRuntimeEffectPriv.h"
|
||||
#include "src/core/SkVerticesPriv.h"
|
||||
#include "src/gpu/BufferWriter.h"
|
||||
#include "src/gpu/KeyBuilder.h"
|
||||
@ -24,6 +25,7 @@
|
||||
#include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
|
||||
#include "src/sksl/codegen/SkSLPipelineStageCodeGenerator.h"
|
||||
#include "src/sksl/ir/SkSLProgram.h"
|
||||
#include "src/sksl/ir/SkSLVarDeclarations.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -42,13 +44,15 @@ public:
|
||||
sk_sp<GrColorSpaceXform> colorSpaceXform,
|
||||
const SkMatrix& viewMatrix,
|
||||
const std::optional<SkPMColor4f>& color,
|
||||
bool needsLocalCoords) {
|
||||
bool needsLocalCoords,
|
||||
sk_sp<const SkData> uniforms) {
|
||||
return arena->make([&](void* ptr) {
|
||||
return new (ptr) MeshGP(std::move(spec),
|
||||
std::move(colorSpaceXform),
|
||||
viewMatrix,
|
||||
std::move(color),
|
||||
needsLocalCoords);
|
||||
needsLocalCoords,
|
||||
std::move(uniforms));
|
||||
});
|
||||
}
|
||||
|
||||
@ -73,11 +77,43 @@ private:
|
||||
void setData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrShaderCaps& shaderCaps,
|
||||
const GrGeometryProcessor& geomProc) override {
|
||||
const auto& cmgp = geomProc.cast<MeshGP>();
|
||||
SetTransform(pdman, shaderCaps, fViewMatrixUniform, cmgp.fViewMatrix, &fViewMatrix);
|
||||
fColorSpaceHelper.setData(pdman, cmgp.fColorSpaceXform.get());
|
||||
const auto& mgp = geomProc.cast<MeshGP>();
|
||||
SetTransform(pdman, shaderCaps, fViewMatrixUniform, mgp.fViewMatrix, &fViewMatrix);
|
||||
fColorSpaceHelper.setData(pdman, mgp.fColorSpaceXform.get());
|
||||
if (fColorUniform.isValid()) {
|
||||
pdman.set4fv(fColorUniform, 1, cmgp.fColor.vec());
|
||||
pdman.set4fv(fColorUniform, 1, mgp.fColor.vec());
|
||||
}
|
||||
if (!mgp.fSpec->uniformSize()) {
|
||||
return;
|
||||
}
|
||||
SkASSERT(mgp.fUniforms);
|
||||
SkASSERT(mgp.fUniforms->size() >= mgp.fSpec->uniformSize());
|
||||
using Type = SkMeshSpecification::Uniform::Type;
|
||||
const void* data = mgp.fUniforms->data();
|
||||
size_t i = 0;
|
||||
for (const auto& u : mgp.fSpec->uniforms()) {
|
||||
const UniformHandle& handle = fSpecUniformHandles[i++];
|
||||
auto floatData = [=] { return SkTAddOffset<const float>(data, u.offset); };
|
||||
auto intData = [=] { return SkTAddOffset<const int>(data, u.offset); };
|
||||
switch (u.type) {
|
||||
case Type::kFloat: pdman.set1fv(handle, u.count, floatData()); break;
|
||||
case Type::kFloat2: pdman.set2fv(handle, u.count, floatData()); break;
|
||||
case Type::kFloat3: pdman.set3fv(handle, u.count, floatData()); break;
|
||||
case Type::kFloat4: pdman.set4fv(handle, u.count, floatData()); break;
|
||||
|
||||
case Type::kFloat2x2: pdman.setMatrix2fv(handle, u.count, floatData()); break;
|
||||
case Type::kFloat3x3: pdman.setMatrix3fv(handle, u.count, floatData()); break;
|
||||
case Type::kFloat4x4: pdman.setMatrix4fv(handle, u.count, floatData()); break;
|
||||
|
||||
case Type::kInt: pdman.set1iv(handle, u.count, intData()); break;
|
||||
case Type::kInt2: pdman.set2iv(handle, u.count, intData()); break;
|
||||
case Type::kInt3: pdman.set3iv(handle, u.count, intData()); break;
|
||||
case Type::kInt4: pdman.set4iv(handle, u.count, intData()); break;
|
||||
|
||||
default:
|
||||
SkDEBUGFAIL("Unsupported uniform type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,13 +121,65 @@ private:
|
||||
class MeshCallbacks : public SkSL::PipelineStage::Callbacks {
|
||||
public:
|
||||
MeshCallbacks(Impl* self,
|
||||
const MeshGP& gp,
|
||||
GrGLSLShaderBuilder* builder,
|
||||
GrGLSLUniformHandler* uniformHandler,
|
||||
const char* mainName,
|
||||
const SkSL::Context& context)
|
||||
: fSelf(self), fBuilder(builder), fMainName(mainName), fContext(context) {}
|
||||
: fSelf(self)
|
||||
, fGP(gp)
|
||||
, fBuilder(builder)
|
||||
, fUniformHandler(uniformHandler)
|
||||
, fMainName(mainName)
|
||||
, fContext(context) {}
|
||||
|
||||
std::string declareUniform(const SkSL::VarDeclaration* decl) override {
|
||||
SK_ABORT("uniforms not allowed");
|
||||
const SkSL::Variable& var = decl->var();
|
||||
SkASSERT(!var.type().isOpaque());
|
||||
|
||||
const SkSL::Type* type = &var.type();
|
||||
bool isArray = false;
|
||||
if (type->isArray()) {
|
||||
type = &type->componentType();
|
||||
isArray = true;
|
||||
}
|
||||
|
||||
SkSLType gpuType;
|
||||
SkAssertResult(SkSL::type_to_sksltype(fContext, *type, &gpuType));
|
||||
|
||||
SkString name(var.name());
|
||||
const SkSpan<const SkMeshSpecification::Uniform> uniforms = fGP.fSpec->uniforms();
|
||||
auto it = std::find_if(uniforms.begin(),
|
||||
uniforms.end(),
|
||||
[&name](SkMeshSpecification::Uniform uniform) {
|
||||
return uniform.name == name;
|
||||
});
|
||||
SkASSERT(it != uniforms.end());
|
||||
|
||||
UniformHandle* handle = &fSelf->fSpecUniformHandles[it - uniforms.begin()];
|
||||
if (handle->isValid()) {
|
||||
const GrShaderVar& uniformVar = fUniformHandler->getUniformVariable(*handle);
|
||||
return std::string(uniformVar.getName().c_str());
|
||||
}
|
||||
|
||||
const SkMeshSpecification::Uniform& uniform = *it;
|
||||
GrShaderFlags shaderFlags = kNone_GrShaderFlags;
|
||||
if (uniform.flags & SkMeshSpecification::Uniform::Flags::kVertex_Flag) {
|
||||
shaderFlags |= kVertex_GrShaderFlag;
|
||||
}
|
||||
if (uniform.flags & SkMeshSpecification::Uniform::Flags::kFragment_Flag) {
|
||||
shaderFlags |= kFragment_GrShaderFlag;
|
||||
}
|
||||
SkASSERT(shaderFlags != kNone_GrShaderFlags);
|
||||
|
||||
const char* mangledName = nullptr;
|
||||
*handle = fUniformHandler->addUniformArray(&fGP,
|
||||
shaderFlags,
|
||||
gpuType,
|
||||
name.c_str(),
|
||||
isArray ? var.type().columns() : 0,
|
||||
&mangledName);
|
||||
return std::string(mangledName);
|
||||
}
|
||||
|
||||
std::string getMangledName(const char* name) override {
|
||||
@ -136,28 +224,38 @@ private:
|
||||
SK_ABORT("Color transform intrinsics not allowed.");
|
||||
}
|
||||
|
||||
Impl* fSelf;
|
||||
GrGLSLShaderBuilder* fBuilder;
|
||||
const char* fMainName;
|
||||
const SkSL::Context& fContext;
|
||||
Impl* fSelf;
|
||||
const MeshGP& fGP;
|
||||
GrGLSLShaderBuilder* fBuilder;
|
||||
GrGLSLUniformHandler* fUniformHandler;
|
||||
const char* fMainName;
|
||||
const SkSL::Context& fContext;
|
||||
};
|
||||
|
||||
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
|
||||
const MeshGP& cmgp = args.fGeomProc.cast<MeshGP>();
|
||||
const MeshGP& mgp = args.fGeomProc.cast<MeshGP>();
|
||||
GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
|
||||
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
|
||||
|
||||
SkASSERT(fSpecUniformHandles.empty());
|
||||
fSpecUniformHandles.resize(mgp.fSpec->uniforms().size());
|
||||
|
||||
////// VS
|
||||
|
||||
// emit attributes
|
||||
varyingHandler->emitAttributes(cmgp);
|
||||
varyingHandler->emitAttributes(mgp);
|
||||
|
||||
// Define the user's vert function.
|
||||
SkString userVertName = vertBuilder->getMangledFunctionName("custom_mesh_vs");
|
||||
const SkSL::Program* customVS = SkMeshSpecificationPriv::VS(*cmgp.fSpec);
|
||||
MeshCallbacks vsCallbacks(this, vertBuilder, userVertName.c_str(), *customVS->fContext);
|
||||
const SkSL::Program* customVS = SkMeshSpecificationPriv::VS(*mgp.fSpec);
|
||||
MeshCallbacks vsCallbacks(this,
|
||||
mgp,
|
||||
vertBuilder,
|
||||
uniformHandler,
|
||||
userVertName.c_str(),
|
||||
*customVS->fContext);
|
||||
SkSL::PipelineStage::ConvertProgram(*customVS,
|
||||
/*sampleCoords=*/"",
|
||||
/*inputColor=*/"",
|
||||
@ -168,10 +266,10 @@ private:
|
||||
vertBuilder->codeAppendf("%s attributes;",
|
||||
vsCallbacks.getMangledName("Attributes").c_str());
|
||||
size_t i = 0;
|
||||
SkASSERT(cmgp.vertexAttributes().count() == (int)cmgp.fSpec->attributes().size());
|
||||
for (auto attr : cmgp.vertexAttributes()) {
|
||||
SkASSERT(mgp.vertexAttributes().count() == (int)mgp.fSpec->attributes().size());
|
||||
for (auto attr : mgp.vertexAttributes()) {
|
||||
vertBuilder->codeAppendf("attributes.%s = %s;",
|
||||
cmgp.fSpec->attributes()[i++].name.c_str(),
|
||||
mgp.fSpec->attributes()[i++].name.c_str(),
|
||||
attr.name());
|
||||
}
|
||||
|
||||
@ -183,8 +281,8 @@ private:
|
||||
|
||||
// Unpack the varyings from the struct into individual varyings.
|
||||
std::vector<GrGLSLVarying> varyings;
|
||||
varyings.reserve(SkMeshSpecificationPriv::Varyings(*cmgp.fSpec).size());
|
||||
for (const auto& v : SkMeshSpecificationPriv::Varyings(*cmgp.fSpec)) {
|
||||
varyings.reserve(SkMeshSpecificationPriv::Varyings(*mgp.fSpec).size());
|
||||
for (const auto& v : SkMeshSpecificationPriv::Varyings(*mgp.fSpec)) {
|
||||
varyings.emplace_back(SkMeshSpecificationPriv::VaryingTypeAsSLType(v.type));
|
||||
varyingHandler->addVarying(v.name.c_str(), &varyings.back());
|
||||
vertBuilder->codeAppendf("%s = varyings.%s;",
|
||||
@ -198,7 +296,7 @@ private:
|
||||
*args.fShaderCaps,
|
||||
gpArgs,
|
||||
"pos",
|
||||
cmgp.fViewMatrix,
|
||||
mgp.fViewMatrix,
|
||||
&fViewMatrixUniform);
|
||||
|
||||
////// FS
|
||||
@ -208,8 +306,13 @@ private:
|
||||
|
||||
// Define the user's frag function.
|
||||
SkString userFragName = fragBuilder->getMangledFunctionName("custom_mesh_fs");
|
||||
const SkSL::Program* customFS = SkMeshSpecificationPriv::FS(*cmgp.fSpec);
|
||||
MeshCallbacks fsCallbacks(this, fragBuilder, userFragName.c_str(), *customFS->fContext);
|
||||
const SkSL::Program* customFS = SkMeshSpecificationPriv::FS(*mgp.fSpec);
|
||||
MeshCallbacks fsCallbacks(this,
|
||||
mgp,
|
||||
fragBuilder,
|
||||
uniformHandler,
|
||||
userFragName.c_str(),
|
||||
*customFS->fContext);
|
||||
SkSL::PipelineStage::ConvertProgram(*customFS,
|
||||
/*sampleCoords=*/"",
|
||||
/*inputColor=*/"",
|
||||
@ -220,15 +323,15 @@ private:
|
||||
fragBuilder->codeAppendf("%s varyings;",
|
||||
fsCallbacks.getMangledName("Varyings").c_str());
|
||||
i = 0;
|
||||
for (const auto& varying : SkMeshSpecificationPriv::Varyings(*cmgp.fSpec)) {
|
||||
for (const auto& varying : SkMeshSpecificationPriv::Varyings(*mgp.fSpec)) {
|
||||
fragBuilder->codeAppendf("varyings.%s = %s;",
|
||||
varying.name.c_str(),
|
||||
varyings[i++].vsOut());
|
||||
}
|
||||
SkMeshSpecificationPriv::ColorType meshColorType =
|
||||
SkMeshSpecificationPriv::GetColorType(*cmgp.fSpec);
|
||||
SkMeshSpecificationPriv::GetColorType(*mgp.fSpec);
|
||||
const char* uniformColorName = nullptr;
|
||||
if (cmgp.fColor != SK_PMColor4fILLEGAL) {
|
||||
if (mgp.fColor != SK_PMColor4fILLEGAL) {
|
||||
fColorUniform = uniformHandler->addUniform(nullptr,
|
||||
kFragment_GrShaderFlag,
|
||||
SkSLType::kHalf4,
|
||||
@ -236,7 +339,7 @@ private:
|
||||
&uniformColorName);
|
||||
}
|
||||
SkString localCoordAssignment;
|
||||
if (SkMeshSpecificationPriv::HasLocalCoords(*cmgp.fSpec) && cmgp.fNeedsLocalCoords) {
|
||||
if (SkMeshSpecificationPriv::HasLocalCoords(*mgp.fSpec) && mgp.fNeedsLocalCoords) {
|
||||
localCoordAssignment = "float2 local =";
|
||||
}
|
||||
if (meshColorType == SkMeshSpecificationPriv::ColorType::kNone) {
|
||||
@ -247,7 +350,7 @@ private:
|
||||
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, uniformColorName);
|
||||
} else {
|
||||
fColorSpaceHelper.emitCode(uniformHandler,
|
||||
cmgp.fColorSpaceXform.get(),
|
||||
mgp.fColorSpaceXform.get(),
|
||||
kFragment_GrShaderFlag);
|
||||
if (meshColorType == SkMeshSpecificationPriv::ColorType::kFloat4) {
|
||||
fragBuilder->codeAppendf("float4 color;");
|
||||
@ -266,8 +369,8 @@ private:
|
||||
fragBuilder->appendColorGamutXform(&xformedColor, color, &fColorSpaceHelper);
|
||||
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, xformedColor.c_str());
|
||||
}
|
||||
if (cmgp.fNeedsLocalCoords) {
|
||||
if (SkMeshSpecificationPriv::HasLocalCoords(*cmgp.fSpec)) {
|
||||
if (mgp.fNeedsLocalCoords) {
|
||||
if (SkMeshSpecificationPriv::HasLocalCoords(*mgp.fSpec)) {
|
||||
gpArgs->fLocalCoordVar = GrShaderVar("local", SkSLType::kFloat2);
|
||||
gpArgs->fLocalCoordShader = kFragment_GrShaderType;
|
||||
} else {
|
||||
@ -280,8 +383,9 @@ private:
|
||||
private:
|
||||
SkMatrix fViewMatrix = SkMatrix::InvalidMatrix();
|
||||
|
||||
UniformHandle fViewMatrixUniform;
|
||||
UniformHandle fColorUniform;
|
||||
UniformHandle fViewMatrixUniform;
|
||||
UniformHandle fColorUniform;
|
||||
std::vector<UniformHandle> fSpecUniformHandles;
|
||||
|
||||
GrGLSLColorSpaceXformHelper fColorSpaceHelper;
|
||||
};
|
||||
@ -290,9 +394,11 @@ private:
|
||||
sk_sp<GrColorSpaceXform> colorSpaceXform,
|
||||
const SkMatrix& viewMatrix,
|
||||
const std::optional<SkPMColor4f>& color,
|
||||
bool needsLocalCoords)
|
||||
bool needsLocalCoords,
|
||||
sk_sp<const SkData> uniforms)
|
||||
: INHERITED(kVerticesGP_ClassID)
|
||||
, fSpec(std::move(spec))
|
||||
, fUniforms(std::move(uniforms))
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fColorSpaceXform(std::move(colorSpaceXform))
|
||||
, fNeedsLocalCoords(needsLocalCoords) {
|
||||
@ -308,6 +414,7 @@ private:
|
||||
}
|
||||
|
||||
sk_sp<SkMeshSpecification> fSpec;
|
||||
sk_sp<const SkData> fUniforms;
|
||||
std::vector<Attribute> fAttributes;
|
||||
SkMatrix fViewMatrix;
|
||||
SkPMColor4f fColor;
|
||||
@ -463,6 +570,7 @@ private:
|
||||
sk_sp<GrColorSpaceXform> fColorSpaceXform;
|
||||
SkPMColor4f fColor; // Used if no color from spec or analysis overrides.
|
||||
SkMatrix fViewMatrix;
|
||||
sk_sp<const SkData> fUniforms;
|
||||
int fVertexCount;
|
||||
int fIndexCount;
|
||||
GrSimpleMesh* fMesh = nullptr;
|
||||
@ -551,6 +659,13 @@ MeshOp::MeshOp(GrProcessorSet* processorSet,
|
||||
fMeshes.emplace_back(mesh);
|
||||
|
||||
fSpecification = mesh.spec();
|
||||
if (fColorSpaceXform) {
|
||||
fUniforms = SkRuntimeEffectPriv::TransformUniforms(mesh.spec()->uniforms(),
|
||||
mesh.uniforms(),
|
||||
fColorSpaceXform->steps());
|
||||
} else {
|
||||
fUniforms = mesh.uniforms();
|
||||
}
|
||||
|
||||
fVertexCount = fMeshes.back().vertexCount();
|
||||
fIndexCount = fMeshes.back().indexCount();
|
||||
@ -704,7 +819,8 @@ GrGeometryProcessor* MeshOp::makeGP(SkArenaAlloc* arena) {
|
||||
fColorSpaceXform,
|
||||
vm,
|
||||
color,
|
||||
fHelper.usesLocalCoords());
|
||||
fHelper.usesLocalCoords(),
|
||||
fUniforms);
|
||||
}
|
||||
|
||||
void MeshOp::onCreateProgramInfo(const GrCaps* caps,
|
||||
@ -839,6 +955,17 @@ GrOp::CombineResult MeshOp::onCombineIfPossible(GrOp* t, SkArenaAlloc*, const Gr
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
|
||||
if (fSpecification->uniformSize()) {
|
||||
size_t size = fSpecification->uniformSize();
|
||||
SkASSERT(fUniforms);
|
||||
SkASSERT(fUniforms->size() >= size);
|
||||
SkASSERT(that->fUniforms);
|
||||
SkASSERT(that->fUniforms->size() >= size);
|
||||
if (memcmp(fUniforms->data(), that->fUniforms->data(), size) != 0) {
|
||||
return GrOp::CombineResult::kCannotCombine;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SkMeshSpecificationPriv::HasColors(*fSpecification) && fColor != that->fColor) {
|
||||
return CombineResult::kCannotCombine;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user