298 lines
12 KiB
C++
298 lines
12 KiB
C++
|
|
/*
|
||
|
|
* Copyright 2022 Google LLC
|
||
|
|
*
|
||
|
|
* Use of this source code is governed by a BSD-style license that can be
|
||
|
|
* found in the LICENSE file.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "tests/Test.h"
|
||
|
|
|
||
|
|
#if defined(SK_GRAPHITE)
|
||
|
|
|
||
|
|
#include "include/core/SkColorSpace.h"
|
||
|
|
#include "include/effects/SkRuntimeEffect.h"
|
||
|
|
#include "src/gpu/graphite/ContextPriv.h"
|
||
|
|
#include "src/gpu/graphite/FactoryFunctions.h"
|
||
|
|
#include "src/gpu/graphite/KeyContext.h"
|
||
|
|
#include "src/gpu/graphite/PaintOptionsPriv.h"
|
||
|
|
#include "src/gpu/graphite/Precompile.h"
|
||
|
|
#include "src/gpu/graphite/RuntimeEffectDictionary.h"
|
||
|
|
|
||
|
|
#include <array>
|
||
|
|
|
||
|
|
using namespace::skgpu::graphite;
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
// The default PaintOptions should create a single combination with a solid color shader and
|
||
|
|
// kSrcOver blending
|
||
|
|
void empty_test(const KeyContext& keyContext, skiatest::Reporter* reporter) {
|
||
|
|
PaintOptions paintOptions;
|
||
|
|
|
||
|
|
REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == 1);
|
||
|
|
|
||
|
|
std::vector<UniquePaintParamsID> precompileIDs;
|
||
|
|
paintOptions.priv().buildCombinations(keyContext,
|
||
|
|
/* addPrimitiveBlender= */ false,
|
||
|
|
[&](UniquePaintParamsID id) {
|
||
|
|
precompileIDs.push_back(id);
|
||
|
|
});
|
||
|
|
|
||
|
|
SkASSERT(precompileIDs.size() == 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// A PaintOptions will supply a default solid color shader if needed.
|
||
|
|
void no_shader_option_test(const KeyContext& keyContext, skiatest::Reporter* reporter) {
|
||
|
|
SkBlendMode blendModes[] = { SkBlendMode::kSrcOver };
|
||
|
|
|
||
|
|
PaintOptions paintOptions;
|
||
|
|
paintOptions.setBlendModes(blendModes);
|
||
|
|
|
||
|
|
REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == 1);
|
||
|
|
|
||
|
|
std::vector<UniquePaintParamsID> precompileIDs;
|
||
|
|
paintOptions.priv().buildCombinations(keyContext,
|
||
|
|
/* addPrimitiveBlender= */ false,
|
||
|
|
[&](UniquePaintParamsID id) {
|
||
|
|
precompileIDs.push_back(id);
|
||
|
|
});
|
||
|
|
|
||
|
|
SkASSERT(precompileIDs.size() == 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// A default kSrcOver blend mode will be supplied if no other blend options are added
|
||
|
|
void no_blend_mode_option_test(const KeyContext& keyContext, skiatest::Reporter* reporter) {
|
||
|
|
PaintOptions paintOptions;
|
||
|
|
paintOptions.setShaders({ PrecompileShaders::Color() });
|
||
|
|
|
||
|
|
REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == 1);
|
||
|
|
|
||
|
|
std::vector<UniquePaintParamsID> precompileIDs;
|
||
|
|
paintOptions.priv().buildCombinations(keyContext,
|
||
|
|
/* addPrimitiveBlender= */ false,
|
||
|
|
[&](UniquePaintParamsID id) {
|
||
|
|
precompileIDs.push_back(id);
|
||
|
|
});
|
||
|
|
|
||
|
|
SkASSERT(precompileIDs.size() == 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
void big_test(const KeyContext& keyContext, skiatest::Reporter* reporter) {
|
||
|
|
// paintOptions (17)
|
||
|
|
// |- sweepGrad_0 (2) | blendShader_0 (15)
|
||
|
|
// | 0: kSrc (1)
|
||
|
|
// | 1: (dsts) linearGrad_0 (2) | solid_0 (1)
|
||
|
|
// | 2: (srcs) linearGrad_1 (2) | blendShader_1 (3)
|
||
|
|
// | 0: kDst (1)
|
||
|
|
// | 1: (dsts) radGrad_0 (2) | solid_1 (1)
|
||
|
|
// | 2: (srcs) imageShader_0 (1)
|
||
|
|
// |
|
||
|
|
// |- 4-built-in-blend-modes (just 1 since all are PorterDuff)
|
||
|
|
|
||
|
|
PaintOptions paintOptions;
|
||
|
|
|
||
|
|
// first, shaders. First top-level option (sweepGrad_0)
|
||
|
|
sk_sp<PrecompileShader> sweepGrad_0 = PrecompileShaders::SweepGradient();
|
||
|
|
|
||
|
|
std::array<SkBlendMode, 1> blendModes{ SkBlendMode::kSrc };
|
||
|
|
|
||
|
|
std::vector<SkBlendMode> moreBlendModes{ SkBlendMode::kDst };
|
||
|
|
|
||
|
|
// Second top-level option (blendShader_0)
|
||
|
|
auto blendShader_0 = PrecompileShaders::Blend(
|
||
|
|
SkSpan<SkBlendMode>(blendModes), // std::array
|
||
|
|
{ // initializer_list
|
||
|
|
PrecompileShaders::LinearGradient(),
|
||
|
|
PrecompileShaders::Color()
|
||
|
|
},
|
||
|
|
{
|
||
|
|
PrecompileShaders::LinearGradient(),
|
||
|
|
PrecompileShaders::Blend(
|
||
|
|
SkSpan<SkBlendMode>(moreBlendModes),// std::vector
|
||
|
|
{
|
||
|
|
PrecompileShaders::RadialGradient(),
|
||
|
|
PrecompileShaders::Color()
|
||
|
|
},
|
||
|
|
{
|
||
|
|
PrecompileShaders::Image()
|
||
|
|
})
|
||
|
|
});
|
||
|
|
|
||
|
|
paintOptions.setShaders({ sweepGrad_0, blendShader_0 });
|
||
|
|
|
||
|
|
SkBlendMode evenMoreBlendModes[] = {
|
||
|
|
SkBlendMode::kSrcOver,
|
||
|
|
SkBlendMode::kSrc,
|
||
|
|
SkBlendMode::kDstOver,
|
||
|
|
SkBlendMode::kDst
|
||
|
|
};
|
||
|
|
|
||
|
|
// now, blend modes
|
||
|
|
paintOptions.setBlendModes(evenMoreBlendModes); // c array
|
||
|
|
|
||
|
|
REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == 17);
|
||
|
|
|
||
|
|
std::vector<UniquePaintParamsID> precompileIDs;
|
||
|
|
paintOptions.priv().buildCombinations(keyContext,
|
||
|
|
/* addPrimitiveBlender= */ false,
|
||
|
|
[&](UniquePaintParamsID id) {
|
||
|
|
precompileIDs.push_back(id);
|
||
|
|
});
|
||
|
|
|
||
|
|
SkASSERT(precompileIDs.size() == 17);
|
||
|
|
}
|
||
|
|
|
||
|
|
template <typename T>
|
||
|
|
std::vector<sk_sp<T>> create_runtime_combos(
|
||
|
|
skiatest::Reporter* reporter,
|
||
|
|
SkRuntimeEffect::Result effectFactory(SkString),
|
||
|
|
sk_sp<T> precompileFactory(sk_sp<SkRuntimeEffect>,
|
||
|
|
SkSpan<const PrecompileChildOptions> childOptions),
|
||
|
|
const char* redCode,
|
||
|
|
const char* greenCode,
|
||
|
|
const char* combineCode) {
|
||
|
|
auto [redEffect, error1] = effectFactory(SkString(redCode));
|
||
|
|
REPORTER_ASSERT(reporter, redEffect, "%s", error1.c_str());
|
||
|
|
auto [greenEffect, error2] = effectFactory(SkString(greenCode));
|
||
|
|
REPORTER_ASSERT(reporter, greenEffect, "%s", error2.c_str());
|
||
|
|
auto [combineEffect, error3] = effectFactory(SkString(combineCode));
|
||
|
|
REPORTER_ASSERT(reporter, combineEffect, "%s", error3.c_str());
|
||
|
|
|
||
|
|
sk_sp<T> red = precompileFactory(redEffect, {});
|
||
|
|
REPORTER_ASSERT(reporter, red);
|
||
|
|
|
||
|
|
sk_sp<T> green = precompileFactory(greenEffect, {});
|
||
|
|
REPORTER_ASSERT(reporter, green);
|
||
|
|
|
||
|
|
sk_sp<T> combine = precompileFactory(combineEffect, { { red, green }, { green, red } });
|
||
|
|
REPORTER_ASSERT(reporter, combine);
|
||
|
|
|
||
|
|
return { combine };
|
||
|
|
}
|
||
|
|
|
||
|
|
void runtime_effect_test(const KeyContext& keyContext, skiatest::Reporter* reporter) {
|
||
|
|
// paintOptions (8)
|
||
|
|
// |- combineShader (2)
|
||
|
|
// | 0: redShader | greenShader
|
||
|
|
// | 1: greenShader | redShader
|
||
|
|
// |
|
||
|
|
// |- combineColorFilter (2)
|
||
|
|
// | 0: redColorFilter | greenColorFilter
|
||
|
|
// | 1: greenColorFilter | redColorFilter
|
||
|
|
// |
|
||
|
|
// |- combineBlender (2)
|
||
|
|
// | 0: redBlender | greenBlender
|
||
|
|
// | 1: greenBlender | redBlender
|
||
|
|
|
||
|
|
PaintOptions paintOptions;
|
||
|
|
|
||
|
|
// shaders
|
||
|
|
{
|
||
|
|
static const char* kRedS = R"(
|
||
|
|
half4 main(vec2 fragcoord) { return half4(.5, 0, 0, .5); }
|
||
|
|
)";
|
||
|
|
static const char* kGreenS = R"(
|
||
|
|
half4 main(vec2 fragcoord) { return half4(0, .5, 0, .5); }
|
||
|
|
)";
|
||
|
|
|
||
|
|
static const char* kCombineS = R"(
|
||
|
|
uniform shader first;
|
||
|
|
uniform shader second;
|
||
|
|
half4 main(vec2 fragcoords) {
|
||
|
|
return first.eval(fragcoords) + second.eval(fragcoords);
|
||
|
|
}
|
||
|
|
)";
|
||
|
|
|
||
|
|
std::vector<sk_sp<PrecompileShader>> combinations =
|
||
|
|
create_runtime_combos<PrecompileShader>(reporter,
|
||
|
|
SkRuntimeEffect::MakeForShader,
|
||
|
|
MakePrecompileShader,
|
||
|
|
kRedS,
|
||
|
|
kGreenS,
|
||
|
|
kCombineS);
|
||
|
|
paintOptions.setShaders(combinations);
|
||
|
|
}
|
||
|
|
|
||
|
|
// color filters
|
||
|
|
{
|
||
|
|
static const char* kRedCF = R"(
|
||
|
|
half4 main(half4 color) { return half4(.5, 0, 0, .5); }
|
||
|
|
)";
|
||
|
|
static const char* kGreenCF = R"(
|
||
|
|
half4 main(half4 color) { return half4(0, .5, 0, .5); }
|
||
|
|
)";
|
||
|
|
|
||
|
|
static const char* kCombineCF = R"(
|
||
|
|
uniform colorFilter first;
|
||
|
|
uniform colorFilter second;
|
||
|
|
half4 main(half4 color) { return first.eval(color) + second.eval(color); }
|
||
|
|
)";
|
||
|
|
|
||
|
|
std::vector<sk_sp<PrecompileColorFilter>> combinations =
|
||
|
|
create_runtime_combos<PrecompileColorFilter>(reporter,
|
||
|
|
SkRuntimeEffect::MakeForColorFilter,
|
||
|
|
MakePrecompileColorFilter,
|
||
|
|
kRedCF,
|
||
|
|
kGreenCF,
|
||
|
|
kCombineCF);
|
||
|
|
paintOptions.setColorFilters(combinations);
|
||
|
|
}
|
||
|
|
|
||
|
|
// blenders
|
||
|
|
{
|
||
|
|
static const char* kRedB = R"(
|
||
|
|
half4 main(half4 src, half4 dst) { return half4(.5, 0, 0, .5); }
|
||
|
|
)";
|
||
|
|
static const char* kGreenB = R"(
|
||
|
|
half4 main(half4 src, half4 dst) { return half4(0, .5, 0, .5); }
|
||
|
|
)";
|
||
|
|
|
||
|
|
static const char* kCombineB = R"(
|
||
|
|
uniform blender first;
|
||
|
|
uniform blender second;
|
||
|
|
half4 main(half4 src, half4 dst) {
|
||
|
|
return first.eval(src, dst) + second.eval(src, dst);
|
||
|
|
}
|
||
|
|
)";
|
||
|
|
|
||
|
|
std::vector<sk_sp<PrecompileBlender>> combinations =
|
||
|
|
create_runtime_combos<PrecompileBlender>(reporter,
|
||
|
|
SkRuntimeEffect::MakeForBlender,
|
||
|
|
MakePrecompileBlender,
|
||
|
|
kRedB,
|
||
|
|
kGreenB,
|
||
|
|
kCombineB);
|
||
|
|
paintOptions.setBlenders(combinations);
|
||
|
|
}
|
||
|
|
|
||
|
|
REPORTER_ASSERT(reporter, paintOptions.priv().numCombinations() == 8);
|
||
|
|
|
||
|
|
std::vector<UniquePaintParamsID> precompileIDs;
|
||
|
|
paintOptions.priv().buildCombinations(keyContext,
|
||
|
|
/* addPrimitiveBlender= */ false,
|
||
|
|
[&](UniquePaintParamsID id) {
|
||
|
|
precompileIDs.push_back(id);
|
||
|
|
});
|
||
|
|
|
||
|
|
SkASSERT(precompileIDs.size() == 8);
|
||
|
|
}
|
||
|
|
|
||
|
|
} // anonymous namespace
|
||
|
|
|
||
|
|
DEF_GRAPHITE_TEST_FOR_ALL_CONTEXTS(CombinationBuilderTest, reporter, context) {
|
||
|
|
ShaderCodeDictionary* dict = context->priv().shaderCodeDictionary();
|
||
|
|
|
||
|
|
auto rtEffectDict = std::make_unique<RuntimeEffectDictionary>();
|
||
|
|
|
||
|
|
SkColorInfo ci(kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
|
||
|
|
KeyContext keyContext(dict, rtEffectDict.get(), ci);
|
||
|
|
|
||
|
|
empty_test(keyContext, reporter);
|
||
|
|
no_shader_option_test(keyContext, reporter);
|
||
|
|
no_blend_mode_option_test(keyContext, reporter);
|
||
|
|
big_test(keyContext, reporter);
|
||
|
|
runtime_effect_test(keyContext, reporter);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif // SK_GRAPHITE
|