Supply device and local coords to SkShader_Base::onProgram
Use that to add support for sk_FragCoord in SkRuntimeEffect. Change-Id: I587ad97057c13ec8a4052c7c20f655eae88786ba Reviewed-on: https://skia-review.googlesource.com/c/skia/+/298504 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
fe02dd1ee6
commit
5aaaeea4da
@ -415,7 +415,7 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
|
||||
std::vector<skvm::F32> stack,
|
||||
/*these parameters are used to call program() on children*/
|
||||
const std::vector<sk_sp<SkShader>>& children,
|
||||
skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Coord device, skvm::Color paint,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) {
|
||||
auto push = [&](skvm::F32 x) { stack.push_back(x); };
|
||||
@ -483,7 +483,7 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
|
||||
x = pop();
|
||||
|
||||
SkOverrideDeviceMatrixProvider mats{matrices, SkMatrix::I()};
|
||||
skvm::Color c = as_SB(children[ix])->program(p, x,y,paint,
|
||||
skvm::Color c = as_SB(children[ix])->program(p, device, {x,y},paint,
|
||||
mats, nullptr,
|
||||
quality, dst,
|
||||
uniforms, alloc);
|
||||
@ -548,6 +548,14 @@ static std::vector<skvm::F32> program_fn(skvm::Builder* p,
|
||||
push(uniform[ix + 3]);
|
||||
} break;
|
||||
|
||||
case Inst::kLoadFragCoord: {
|
||||
// TODO: Actually supply Z and 1/W from the rasterizer?
|
||||
push(device.x);
|
||||
push(device.y);
|
||||
push(p->splat(0.0f)); // Z
|
||||
push(p->splat(1.0f)); // 1/W
|
||||
} break;
|
||||
|
||||
case Inst::kStore: {
|
||||
int ix = u8();
|
||||
stack[ix + 0] = pop();
|
||||
@ -828,7 +836,7 @@ public:
|
||||
std::vector<skvm::F32> stack =
|
||||
program_fn(p, *fn, uniform, SkSimpleMatrixProvider{SkMatrix::I()}, {c.r, c.g, c.b, c.a},
|
||||
/* the remaining parameters are for shaders only and won't be used here */
|
||||
{},{},{},{},{},{},{},{});
|
||||
{},{},{},{},{},{},{});
|
||||
|
||||
if (stack.size() == 4) {
|
||||
return {stack[0], stack[1], stack[2], stack[3]};
|
||||
@ -1017,7 +1025,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder* p,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
|
||||
@ -1047,12 +1056,13 @@ public:
|
||||
if (!this->computeTotalInverse(matrices.localToDevice(), localM, &inv)) {
|
||||
return {};
|
||||
}
|
||||
SkShaderBase::ApplyMatrix(p,inv, &x,&y,uniforms);
|
||||
SkShaderBase::ApplyMatrix(p,inv, &local,uniforms);
|
||||
|
||||
std::vector<skvm::F32> stack =
|
||||
program_fn(p, *fn, uniform, matrices, {x,y, paint.r, paint.g, paint.b, paint.a},
|
||||
program_fn(p, *fn, uniform, matrices,
|
||||
{local.x,local.y, paint.r, paint.g, paint.b, paint.a},
|
||||
/*parameters for calling program() on children*/
|
||||
fChildren, x,y,paint, quality,dst, uniforms,alloc);
|
||||
fChildren, device,paint, quality,dst, uniforms,alloc);
|
||||
|
||||
if (stack.size() == 6) {
|
||||
return {stack[2], stack[3], stack[4], stack[5]};
|
||||
|
@ -476,6 +476,12 @@ namespace skvm {
|
||||
Builder* operator->() const { return a.operator->(); }
|
||||
};
|
||||
|
||||
struct Coord {
|
||||
F32 x,y;
|
||||
explicit operator bool() const { return x && y; }
|
||||
Builder* operator->() const { return x.operator->(); }
|
||||
};
|
||||
|
||||
struct Uniform {
|
||||
Arg ptr;
|
||||
int offset;
|
||||
|
@ -117,8 +117,9 @@ namespace {
|
||||
skvm::I32 dx = p.uniform32(uniforms->base, offsetof(BlitterUniforms, right))
|
||||
- p.index(),
|
||||
dy = p.uniform32(uniforms->base, offsetof(BlitterUniforms, y));
|
||||
skvm::F32 x = to_f32(dx) + 0.5f,
|
||||
y = to_f32(dy) + 0.5f;
|
||||
skvm::Coord device = {to_f32(dx) + 0.5f,
|
||||
to_f32(dy) + 0.5f},
|
||||
local = device;
|
||||
|
||||
skvm::Color paint = {
|
||||
p.uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fR)),
|
||||
@ -129,7 +130,7 @@ namespace {
|
||||
|
||||
uint64_t hash = 0;
|
||||
if (auto c = sb->program(&p,
|
||||
x,y, paint,
|
||||
device,local, paint,
|
||||
params.matrices, /*localM=*/nullptr,
|
||||
params.quality, params.dst,
|
||||
uniforms,alloc)) {
|
||||
@ -197,8 +198,9 @@ namespace {
|
||||
skvm::I32 dx = p->uniform32(uniforms->base, offsetof(BlitterUniforms, right))
|
||||
- p->index(),
|
||||
dy = p->uniform32(uniforms->base, offsetof(BlitterUniforms, y));
|
||||
skvm::F32 x = to_f32(dx) + 0.5f,
|
||||
y = to_f32(dy) + 0.5f;
|
||||
skvm::Coord device = {to_f32(dx) + 0.5f,
|
||||
to_f32(dy) + 0.5f},
|
||||
local = device;
|
||||
|
||||
skvm::Color paint = {
|
||||
p->uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fR)),
|
||||
@ -207,7 +209,7 @@ namespace {
|
||||
p->uniformF(uniforms->base, offsetof(BlitterUniforms, paint.fA)),
|
||||
};
|
||||
|
||||
skvm::Color src = as_SB(params.shader)->program(p, x,y, paint,
|
||||
skvm::Color src = as_SB(params.shader)->program(p, device,local, paint,
|
||||
params.matrices, /*localM=*/nullptr,
|
||||
params.quality, params.dst,
|
||||
uniforms, alloc);
|
||||
@ -274,7 +276,7 @@ namespace {
|
||||
}
|
||||
|
||||
if (params.clip) {
|
||||
skvm::Color clip = as_SB(params.clip)->program(p, x,y, paint,
|
||||
skvm::Color clip = as_SB(params.clip)->program(p, device,local, paint,
|
||||
params.matrices, /*localM=*/nullptr,
|
||||
params.quality, params.dst,
|
||||
uniforms, alloc);
|
||||
@ -428,12 +430,13 @@ namespace {
|
||||
|
||||
bool isOpaque() const override { return fShader->isOpaque(); }
|
||||
|
||||
skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder* p,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
|
||||
// Run our wrapped shader.
|
||||
skvm::Color c = as_SB(fShader)->program(p, x,y, paint,
|
||||
skvm::Color c = as_SB(fShader)->program(p, device,local, paint,
|
||||
matrices,localM, quality,dst, uniforms,alloc);
|
||||
if (!c) {
|
||||
return {};
|
||||
@ -467,8 +470,10 @@ namespace {
|
||||
|
||||
// See SkRasterPipeline dither stage.
|
||||
// This is 8x8 ordered dithering. From here we'll only need dx and dx^dy.
|
||||
skvm::I32 X = trunc(x - 0.5f),
|
||||
Y = X ^ trunc(y - 0.5f);
|
||||
SkASSERT(local.x.id == device.x.id);
|
||||
SkASSERT(local.y.id == device.y.id);
|
||||
skvm::I32 X = trunc(device.x - 0.5f),
|
||||
Y = X ^ trunc(device.y - 0.5f);
|
||||
|
||||
// If X's low bits are abc and Y's def, M is fcebda,
|
||||
// 6 bits producing all values [0,63] shuffled over an 8x8 grid.
|
||||
|
@ -16,6 +16,7 @@ namespace skvm {
|
||||
struct I32;
|
||||
struct F32;
|
||||
struct Color;
|
||||
struct Coord;
|
||||
struct Uniforms;
|
||||
}
|
||||
|
||||
|
@ -62,12 +62,12 @@ bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const {
|
||||
}
|
||||
|
||||
skvm::Color SkColorFilterShader::onProgram(skvm::Builder* p,
|
||||
skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
// Run the shader.
|
||||
skvm::Color c = as_SB(fShader)->program(p, x,y, paint,
|
||||
skvm::Color c = as_SB(fShader)->program(p, device,local, paint,
|
||||
matrices,localM,
|
||||
quality,dst,
|
||||
uniforms,alloc);
|
||||
|
@ -26,7 +26,7 @@ private:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
|
||||
|
@ -92,7 +92,8 @@ bool SkColor4Shader::onAppendStages(const SkStageRec& rec) const {
|
||||
}
|
||||
|
||||
skvm::Color SkColorShader::onProgram(skvm::Builder* p,
|
||||
skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
|
||||
skvm::Coord /*device*/, skvm::Coord /*local*/,
|
||||
skvm::Color /*paint*/,
|
||||
const SkMatrixProvider&, const SkMatrix* /*localM*/,
|
||||
SkFilterQuality /*quality*/, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc*) const {
|
||||
@ -100,7 +101,8 @@ skvm::Color SkColorShader::onProgram(skvm::Builder* p,
|
||||
uniforms, dst.colorSpace());
|
||||
}
|
||||
skvm::Color SkColor4Shader::onProgram(skvm::Builder* p,
|
||||
skvm::F32 /*x*/, skvm::F32 /*y*/, skvm::Color /*paint*/,
|
||||
skvm::Coord /*device*/, skvm::Coord /*local*/,
|
||||
skvm::Color /*paint*/,
|
||||
const SkMatrixProvider&, const SkMatrix* /*localM*/,
|
||||
SkFilterQuality /*quality*/, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc*) const {
|
||||
|
@ -44,7 +44,7 @@ private:
|
||||
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
|
||||
@ -69,7 +69,7 @@ private:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
|
||||
|
@ -127,13 +127,14 @@ bool SkShader_Blend::onAppendStages(const SkStageRec& orig_rec) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
skvm::Color SkShader_Blend::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
skvm::Color SkShader_Blend::onProgram(skvm::Builder* p,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& mats, const SkMatrix* localM,
|
||||
SkFilterQuality q, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
skvm::Color d,s;
|
||||
if ((d = as_SB(fDst)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)) &&
|
||||
(s = as_SB(fSrc)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)))
|
||||
if ((d = as_SB(fDst)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)) &&
|
||||
(s = as_SB(fSrc)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)))
|
||||
{
|
||||
return p->blend(fMode, s,d);
|
||||
}
|
||||
@ -167,13 +168,14 @@ bool SkShader_Lerp::onAppendStages(const SkStageRec& orig_rec) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
skvm::Color SkShader_Lerp::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
skvm::Color SkShader_Lerp::onProgram(skvm::Builder* p,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& mats, const SkMatrix* localM,
|
||||
SkFilterQuality q, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
skvm::Color d,s;
|
||||
if ((d = as_SB(fDst)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)) &&
|
||||
(s = as_SB(fSrc)->program(p, x,y, paint, matrices,localM, q, dst, uniforms, alloc)))
|
||||
if ((d = as_SB(fDst)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)) &&
|
||||
(s = as_SB(fSrc)->program(p, device,local, paint, mats,localM, q,dst, uniforms,alloc)))
|
||||
{
|
||||
auto t = p->uniformF(uniforms->pushF(fWeight));
|
||||
return {
|
||||
|
@ -27,7 +27,7 @@ protected:
|
||||
SkShader_Blend(SkReadBuffer&);
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality, const SkColorInfo& dst,
|
||||
skvm::Uniforms*, SkArenaAlloc*) const override;
|
||||
@ -60,7 +60,7 @@ protected:
|
||||
SkShader_Lerp(SkReadBuffer&);
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality, const SkColorInfo& dst,
|
||||
skvm::Uniforms*, SkArenaAlloc*) const override;
|
||||
|
@ -37,7 +37,7 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32, skvm::F32, skvm::Color,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord, skvm::Coord, skvm::Color,
|
||||
const SkMatrixProvider&, const SkMatrix*,
|
||||
SkFilterQuality, const SkColorInfo&,
|
||||
skvm::Uniforms*, SkArenaAlloc*) const override;
|
||||
|
@ -639,7 +639,8 @@ SkStageUpdater* SkImageShader::onAppendUpdatableStages(const SkStageRec& rec) co
|
||||
return this->doStages(rec, updater) ? updater : nullptr;
|
||||
}
|
||||
|
||||
skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color SkImageShader::onProgram(skvm::Builder* p,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
@ -663,7 +664,7 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
|
||||
inv.normalizePerspective();
|
||||
|
||||
// Apply matrix to convert dst coords to sample center coords.
|
||||
SkShaderBase::ApplyMatrix(p, inv, &x,&y,uniforms);
|
||||
SkShaderBase::ApplyMatrix(p, inv, &local, uniforms);
|
||||
|
||||
// Bail out if sample() can't yet handle our image's color type.
|
||||
switch (pm.colorType()) {
|
||||
@ -788,14 +789,14 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
|
||||
skvm::Color c;
|
||||
|
||||
if (quality == kNone_SkFilterQuality) {
|
||||
c = sample(x,y);
|
||||
c = sample(local.x,local.y);
|
||||
} else if (quality == kLow_SkFilterQuality) {
|
||||
// Our four sample points are the corners of a logical 1x1 pixel
|
||||
// box surrounding (x,y) at (0.5,0.5) off-center.
|
||||
skvm::F32 left = x - 0.5f,
|
||||
top = y - 0.5f,
|
||||
right = x + 0.5f,
|
||||
bottom = y + 0.5f;
|
||||
skvm::F32 left = local.x - 0.5f,
|
||||
top = local.y - 0.5f,
|
||||
right = local.x + 0.5f,
|
||||
bottom = local.y + 0.5f;
|
||||
|
||||
// The fractional parts of right and bottom are our lerp factors in x and y respectively.
|
||||
skvm::F32 fx = fract(right ),
|
||||
@ -808,8 +809,8 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
|
||||
|
||||
// All bicubic samples have the same fractional offset (fx,fy) from the center.
|
||||
// They're either the 16 corners of a 3x3 grid/ surrounding (x,y) at (0.5,0.5) off-center.
|
||||
skvm::F32 fx = fract(x + 0.5f),
|
||||
fy = fract(y + 0.5f);
|
||||
skvm::F32 fx = fract(local.x + 0.5f),
|
||||
fy = fract(local.y + 0.5f);
|
||||
|
||||
// See GrCubicEffect for details of these weights.
|
||||
// TODO: these maybe don't seem right looking at gm/bicubic and GrBicubicEffect.
|
||||
@ -836,9 +837,9 @@ skvm::Color SkImageShader::onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y,
|
||||
|
||||
c.r = c.g = c.b = c.a = p->splat(0.0f);
|
||||
|
||||
skvm::F32 sy = y - 1.5f;
|
||||
skvm::F32 sy = local.y - 1.5f;
|
||||
for (int j = 0; j < 4; j++, sy += 1.0f) {
|
||||
skvm::F32 sx = x - 1.5f;
|
||||
skvm::F32 sx = local.x - 1.5f;
|
||||
for (int i = 0; i < 4; i++, sx += 1.0f) {
|
||||
skvm::Color s = sample(sx,sy);
|
||||
skvm::F32 w = wx[i] * wy[j];
|
||||
|
@ -58,7 +58,7 @@ private:
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
SkStageUpdater* onAppendUpdatableStages(const SkStageRec&) const override;
|
||||
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
|
||||
|
@ -78,7 +78,7 @@ bool SkLocalMatrixShader::onAppendStages(const SkStageRec& rec) const {
|
||||
|
||||
|
||||
skvm::Color SkLocalMatrixShader::onProgram(skvm::Builder* p,
|
||||
skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
@ -86,7 +86,7 @@ skvm::Color SkLocalMatrixShader::onProgram(skvm::Builder* p,
|
||||
if (localM) {
|
||||
lm.writable()->preConcat(*localM);
|
||||
}
|
||||
return as_SB(fProxyShader)->program(p, x,y, paint,
|
||||
return as_SB(fProxyShader)->program(p, device,local, paint,
|
||||
matrices,lm.get(),
|
||||
quality,dst,
|
||||
uniforms,alloc);
|
||||
@ -156,12 +156,13 @@ protected:
|
||||
return as_SB(fProxyShader)->appendStages(newRec);
|
||||
}
|
||||
|
||||
skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder* p,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
|
||||
SkOverrideDeviceMatrixProvider matrixProvider(matrices, fCTM);
|
||||
return as_SB(fProxyShader)->program(p, x,y,paint,
|
||||
return as_SB(fProxyShader)->program(p, device,local, paint,
|
||||
matrixProvider,localM,
|
||||
quality,dst,
|
||||
uniforms,alloc);
|
||||
|
@ -48,7 +48,7 @@ protected:
|
||||
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc*) const override;
|
||||
|
@ -275,7 +275,7 @@ bool SkPictureShader::onAppendStages(const SkStageRec& rec) const {
|
||||
}
|
||||
|
||||
skvm::Color SkPictureShader::onProgram(skvm::Builder* p,
|
||||
skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
@ -289,7 +289,10 @@ skvm::Color SkPictureShader::onProgram(skvm::Builder* p,
|
||||
return {};
|
||||
}
|
||||
|
||||
return as_SB(bitmapShader)->program(p, x,y, paint, matrices, lm, quality, dst, uniforms, alloc);
|
||||
return as_SB(bitmapShader)->program(p, device,local, paint,
|
||||
matrices,lm,
|
||||
quality,dst,
|
||||
uniforms,alloc);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -37,7 +37,7 @@ protected:
|
||||
SkPictureShader(SkReadBuffer&);
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override;
|
||||
|
@ -195,7 +195,8 @@ bool SkShaderBase::onAppendStages(const SkStageRec& rec) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
skvm::Color SkShaderBase::program(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color SkShaderBase::program(skvm::Builder* p,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider& matrices, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
@ -211,7 +212,8 @@ skvm::Color SkShaderBase::program(skvm::Builder* p, skvm::F32 x, skvm::F32 y, sk
|
||||
// shader program hash and blitter Key. This makes it safe for us to use
|
||||
// that bit to make decisions when constructing an SkVMBlitter, like doing
|
||||
// SrcOver -> Src strength reduction.
|
||||
if (auto color = this->onProgram(p, x,y, paint, matrices,localM, quality,dst, uniforms,alloc)) {
|
||||
if (auto color = this->onProgram(p, device,local, paint, matrices,localM, quality,dst,
|
||||
uniforms,alloc)) {
|
||||
if (this->isOpaque()) {
|
||||
color.a = p->splat(1.0f);
|
||||
}
|
||||
@ -220,11 +222,12 @@ skvm::Color SkShaderBase::program(skvm::Builder* p, skvm::F32 x, skvm::F32 y, sk
|
||||
return {};
|
||||
}
|
||||
|
||||
skvm::Color SkShaderBase::onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color SkShaderBase::onProgram(skvm::Builder*,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
//SkDebugf("cannot onProgram %s\n", this->getTypeName());
|
||||
// SkDebugf("cannot onProgram %s\n", this->getTypeName());
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -235,7 +238,9 @@ sk_sp<SkShader> SkShaderBase::makeInvertAlpha() const {
|
||||
|
||||
|
||||
void SkShaderBase::ApplyMatrix(skvm::Builder* p, const SkMatrix& m,
|
||||
skvm::F32* x, skvm::F32* y, skvm::Uniforms* uniforms) {
|
||||
skvm::Coord* coord, skvm::Uniforms* uniforms) {
|
||||
skvm::F32 *x = &coord->x,
|
||||
*y = &coord->y;
|
||||
if (m.isIdentity()) {
|
||||
// That was easy.
|
||||
} else if (m.isTranslate()) {
|
||||
@ -261,7 +266,7 @@ void SkShaderBase::ApplyMatrix(skvm::Builder* p, const SkMatrix& m,
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
skvm::Color SkEmptyShader::onProgram(skvm::Builder*, skvm::F32, skvm::F32, skvm::Color,
|
||||
skvm::Color SkEmptyShader::onProgram(skvm::Builder*, skvm::Coord, skvm::Coord, skvm::Color,
|
||||
const SkMatrixProvider&, const SkMatrix*,
|
||||
SkFilterQuality, const SkColorInfo&,
|
||||
skvm::Uniforms*, SkArenaAlloc*) const {
|
||||
|
@ -211,7 +211,7 @@ public:
|
||||
return this->onAppendUpdatableStages(rec);
|
||||
}
|
||||
|
||||
skvm::Color program(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color program(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const;
|
||||
@ -241,13 +241,14 @@ protected:
|
||||
virtual SkStageUpdater* onAppendUpdatableStages(const SkStageRec&) const { return nullptr; }
|
||||
|
||||
protected:
|
||||
static void ApplyMatrix(skvm::Builder*, const SkMatrix&, skvm::F32* x, skvm::F32* y, skvm::Uniforms*);
|
||||
static void ApplyMatrix(skvm::Builder*, const SkMatrix&, skvm::Coord*, skvm::Uniforms*);
|
||||
|
||||
private:
|
||||
// This is essentially const, but not officially so it can be modified in constructors.
|
||||
SkMatrix fLocalMatrix;
|
||||
|
||||
virtual skvm::Color onProgram(skvm::Builder*, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
virtual skvm::Color onProgram(skvm::Builder*,
|
||||
skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dst,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const;
|
||||
|
@ -420,7 +420,8 @@ bool SkGradientShaderBase::onAppendStages(const SkStageRec& rec) const {
|
||||
}
|
||||
|
||||
skvm::Color SkGradientShaderBase::onProgram(skvm::Builder* p,
|
||||
skvm::F32 x, skvm::F32 y, skvm::Color /*paint*/,
|
||||
skvm::Coord device, skvm::Coord local,
|
||||
skvm::Color /*paint*/,
|
||||
const SkMatrixProvider& mats, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dstInfo,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const {
|
||||
@ -431,10 +432,10 @@ skvm::Color SkGradientShaderBase::onProgram(skvm::Builder* p,
|
||||
inv.postConcat(fPtsToUnit);
|
||||
inv.normalizePerspective();
|
||||
|
||||
SkShaderBase::ApplyMatrix(p, inv, &x,&y,uniforms);
|
||||
SkShaderBase::ApplyMatrix(p, inv, &local, uniforms);
|
||||
|
||||
skvm::I32 mask = p->splat(~0);
|
||||
skvm::F32 t = this->transformT(p,uniforms, x,y, &mask);
|
||||
skvm::F32 t = this->transformT(p,uniforms, local, &mask);
|
||||
|
||||
// Perhaps unexpectedly, clamping is handled naturally by our search, so we
|
||||
// don't explicitly clamp t to [0,1]. That clamp would break hard stops
|
||||
|
@ -79,7 +79,7 @@ protected:
|
||||
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
skvm::Color onProgram(skvm::Builder* p, skvm::F32 x, skvm::F32 y, skvm::Color paint,
|
||||
skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
|
||||
const SkMatrixProvider&, const SkMatrix* localM,
|
||||
SkFilterQuality quality, const SkColorInfo& dstCS,
|
||||
skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override;
|
||||
@ -89,7 +89,7 @@ protected:
|
||||
|
||||
// Produce t from (x,y), modifying mask if it should be anything other than ~0.
|
||||
virtual skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const = 0;
|
||||
skvm::Coord coord, skvm::I32* mask) const = 0;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
|
||||
|
@ -76,9 +76,9 @@ void SkLinearGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline*,
|
||||
}
|
||||
|
||||
skvm::F32 SkLinearGradient::transformT(skvm::Builder* p, skvm::Uniforms*,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
|
||||
skvm::Coord coord, skvm::I32* mask) const {
|
||||
// We've baked getting t in x into the matrix, so this is pretty trivial.
|
||||
return x;
|
||||
return coord.x;
|
||||
}
|
||||
|
||||
SkShader::GradientType SkLinearGradient::asAGradient(GradientInfo* info) const {
|
||||
|
@ -30,7 +30,7 @@ protected:
|
||||
SkRasterPipeline* postPipeline) const final;
|
||||
|
||||
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
|
||||
skvm::Coord coord, skvm::I32* mask) const final;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkLinearGradient)
|
||||
|
@ -64,8 +64,8 @@ void SkRadialGradient::appendGradientStages(SkArenaAlloc*, SkRasterPipeline* p,
|
||||
}
|
||||
|
||||
skvm::F32 SkRadialGradient::transformT(skvm::Builder* p, skvm::Uniforms*,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
|
||||
return sqrt(x*x + y*y);
|
||||
skvm::Coord coord, skvm::I32* mask) const {
|
||||
return sqrt(coord.x*coord.x + coord.y*coord.y);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -27,7 +27,7 @@ protected:
|
||||
SkRasterPipeline* postPipeline) const override;
|
||||
|
||||
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
|
||||
skvm::Coord coord, skvm::I32* mask) const final;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkRadialGradient)
|
||||
|
@ -68,9 +68,9 @@ void SkSweepGradient::appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline
|
||||
}
|
||||
|
||||
skvm::F32 SkSweepGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
|
||||
skvm::F32 xabs = abs(x),
|
||||
yabs = abs(y),
|
||||
skvm::Coord coord, skvm::I32* mask) const {
|
||||
skvm::F32 xabs = abs(coord.x),
|
||||
yabs = abs(coord.y),
|
||||
slope = min(xabs, yabs) / max(xabs, yabs);
|
||||
skvm::F32 s = slope * slope;
|
||||
|
||||
@ -82,9 +82,9 @@ skvm::F32 SkSweepGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms
|
||||
+2.476101927459239959716796875e-2f,
|
||||
-5.185396969318389892578125e-2f,
|
||||
+0.15912117063999176025390625f);
|
||||
phi = select(xabs < yabs, (1/4.0f) - phi, phi);
|
||||
phi = select( x < 0.0f, (1/2.0f) - phi, phi);
|
||||
phi = select( y < 0.0f, (1/1.0f) - phi, phi);
|
||||
phi = select( xabs < yabs, (1/4.0f) - phi, phi);
|
||||
phi = select(coord.x < 0.0f, (1/2.0f) - phi, phi);
|
||||
phi = select(coord.y < 0.0f, (1/1.0f) - phi, phi);
|
||||
|
||||
skvm::F32 t = select(is_NaN(phi), p->splat(0.0f)
|
||||
, phi);
|
||||
|
@ -31,7 +31,7 @@ protected:
|
||||
SkRasterPipeline* postPipeline) const override;
|
||||
|
||||
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
|
||||
skvm::Coord coord, skvm::I32* mask) const final;
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkSweepGradient)
|
||||
|
||||
|
@ -234,11 +234,13 @@ void SkTwoPointConicalGradient::appendGradientStages(SkArenaAlloc* alloc, SkRast
|
||||
}
|
||||
|
||||
skvm::F32 SkTwoPointConicalGradient::transformT(skvm::Builder* p, skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const {
|
||||
skvm::Coord coord, skvm::I32* mask) const {
|
||||
// See https://skia.org/dev/design/conical, and onAppendStages() above.
|
||||
// There's a lot going on here, and I'm not really sure what's independent
|
||||
// or disjoint, what can be reordered, simplified, etc. Tweak carefully.
|
||||
|
||||
const skvm::F32 x = coord.x,
|
||||
y = coord.y;
|
||||
if (fType == Type::kRadial) {
|
||||
float denom = 1.0f / (fRadius2 - fRadius1),
|
||||
scale = std::max(fRadius1, fRadius2) * denom,
|
||||
|
@ -70,7 +70,7 @@ protected:
|
||||
SkRasterPipeline* postPipeline) const override;
|
||||
|
||||
skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
|
||||
skvm::F32 x, skvm::F32 y, skvm::I32* mask) const final;
|
||||
skvm::Coord coord, skvm::I32* mask) const final;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkTwoPointConicalGradient)
|
||||
|
@ -110,6 +110,7 @@ static const uint8_t* DisassembleInstruction(const uint8_t* ip) {
|
||||
break;
|
||||
case ByteCodeInstruction::kLoadExtendedUniform: printf("loadextendeduniform %d", READ8());
|
||||
break;
|
||||
case ByteCodeInstruction::kLoadFragCoord: printf("loadfragcoord"); break;
|
||||
case ByteCodeInstruction::kMatrixToMatrix: {
|
||||
int srcCols = READ8();
|
||||
int srcRows = READ8();
|
||||
@ -926,11 +927,6 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
|
||||
}
|
||||
}
|
||||
|
||||
case ByteCodeInstruction::kSampleExplicit:
|
||||
case ByteCodeInstruction::kSampleMatrix:
|
||||
// TODO: Support these?
|
||||
return false;
|
||||
|
||||
case ByteCodeInstruction::kScalarToMatrix: {
|
||||
int cols = READ8();
|
||||
int rows = READ8();
|
||||
@ -1105,6 +1101,14 @@ static bool InnerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue
|
||||
*loopPtr &= ~m;
|
||||
continue;
|
||||
}
|
||||
|
||||
case ByteCodeInstruction::kLoadFragCoord:
|
||||
case ByteCodeInstruction::kSampleExplicit:
|
||||
case ByteCodeInstruction::kSampleMatrix:
|
||||
default:
|
||||
// TODO: Support these?
|
||||
SkASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,8 @@ enum class ByteCodeInstruction : uint16_t {
|
||||
kLoadExtended,
|
||||
kLoadExtendedGlobal,
|
||||
kLoadExtendedUniform,
|
||||
// Loads "sk_FragCoord" [X, Y, Z, 1/W]
|
||||
kLoadFragCoord,
|
||||
// Followed by four bytes: srcCols, srcRows, dstCols, dstRows. Consumes the src matrix from the
|
||||
// stack, and replaces it with the dst matrix. Per GLSL rules, there are no restrictions on
|
||||
// dimensions. Any overlapping values are copied, and any other values are filled in with the
|
||||
@ -275,7 +277,7 @@ public:
|
||||
* Some byte code programs can't be executed by the interpreter, due to unsupported features.
|
||||
* They may still be used to convert to other formats, or for reflection of uniforms.
|
||||
*/
|
||||
bool canRun() const { return fChildFPCount == 0; }
|
||||
bool canRun() const { return fChildFPCount == 0 && !fUsesFragCoord; }
|
||||
|
||||
private:
|
||||
ByteCode(const ByteCode&) = delete;
|
||||
@ -287,6 +289,7 @@ private:
|
||||
int fGlobalSlotCount = 0;
|
||||
int fUniformSlotCount = 0;
|
||||
int fChildFPCount = 0;
|
||||
bool fUsesFragCoord = false;
|
||||
std::vector<Uniform> fUniforms;
|
||||
|
||||
std::vector<std::unique_ptr<ByteCodeFunction>> fFunctions;
|
||||
|
@ -207,10 +207,27 @@ std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const Functio
|
||||
return result;
|
||||
}
|
||||
|
||||
// If the expression is a reference to a builtin global variable, return the builtin ID.
|
||||
// Otherwise, return -1.
|
||||
static int expression_as_builtin(const Expression& e) {
|
||||
if (e.fKind == Expression::kVariableReference_Kind) {
|
||||
const Variable& var(((VariableReference&)e).fVariable);
|
||||
if (var.fStorage == Variable::kGlobal_Storage) {
|
||||
return var.fModifiers.fLayout.fBuiltin;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// A "simple" Swizzle is based on a variable (or a compound variable like a struct or array), and
|
||||
// that references consecutive values, such that it can be implemented using normal load/store ops
|
||||
// with an offset. Note that all single-component swizzles (of suitable base types) are simple.
|
||||
static bool swizzle_is_simple(const Swizzle& s) {
|
||||
// Builtin variables use dedicated instructions that don't allow subset loads
|
||||
if (expression_as_builtin(*s.fBase) >= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (s.fBase->fKind) {
|
||||
case Expression::kFieldAccess_Kind:
|
||||
case Expression::kIndex_Kind:
|
||||
@ -366,6 +383,7 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
|
||||
case ByteCodeInstruction::kLoadGlobal4:
|
||||
case ByteCodeInstruction::kLoadUniform4:
|
||||
case ByteCodeInstruction::kReadExternal4:
|
||||
case ByteCodeInstruction::kLoadFragCoord:
|
||||
return 4;
|
||||
|
||||
case ByteCodeInstruction::kDupN:
|
||||
@ -1015,6 +1033,19 @@ void ByteCodeGenerator::writeExternalValue(const ExternalValueReference& e) {
|
||||
}
|
||||
|
||||
void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
|
||||
if (int builtin = expression_as_builtin(expr); builtin >= 0) {
|
||||
switch (builtin) {
|
||||
case SK_FRAGCOORD_BUILTIN:
|
||||
this->write(ByteCodeInstruction::kLoadFragCoord);
|
||||
fOutput->fUsesFragCoord = true;
|
||||
break;
|
||||
default:
|
||||
fErrors.error(expr.fOffset, "Unsupported builtin");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Location location = this->getLocation(expr);
|
||||
int count = SlotCount(expr.fType);
|
||||
if (count == 0) {
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
}
|
||||
|
||||
void test(skiatest::Reporter* r, sk_sp<SkSurface> surface,
|
||||
uint32_t TL, uint32_t TR, uint32_t BL, uint32_t BR) {
|
||||
uint32_t TL, uint32_t TR, uint32_t BL, uint32_t BR, SkScalar rotate = 0.0f) {
|
||||
auto shader = fBuilder->makeShader(nullptr, false);
|
||||
if (!shader) {
|
||||
REPORT_FAILURE(r, "shader", SkString("Effect didn't produce a shader"));
|
||||
@ -86,6 +86,7 @@ public:
|
||||
SkPaint paint;
|
||||
paint.setShader(std::move(shader));
|
||||
paint.setBlendMode(SkBlendMode::kSrc);
|
||||
surface->getCanvas()->rotate(rotate);
|
||||
surface->getCanvas()->drawPaint(paint);
|
||||
|
||||
uint32_t actual[4];
|
||||
@ -153,11 +154,8 @@ static void test_RuntimeEffect_Shaders(skiatest::Reporter* r, GrContext* context
|
||||
|
||||
// Test sk_FragCoord, which we output to color. Since the surface is 2x2, we should see
|
||||
// (0,0), (1,0), (0,1), (1,1), multiply by 0.498 to make sure we're not saturating unexpectedly.
|
||||
// TODO: Remove this when sk_FragCoord is supported by interpreter.
|
||||
if (context) {
|
||||
TestEffect fragCoord(r, "", "color = half4(0.498 * (half2(sk_FragCoord.xy) - 0.5), 0, 1);");
|
||||
fragCoord.test(r, surface, 0xFF000000, 0xFF00007F, 0xFF007F00, 0xFF007F7F);
|
||||
}
|
||||
TestEffect fragCoord(r, "", "color = half4(0.498 * (half2(sk_FragCoord.xy) - 0.5), 0, 1);");
|
||||
fragCoord.test(r, surface, 0xFF000000, 0xFF00007F, 0xFF007F00, 0xFF007F7F, 45.0f);
|
||||
}
|
||||
|
||||
DEF_TEST(SkRuntimeEffectSimple, r) {
|
||||
|
Loading…
Reference in New Issue
Block a user