04aef10c64
Allows creation of an image directly from a RTE. Caller provides the effect input bindings, image info for the image, and optional local matrix. The info's alpha type and colorspace are tags for the output image. No alpha type or color space conversions are applied to the output of RTE. CPU does not yet support making kUnpremul images. Bug: chromium:1151490 Change-Id: I69babc9dbbce4431d756cd7a3eef4753e727d6fe Reviewed-on: https://skia-review.googlesource.com/c/skia/+/357284 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Derek Sollenberger <djsollen@google.com> Reviewed-by: Mike Reed <reed@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
136 lines
5.1 KiB
C++
136 lines
5.1 KiB
C++
/*
|
|
* Copyright 2021 Google LLC
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "gm/gm.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkSize.h"
|
|
#include "include/core/SkString.h"
|
|
#include "include/core/SkSurface.h"
|
|
#include "include/effects/SkGradientShader.h"
|
|
#include "include/effects/SkRuntimeEffect.h"
|
|
#include "tools/Resources.h"
|
|
#include "tools/ToolUtils.h"
|
|
|
|
class RuntimeEffectImage : public skiagm::GM {
|
|
public:
|
|
RuntimeEffectImage() = default;
|
|
|
|
SkString onShortName() override { return SkString("runtime_effect_image"); }
|
|
|
|
SkISize onISize() override { return {800, 200}; }
|
|
|
|
protected:
|
|
void onOnceBeforeDraw() override {
|
|
SkString sksl(R"(
|
|
uniform shader child;
|
|
uniform half gAlphaType; // 0 is premul, non-zero unpremul.
|
|
|
|
half4 main(float2 p) {
|
|
half r = fract(p.x/20);
|
|
half g = fract(p.y/20);
|
|
half b = fract((p.x + 5)/10);
|
|
half a = min(distance(p, vec2(50, 50))/50 + 0.3, 1);
|
|
half4 result = half4(r, g, b, a);
|
|
result *= sample(child);
|
|
if (gAlphaType == 0) {
|
|
result.rgb *= a;
|
|
}
|
|
return result;
|
|
}
|
|
)");
|
|
auto [effect, error] = SkRuntimeEffect::Make(sksl);
|
|
if (!effect) {
|
|
SkDebugf("RuntimeShader error: %s\n", error.c_str());
|
|
}
|
|
fEffect = std::move(effect);
|
|
}
|
|
|
|
DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
|
|
GrRecordingContext* rc = canvas->recordingContext();
|
|
SkRuntimeShaderBuilder builder(fEffect);
|
|
SkImageInfo info = SkImageInfo::Make(100, 100, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
|
|
|
|
SkSamplingOptions nn{SkFilterMode::kNearest};
|
|
SkSamplingOptions mm{SkFilterMode::kLinear, SkMipmapMode::kNearest};
|
|
auto whiteShader = SkShaders::Color(SK_ColorWHITE);
|
|
auto imageForShader = GetResourceAsImage("images/ducky.jpg");
|
|
if (!imageForShader) {
|
|
*errorMsg = "Could not load image";
|
|
return DrawResult::kFail;
|
|
}
|
|
auto imageShader = imageForShader->makeShader(SkTileMode::kRepeat,
|
|
SkTileMode::kRepeat,
|
|
SkSamplingOptions(SkFilterMode::kLinear),
|
|
SkMatrix::Scale(0.2f, 0.2f));
|
|
|
|
builder.uniform("gAlphaType") = 0.f;
|
|
builder.child("child") = whiteShader;
|
|
ToolUtils::draw_checkerboard(canvas, SK_ColorWHITE, SK_ColorLTGRAY, 50);
|
|
canvas->translate(5, 5);
|
|
SkPaint aaPaint;
|
|
aaPaint.setAntiAlias(true);
|
|
for (const auto& vm : {SkMatrix::Scale(1.5f, 1.5f), SkMatrix::Scale(0.3f, 0.3f)}) {
|
|
canvas->save();
|
|
canvas->concat(vm);
|
|
|
|
sk_sp<SkImage> image;
|
|
|
|
// basic
|
|
image = builder.makeImage(rc, nullptr, info, false);
|
|
canvas->drawImage(image, 0, 0, nn, &aaPaint);
|
|
canvas->translate(105, 0);
|
|
|
|
// local matrix
|
|
SkMatrix lm = SkMatrix::RotateDeg(45, {50, 50});
|
|
lm.preTranslate(10, 10);
|
|
image = builder.makeImage(rc, &lm, info, false);
|
|
canvas->drawImage(image, 0, 0, nn, &aaPaint);
|
|
canvas->translate(105, 0);
|
|
|
|
// unpremul
|
|
if (rc) {
|
|
// use a uniform to make the effect output be unpremul so it looks the same as the
|
|
// premul case when drawn to the canvas.
|
|
builder.uniform("gAlphaType") = 1.f;
|
|
image = builder.makeImage(rc,
|
|
nullptr,
|
|
info.makeAlphaType(kUnpremul_SkAlphaType),
|
|
false);
|
|
builder.uniform("gAlphaType") = 0.f;
|
|
canvas->drawImage(image, 0, 0, nn, &aaPaint);
|
|
canvas->translate(105, 0);
|
|
} else {
|
|
// CPU doesn't yet support making kUnpremul images. Just draw the basic one again.
|
|
image = builder.makeImage(nullptr, nullptr, info, false);
|
|
canvas->drawImage(image, 0, 0, nn, &aaPaint);
|
|
canvas->translate(105, 0);
|
|
}
|
|
|
|
// color space
|
|
sk_sp<SkColorSpace> cs = SkColorSpace::MakeSRGB()->makeColorSpin();
|
|
image = builder.makeImage(rc, nullptr, info.makeColorSpace(std::move(cs)), false);
|
|
canvas->drawImage(image, 0, 0, nn, &aaPaint);
|
|
canvas->translate(105, 0);
|
|
|
|
// mipmapped and different child
|
|
builder.child("child") = imageShader;
|
|
image = builder.makeImage(rc, nullptr, info, true);
|
|
builder.child("child") = whiteShader;
|
|
canvas->drawImage(image, 0, 0, mm, &aaPaint);
|
|
canvas->translate(105, 0);
|
|
|
|
canvas->restore();
|
|
canvas->translate(0, 105*vm.getScaleY());
|
|
}
|
|
return DrawResult::kOk;
|
|
}
|
|
|
|
private:
|
|
sk_sp<SkRuntimeEffect> fEffect;
|
|
};
|
|
DEF_GM(return new RuntimeEffectImage;)
|