mirror of
https://github.com/aseprite/aseprite.git
synced 2024-12-28 06:21:25 +00:00
Add helper functions make_shader(), make_skimage/skcanvas_for_docimage()
These functions can be used to create a new Skia shader from SkSL code, and a new SkImage/SkCanvas to modify a doc::Image*
This commit is contained in:
parent
50d4f9d802
commit
b8514ad1c6
@ -699,6 +699,7 @@ add_library(app-lib
|
||||
util/range_utils.cpp
|
||||
util/readable_time.cpp
|
||||
util/resize_image.cpp
|
||||
util/shader_helpers.cpp
|
||||
util/tile_flags_utils.cpp
|
||||
util/tileset_utils.cpp
|
||||
util/wrap_point.cpp
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022-2023 Igara Studio S.A.
|
||||
// Copyright (C) 2022-2024 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -87,19 +87,9 @@ ShaderRenderer::ShaderRenderer()
|
||||
m_properties.renderBgOnScreen = true;
|
||||
m_properties.requiresRgbaBackbuffer = true;
|
||||
|
||||
auto makeShader = [](const char* code) {
|
||||
auto result = SkRuntimeEffect::MakeForShader(SkString(code));
|
||||
if (!result.errorText.isEmpty()) {
|
||||
LOG(ERROR, "Shader error: %s\n", result.errorText.c_str());
|
||||
std::printf("Shader error: %s\n", result.errorText.c_str());
|
||||
throw std::runtime_error("Cannot compile shaders for ShaderRenderer");
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
m_bgEffect = makeShader(kBgShaderCode).effect;
|
||||
m_indexedEffect = makeShader(kIndexedShaderCode).effect;
|
||||
m_grayscaleEffect = makeShader(kGrayscaleShaderCode).effect;
|
||||
m_bgEffect = make_shader(kBgShaderCode);
|
||||
m_indexedEffect = make_shader(kIndexedShaderCode);
|
||||
m_grayscaleEffect = make_shader(kGrayscaleShaderCode);
|
||||
}
|
||||
|
||||
ShaderRenderer::~ShaderRenderer() = default;
|
||||
@ -416,21 +406,11 @@ void ShaderRenderer::drawImage(SkCanvas* canvas,
|
||||
const int opacity,
|
||||
const doc::BlendMode blendMode)
|
||||
{
|
||||
auto skData = SkData::MakeWithoutCopy(
|
||||
(const void*)srcImage->getPixelAddress(0, 0),
|
||||
srcImage->rowBytes() * srcImage->height());
|
||||
auto skImg = make_skimage_for_docimage(srcImage);
|
||||
|
||||
switch (srcImage->colorMode()) {
|
||||
|
||||
case doc::ColorMode::RGB: {
|
||||
auto skImg = SkImage::MakeRasterData(
|
||||
SkImageInfo::Make(srcImage->width(),
|
||||
srcImage->height(),
|
||||
kRGBA_8888_SkColorType,
|
||||
kUnpremul_SkAlphaType),
|
||||
skData,
|
||||
srcImage->rowBytes());
|
||||
|
||||
SkPaint p;
|
||||
p.setAlpha(opacity);
|
||||
p.setBlendMode(to_skia(blendMode));
|
||||
@ -443,15 +423,6 @@ void ShaderRenderer::drawImage(SkCanvas* canvas,
|
||||
}
|
||||
|
||||
case doc::ColorMode::GRAYSCALE: {
|
||||
// We use kR8G8_unorm_SkColorType to access gray and alpha
|
||||
auto skImg = SkImage::MakeRasterData(
|
||||
SkImageInfo::Make(srcImage->width(),
|
||||
srcImage->height(),
|
||||
kR8G8_unorm_SkColorType,
|
||||
kOpaque_SkAlphaType),
|
||||
skData,
|
||||
srcImage->rowBytes());
|
||||
|
||||
SkRuntimeShaderBuilder builder(m_grayscaleEffect);
|
||||
builder.child("iImg") = skImg->makeRawShader(SkSamplingOptions(SkFilterMode::kNearest));
|
||||
|
||||
@ -471,15 +442,6 @@ void ShaderRenderer::drawImage(SkCanvas* canvas,
|
||||
}
|
||||
|
||||
case doc::ColorMode::INDEXED: {
|
||||
// We use kAlpha_8_SkColorType to access to the index value through the alpha channel
|
||||
auto skImg = SkImage::MakeRasterData(
|
||||
SkImageInfo::Make(srcImage->width(),
|
||||
srcImage->height(),
|
||||
kAlpha_8_SkColorType,
|
||||
kUnpremul_SkAlphaType),
|
||||
skData,
|
||||
srcImage->rowBytes());
|
||||
|
||||
// Use the palette data as an "width x height" image where
|
||||
// width=number of palette colors, and height=1
|
||||
const size_t palSize = sizeof(color_t) * m_palette.size();
|
||||
|
94
src/app/util/shader_helpers.cpp
Normal file
94
src/app/util/shader_helpers.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2024 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
|
||||
#include "app/util/shader_helpers.h"
|
||||
|
||||
#include "base/exception.h"
|
||||
#include "doc/image.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
sk_sp<SkRuntimeEffect> make_shader(const char* code)
|
||||
{
|
||||
auto result = SkRuntimeEffect::MakeForShader(SkString(code));
|
||||
if (!result.errorText.isEmpty()) {
|
||||
std::string error = fmt::format("Error compiling shader.\nError: {}\n",
|
||||
result.errorText.c_str());
|
||||
LOG(ERROR, error.c_str());
|
||||
std::printf("%s", error.c_str());
|
||||
throw base::Exception(error);
|
||||
}
|
||||
return result.effect;
|
||||
}
|
||||
|
||||
SkImageInfo get_skimageinfo_for_docimage(const doc::Image* img)
|
||||
{
|
||||
switch (img->colorMode()) {
|
||||
|
||||
case doc::ColorMode::RGB:
|
||||
return SkImageInfo::Make(img->width(),
|
||||
img->height(),
|
||||
kRGBA_8888_SkColorType,
|
||||
kUnpremul_SkAlphaType);
|
||||
|
||||
case doc::ColorMode::GRAYSCALE:
|
||||
// We use kR8G8_unorm_SkColorType to access gray and alpha
|
||||
return SkImageInfo::Make(img->width(),
|
||||
img->height(),
|
||||
kR8G8_unorm_SkColorType,
|
||||
kOpaque_SkAlphaType);
|
||||
|
||||
case doc::ColorMode::INDEXED: {
|
||||
// We use kAlpha_8_SkColorType to access to the index value through the alpha channel
|
||||
return SkImageInfo::Make(img->width(),
|
||||
img->height(),
|
||||
kAlpha_8_SkColorType,
|
||||
kUnpremul_SkAlphaType);
|
||||
|
||||
}
|
||||
}
|
||||
return SkImageInfo();
|
||||
}
|
||||
|
||||
sk_sp<SkImage> make_skimage_for_docimage(const doc::Image* img)
|
||||
{
|
||||
switch (img->colorMode()) {
|
||||
case doc::ColorMode::RGB:
|
||||
case doc::ColorMode::GRAYSCALE:
|
||||
case doc::ColorMode::INDEXED: {
|
||||
auto skData = SkData::MakeWithoutCopy(
|
||||
(const void*)img->getPixelAddress(0, 0),
|
||||
img->rowBytes() * img->height());
|
||||
|
||||
return SkImage::MakeRasterData(
|
||||
get_skimageinfo_for_docimage(img),
|
||||
skData,
|
||||
img->rowBytes());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<SkCanvas> make_skcanvas_for_docimage(const doc::Image* img)
|
||||
{
|
||||
return SkCanvas::MakeRasterDirect(
|
||||
get_skimageinfo_for_docimage(img),
|
||||
(void*)img->getPixelAddress(0, 0),
|
||||
img->rowBytes());
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif // SK_ENABLE_SKSL
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
// Copyright (C) 2022-2024 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -8,18 +8,32 @@
|
||||
#define APP_UTIL_SHADER_HELPERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
#if LAF_SKIA
|
||||
|
||||
#include "app/color.h"
|
||||
#include "gfx/color.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/core/SkImage.h"
|
||||
#include "include/core/SkM44.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
|
||||
// To include kRGB_to_HSL_sksl and kHSL_to_RGB_sksl
|
||||
#include "src/core/SkRuntimeEffectPriv.h"
|
||||
#if SK_ENABLE_SKSL
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
// To include kRGB_to_HSL_sksl and kHSL_to_RGB_sksl
|
||||
#include "src/core/SkRuntimeEffectPriv.h"
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace doc {
|
||||
class Image;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
|
||||
// rgb_to_hsl() and hsv_to_hsl() functions by Sam Hocevar licensed
|
||||
// under WTFPL (https://en.wikipedia.org/wiki/WTFPL)
|
||||
// Source:
|
||||
@ -74,8 +88,16 @@ inline SkV4 appColorHsl_to_SkV4(const app::Color& color) {
|
||||
float(color.getAlpha() / 255.0)};
|
||||
}
|
||||
|
||||
sk_sp<SkRuntimeEffect> make_shader(const char* code);
|
||||
|
||||
#endif // SK_ENABLE_SKSL
|
||||
|
||||
SkImageInfo get_skimageinfo_for_docimage(const doc::Image* img);
|
||||
sk_sp<SkImage> make_skimage_for_docimage(const doc::Image* img);
|
||||
std::unique_ptr<SkCanvas> make_skcanvas_for_docimage(const doc::Image* img);
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
#endif // LAF_SKIA
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user