add store(PixelFormat,...)

Add store(PixelFormat,...) to mirror earlier load/gather.
Use store() in SkVMBlitter to let us to write to any format
supported by SkColorType_to_PixelFormat().

This means we can read and write all the same formats now.  There's a
note on the SkColorType enum about some SkColorTypes being read-only,
but I've taken that to be descriptive and not proscriptive.

It's worth paying attention to grayscale.  Gray PixelFormats hold the
same bit size and shift for each of r,g,b so load/gather just naturally
unpack the same value into each channel.  When we want to store gray we
need to dot r,g,b together, here back into the red channel to
accommodate future gray-alpha.

Change-Id: I81ad252a35e2534d2d8c6123354b1d19c7018898
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302330
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Mike Klein 2020-07-13 12:34:09 -05:00 committed by Skia Commit-Bot
parent 03c932c74f
commit e552f925da
3 changed files with 34 additions and 42 deletions

View File

@ -1190,6 +1190,34 @@ namespace skvm {
return {};
}
bool Builder::store(PixelFormat f, Arg ptr, Color c) {
// Detect a grayscale PixelFormat: r,g,b bit counts and shifts all equal.
if (f.r_bits == f.g_bits && f.g_bits == f.b_bits &&
f.r_shift == f.g_shift && f.g_shift == f.b_shift) {
// TODO: pull these coefficients from an SkColorSpace? This is sRGB luma/luminance.
c.r = c.r * 0.2126f
+ c.g * 0.7152f
+ c.b * 0.0722f;
f.g_bits = f.b_bits = 0;
}
I32 bits = splat(0);
if (f.r_bits) { bits = pack(bits, to_unorm(f.r_bits, c.r), f.r_shift); }
if (f.g_bits) { bits = pack(bits, to_unorm(f.g_bits, c.g), f.g_shift); }
if (f.b_bits) { bits = pack(bits, to_unorm(f.b_bits, c.b), f.b_shift); }
if (f.a_bits) { bits = pack(bits, to_unorm(f.a_bits, c.a), f.a_shift); }
switch (byte_size(f)) {
case 1: store8 (ptr, bits); return true;
case 2: store16(ptr, bits); return true;
case 4: store32(ptr, bits); return true;
// TODO: 8,16
default: SkUNREACHABLE;
}
return false;
}
void Builder::unpremul(F32* r, F32* g, F32* b, F32 a) {
skvm::F32 invA = 1.0f / a,
inf = bit_cast(splat(0x7f800000));

View File

@ -718,6 +718,7 @@ namespace skvm {
I32 to_unorm(int bits, F32); // E.g. to_unorm(8, x) -> round(x * 255)
Color load(PixelFormat, Arg ptr);
bool store(PixelFormat, Arg ptr, Color);
Color gather(PixelFormat, Arg ptr, int offset, I32 index);
Color gather(PixelFormat f, Uniform u, I32 index) {
return gather(f, u.ptr, u.offset, index);
@ -1041,6 +1042,7 @@ namespace skvm {
static inline F32 from_unorm(int bits, I32 x) { return x->from_unorm(bits,x); }
static inline I32 to_unorm(int bits, F32 x) { return x-> to_unorm(bits,x); }
static inline bool store(PixelFormat f, Arg p, Color c) { return c->store(f,p,c); }
static inline Color gather(PixelFormat f, Arg p, int off, I32 ix) {
return ix->gather(f,p,off,ix);
}

View File

@ -159,18 +159,9 @@ namespace {
}
}
switch (params.dst.colorType()) {
default: *ok = false;
break;
case kRGB_565_SkColorType:
case kRGB_888x_SkColorType:
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
case kRGBA_1010102_SkColorType:
case kBGRA_1010102_SkColorType:
case kRGB_101010x_SkColorType:
case kBGR_101010x_SkColorType: break;
skvm::PixelFormat unused;
if (!SkColorType_to_PixelFormat(params.dst.colorType(), &unused)) {
*ok = false;
}
return {
@ -359,36 +350,7 @@ namespace {
src.a = clamp01(src.a);
}
// Store back to the destination.
// TODO: use PixelFormat like we do for unpacking.
switch (params.dst.colorType()) {
default: SkUNREACHABLE;
case kRGB_565_SkColorType:
store16(dst_ptr, pack(pack(to_unorm(5,src.b),
to_unorm(6,src.g), 5),
to_unorm(5,src.r),11));
break;
case kBGRA_8888_SkColorType: std::swap(src.r, src.b); [[fallthrough]];
case kRGB_888x_SkColorType: [[fallthrough]];
case kRGBA_8888_SkColorType:
store32(dst_ptr, pack(pack(to_unorm(8, src.r),
to_unorm(8, src.g), 8),
pack(to_unorm(8, src.b),
to_unorm(8, src.a), 8), 16));
break;
case kBGR_101010x_SkColorType: [[fallthrough]];
case kBGRA_1010102_SkColorType: std::swap(src.r, src.b); [[fallthrough]];
case kRGB_101010x_SkColorType: [[fallthrough]];
case kRGBA_1010102_SkColorType:
store32(dst_ptr, pack(pack(to_unorm(10, src.r),
to_unorm(10, src.g), 10),
pack(to_unorm(10, src.b),
to_unorm( 2, src.a), 10), 20));
break;
}
SkAssertResult(store(pixelFormat, dst_ptr, src));
}