[graphite] Add ImageShader and BlendShader SkPaintParamKey support
Unfortunately, this won't change any behavior until ExtractPaintData is switched over to using PaintParams::toKey Bug: skia:12701 Change-Id: I4f51dbb43983fe2f01947e26814f581a6d9033cd Reviewed-on: https://skia-review.googlesource.com/c/skia/+/496783 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
6edd5d9e19
commit
7e8fdf4706
@ -334,6 +334,7 @@ metal_tests_sources = [
|
||||
|
||||
graphite_tests_sources = [
|
||||
"$_tests/graphite/BackendTextureTest.cpp",
|
||||
"$_tests/graphite/ComboTest.cpp",
|
||||
"$_tests/graphite/CommandBufferTest.cpp",
|
||||
"$_tests/graphite/IntersectionTreeTest.cpp",
|
||||
"$_tests/graphite/MaskTest.cpp",
|
||||
|
@ -32,6 +32,9 @@ enum class CodeSnippetID : uint8_t {
|
||||
kSweepGradientShader,
|
||||
kConicalGradientShader,
|
||||
|
||||
kImageShader,
|
||||
kBlendShader, // aka ComposeShader
|
||||
|
||||
// BlendMode code snippets
|
||||
kSimpleBlendMode,
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "include/private/SkPaintParamsKey.h"
|
||||
#include "src/core/SkDebugUtils.h"
|
||||
#include "src/shaders/SkShaderBase.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -185,6 +186,120 @@ void Dump(const SkPaintParamsKey& key, int headerOffset) {
|
||||
|
||||
} // namespace GradientShaderBlocks
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
namespace ImageShaderBlock {
|
||||
|
||||
inline static constexpr int kTileModeBits = 2;
|
||||
|
||||
static const int kXTileModeShift = 0;
|
||||
static const int kYTileModeShift = kTileModeBits;
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
static const int kBlockDataSize = 1;
|
||||
|
||||
inline static constexpr int kTileModeMask = 0x3;
|
||||
|
||||
ImageData ExtractFromKey(const SkPaintParamsKey& key, uint32_t headerOffset) {
|
||||
validate_block_header(key, headerOffset,
|
||||
CodeSnippetID::kImageShader, kBlockDataSize);
|
||||
|
||||
uint8_t data = key.byte(headerOffset+SkPaintParamsKey::kBlockHeaderSizeInBytes);
|
||||
|
||||
SkTileMode tmX = to_tilemode(((data) >> kXTileModeShift) & kTileModeMask);
|
||||
SkTileMode tmY = to_tilemode(((data) >> kYTileModeShift) & kTileModeMask);
|
||||
|
||||
return { tmX, tmY };
|
||||
}
|
||||
#endif
|
||||
|
||||
void AddToKey(SkBackend backend, SkPaintParamsKey* key, const ImageData& imgData) {
|
||||
|
||||
if (backend == SkBackend::kGraphite) {
|
||||
|
||||
uint8_t data = (static_cast<uint8_t>(imgData.fTileModes[0]) << kXTileModeShift) |
|
||||
(static_cast<uint8_t>(imgData.fTileModes[1]) << kYTileModeShift);
|
||||
|
||||
int headerOffset = key->beginBlock(CodeSnippetID::kImageShader);
|
||||
|
||||
key->addByte(data);
|
||||
|
||||
key->endBlock(headerOffset, CodeSnippetID::kImageShader);
|
||||
|
||||
SkASSERT(imgData == ExtractFromKey(*key, headerOffset));
|
||||
} else {
|
||||
// TODO: add implementation for other backends
|
||||
SolidColorShaderBlock::AddToKey(backend, key);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void Dump(const SkPaintParamsKey& key, int headerOffset) {
|
||||
ImageData imgData = ExtractFromKey(key, headerOffset);
|
||||
|
||||
SkDebugf("kImageShader: tileModes(%s, %s) ",
|
||||
SkTileModeToStr(imgData.fTileModes[0]),
|
||||
SkTileModeToStr(imgData.fTileModes[1]));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ImageShaderBlock
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
namespace BlendShaderBlock {
|
||||
|
||||
void AddToKey(SkBackend backend, SkPaintParamsKey *key, const BlendData& blendData) {
|
||||
|
||||
if (backend == SkBackend::kGraphite) {
|
||||
int headerOffset = key->beginBlock(CodeSnippetID::kBlendShader);
|
||||
|
||||
add_blendmode_to_key(key, blendData.fBM);
|
||||
int start = key->sizeInBytes();
|
||||
as_SB(blendData.fDst)->addToKey(nullptr, backend, key);
|
||||
int firstShaderSize = key->sizeInBytes() - start;
|
||||
|
||||
start = key->sizeInBytes();
|
||||
as_SB(blendData.fSrc)->addToKey(nullptr, backend, key);
|
||||
int secondShaderSize = key->sizeInBytes() - start;
|
||||
|
||||
key->endBlock(headerOffset, CodeSnippetID::kBlendShader);
|
||||
|
||||
int expectedBlockSize = SkPaintParamsKey::kBlockHeaderSizeInBytes +
|
||||
1 + firstShaderSize + secondShaderSize;
|
||||
validate_block_header(*key, headerOffset, CodeSnippetID::kBlendShader, expectedBlockSize);
|
||||
} else {
|
||||
// TODO: add implementation for other backends
|
||||
SolidColorShaderBlock::AddToKey(backend, key);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void Dump(const SkPaintParamsKey& key, int headerOffset) {
|
||||
auto [id, storedBlockSize] = key.readCodeSnippetID(headerOffset);
|
||||
SkASSERT(id == CodeSnippetID::kBlendShader);
|
||||
|
||||
int runningOffset = headerOffset + SkPaintParamsKey::kBlockHeaderSizeInBytes;
|
||||
|
||||
uint8_t data = key.byte(runningOffset);
|
||||
SkBlendMode bm = to_blendmode(data);
|
||||
|
||||
SkDebugf("BlendMode: %s\n", SkBlendMode_Name(bm));
|
||||
runningOffset += 1; // 1 byte for blendmode
|
||||
|
||||
SkDebugf("\nDst: ");
|
||||
int firstBlockSize = SkPaintParamsKey::DumpBlock(key, runningOffset);
|
||||
runningOffset += firstBlockSize;
|
||||
|
||||
SkDebugf("Src: ");
|
||||
int secondBlockSize = SkPaintParamsKey::DumpBlock(key, runningOffset);
|
||||
|
||||
int calculatedBlockSize = SkPaintParamsKey::kBlockHeaderSizeInBytes +
|
||||
firstBlockSize + secondBlockSize + 1;
|
||||
SkASSERT(calculatedBlockSize == storedBlockSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace BlendShaderBlock
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
namespace BlendModeBlock {
|
||||
|
||||
|
@ -62,6 +62,43 @@ namespace GradientShaderBlocks {
|
||||
|
||||
} // namespace GradientShaderBlocks
|
||||
|
||||
namespace ImageShaderBlock {
|
||||
|
||||
struct ImageData {
|
||||
bool operator==(const ImageData& rhs) const {
|
||||
return fTileModes[0] == rhs.fTileModes[0] &&
|
||||
fTileModes[1] == rhs.fTileModes[1];
|
||||
}
|
||||
bool operator!=(const ImageData& rhs) const { return !(*this == rhs); }
|
||||
|
||||
// TODO: add the other image shader parameters that could impact code snippet selection
|
||||
// (e.g., sampling options, subsetting, etc.)
|
||||
SkTileMode fTileModes[2];
|
||||
};
|
||||
|
||||
void AddToKey(SkBackend, SkPaintParamsKey*, const ImageData&);
|
||||
#ifdef SK_DEBUG
|
||||
void Dump(const SkPaintParamsKey&, int headerOffset);
|
||||
#endif
|
||||
|
||||
} // namespace ImageShaderBlock
|
||||
|
||||
namespace BlendShaderBlock {
|
||||
|
||||
struct BlendData {
|
||||
SkShader* fDst;
|
||||
SkShader* fSrc;
|
||||
// TODO: add support for blenders
|
||||
SkBlendMode fBM;
|
||||
};
|
||||
|
||||
void AddToKey(SkBackend, SkPaintParamsKey*, const BlendData&);
|
||||
#ifdef SK_DEBUG
|
||||
void Dump(const SkPaintParamsKey&, int headerOffset);
|
||||
#endif
|
||||
|
||||
} // namespace BlendShaderBlock
|
||||
|
||||
namespace BlendModeBlock {
|
||||
|
||||
void AddToKey(SkBackend, SkPaintParamsKey*, SkBlendMode);
|
||||
|
@ -40,6 +40,9 @@ DumpMethod get_dump_method(CodeSnippetID id) {
|
||||
case CodeSnippetID::kSweepGradientShader: [[fallthrough]];
|
||||
case CodeSnippetID::kConicalGradientShader: return GradientShaderBlocks::Dump;
|
||||
|
||||
case CodeSnippetID::kImageShader: return ImageShaderBlock::Dump;
|
||||
case CodeSnippetID::kBlendShader: return BlendShaderBlock::Dump;
|
||||
|
||||
// BlendMode code snippets
|
||||
case CodeSnippetID::kSimpleBlendMode: return BlendModeBlock::Dump;
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "src/core/SkArenaAlloc.h"
|
||||
#include "src/core/SkBlendModePriv.h"
|
||||
#include "src/core/SkBlenderBase.h"
|
||||
#include "src/core/SkKeyHelpers.h"
|
||||
#include "src/core/SkRasterPipeline.h"
|
||||
#include "src/core/SkReadBuffer.h"
|
||||
#include "src/core/SkRuntimeEffectPriv.h"
|
||||
@ -187,3 +188,12 @@ std::unique_ptr<GrFragmentProcessor> SkShader_Blend::asFragmentProcessor(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void SkShader_Blend::addToKey(SkShaderCodeDictionary* dict,
|
||||
SkBackend backend,
|
||||
SkPaintParamsKey* key) const {
|
||||
// TODO: add blender support
|
||||
SkASSERT(!fBlender);
|
||||
|
||||
BlendShaderBlock::AddToKey(backend, key, { fDst.get(), fSrc.get(), fMode });
|
||||
}
|
||||
|
@ -28,6 +28,10 @@ public:
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
|
||||
#endif
|
||||
|
||||
void addToKey(SkShaderCodeDictionary*,
|
||||
SkBackend,
|
||||
SkPaintParamsKey*) const override;
|
||||
|
||||
protected:
|
||||
SkShader_Blend(SkReadBuffer&);
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "src/core/SkArenaAlloc.h"
|
||||
#include "src/core/SkColorSpacePriv.h"
|
||||
#include "src/core/SkColorSpaceXformSteps.h"
|
||||
#include "src/core/SkKeyHelpers.h"
|
||||
#include "src/core/SkMatrixPriv.h"
|
||||
#include "src/core/SkMatrixProvider.h"
|
||||
#include "src/core/SkMipmapAccessor.h"
|
||||
@ -372,6 +373,12 @@ std::unique_ptr<GrFragmentProcessor> SkImageShader::asFragmentProcessor(
|
||||
|
||||
#endif
|
||||
|
||||
void SkImageShader::addToKey(SkShaderCodeDictionary* dict,
|
||||
SkBackend backend,
|
||||
SkPaintParamsKey* key) const {
|
||||
ImageShaderBlock::AddToKey(backend, key, { fTileModeX, fTileModeY });
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "src/core/SkImagePriv.h"
|
||||
|
||||
|
@ -44,6 +44,10 @@ public:
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
|
||||
#endif
|
||||
|
||||
void addToKey(SkShaderCodeDictionary*,
|
||||
SkBackend,
|
||||
SkPaintParamsKey*) const override;
|
||||
|
||||
static SkM44 CubicResamplerMatrix(float B, float C);
|
||||
|
||||
private:
|
||||
|
84
tests/graphite/ComboTest.cpp
Normal file
84
tests/graphite/ComboTest.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 "include/core/SkCanvas.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/effects/SkGradientShader.h"
|
||||
#include "include/private/SkPaintParamsKey.h"
|
||||
#include "include/private/SkShaderCodeDictionary.h"
|
||||
#include "src/core/SkPaintPriv.h"
|
||||
#include "tests/Test.h"
|
||||
|
||||
namespace {
|
||||
|
||||
sk_sp<SkShader> make_image_shader(int imageWidth, int imageHeight,
|
||||
SkTileMode xTileMode, SkTileMode yTileMode,
|
||||
SkColor color) {
|
||||
auto surface = SkSurface::MakeRasterN32Premul(imageWidth, imageHeight);
|
||||
SkCanvas *canvas = surface->getCanvas();
|
||||
canvas->clear(color);
|
||||
return surface->makeImageSnapshot()->makeShader(xTileMode, yTileMode, SkSamplingOptions());
|
||||
}
|
||||
|
||||
sk_sp<SkShader> make_linear_gradient_shader(SkTileMode tileMode) {
|
||||
SkPoint pts[2];
|
||||
SkColor colors[2] = {SK_ColorRED, SK_ColorBLUE};
|
||||
|
||||
pts[0].set(0, 0);
|
||||
pts[1].set(SkIntToScalar(100), 0);
|
||||
return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, tileMode);
|
||||
}
|
||||
|
||||
sk_sp<SkShader> make_blend_shader(sk_sp<SkShader> shaderA,
|
||||
sk_sp<SkShader> shaderB,
|
||||
SkBlendMode mode) {
|
||||
return SkShaders::Blend(mode, std::move(shaderA), std::move(shaderB));
|
||||
}
|
||||
|
||||
void dump_keys(SkShaderCodeDictionary *dict, const SkPaint &paint) {
|
||||
auto keys = SkPaintPriv::ToKeys(paint, dict, SkBackend::kGanesh);
|
||||
|
||||
for (auto k: keys) {
|
||||
// TODO: we need a better way to assess that key creation succeeded
|
||||
k.dump();
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DEF_GRAPHITE_TEST(ComboTest, r) {
|
||||
SkShaderCodeDictionary dict;
|
||||
|
||||
{
|
||||
SkPaint paint;
|
||||
paint.setBlendMode(SkBlendMode::kLighten);
|
||||
dump_keys(&dict, paint);
|
||||
}
|
||||
|
||||
{
|
||||
SkPaint paint;
|
||||
paint.setShader(make_image_shader(16, 16, SkTileMode::kClamp,
|
||||
SkTileMode::kRepeat, SK_ColorRED));
|
||||
dump_keys(&dict, paint);
|
||||
}
|
||||
|
||||
{
|
||||
SkPaint paint;
|
||||
paint.setShader(make_linear_gradient_shader(SkTileMode::kClamp));
|
||||
dump_keys(&dict, paint);
|
||||
}
|
||||
|
||||
{
|
||||
SkPaint paint;
|
||||
auto shaderA = make_image_shader(16, 16, SkTileMode::kDecal,
|
||||
SkTileMode::kRepeat, SK_ColorBLUE);
|
||||
auto shaderB = make_linear_gradient_shader(SkTileMode::kClamp);
|
||||
paint.setShader(make_blend_shader(std::move(shaderA), std::move(shaderB),
|
||||
SkBlendMode::kDstIn));
|
||||
dump_keys(&dict, paint);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user