diff options
Diffstat (limited to 'chromium/third_party/skia/gm/runtimeshader.cpp')
-rw-r--r-- | chromium/third_party/skia/gm/runtimeshader.cpp | 108 |
1 files changed, 94 insertions, 14 deletions
diff --git a/chromium/third_party/skia/gm/runtimeshader.cpp b/chromium/third_party/skia/gm/runtimeshader.cpp index ef5ee712694..63be548cc85 100644 --- a/chromium/third_party/skia/gm/runtimeshader.cpp +++ b/chromium/third_party/skia/gm/runtimeshader.cpp @@ -48,8 +48,8 @@ class RuntimeShader : public skiagm::GM { DEF_GM(return new RuntimeShader;) static sk_sp<SkShader> make_shader(sk_sp<SkImage> img, SkISize size) { - SkMatrix scale = SkMatrix::MakeScale(size.width() / (float)img->width(), - size.height() / (float)img->height()); + SkMatrix scale = SkMatrix::Scale(size.width() / (float)img->width(), + size.height() / (float)img->height()); return img->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, &scale); } @@ -102,9 +102,9 @@ class ThresholdRT : public skiagm::GM { fAfter = make_shader(GetResourceAsImage("images/dog.jpg"), size); const char code[] = R"( - in fragmentProcessor before_map; - in fragmentProcessor after_map; - in fragmentProcessor threshold_map; + in shader before_map; + in shader after_map; + in shader threshold_map; uniform float cutoff; uniform float slope; @@ -118,7 +118,7 @@ class ThresholdRT : public skiagm::GM { half4 before = sample(before_map, xy); half4 after = sample(after_map, xy); - float m = smooth_cutoff(sample(threshold_map, xy).r); + float m = smooth_cutoff(sample(threshold_map, xy).a); color = mix(before, after, half(m)); } )"; @@ -135,12 +135,7 @@ class ThresholdRT : public skiagm::GM { SkISize onISize() override { return {256, 256}; } - DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { - if (canvas->getGrContext() == nullptr) { - // until SkSL can handle child processors on the raster backend - return DrawResult::kSkip; - } - + void onDraw(SkCanvas* canvas) override { struct { float cutoff, slope; } uni = { @@ -164,8 +159,6 @@ class ThresholdRT : public skiagm::GM { draw(256, 0, fThreshold); draw( 0, 256, fBefore); draw(256, 256, fAfter); - - return DrawResult::kOk; } bool onAnimate(double nanos) override { @@ -237,3 +230,90 @@ class SpiralRT : public skiagm::GM { } }; DEF_GM(return new SpiralRT;) + +class ColorCubeRT : public skiagm::GM { + sk_sp<SkImage> fMandrill, fMandrillSepia, fIdentityCube, fSepiaCube; + sk_sp<SkRuntimeEffect> fEffect; + + void onOnceBeforeDraw() override { + fMandrill = GetResourceAsImage("images/mandrill_256.png"); + fMandrillSepia = GetResourceAsImage("images/mandrill_sepia.png"); + fIdentityCube = GetResourceAsImage("images/lut_identity.png"); + fSepiaCube = GetResourceAsImage("images/lut_sepia.png"); + + const char code[] = R"( + in shader input; + in shader color_cube; + + uniform float rg_scale; + uniform float rg_bias; + uniform float b_scale; + uniform float inv_size; + + void main(float2 xy, inout half4 color) { + float4 c = float4(unpremul(sample(input, xy))); + + // Map to cube coords: + float3 cubeCoords = float3(c.rg * rg_scale + rg_bias, c.b * b_scale); + + // Compute slice coordinate + float2 coords1 = float2((floor(cubeCoords.b) + cubeCoords.r) * inv_size, cubeCoords.g); + float2 coords2 = float2(( ceil(cubeCoords.b) + cubeCoords.r) * inv_size, cubeCoords.g); + + // Two bilinear fetches, plus a manual lerp for the third axis: + color = mix(sample(color_cube, coords1), sample(color_cube, coords2), + half(fract(cubeCoords.b))); + + // Premul again + color.rgb *= color.a; + } + )"; + auto [effect, error] = SkRuntimeEffect::Make(SkString(code)); + if (!effect) { + SkDebugf("runtime error %s\n", error.c_str()); + } + fEffect = effect; + } + + SkString onShortName() override { return SkString("color_cube_rt"); } + + SkISize onISize() override { return {512, 512}; } + + void onDraw(SkCanvas* canvas) override { + // First we draw the unmodified image, and a copy that was sepia-toned in Photoshop: + canvas->drawImage(fMandrill, 0, 0); + canvas->drawImage(fMandrillSepia, 0, 256); + + // LUT dimensions should be (kSize^2, kSize) + constexpr float kSize = 16.0f; + + SkRuntimeShaderBuilder builder(fEffect); + builder.input("rg_scale") = (kSize - 1) / kSize; + builder.input("rg_bias") = 0.5f / kSize; + builder.input("b_scale") = kSize - 1; + builder.input("inv_size") = 1.0f / kSize; + + builder.child("input") = fMandrill->makeShader(); + + // TODO: Move filter quality to the shader itself. We need to enforce at least kLow here + // so that we bilerp the color cube image. + SkPaint paint; + paint.setFilterQuality(kLow_SkFilterQuality); + + // TODO: Should we add SkImage::makeNormalizedShader() to handle this automatically? + SkMatrix normalize = SkMatrix::Scale(1.0f / (kSize * kSize), 1.0f / kSize); + + // Now draw the image with an identity color cube - it should look like the original + builder.child("color_cube") = fIdentityCube->makeShader(normalize); + paint.setShader(builder.makeShader(nullptr, true)); + canvas->translate(256, 0); + canvas->drawRect({ 0, 0, 256, 256 }, paint); + + // ... and with a sepia-tone color cube. This should match the sepia-toned image. + builder.child("color_cube") = fSepiaCube->makeShader(normalize); + paint.setShader(builder.makeShader(nullptr, true)); + canvas->translate(0, 256); + canvas->drawRect({ 0, 0, 256, 256 }, paint); + } +}; +DEF_GM(return new ColorCubeRT;) |