rough sketch of shaders in SkVMBlitter
Change-Id: I5f96475a6dec26dde0bdf883153a1fd7c7e3b148 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251409 Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
parent
bfdab5f027
commit
e4522dcf9a
@ -24,6 +24,7 @@ namespace {
|
||||
SkAlphaType alphaType;
|
||||
Coverage coverage;
|
||||
SkBlendMode blendMode;
|
||||
SkColorSpace* colorSpace;
|
||||
SkShader* shader;
|
||||
SkColorFilter* colorFilter;
|
||||
|
||||
@ -40,16 +41,18 @@ namespace {
|
||||
&& x.alphaType == y.alphaType
|
||||
&& x.coverage == y.coverage
|
||||
&& x.blendMode == y.blendMode
|
||||
&& x.colorSpace == y.colorSpace // SkColorSpace::Equals() would make hashing unsound.
|
||||
&& x.shader == y.shader
|
||||
&& x.colorFilter == y.colorFilter;
|
||||
}
|
||||
|
||||
static SkString debug_name(const Key& key) {
|
||||
return SkStringPrintf("CT%d-AT%d-Cov%d-Blend%d-Shader%d-CF%d",
|
||||
return SkStringPrintf("CT%d-AT%d-Cov%d-Blend%d-CS%d-Shader%d-CF%d",
|
||||
key.colorType,
|
||||
key.alphaType,
|
||||
key.coverage,
|
||||
key.blendMode,
|
||||
SkToBool(key.colorSpace),
|
||||
SkToBool(key.shader),
|
||||
SkToBool(key.colorFilter));
|
||||
}
|
||||
@ -148,7 +151,15 @@ namespace {
|
||||
|
||||
static bool CanBuild(const Key& key) {
|
||||
// These checks parallel the TODOs in Builder::Builder().
|
||||
if (key.shader) { return false; }
|
||||
if (key.shader) {
|
||||
// TODO: maybe passing the whole Key is going to be what we'll want here?
|
||||
if (!as_SB(key.shader)->program(nullptr,
|
||||
key.colorSpace,
|
||||
skvm::Arg{0}, 0,
|
||||
nullptr,nullptr,nullptr,nullptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (key.colorFilter) { return false; }
|
||||
|
||||
switch (key.colorType) {
|
||||
@ -177,10 +188,24 @@ namespace {
|
||||
// If coverage is Mask3D there'll next come two varyings for mul and add planes,
|
||||
// and then finally if coverage is any Mask?? format, a varying for the mask.
|
||||
|
||||
// When there's no shader and no color filter, the source color is the paint color.
|
||||
if (key.shader) { TODO; }
|
||||
if (key.colorFilter) { TODO; }
|
||||
Color src = unpack_8888(uniform32(uniforms, offsetof(Uniforms, paint_color)));
|
||||
if (key.shader) {
|
||||
skvm::I32 paint_alpha = src.a;
|
||||
SkAssertResult(as_SB(key.shader)->program(this,
|
||||
key.colorSpace,
|
||||
uniforms, sizeof(Uniforms),
|
||||
&src.r, &src.g, &src.b, &src.a));
|
||||
|
||||
// TODO: skip when paint is opaque.
|
||||
if (false) {
|
||||
// I thought I had to do this, but it seems to screw things up?
|
||||
src.r = div255(mul(src.r, paint_alpha));
|
||||
src.g = div255(mul(src.g, paint_alpha));
|
||||
src.b = div255(mul(src.b, paint_alpha));
|
||||
src.a = div255(mul(src.a, paint_alpha));
|
||||
}
|
||||
}
|
||||
if (key.colorFilter) { TODO; }
|
||||
|
||||
if (key.coverage == Coverage::Mask3D) {
|
||||
skvm::I32 M = load8(varying<uint8_t>()),
|
||||
@ -307,6 +332,7 @@ namespace {
|
||||
device.alphaType(),
|
||||
Coverage::Full,
|
||||
paint.getBlendMode(),
|
||||
device.colorSpace(),
|
||||
paint.getShader(),
|
||||
paint.getColorFilter(),
|
||||
}
|
||||
@ -316,7 +342,8 @@ namespace {
|
||||
device.colorSpace(), kUnpremul_SkAlphaType}.apply(color.vec());
|
||||
|
||||
if (color.fitsInBytes() && Builder::CanBuild(fKey)) {
|
||||
fUniforms.paint_color = color.premul().toBytes_RGBA();
|
||||
uint32_t rgba = color.premul().toBytes_RGBA();
|
||||
memcpy(fUniforms.data() + offsetof(Uniforms, paint_color), &rgba, sizeof(rgba));
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
@ -344,9 +371,9 @@ namespace {
|
||||
}
|
||||
|
||||
private:
|
||||
SkPixmap fDevice; // TODO: can this be const&?
|
||||
const Key fKey;
|
||||
Uniforms fUniforms;
|
||||
SkPixmap fDevice; // TODO: can this be const&?
|
||||
const Key fKey;
|
||||
std::vector<uint8_t> fUniforms{sizeof(Uniforms)};
|
||||
skvm::Program fBlitH,
|
||||
fBlitAntiH,
|
||||
fBlitMaskA8,
|
||||
@ -383,20 +410,30 @@ namespace {
|
||||
return program;
|
||||
}
|
||||
|
||||
void updateUniforms() {
|
||||
if (SkShaderBase* shader = as_SB(fKey.shader)) {
|
||||
size_t extra = shader->uniforms(fKey.colorSpace, nullptr);
|
||||
fUniforms.resize(sizeof(Uniforms) + extra);
|
||||
shader->uniforms(fKey.colorSpace, fUniforms.data() + sizeof(Uniforms));
|
||||
}
|
||||
}
|
||||
|
||||
void blitH(int x, int y, int w) override {
|
||||
if (fBlitH.empty()) {
|
||||
fBlitH = this->buildProgram(Coverage::Full);
|
||||
}
|
||||
fBlitH.eval(w, &fUniforms, fDevice.addr(x,y));
|
||||
this->updateUniforms();
|
||||
fBlitH.eval(w, fUniforms.data(), fDevice.addr(x,y));
|
||||
}
|
||||
|
||||
void blitAntiH(int x, int y, const SkAlpha cov[], const int16_t runs[]) override {
|
||||
if (fBlitAntiH.empty()) {
|
||||
fBlitAntiH = this->buildProgram(Coverage::UniformA8);
|
||||
}
|
||||
this->updateUniforms();
|
||||
for (int16_t run = *runs; run > 0; run = *runs) {
|
||||
fUniforms.coverage = *cov;
|
||||
fBlitAntiH.eval(run, &fUniforms, fDevice.addr(x,y));
|
||||
memcpy(fUniforms.data() + offsetof(Uniforms, coverage), cov, sizeof(*cov));
|
||||
fBlitAntiH.eval(run, fUniforms.data(), fDevice.addr(x,y));
|
||||
|
||||
x += run;
|
||||
runs += run;
|
||||
@ -438,19 +475,20 @@ namespace {
|
||||
|
||||
SkASSERT(program);
|
||||
if (program) {
|
||||
this->updateUniforms();
|
||||
for (int y = clip.top(); y < clip.bottom(); y++) {
|
||||
void* dptr = fDevice.writable_addr(clip.left(), y);
|
||||
auto mptr = (const uint8_t*)mask.getAddr(clip.left(), y);
|
||||
|
||||
if (program == &fBlitMask3D) {
|
||||
size_t plane = mask.computeImageSize();
|
||||
program->eval(clip.width(), &fUniforms,
|
||||
program->eval(clip.width(), fUniforms.data(),
|
||||
dptr,
|
||||
mptr + 1*plane,
|
||||
mptr + 2*plane,
|
||||
mptr + 0*plane);
|
||||
} else {
|
||||
program->eval(clip.width(), &fUniforms,
|
||||
program->eval(clip.width(), fUniforms.data(),
|
||||
dptr, mptr);
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,43 @@ bool SkColor4Shader::onAppendStages(const SkStageRec& rec) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkColorShader::program(skvm::Builder* p,
|
||||
SkColorSpace* dstCS,
|
||||
skvm::Arg uniforms, int offset,
|
||||
skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) const {
|
||||
|
||||
SkColor4f color = SkColor4f::FromColor(fColor);
|
||||
SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
|
||||
dstCS, kUnpremul_SkAlphaType).apply(color.vec());
|
||||
|
||||
if (color.fitsInBytes()) {
|
||||
if (p) {
|
||||
skvm::I32 rgba = p->uniform32(uniforms, offset);
|
||||
*r = p->extract(rgba, 0, p->splat(0xff));
|
||||
*g = p->extract(rgba, 8, p->splat(0xff));
|
||||
*b = p->extract(rgba, 16, p->splat(0xff));
|
||||
*a = p->extract(rgba, 24, p->splat(0xff));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t SkColorShader::uniforms(SkColorSpace* dstCS, uint8_t* uniform_buffer) const {
|
||||
SkColor4f color = SkColor4f::FromColor(fColor);
|
||||
SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
|
||||
dstCS, kUnpremul_SkAlphaType).apply(color.vec());
|
||||
|
||||
SkASSERT(color.fitsInBytes());
|
||||
|
||||
uint32_t rgba = color.premul().toBytes_RGBA();
|
||||
if (uniform_buffer) {
|
||||
memcpy(uniform_buffer, &rgba, sizeof(rgba));
|
||||
}
|
||||
return sizeof(rgba);
|
||||
}
|
||||
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
#include "src/gpu/GrColorInfo.h"
|
||||
|
@ -44,6 +44,12 @@ private:
|
||||
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
bool program(skvm::Builder*,
|
||||
SkColorSpace* dstCS,
|
||||
skvm::Arg uniforms, int offset,
|
||||
skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) const override;
|
||||
size_t uniforms(SkColorSpace* dstCS, uint8_t* uniform_buffer) const override;
|
||||
|
||||
SkColor fColor;
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "src/core/SkEffectPriv.h"
|
||||
#include "src/core/SkMask.h"
|
||||
#include "src/core/SkTLazy.h"
|
||||
#include "src/core/SkVM.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "src/gpu/GrFPArgs.h"
|
||||
@ -206,6 +207,16 @@ public:
|
||||
return this->onAppendUpdatableStages(rec);
|
||||
}
|
||||
|
||||
|
||||
virtual bool program(skvm::Builder*,
|
||||
SkColorSpace* dstCS,
|
||||
skvm::Arg uniforms, int offset,
|
||||
skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual size_t uniforms(SkColorSpace* dstCS, uint8_t* uniform_buffer) const { return 0; }
|
||||
|
||||
protected:
|
||||
SkShaderBase(const SkMatrix* localMatrix = nullptr);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user