let color filters tell us their alpha format
There are a bunch of native premul->premul color filters, and about an equal number of native unpremul->unpremul filters that all have roughly the same logic to interoperate with a premul color pipeline. I haven't seen anything that wants premul in and unpremul out or vice versa. (It's easy to find by grepping for ::unpremul.) This CL flags the natively unpremul color filters and centralizes the logic to handle premul interop. This mostly eliminates the need for SkColorFilter subclasses to know shaderIsOpaque, but not quite entirely. It's of course used in the centralized SkColorFilter::appendStages(), but is still also needed by any subclass that calls that, any subclass that composes other color filters. I've commented out any unused shaderIsOpaque arguments. In the future we could imagine handling this outside in a more sophisticated way, like eliding unnecessary alpha format conversions. We'd need to move this logic out of SkColorFilter::appendStages() to it's callers... the blitter, composing subclasses, and any other misc. Should be no diffs and no interesting perf change. I couldn't help but correct some misuse of "protected" where I was editing anyway. I'm feeling a mega CL coming... Change-Id: If3528820ca639357864b8b99c8fe11ab60c1ae0d Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231465 Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
parent
c711a86493
commit
0355f05b26
@ -117,9 +117,6 @@ public:
|
||||
protected:
|
||||
SkColorFilter() {}
|
||||
|
||||
virtual bool onAsAColorMatrix(float[20]) const;
|
||||
virtual bool onAsAColorMode(SkColor* color, SkBlendMode* bmode) const;
|
||||
|
||||
private:
|
||||
/*
|
||||
* Returns 1 if this is a single filter (not a composition of other filters), otherwise it
|
||||
@ -130,8 +127,14 @@ private:
|
||||
*/
|
||||
virtual int privateComposedFilterCount() const { return 1; }
|
||||
|
||||
virtual bool onAsAColorMatrix(float[20]) const;
|
||||
virtual bool onAsAColorMode(SkColor* color, SkBlendMode* bmode) const;
|
||||
virtual bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const = 0;
|
||||
|
||||
// Return the alpha type this effect most naturally operates on (default premul).
|
||||
// Inputs to onAppendStages() will be in this format, and its outputs should be left that way.
|
||||
virtual SkAlphaType onAlphaType() const;
|
||||
|
||||
friend class SkComposeColorFilter;
|
||||
|
||||
typedef SkFlattenable INHERITED;
|
||||
|
@ -32,6 +32,8 @@ bool SkColorFilter::onAsAColorMatrix(float matrix[20]) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkAlphaType SkColorFilter::onAlphaType() const { return kPremul_SkAlphaType; }
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(
|
||||
GrRecordingContext*, const GrColorSpaceInfo&) const {
|
||||
@ -39,8 +41,18 @@ std::unique_ptr<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SkColorFilter::appendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
|
||||
return this->onAppendStages(rec, shaderIsOpaque);
|
||||
bool SkColorFilter::appendStages(const SkStageRec& rec, bool opaque) const {
|
||||
const bool unpremul = this->onAlphaType() == kUnpremul_SkAlphaType;
|
||||
|
||||
if (unpremul && !opaque) { rec.fPipeline->append(SkRasterPipeline::unpremul); }
|
||||
|
||||
const bool ok = this->onAppendStages(rec, opaque);
|
||||
|
||||
opaque = opaque && (this->getFlags() & kAlphaUnchanged_Flag) != 0;
|
||||
|
||||
if (unpremul && !opaque) { rec.fPipeline->append(SkRasterPipeline::premul); }
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
SkColor SkColorFilter::filterColor(SkColor c) const {
|
||||
@ -186,6 +198,8 @@ public:
|
||||
}
|
||||
}()) {}
|
||||
|
||||
private:
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
|
||||
GrRecordingContext*, const GrColorSpaceInfo&) const override {
|
||||
@ -201,27 +215,20 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
|
||||
if (!shaderIsOpaque) {
|
||||
rec.fPipeline->append(SkRasterPipeline::unpremul);
|
||||
}
|
||||
uint32_t getFlags() const override { return kAlphaUnchanged_Flag; }
|
||||
SkAlphaType onAlphaType() const override { return kUnpremul_SkAlphaType; }
|
||||
|
||||
bool onAppendStages(const SkStageRec& rec, bool /*shaderIsOpaque*/) const override {
|
||||
// TODO: is it valuable to thread this through appendStages()?
|
||||
bool shaderIsNormalized = false;
|
||||
fSteps.apply(rec.fPipeline, shaderIsNormalized);
|
||||
|
||||
if (!shaderIsOpaque) {
|
||||
rec.fPipeline->append(SkRasterPipeline::premul);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void flatten(SkWriteBuffer& buffer) const override {
|
||||
buffer.write32(static_cast<uint32_t>(fDir));
|
||||
}
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkSRGBGammaColorFilter)
|
||||
|
||||
const Direction fDir;
|
||||
@ -387,7 +394,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
|
||||
bool onAppendStages(const SkStageRec& rec, bool /*shaderIsOpaque*/) const override {
|
||||
if (fCpuFunction) {
|
||||
struct CpuFuncCtx : public SkRasterPipeline_CallbackCtx {
|
||||
SkRuntimeColorFilterFn cpuFn;
|
||||
|
@ -52,15 +52,11 @@ bool SkColorFilter_Matrix::onAsAColorMatrix(float matrix[20]) const {
|
||||
}
|
||||
|
||||
bool SkColorFilter_Matrix::onAppendStages(const SkStageRec& rec,
|
||||
bool shaderIsOpaque) const {
|
||||
const bool willStayOpaque = shaderIsOpaque && (fFlags & kAlphaUnchanged_Flag);
|
||||
|
||||
bool /*shaderIsOpaque*/) const {
|
||||
SkRasterPipeline* p = rec.fPipeline;
|
||||
if (!shaderIsOpaque) { p->append(SkRasterPipeline::unpremul); }
|
||||
if ( true) { p->append(SkRasterPipeline::matrix_4x5, fMatrix); }
|
||||
if ( true) { p->append(SkRasterPipeline::clamp_0); }
|
||||
if ( true) { p->append(SkRasterPipeline::clamp_1); }
|
||||
if (!willStayOpaque) { p->append(SkRasterPipeline::premul); }
|
||||
p->append(SkRasterPipeline::matrix_4x5, fMatrix);
|
||||
p->append(SkRasterPipeline::clamp_0);
|
||||
p->append(SkRasterPipeline::clamp_1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -25,14 +25,13 @@ public:
|
||||
|
||||
static void RegisterFlattenables();
|
||||
|
||||
protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAsAColorMatrix(float matrix[20]) const override;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkColorFilter_Matrix)
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
|
||||
bool onAsAColorMatrix(float matrix[20]) const override;
|
||||
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override;
|
||||
SkAlphaType onAlphaType() const override { return kUnpremul_SkAlphaType; }
|
||||
|
||||
float fMatrix[20];
|
||||
uint32_t fFlags;
|
||||
|
@ -61,7 +61,7 @@ sk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
|
||||
return SkColorFilters::Blend(color, mode);
|
||||
}
|
||||
|
||||
bool SkModeColorFilter::onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
|
||||
bool SkModeColorFilter::onAppendStages(const SkStageRec& rec, bool /*shaderIsOpaque*/) const {
|
||||
rec.fPipeline->append(SkRasterPipeline::move_src_dst);
|
||||
SkColor4f color = SkColor4f::FromColor(fColor);
|
||||
SkColorSpaceXformSteps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
|
||||
|
@ -25,44 +25,36 @@ using InvertStyle = SkHighContrastConfig::InvertStyle;
|
||||
|
||||
class SkHighContrast_Filter : public SkColorFilter {
|
||||
public:
|
||||
SkHighContrast_Filter(const SkHighContrastConfig& config) {
|
||||
fConfig = config;
|
||||
SkHighContrast_Filter(const SkHighContrastConfig& config) : fConfig(config) {
|
||||
// Clamp contrast to just inside -1 to 1 to avoid division by zero.
|
||||
fConfig.fContrast = SkScalarPin(fConfig.fContrast,
|
||||
-1.0f + FLT_EPSILON,
|
||||
1.0f - FLT_EPSILON);
|
||||
+1.0f - FLT_EPSILON);
|
||||
}
|
||||
|
||||
~SkHighContrast_Filter() override {}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
|
||||
GrRecordingContext*, const GrColorSpaceInfo&) const override;
|
||||
#endif
|
||||
|
||||
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override;
|
||||
|
||||
protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkHighContrast_Filter)
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
|
||||
uint32_t getFlags() const override { return kAlphaUnchanged_Flag; }
|
||||
SkAlphaType onAlphaType() const override { return kUnpremul_SkAlphaType; }
|
||||
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override;
|
||||
|
||||
SkHighContrastConfig fConfig;
|
||||
|
||||
friend class SkHighContrastFilter;
|
||||
|
||||
typedef SkColorFilter INHERITED;
|
||||
};
|
||||
|
||||
bool SkHighContrast_Filter::onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
|
||||
bool SkHighContrast_Filter::onAppendStages(const SkStageRec& rec, bool /*shaderIsOpaque*/) const {
|
||||
SkRasterPipeline* p = rec.fPipeline;
|
||||
SkArenaAlloc* alloc = rec.fAlloc;
|
||||
|
||||
if (!shaderIsOpaque) {
|
||||
p->append(SkRasterPipeline::unpremul);
|
||||
}
|
||||
|
||||
// Linearize before applying high-contrast filter.
|
||||
auto tf = alloc->make<skcms_TransferFunction>();
|
||||
if (rec.fDstCS) {
|
||||
@ -122,9 +114,6 @@ bool SkHighContrast_Filter::onAppendStages(const SkStageRec& rec, bool shaderIsO
|
||||
}
|
||||
p->append(SkRasterPipeline::parametric, invTF);
|
||||
|
||||
if (!shaderIsOpaque) {
|
||||
p->append(SkRasterPipeline::premul);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#endif
|
||||
|
||||
bool SkLumaColorFilter::onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const {
|
||||
bool SkLumaColorFilter::onAppendStages(const SkStageRec& rec, bool /*shaderIsOpaque*/) const {
|
||||
rec.fPipeline->append(SkRasterPipeline::bt709_luminance_or_luma_to_alpha);
|
||||
rec.fPipeline->append(SkRasterPipeline::clamp_0);
|
||||
rec.fPipeline->append(SkRasterPipeline::clamp_1);
|
||||
|
@ -89,6 +89,12 @@ public:
|
||||
GrRecordingContext*, const GrColorSpaceInfo&) const override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
SK_FLATTENABLE_HOOKS(SkTable_ColorFilter)
|
||||
|
||||
void getTableAsBitmap(SkBitmap* table) const;
|
||||
|
||||
enum {
|
||||
kA_Flag = 1 << 0,
|
||||
kR_Flag = 1 << 1,
|
||||
@ -96,7 +102,14 @@ public:
|
||||
kB_Flag = 1 << 3,
|
||||
};
|
||||
|
||||
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
|
||||
|
||||
uint32_t getFlags() const override {
|
||||
return (fFlags & kA_Flag) == 0 ? kAlphaUnchanged_Flag
|
||||
: 0;
|
||||
}
|
||||
SkAlphaType onAlphaType() const override { return kUnpremul_SkAlphaType; }
|
||||
|
||||
bool onAppendStages(const SkStageRec& rec, bool /*shaderIsOpaque*/) const override {
|
||||
const uint8_t *r = gIdentityTable,
|
||||
*g = gIdentityTable,
|
||||
*b = gIdentityTable,
|
||||
@ -107,28 +120,12 @@ public:
|
||||
if (fFlags & kG_Flag) { g = ptr; ptr += 256; }
|
||||
if (fFlags & kB_Flag) { b = ptr; }
|
||||
|
||||
SkRasterPipeline* p = rec.fPipeline;
|
||||
if (!shaderIsOpaque) {
|
||||
p->append(SkRasterPipeline::unpremul);
|
||||
}
|
||||
|
||||
struct Tables { const uint8_t *r, *g, *b, *a; };
|
||||
p->append(SkRasterPipeline::byte_tables, rec.fAlloc->make<Tables>(Tables{r,g,b,a}));
|
||||
|
||||
bool definitelyOpaque = shaderIsOpaque && a[0xff] == 0xff;
|
||||
if (!definitelyOpaque) {
|
||||
p->append(SkRasterPipeline::premul);
|
||||
}
|
||||
rec.fPipeline->append(SkRasterPipeline::byte_tables,
|
||||
rec.fAlloc->make<Tables>(Tables{r,g,b,a}));
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkTable_ColorFilter)
|
||||
|
||||
void getTableAsBitmap(SkBitmap* table) const;
|
||||
|
||||
mutable const SkBitmap* fBitmap; // lazily allocated
|
||||
|
||||
|
@ -46,13 +46,12 @@ public:
|
||||
GrRecordingContext*, const GrColorSpaceInfo&) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
private:
|
||||
void flatten(SkWriteBuffer&) const override {}
|
||||
bool onAppendStages(const SkStageRec& rec, bool shaderIsOpaque) const override {
|
||||
bool onAppendStages(const SkStageRec& rec, bool /*shaderIsOpaque*/) const override {
|
||||
rec.fPipeline->append(SkRasterPipeline::gauss_a_to_rgba);
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkGaussianColorFilter)
|
||||
|
||||
SkGaussianColorFilter() : INHERITED() {}
|
||||
|
Loading…
Reference in New Issue
Block a user