Revert "Add public API support for SkImageFilters::RuntimeShader"
This reverts commit ad9d774c1f
.
Reason for revert: Task Test-Debian10-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-DDL3_TSAN has been failing since this CL landed.
Original change's description:
> Add public API support for SkImageFilters::RuntimeShader
>
> This new image filter constructor enables SkRuntimeEffects to be
> used as shaders within the ImageFilter DAG. The shader is created
> lazily using the SkRuntimeShaderBuilder enabling the resulting
> shader to consume the previous stage of the ImageFilter graph.
>
> Change-Id: I5d6917e34a8e5fdd053399f15a1e2cc7409e686f
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/470459
> Reviewed-by: Brian Osman <brianosman@google.com>
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Derek Sollenberger <djsollen@google.com>
Change-Id: I0367a5c480df109c6116eb168792fe3c2fc58807
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/475644
Auto-Submit: Leandro Lovisolo <lovisolo@google.com>
Reviewed-by: Leandro Lovisolo <lovisolo@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Leandro Lovisolo <lovisolo@google.com>
This commit is contained in:
parent
cc9d0cd5a9
commit
5f4055d03d
@ -16,10 +16,6 @@ Milestone 98
|
||||
could be created, but the CPU backend would fail to index them correctly.
|
||||
* SkCanvas::drawVertices and SkCanvas::drawPatch variants that did not take SkBlendMode are
|
||||
removed.
|
||||
* SkImageFilters::RuntimeShader is a new public API that enables adding RuntimeShaderEffects into
|
||||
image filter graph.
|
||||
|
||||
* * *
|
||||
|
||||
Milestone 97
|
||||
------------
|
||||
|
@ -30,8 +30,9 @@ static sk_sp<SkImageFilter> make_filter() {
|
||||
return child.eval(coord);
|
||||
}
|
||||
)")).effect;
|
||||
SkRuntimeShaderBuilder builder(std::move(effect));
|
||||
return SkImageFilters::RuntimeShader(builder, /*childShaderName=*/nullptr, /*input=*/nullptr);
|
||||
return SkMakeRuntimeImageFilter(std::move(effect),
|
||||
/*uniforms=*/nullptr,
|
||||
/*input=*/nullptr);
|
||||
}
|
||||
|
||||
DEF_SIMPLE_GM_BG(rtif_distort, canvas, 500, 750, SK_ColorBLACK) {
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include "include/core/SkPicture.h"
|
||||
#include "include/core/SkRect.h"
|
||||
#include "include/core/SkTileMode.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
@ -334,26 +332,6 @@ public:
|
||||
return Picture(std::move(pic), target);
|
||||
}
|
||||
|
||||
#ifdef SK_ENABLE_SKSL
|
||||
/**
|
||||
* Create a filter that fills the output with the per-pixel evaluation of the SkShader produced
|
||||
* by the SkRuntimeShaderBuilder. The shader is defined in the image filter's local coordinate
|
||||
* system, so it will automatically be affected by SkCanvas' transform.
|
||||
*
|
||||
* @param builder The builder used to produce the runtime shader, that will in turn
|
||||
* fill the result image
|
||||
* @param childShaderName The name of the child shader defined in the builder that will be
|
||||
* bound to the input param (or the source image if the input param
|
||||
* is null). If null the builder can have exactly one child shader,
|
||||
* which automatically binds the input param.
|
||||
* @param input The image filter that will be provided as input to the runtime
|
||||
* shader. If null the implicit source image is used instead
|
||||
*/
|
||||
static sk_sp<SkImageFilter> RuntimeShader(const SkRuntimeShaderBuilder& builder,
|
||||
const char* childShaderName,
|
||||
sk_sp<SkImageFilter> input);
|
||||
#endif // SK_ENABLE_SKSL
|
||||
|
||||
enum class Dither : bool {
|
||||
kNo = false,
|
||||
kYes = true
|
||||
|
@ -28,7 +28,6 @@
|
||||
class GrRecordingContext;
|
||||
class SkFilterColorProgram;
|
||||
class SkImage;
|
||||
class SkRuntimeImageFilter;
|
||||
|
||||
namespace SkSL {
|
||||
class FunctionDefinition;
|
||||
@ -383,10 +382,6 @@ protected:
|
||||
: fEffect(std::move(effect))
|
||||
, fUniforms(SkData::MakeZeroInitialized(fEffect->uniformSize()))
|
||||
, fChildren(fEffect->children().size()) {}
|
||||
explicit SkRuntimeEffectBuilder(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> uniforms)
|
||||
: fEffect(std::move(effect))
|
||||
, fUniforms(std::move(uniforms))
|
||||
, fChildren(fEffect->children().size()) {}
|
||||
|
||||
SkRuntimeEffectBuilder(SkRuntimeEffectBuilder&&) = default;
|
||||
SkRuntimeEffectBuilder(const SkRuntimeEffectBuilder&) = default;
|
||||
@ -447,11 +442,6 @@ public:
|
||||
|
||||
private:
|
||||
using INHERITED = SkRuntimeEffectBuilder;
|
||||
|
||||
explicit SkRuntimeShaderBuilder(sk_sp<SkRuntimeEffect> effect, sk_sp<SkData> uniforms)
|
||||
: INHERITED(std::move(effect), std::move(uniforms)) {}
|
||||
|
||||
friend class SkRuntimeImageFilter;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -19,20 +19,16 @@
|
||||
|
||||
#ifdef SK_ENABLE_SKSL
|
||||
|
||||
namespace {
|
||||
|
||||
class SkRuntimeImageFilter final : public SkImageFilter_Base {
|
||||
public:
|
||||
SkRuntimeImageFilter(sk_sp<SkRuntimeEffect> effect,
|
||||
sk_sp<SkData> uniforms,
|
||||
sk_sp<SkImageFilter> input)
|
||||
: INHERITED(&input, 1, /*cropRect=*/nullptr)
|
||||
, fShaderBuilder(std::move(effect), std::move(uniforms))
|
||||
, fChildShaderName(fShaderBuilder.effect()->children().front().name) {}
|
||||
SkRuntimeImageFilter(const SkRuntimeShaderBuilder& builder,
|
||||
const char* childShaderName,
|
||||
sk_sp<SkImageFilter> input)
|
||||
: INHERITED(&input, 1, /*cropRect=*/nullptr)
|
||||
, fShaderBuilder(builder)
|
||||
, fChildShaderName(childShaderName) {}
|
||||
, fEffect(std::move(effect))
|
||||
, fUniforms(std::move(uniforms)) {}
|
||||
|
||||
bool onAffectsTransparentBlack() const override { return true; }
|
||||
MatrixCapability onGetCTMCapability() const override { return MatrixCapability::kTranslate; }
|
||||
@ -45,12 +41,14 @@ private:
|
||||
friend void ::SkRegisterRuntimeImageFilterFlattenable();
|
||||
SK_FLATTENABLE_HOOKS(SkRuntimeImageFilter)
|
||||
|
||||
mutable SkRuntimeShaderBuilder fShaderBuilder;
|
||||
SkString fChildShaderName;
|
||||
sk_sp<SkRuntimeEffect> fEffect;
|
||||
sk_sp<SkData> fUniforms;
|
||||
|
||||
using INHERITED = SkImageFilter_Base;
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
sk_sp<SkImageFilter> SkMakeRuntimeImageFilter(sk_sp<SkRuntimeEffect> effect,
|
||||
sk_sp<SkData> uniforms,
|
||||
sk_sp<SkImageFilter> input) {
|
||||
@ -73,67 +71,25 @@ void SkRegisterRuntimeImageFilterFlattenable() {
|
||||
|
||||
sk_sp<SkFlattenable> SkRuntimeImageFilter::CreateProc(SkReadBuffer& buffer) {
|
||||
SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
|
||||
if (common.cropRect()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Read the SkSL string and convert it into a runtime effect
|
||||
SkString sksl;
|
||||
buffer.readString(&sksl);
|
||||
sk_sp<SkData> uniforms = buffer.readByteArrayAsData();
|
||||
|
||||
auto effect = SkMakeCachedRuntimeEffect(SkRuntimeEffect::MakeForShader, std::move(sksl));
|
||||
if (!buffer.validate(effect != nullptr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Read the uniform data and make sure it matches the size from the runtime effect
|
||||
sk_sp<SkData> uniforms = buffer.readByteArrayAsData();
|
||||
if (!buffer.validate(uniforms->size() == effect->uniformSize())) {
|
||||
if (common.cropRect()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Read the child shader name and make sure it matches one declared in the effect
|
||||
SkString childShaderName;
|
||||
buffer.readString(&childShaderName);
|
||||
if (!buffer.validate(effect->findChild(childShaderName.c_str()) != nullptr)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkRuntimeShaderBuilder builder(std::move(effect), std::move(uniforms));
|
||||
|
||||
// Populate the builder with the corresponding children
|
||||
for (auto& child : builder.effect()->children()) {
|
||||
const char* name = child.name.c_str();
|
||||
switch (child.type) {
|
||||
case SkRuntimeEffect::ChildType::kBlender: {
|
||||
builder.child(name) = buffer.readBlender();
|
||||
break;
|
||||
}
|
||||
case SkRuntimeEffect::ChildType::kColorFilter: {
|
||||
builder.child(name) = buffer.readColorFilter();
|
||||
break;
|
||||
}
|
||||
case SkRuntimeEffect::ChildType::kShader: {
|
||||
builder.child(name) = buffer.readShader();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!buffer.isValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return SkImageFilters::RuntimeShader(builder, childShaderName.c_str(), common.getInput(0));
|
||||
return SkMakeRuntimeImageFilter(std::move(effect), std::move(uniforms), common.getInput(0));
|
||||
}
|
||||
|
||||
void SkRuntimeImageFilter::flatten(SkWriteBuffer& buffer) const {
|
||||
this->INHERITED::flatten(buffer);
|
||||
buffer.writeString(fShaderBuilder.effect()->source().c_str());
|
||||
buffer.writeDataAsByteArray(fShaderBuilder.uniforms().get());
|
||||
buffer.writeString(fChildShaderName.c_str());
|
||||
for (size_t x = 0; x < fShaderBuilder.numChildren(); x++) {
|
||||
buffer.writeFlattenable(fShaderBuilder.children()[x].flattenable());
|
||||
}
|
||||
buffer.writeString(fEffect->source().c_str());
|
||||
buffer.writeDataAsByteArray(fUniforms.get());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -163,9 +119,8 @@ sk_sp<SkSpecialImage> SkRuntimeImageFilter::onFilterImage(const Context& ctx,
|
||||
input->asImage()->makeShader(SkSamplingOptions(SkFilterMode::kLinear), &localM);
|
||||
SkASSERT(inputShader);
|
||||
|
||||
fShaderBuilder.child(fChildShaderName.c_str()) = inputShader;
|
||||
sk_sp<SkShader> shader = fShaderBuilder.makeShader(nullptr, false);
|
||||
SkASSERT(shader.get());
|
||||
auto shader = fEffect->makeShader(fUniforms, &inputShader, 1, nullptr, false);
|
||||
SkASSERT(shader);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setShader(std::move(shader));
|
||||
@ -181,31 +136,8 @@ sk_sp<SkSpecialImage> SkRuntimeImageFilter::onFilterImage(const Context& ctx,
|
||||
|
||||
canvas->drawPaint(paint);
|
||||
|
||||
// Remove the shader from the builder to avoid unnecessarily prolonging the shader's lifetime
|
||||
fShaderBuilder.child(fChildShaderName.c_str()) = nullptr;
|
||||
|
||||
*offset = outputBounds.topLeft();
|
||||
return surf->makeImageSnapshot();
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> SkImageFilters::RuntimeShader(const SkRuntimeShaderBuilder& builder,
|
||||
const char* childShaderName,
|
||||
sk_sp<SkImageFilter> input) {
|
||||
// if no childShaderName is provided check to see if we can implicitly assign it to the only
|
||||
// child in the effect
|
||||
if (childShaderName == nullptr) {
|
||||
auto children = builder.effect()->children();
|
||||
if (children.size() != 1) {
|
||||
return nullptr;
|
||||
}
|
||||
childShaderName = children.front().name.c_str();
|
||||
} else if (builder.effect()->findChild(childShaderName) == nullptr) {
|
||||
// there was no child declared in the runtime effect that matches the provided name
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sk_sp<SkImageFilter>(
|
||||
new SkRuntimeImageFilter(builder, childShaderName, std::move(input)));
|
||||
}
|
||||
|
||||
#endif // SK_ENABLE_SKSL
|
||||
|
@ -8,11 +8,8 @@
|
||||
#include "include/core/SkBitmap.h"
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkShader.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/effects/SkGradientShader.h"
|
||||
#include "include/effects/SkImageFilters.h"
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
#include "src/effects/imagefilters/SkRuntimeImageFilter.h"
|
||||
#include "tests/Test.h"
|
||||
|
||||
static void test_unscaled(skiatest::Reporter* reporter) {
|
||||
@ -117,78 +114,3 @@ DEF_TEST(PaintImageFilter, reporter) {
|
||||
test_unscaled(reporter);
|
||||
test_scaled(reporter);
|
||||
}
|
||||
|
||||
static void test_runtime_shader(skiatest::Reporter* r, SkSurface* surface) {
|
||||
sk_sp<SkRuntimeEffect> effect = SkRuntimeEffect::MakeForShader(SkString(R"(
|
||||
uniform shader child;
|
||||
vec4 main(vec2 coord) {
|
||||
return child.eval(coord) * 0.5;
|
||||
}
|
||||
)"))
|
||||
.effect;
|
||||
SkRuntimeShaderBuilder builder(effect);
|
||||
|
||||
// create a red image filter to feed as input into the SkImageFilters::RuntimeShader
|
||||
SkPaint redPaint;
|
||||
redPaint.setColor(SK_ColorRED);
|
||||
sk_sp<SkImageFilter> input = SkImageFilters::Paint(redPaint);
|
||||
|
||||
// Create the different variations of SkImageFilters::RuntimeShader
|
||||
// All 3 variations should produce the same pixel output
|
||||
std::vector<sk_sp<SkImageFilter>> filters = {
|
||||
SkMakeRuntimeImageFilter(effect, /*uniforms=*/nullptr, input),
|
||||
SkImageFilters::RuntimeShader(builder, /*childShaderName=*/nullptr, input),
|
||||
SkImageFilters::RuntimeShader(builder, /*childShaderName=*/"child", input)};
|
||||
|
||||
for (auto&& filter : filters) {
|
||||
auto canvas = surface->getCanvas();
|
||||
|
||||
// clear to transparent
|
||||
SkPaint paint;
|
||||
paint.setColor(SK_ColorTRANSPARENT);
|
||||
paint.setBlendMode(SkBlendMode::kSrc);
|
||||
canvas->drawPaint(paint);
|
||||
|
||||
SkPaint filterPaint;
|
||||
// the green color will be ignored by the filter within the runtime shader
|
||||
filterPaint.setColor(SK_ColorGREEN);
|
||||
filterPaint.setImageFilter(filter);
|
||||
canvas->saveLayer(nullptr, &filterPaint);
|
||||
// the blue color will be ignored by the filter because the input to the image filter is not
|
||||
// null
|
||||
canvas->drawColor(SK_ColorBLUE);
|
||||
canvas->restore();
|
||||
|
||||
// This is expected to read back the half transparent red pixel produced by the image filter
|
||||
SkBitmap bitmap;
|
||||
REPORTER_ASSERT(r, bitmap.tryAllocPixels(surface->imageInfo()));
|
||||
REPORTER_ASSERT(r,
|
||||
surface->readPixels(bitmap.info(),
|
||||
bitmap.getPixels(),
|
||||
bitmap.rowBytes(),
|
||||
/*srcX=*/0,
|
||||
/*srcY=*/0));
|
||||
SkColor color = bitmap.getColor(/*x=*/0, /*y=*/0);
|
||||
|
||||
// check alpha with a small tolerance
|
||||
SkAlpha alpha = SkColorGetA(color);
|
||||
REPORTER_ASSERT(r, alpha >= 127 && alpha <= 129, "Expected: %d Actual: %d", 128, alpha);
|
||||
|
||||
// check each color channel
|
||||
color = SkColorSetA(color, 255);
|
||||
REPORTER_ASSERT(r, SK_ColorRED == color, "Expected: %08x Actual: %08x", SK_ColorRED, color);
|
||||
}
|
||||
}
|
||||
|
||||
DEF_TEST(SkRuntimeShaderImageFilter_CPU, r) {
|
||||
const SkImageInfo info = SkImageInfo::MakeN32Premul(/*width=*/1, /*height=*/1);
|
||||
sk_sp<SkSurface> surface(SkSurface::MakeRaster(info));
|
||||
test_runtime_shader(r, surface.get());
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRuntimeShaderImageFilter_GPU, r, ctxInfo) {
|
||||
const SkImageInfo info = SkImageInfo::MakeN32Premul(/*width=*/1, /*height=*/1);
|
||||
sk_sp<SkSurface> surface(
|
||||
SkSurface::MakeRenderTarget(ctxInfo.directContext(), SkBudgeted::kNo, info));
|
||||
test_runtime_shader(r, surface.get());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user