[graphite] Expand GradientData to include everything needed for uniform generation

Bug: skia:12701
Change-Id: Ib081e07731d30d5da19fef9191958ee3ee3a23a5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/502777
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2022-02-01 14:23:51 -05:00 committed by SkCQ
parent f34afe8725
commit 3998cdea26
3 changed files with 132 additions and 71 deletions

View File

@ -22,10 +22,10 @@
namespace skgpu {
using GradientData = GradientShaderBlocks::GradientData;
namespace {
// TODO: For the sprint we only support 4 stops in the gradients
static constexpr int kMaxStops = 4;
// TODO: For the sprint we unify all the gradient uniforms into a standard set of 6:
// kMaxStops colors
// kMaxStops offsets
@ -33,8 +33,8 @@ static constexpr int kMaxStops = 4;
// 2 radii
static constexpr int kNumGradientUniforms = 6;
static constexpr SkUniform kGradientUniforms[kNumGradientUniforms] {
{"colors", SkSLType::kHalf4 , kMaxStops },
{"offsets", SkSLType::kFloat, kMaxStops },
{"colors", SkSLType::kHalf4 , GradientData::kMaxStops },
{"offsets", SkSLType::kFloat, GradientData::kMaxStops },
{"point0", SkSLType::kFloat2 },
{"point1", SkSLType::kFloat2 },
{"radius0", SkSLType::kFloat },
@ -90,8 +90,8 @@ sk_sp<SkUniformData> make_gradient_uniform_data_common(const void* srcs[kNumGrad
sk_sp<SkUniformData> make_linear_gradient_uniform_data(SkPoint startPoint,
SkPoint endPoint,
SkColor4f colors[kMaxStops],
float offsets[kMaxStops]) {
SkColor4f colors[GradientData::kMaxStops],
float offsets[GradientData::kMaxStops]) {
float unusedRadii[2] = { 0.0f, 0.0f };
const void* srcs[kNumGradientUniforms] = {
colors,
@ -107,8 +107,8 @@ sk_sp<SkUniformData> make_linear_gradient_uniform_data(SkPoint startPoint,
sk_sp<SkUniformData> make_radial_gradient_uniform_data(SkPoint point,
float radius,
SkColor4f colors[kMaxStops],
float offsets[kMaxStops]) {
SkColor4f colors[GradientData::kMaxStops],
float offsets[GradientData::kMaxStops]) {
SkPoint unusedPoint = {0.0f, 0.0f};
float unusedRadius = 0.0f;
@ -125,8 +125,8 @@ sk_sp<SkUniformData> make_radial_gradient_uniform_data(SkPoint point,
};
sk_sp<SkUniformData> make_sweep_gradient_uniform_data(SkPoint point,
SkColor4f colors[kMaxStops],
float offsets[kMaxStops]) {
SkColor4f colors[GradientData::kMaxStops],
float offsets[GradientData::kMaxStops]) {
SkPoint unusedPoint = {0.0f, 0.0f};
float unusedRadii[2] = {0.0f, 0.0f};
@ -146,8 +146,8 @@ sk_sp<SkUniformData> make_conical_gradient_uniform_data(SkPoint point0,
SkPoint point1,
float radius0,
float radius1,
SkColor4f colors[kMaxStops],
float offsets[kMaxStops]) {
SkColor4f colors[GradientData::kMaxStops],
float offsets[GradientData::kMaxStops]) {
const void* srcs[kNumGradientUniforms] = {
colors,
@ -161,26 +161,6 @@ sk_sp<SkUniformData> make_conical_gradient_uniform_data(SkPoint point0,
return make_gradient_uniform_data_common(srcs);
};
void to_color4fs(int numColors, SkColor colors[kMaxStops], SkColor4f color4fs[kMaxStops]) {
SkASSERT(numColors >= 2 && numColors <= kMaxStops);
int i;
for (i = 0; i < numColors; ++i) {
color4fs[i] = SkColor4f::FromColor(colors[i]);
}
for ( ; i < kMaxStops; ++i) {
color4fs[i] = color4fs[numColors-1];
}
}
void expand_stops(int numStops, float offsets[kMaxStops]) {
SkASSERT(numStops >= 2 && numStops <= kMaxStops);
for (int i = numStops ; i < kMaxStops; ++i) {
offsets[i] = offsets[numStops-1];
}
}
sk_sp<SkUniformData> make_solid_uniform_data(SkColor4f color) {
UniformManager mgr(Layout::kMetal);
@ -207,81 +187,72 @@ std::tuple<SkUniquePaintParamsID, std::unique_ptr<SkUniformBlock>> ExtractPaintD
// TODO: add UniformData generation to PaintParams::toKey and use it here
if (auto s = p.shader()) {
SkColor colors[kMaxStops];
SkColor4f color4fs[kMaxStops];
float offsets[kMaxStops];
SkColor colors[GradientData::kMaxStops];
float offsets[GradientData::kMaxStops];
SkShader::GradientInfo gradInfo;
gradInfo.fColorCount = kMaxStops;
gradInfo.fColorCount = GradientData::kMaxStops;
gradInfo.fColors = colors;
gradInfo.fColorOffsets = offsets;
SkShader::GradientType type = s->asAGradient(&gradInfo);
if (gradInfo.fColorCount > kMaxStops) {
if (gradInfo.fColorCount > GradientData::kMaxStops) {
type = SkShader::GradientType::kNone_GradientType;
}
GradientData data(type, gradInfo.fPoint, gradInfo.fRadius,
gradInfo.fTileMode, gradInfo.fColorCount,
colors, offsets);
switch (type) {
case SkShader::kLinear_GradientType: {
to_color4fs(gradInfo.fColorCount, colors, color4fs);
expand_stops(gradInfo.fColorCount, offsets);
GradientShaderBlocks::AddToKey(SkBackend::kGraphite,
&key,
block.get(),
{ type, gradInfo.fTileMode, gradInfo.fColorCount });
data);
// TODO: move this into GradientShaderBlocks::AddToKey
uniforms = make_linear_gradient_uniform_data(gradInfo.fPoint[0],
gradInfo.fPoint[1],
color4fs,
offsets);
uniforms = make_linear_gradient_uniform_data(data.fPoints[0],
data.fPoints[1],
data.fColor4fs,
data.fOffsets);
} break;
case SkShader::kRadial_GradientType: {
to_color4fs(gradInfo.fColorCount, colors, color4fs);
expand_stops(gradInfo.fColorCount, offsets);
GradientShaderBlocks::AddToKey(SkBackend::kGraphite,
&key,
block.get(),
{ type, gradInfo.fTileMode, gradInfo.fColorCount });
data);
// TODO: move this into GradientShaderBlocks::AddToKey
uniforms = make_radial_gradient_uniform_data(gradInfo.fPoint[0],
gradInfo.fRadius[0],
color4fs,
offsets);
uniforms = make_radial_gradient_uniform_data(data.fPoints[0],
data.fRadii[0],
data.fColor4fs,
data.fOffsets);
} break;
case SkShader::kSweep_GradientType:
to_color4fs(gradInfo.fColorCount, colors, color4fs);
expand_stops(gradInfo.fColorCount, offsets);
GradientShaderBlocks::AddToKey(SkBackend::kGraphite,
&key,
block.get(),
{ type, gradInfo.fTileMode, gradInfo.fColorCount });
data);
// TODO: move this into GradientShaderBlocks::AddToKey
uniforms = make_sweep_gradient_uniform_data(gradInfo.fPoint[0],
color4fs,
offsets);
uniforms = make_sweep_gradient_uniform_data(data.fPoints[0],
data.fColor4fs,
data.fOffsets);
break;
case SkShader::GradientType::kConical_GradientType:
to_color4fs(gradInfo.fColorCount, colors, color4fs);
expand_stops(gradInfo.fColorCount, offsets);
GradientShaderBlocks::AddToKey(SkBackend::kGraphite,
&key,
block.get(),
{ type, gradInfo.fTileMode, gradInfo.fColorCount });
data);
// TODO: move this into GradientShaderBlocks::AddToKey
uniforms = make_conical_gradient_uniform_data(gradInfo.fPoint[0],
gradInfo.fPoint[1],
gradInfo.fRadius[0],
gradInfo.fRadius[1],
color4fs,
offsets);
uniforms = make_conical_gradient_uniform_data(data.fPoints[0],
data.fPoints[1],
data.fRadii[0],
data.fRadii[1],
data.fColor4fs,
data.fOffsets);
break;
case SkShader::GradientType::kColor_GradientType: [[fallthrough]];
// TODO: The solid color gradient type should use its color, not

View File

@ -106,6 +106,62 @@ void Dump(const SkPaintParamsKey& key, int headerOffset) {
//--------------------------------------------------------------------------------------------------
namespace GradientShaderBlocks {
GradientData::GradientData(SkShader::GradientType type,
SkTileMode tm,
int numStops)
: fType(type)
, fPoints{{0.0f, 0.0f}, {0.0f, 0.0f}}
, fRadii{0.0f, 0.0f}
, fTM(tm)
, fNumStops(numStops) {
sk_bzero(fColor4fs, sizeof(fColor4fs));
sk_bzero(fOffsets, sizeof(fOffsets));
}
GradientData::GradientData(SkShader::GradientType type,
SkPoint points[2],
float radii[2],
SkTileMode tm,
int numStops,
SkColor colors[kMaxStops],
float offsets[kMaxStops])
: fType(type)
, fTM(tm)
, fNumStops(numStops) {
memcpy(fPoints, points, sizeof(fPoints));
memcpy(fRadii, radii, sizeof(fRadii));
this->toColor4fs(fNumStops, colors);
this->toOffsets(fNumStops, offsets);
}
void GradientData::toColor4fs(int numColors, SkColor colors[kMaxStops]) {
if (numColors < 2 || numColors > kMaxStops) {
sk_bzero(fColor4fs, sizeof(fColor4fs));
return;
}
int i;
for (i = 0; i < numColors; ++i) {
fColor4fs[i] = SkColor4f::FromColor(colors[i]);
}
for ( ; i < kMaxStops; ++i) {
fColor4fs[i] = fColor4fs[numColors-1];
}
}
void GradientData::toOffsets(int numStops, float inputOffsets[kMaxStops]) {
if (numStops < 2 || numStops > kMaxStops) {
sk_bzero(fOffsets, sizeof(fOffsets));
return;
}
memcpy(fOffsets, inputOffsets, numStops * sizeof(float));
for (int i = numStops ; i < kMaxStops; ++i) {
fOffsets[i] = fOffsets[numStops-1];
}
}
static const int kBlockDataSize = 1;
void AddToKey(SkBackend backend,

View File

@ -47,16 +47,50 @@ namespace SolidColorShaderBlock {
namespace GradientShaderBlocks {
struct GradientData {
// TODO: For the sprint we only support 4 stops in the gradients
static constexpr int kMaxStops = 4;
// This ctor is used during pre-compilation when we don't have enough information to
// extract uniform data. However, we must be able to provide enough data to make all the
// relevant decisions about which code snippets to use.
GradientData(SkShader::GradientType,
SkTileMode,
int numStops);
// This ctor is used when extracting information from PaintParams. It must provide
// enough data to generate the uniform data the selected code snippet will require.
GradientData(SkShader::GradientType,
SkPoint points[2],
float radii[2],
SkTileMode,
int numStops,
SkColor colors[kMaxStops],
float offsets[kMaxStops]);
bool operator==(const GradientData& rhs) const {
return fType == rhs.fType &&
fPoints[0] == rhs.fPoints[0] &&
fPoints[1] == rhs.fPoints[1] &&
fRadii[0] == rhs.fRadii[0] &&
fRadii[1] == rhs.fRadii[1] &&
fTM == rhs.fTM &&
fNumStops == rhs.fNumStops;
fNumStops == rhs.fNumStops &&
!memcmp(fColor4fs, rhs.fColor4fs, sizeof(fColor4fs)) &&
!memcmp(fOffsets, rhs.fOffsets, sizeof(fOffsets));
}
bool operator!=(const GradientData& rhs) const { return !(*this == rhs); }
SkShader::GradientType fType;
SkPoint fPoints[2];
float fRadii[2];
SkTileMode fTM;
int fNumStops;
SkColor4f fColor4fs[kMaxStops];
float fOffsets[kMaxStops];
private:
void toColor4fs(int numColors, SkColor colors[kMaxStops]);
void toOffsets(int numStops, float inputOffsets[kMaxStops]);
};
void AddToKey(SkBackend,