6fd158ea47
Removes the runtime logic used by PorterDuffXferProcessor to decide blend coeffs and shader outputs, and instead uses a compile-time constant table of pre-selected blend formulas. Separates out the dst read fallback into its own XP. Introduces a new blend strategy for srcCoeff=0 that can apply coverage with a reverse subtract blend equation instead of dual source blending. Adds new macros in GrBlend.h to analyze blend formulas both runtime. Removes kSetCoverageDrawing_OptFlag and GrSimplifyBlend as they are no longer used. Adds a GM that verifies all xfermodes, including arithmetic, with the color/coverage invariants used by Porter Duff. Adds a unit test that verifies each Porter Duff formula with every color/coverage invariant. Major changes: * Uses a reverse subtract blend equation for coverage when srcCoeff=0 (clear, dst-out [Sa=1], dst-in, modulate). Platforms that don't support dual source blending no longer require a dst copy for dst-in and modulate. * Sets BlendInfo::fWriteColor to false when the blend does not modify the dst. GrGLGpu will now use glColorMask instead of blending for these modes (dst, dst-in [Sa=1], modulate ignored for [Sc=1]). * Converts all SA blend coeffs to One for opaque inputs, and ISA to Zero if there is also no coverage. (We keep ISA around when there is coverage because we use it to tweak alpha for coverage.) * Abandons solid white optimizations for the sake of simplicity (screen was the only mode that previous had solid white opts). Minor differences: * Inconsequential differences in opt flags (e.g. we now return kCanTweakAlphaForCoverage_OptFlag even when there is no coverage). * Src coeffs when the shader outputs 0. * IS2C vs IS2A when the secondary output is scalar. BUG=skia: Committed: https://skia.googlesource.com/skia/+/9a70920db22b6309c671f8e5d519bb95570e4414 Review URL: https://codereview.chromium.org/1124373002
213 lines
7.2 KiB
C
213 lines
7.2 KiB
C
|
|
/*
|
|
* Copyright 2010 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
|
|
|
|
#ifndef GrColor_DEFINED
|
|
#define GrColor_DEFINED
|
|
|
|
#include "GrTypes.h"
|
|
#include "SkColor.h"
|
|
#include "SkColorPriv.h"
|
|
#include "SkUnPreMultiply.h"
|
|
|
|
/**
|
|
* GrColor is 4 bytes for R, G, B, A, in a specific order defined below. The components are stored
|
|
* premultiplied.
|
|
*/
|
|
typedef uint32_t GrColor;
|
|
|
|
// shift amount to assign a component to a GrColor int
|
|
// These shift values are chosen for compatibility with GL attrib arrays
|
|
// ES doesn't allow BGRA vertex attrib order so if they were not in this order
|
|
// we'd have to swizzle in shaders.
|
|
#ifdef SK_CPU_BENDIAN
|
|
#define GrColor_SHIFT_R 24
|
|
#define GrColor_SHIFT_G 16
|
|
#define GrColor_SHIFT_B 8
|
|
#define GrColor_SHIFT_A 0
|
|
#else
|
|
#define GrColor_SHIFT_R 0
|
|
#define GrColor_SHIFT_G 8
|
|
#define GrColor_SHIFT_B 16
|
|
#define GrColor_SHIFT_A 24
|
|
#endif
|
|
|
|
/**
|
|
* Pack 4 components (RGBA) into a GrColor int
|
|
*/
|
|
static inline GrColor GrColorPackRGBA(unsigned r, unsigned g, unsigned b, unsigned a) {
|
|
SkASSERT((uint8_t)r == r);
|
|
SkASSERT((uint8_t)g == g);
|
|
SkASSERT((uint8_t)b == b);
|
|
SkASSERT((uint8_t)a == a);
|
|
return (r << GrColor_SHIFT_R) |
|
|
(g << GrColor_SHIFT_G) |
|
|
(b << GrColor_SHIFT_B) |
|
|
(a << GrColor_SHIFT_A);
|
|
}
|
|
|
|
/**
|
|
* Packs a color with an alpha channel replicated across all four channels.
|
|
*/
|
|
static inline GrColor GrColorPackA4(unsigned a) {
|
|
SkASSERT((uint8_t)a == a);
|
|
return (a << GrColor_SHIFT_R) |
|
|
(a << GrColor_SHIFT_G) |
|
|
(a << GrColor_SHIFT_B) |
|
|
(a << GrColor_SHIFT_A);
|
|
}
|
|
|
|
// extract a component (byte) from a GrColor int
|
|
|
|
#define GrColorUnpackR(color) (((color) >> GrColor_SHIFT_R) & 0xFF)
|
|
#define GrColorUnpackG(color) (((color) >> GrColor_SHIFT_G) & 0xFF)
|
|
#define GrColorUnpackB(color) (((color) >> GrColor_SHIFT_B) & 0xFF)
|
|
#define GrColorUnpackA(color) (((color) >> GrColor_SHIFT_A) & 0xFF)
|
|
|
|
/**
|
|
* Since premultiplied means that alpha >= color, we construct a color with
|
|
* each component==255 and alpha == 0 to be "illegal"
|
|
*/
|
|
#define GrColor_ILLEGAL (~(0xFF << GrColor_SHIFT_A))
|
|
|
|
#define GrColor_WHITE 0xFFFFFFFF
|
|
#define GrColor_TRANS_BLACK 0x0
|
|
|
|
/**
|
|
* Assert in debug builds that a GrColor is premultiplied.
|
|
*/
|
|
static inline void GrColorIsPMAssert(GrColor SkDEBUGCODE(c)) {
|
|
#ifdef SK_DEBUG
|
|
unsigned a = GrColorUnpackA(c);
|
|
unsigned r = GrColorUnpackR(c);
|
|
unsigned g = GrColorUnpackG(c);
|
|
unsigned b = GrColorUnpackB(c);
|
|
|
|
SkASSERT(r <= a);
|
|
SkASSERT(g <= a);
|
|
SkASSERT(b <= a);
|
|
#endif
|
|
}
|
|
|
|
/** Converts a GrColor to an rgba array of GrGLfloat */
|
|
static inline void GrColorToRGBAFloat(GrColor color, float rgba[4]) {
|
|
static const float ONE_OVER_255 = 1.f / 255.f;
|
|
rgba[0] = GrColorUnpackR(color) * ONE_OVER_255;
|
|
rgba[1] = GrColorUnpackG(color) * ONE_OVER_255;
|
|
rgba[2] = GrColorUnpackB(color) * ONE_OVER_255;
|
|
rgba[3] = GrColorUnpackA(color) * ONE_OVER_255;
|
|
}
|
|
|
|
/** Normalizes and coverts an uint8_t to a float. [0, 255] -> [0.0, 1.0] */
|
|
static inline float GrNormalizeByteToFloat(uint8_t value) {
|
|
static const float ONE_OVER_255 = 1.f / 255.f;
|
|
return value * ONE_OVER_255;
|
|
}
|
|
|
|
/** Determines whether the color is opaque or not. */
|
|
static inline bool GrColorIsOpaque(GrColor color) {
|
|
return (color & (0xFFU << GrColor_SHIFT_A)) == (0xFFU << GrColor_SHIFT_A);
|
|
}
|
|
|
|
/** Returns an unpremuled version of the GrColor. */
|
|
static inline GrColor GrUnPreMulColor(GrColor color) {
|
|
unsigned r = GrColorUnpackR(color);
|
|
unsigned g = GrColorUnpackG(color);
|
|
unsigned b = GrColorUnpackB(color);
|
|
unsigned a = GrColorUnpackA(color);
|
|
SkPMColor colorPM = SkPackARGB32(a, r, g, b);
|
|
SkColor colorUPM = SkUnPreMultiply::PMColorToColor(colorPM);
|
|
|
|
r = SkColorGetR(colorUPM);
|
|
g = SkColorGetG(colorUPM);
|
|
b = SkColorGetB(colorUPM);
|
|
a = SkColorGetA(colorUPM);
|
|
|
|
return GrColorPackRGBA(r, g, b, a);
|
|
}
|
|
|
|
/**
|
|
* Flags used for bitfields of color components. They are defined so that the bit order reflects the
|
|
* GrColor shift order.
|
|
*/
|
|
enum GrColorComponentFlags {
|
|
kR_GrColorComponentFlag = 1 << (GrColor_SHIFT_R / 8),
|
|
kG_GrColorComponentFlag = 1 << (GrColor_SHIFT_G / 8),
|
|
kB_GrColorComponentFlag = 1 << (GrColor_SHIFT_B / 8),
|
|
kA_GrColorComponentFlag = 1 << (GrColor_SHIFT_A / 8),
|
|
|
|
kNone_GrColorComponentFlags = 0,
|
|
|
|
kRGB_GrColorComponentFlags = (kR_GrColorComponentFlag | kG_GrColorComponentFlag |
|
|
kB_GrColorComponentFlag),
|
|
|
|
kRGBA_GrColorComponentFlags = (kR_GrColorComponentFlag | kG_GrColorComponentFlag |
|
|
kB_GrColorComponentFlag | kA_GrColorComponentFlag)
|
|
};
|
|
|
|
GR_MAKE_BITFIELD_OPS(GrColorComponentFlags)
|
|
|
|
static inline char GrColorComponentFlagToChar(GrColorComponentFlags component) {
|
|
SkASSERT(SkIsPow2(component));
|
|
switch (component) {
|
|
case kR_GrColorComponentFlag:
|
|
return 'r';
|
|
case kG_GrColorComponentFlag:
|
|
return 'g';
|
|
case kB_GrColorComponentFlag:
|
|
return 'b';
|
|
case kA_GrColorComponentFlag:
|
|
return 'a';
|
|
default:
|
|
SkFAIL("Invalid color component flag.");
|
|
return '\0';
|
|
}
|
|
}
|
|
|
|
static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) {
|
|
SkASSERT(config >= 0 && config < kGrPixelConfigCnt);
|
|
static const uint32_t kFlags[] = {
|
|
0, // kUnknown_GrPixelConfig
|
|
kA_GrColorComponentFlag, // kAlpha_8_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kIndex_8_GrPixelConfig
|
|
kRGB_GrColorComponentFlags, // kRGB_565_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kRGBA_4444_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kRGBA_8888_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kBGRA_8888_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kSRGBA_8888_GrPixelConfig
|
|
kRGB_GrColorComponentFlags, // kETC1_GrPixelConfig
|
|
kA_GrColorComponentFlag, // kLATC_GrPixelConfig
|
|
kA_GrColorComponentFlag, // kR11_EAC_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kASTC_12x12_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kRGBA_float_GrPixelConfig
|
|
kA_GrColorComponentFlag, // kAlpha_16_GrPixelConfig
|
|
kRGBA_GrColorComponentFlags, // kRGBA_half_GrPixelConfig
|
|
};
|
|
return kFlags[config];
|
|
|
|
GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
|
|
GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
|
|
GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
|
|
GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
|
|
GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
|
|
GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
|
|
GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
|
|
GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig);
|
|
GR_STATIC_ASSERT(8 == kETC1_GrPixelConfig);
|
|
GR_STATIC_ASSERT(9 == kLATC_GrPixelConfig);
|
|
GR_STATIC_ASSERT(10 == kR11_EAC_GrPixelConfig);
|
|
GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig);
|
|
GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig);
|
|
GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig);
|
|
GR_STATIC_ASSERT(14 == kRGBA_half_GrPixelConfig);
|
|
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFlags) == kGrPixelConfigCnt);
|
|
}
|
|
|
|
#endif
|