add srgb gamma colorfilters

... faster and more accurate than using SkTableColorFilter

todo: update blink after this lands

Bug:737981
Change-Id: I55b5c60dd23b9d2cbe9d60f83c74be1a8f3dcfcf
Reviewed-on: https://skia-review.googlesource.com/21368
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Reed 2017-07-05 15:43:15 -04:00 committed by Skia Commit-Bot
parent 2d171397f8
commit 412cda7379
7 changed files with 93 additions and 63 deletions

View File

@ -113,6 +113,14 @@ public:
*/
static sk_sp<SkColorFilter> MakeMatrixFilterRowMajor255(const SkScalar array[20]);
/** Construct a colorfilter that applies the srgb gamma curve to the RGB channels */
static sk_sp<SkColorFilter> MakeLinearToSRGBGamma();
/** Construct a colorfilter that applies the inverse of the srgb gamma curve to the
* RGB channels
*/
static sk_sp<SkColorFilter> MakeSRGBToLinearGamma();
#if SK_SUPPORT_GPU
/**
* A subclass may implement this factory function to work with the GPU backend. It returns

View File

@ -370,7 +370,7 @@ public:
SkPaint gammaPaint;
gammaPaint.setBlendMode(SkBlendMode::kSrc);
if (doGamma) {
gammaPaint.setColorFilter(sk_tool_utils::MakeLinearToSRGBColorFilter());
gammaPaint.setColorFilter(SkColorFilter::MakeLinearToSRGBGamma());
}
gpuCanvas->drawImage(offscreenImage, 0, 0, &gammaPaint);

View File

@ -174,8 +174,6 @@ sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
return MakeComposeFilter(std::move(outer), std::move(inner));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer,
sk_sp<SkColorFilter> inner) {
if (!outer) {
@ -198,9 +196,91 @@ sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer
return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#if SK_SUPPORT_GPU
#include "../gpu/effects/GrSRGBEffect.h"
#endif
class SkSRGBGammaColorFilter : public SkColorFilter {
public:
enum class Direction {
kLinearToSRGB,
kSRGBToLinear,
};
SkSRGBGammaColorFilter(Direction dir) : fDir(dir) {}
#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* x, SkColorSpace* cs) const override {
switch (fDir) {
case Direction::kLinearToSRGB:
return GrSRGBEffect::Make(GrSRGBEffect::Mode::kLinearToSRGB);
case Direction::kSRGBToLinear:
return GrSRGBEffect::Make(GrSRGBEffect::Mode::kSRGBToLinear);
}
return nullptr;
}
#endif
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSRGBGammaColorFilter)
void onAppendStages(SkRasterPipeline* p, SkColorSpace*, SkArenaAlloc* alloc,
bool shaderIsOpaque) const override {
switch (fDir) {
case Direction::kLinearToSRGB:
p->append(SkRasterPipeline::to_srgb);
break;
case Direction::kSRGBToLinear:
p->append_from_srgb(shaderIsOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
break;
}
}
protected:
void flatten(SkWriteBuffer& buffer) const override {
buffer.write32(static_cast<uint32_t>(fDir));
}
private:
const Direction fDir;
friend class SkColorFilter;
typedef SkColorFilter INHERITED;
};
sk_sp<SkFlattenable> SkSRGBGammaColorFilter::CreateProc(SkReadBuffer& buffer) {
uint32_t dir = buffer.read32();
if (dir <= 1) {
return sk_sp<SkFlattenable>(new SkSRGBGammaColorFilter(static_cast<Direction>(dir)));
}
buffer.validate(false);
return nullptr;
}
#ifndef SK_IGNORE_TO_STRING
void SkSRGBGammaColorFilter::toString(SkString* str) const {
str->append("srgbgamma");
}
#endif
sk_sp<SkColorFilter> SkColorFilter::MakeLinearToSRGBGamma() {
return sk_sp<SkColorFilter>(new SkSRGBGammaColorFilter(
SkSRGBGammaColorFilter::Direction::kLinearToSRGB));
}
sk_sp<SkColorFilter> SkColorFilter::MakeSRGBToLinearGamma() {
return sk_sp<SkColorFilter>(new SkSRGBGammaColorFilter(
SkSRGBGammaColorFilter::Direction::kSRGBToLinear));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "SkModeColorFilter.h"
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSRGBGammaColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

View File

@ -546,16 +546,6 @@ sk_sp<GrFragmentProcessor> SkTable_ColorFilter::asFragmentProcessor(GrContext* c
///////////////////////////////////////////////////////////////////////////////
#ifdef SK_CPU_BENDIAN
#else
#define SK_A32_INDEX (3 - (SK_A32_SHIFT >> 3))
#define SK_R32_INDEX (3 - (SK_R32_SHIFT >> 3))
#define SK_G32_INDEX (3 - (SK_G32_SHIFT >> 3))
#define SK_B32_INDEX (3 - (SK_B32_SHIFT >> 3))
#endif
///////////////////////////////////////////////////////////////////////////////
sk_sp<SkColorFilter> SkTableColorFilter::Make(const uint8_t table[256]) {
return sk_make_sp<SkTable_ColorFilter>(table, table, table, table);
}

View File

@ -15,7 +15,6 @@
#include "SkColorFilter.h"
#include "SkSurface.h"
#include "SkUtils.h"
#include "sk_tool_utils.h"
/** convert 0..1 linear value to 0..1 srgb */
static float linear_to_srgb(float linear) {
@ -112,8 +111,8 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ApplyGamma, reporter, ctxInfo) {
SkPaint gammaPaint;
gammaPaint.setBlendMode(SkBlendMode::kSrc);
gammaPaint.setColorFilter(toSRGB ? sk_tool_utils::MakeLinearToSRGBColorFilter()
: sk_tool_utils::MakeSRGBToLinearColorFilter());
gammaPaint.setColorFilter(toSRGB ? SkColorFilter::MakeLinearToSRGBGamma()
: SkColorFilter::MakeSRGBToLinearGamma());
dstCanvas->drawBitmap(bm, 0, 0, &gammaPaint);
dstCanvas->flush();

View File

@ -22,38 +22,6 @@
DEFINE_bool(portableFonts, false, "Use portable fonts");
#if SK_SUPPORT_GPU
#include "effects/GrSRGBEffect.h"
#include "SkColorFilter.h"
// Color filter that just wraps GrSRGBEffect
class SkSRGBColorFilter : public SkColorFilter {
public:
static sk_sp<SkColorFilter> Make(GrSRGBEffect::Mode mode) {
return sk_sp<SkColorFilter>(new SkSRGBColorFilter(mode));
}
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override {
return GrSRGBEffect::Make(fMode);
}
void onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool) const override {
SK_ABORT("SkSRGBColorFilter is only implemented for GPU");
}
Factory getFactory() const override { return nullptr; }
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const override {}
#endif
private:
SkSRGBColorFilter(GrSRGBEffect::Mode mode) : fMode(mode) {}
GrSRGBEffect::Mode fMode;
typedef SkColorFilter INHERITED;
};
#endif
namespace sk_tool_utils {
/* these are the default fonts chosen by Chrome for serif, sans-serif, and monospace */
@ -655,14 +623,4 @@ void copy_to_g8(SkBitmap* dst, const SkBitmap& src) {
}
}
#if SK_SUPPORT_GPU
sk_sp<SkColorFilter> MakeLinearToSRGBColorFilter() {
return SkSRGBColorFilter::Make(GrSRGBEffect::Mode::kLinearToSRGB);
}
sk_sp<SkColorFilter> MakeSRGBToLinearColorFilter() {
return SkSRGBColorFilter::Make(GrSRGBEffect::Mode::kSRGBToLinear);
}
#endif
} // namespace sk_tool_utils

View File

@ -256,11 +256,6 @@ namespace sk_tool_utils {
bool copy_to(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src);
void copy_to_g8(SkBitmap* dst, const SkBitmap& src);
#if SK_SUPPORT_GPU
sk_sp<SkColorFilter> MakeLinearToSRGBColorFilter();
sk_sp<SkColorFilter> MakeSRGBToLinearColorFilter();
#endif
} // namespace sk_tool_utils
#endif // sk_tool_utils_DEFINED