92aee3d685
Change-Id: I737b901a19d3c67d2ff7f95802fb4df35656beb2 Reviewed-on: https://skia-review.googlesource.com/6199 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
348 lines
12 KiB
C++
348 lines
12 KiB
C++
/*
|
|
* Copyright 2014 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef GrInvariantOutput_DEFINED
|
|
#define GrInvariantOutput_DEFINED
|
|
|
|
#include "GrColor.h"
|
|
|
|
/**
|
|
* This describes the color or coverage input that will be seen by the first color or coverage stage
|
|
* of a GrPipeline. This is also the GrPrimitiveProcessor color or coverage *output*.
|
|
*/
|
|
struct GrPipelineInput {
|
|
GrPipelineInput()
|
|
: fValidFlags(kNone_GrColorComponentFlags)
|
|
, fColor(0)
|
|
, fIsSingleComponent(false)
|
|
, fIsLCDCoverage(false) {}
|
|
|
|
void setKnownFourComponents(GrColor color) {
|
|
fColor = color;
|
|
fValidFlags = kRGBA_GrColorComponentFlags;
|
|
fIsSingleComponent = false;
|
|
}
|
|
|
|
void setUnknownFourComponents() {
|
|
fValidFlags = kNone_GrColorComponentFlags;
|
|
fIsSingleComponent = false;
|
|
}
|
|
|
|
void setUnknownOpaqueFourComponents() {
|
|
fColor = 0xffU << GrColor_SHIFT_A;
|
|
fValidFlags = kA_GrColorComponentFlag;
|
|
fIsSingleComponent = false;
|
|
}
|
|
|
|
void setKnownSingleComponent(uint8_t alpha) {
|
|
fColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
|
|
fValidFlags = kRGBA_GrColorComponentFlags;
|
|
fIsSingleComponent = true;
|
|
}
|
|
|
|
void setUnknownSingleComponent() {
|
|
fValidFlags = kNone_GrColorComponentFlags;
|
|
fIsSingleComponent = true;
|
|
}
|
|
|
|
void setUsingLCDCoverage() { fIsLCDCoverage = true; }
|
|
|
|
GrColorComponentFlags fValidFlags;
|
|
GrColor fColor;
|
|
bool fIsSingleComponent;
|
|
bool fIsLCDCoverage; // Temorary data member until texture pixel configs are
|
|
// updated
|
|
};
|
|
|
|
/** This describes the output of a GrFragmentProcessor in a GrPipeline. */
|
|
class GrInvariantOutput {
|
|
public:
|
|
GrInvariantOutput(GrColor color, GrColorComponentFlags flags, bool isSingleComponent)
|
|
: fColor(color)
|
|
, fValidFlags(flags)
|
|
, fIsSingleComponent(isSingleComponent)
|
|
, fNonMulStageFound(false)
|
|
, fWillUseInputColor(true)
|
|
, fIsLCDCoverage(false) {}
|
|
|
|
GrInvariantOutput(const GrPipelineInput& input)
|
|
: fColor(input.fColor)
|
|
, fValidFlags(input.fValidFlags)
|
|
, fIsSingleComponent(input.fIsSingleComponent)
|
|
, fNonMulStageFound(false)
|
|
, fWillUseInputColor(false)
|
|
, fIsLCDCoverage(input.fIsLCDCoverage) {}
|
|
|
|
virtual ~GrInvariantOutput() {}
|
|
|
|
enum ReadInput {
|
|
kWill_ReadInput,
|
|
kWillNot_ReadInput,
|
|
};
|
|
|
|
void mulByUnknownOpaqueFourComponents() {
|
|
SkDEBUGCODE(this->validate());
|
|
if (this->isOpaque()) {
|
|
fValidFlags = kA_GrColorComponentFlag;
|
|
fIsSingleComponent = false;
|
|
} else {
|
|
// Since the current state is not opaque we no longer care if the color being
|
|
// multiplied is opaque.
|
|
this->mulByUnknownFourComponents();
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void mulByUnknownFourComponents() {
|
|
SkDEBUGCODE(this->validate());
|
|
if (this->hasZeroAlpha()) {
|
|
this->internalSetToTransparentBlack();
|
|
} else {
|
|
this->internalSetToUnknown();
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void mulByUnknownSingleComponent() {
|
|
SkDEBUGCODE(this->validate());
|
|
if (this->hasZeroAlpha()) {
|
|
this->internalSetToTransparentBlack();
|
|
} else {
|
|
// We don't need to change fIsSingleComponent in this case
|
|
fValidFlags = kNone_GrColorComponentFlags;
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void mulByKnownSingleComponent(uint8_t alpha) {
|
|
SkDEBUGCODE(this->validate());
|
|
if (this->hasZeroAlpha() || 0 == alpha) {
|
|
this->internalSetToTransparentBlack();
|
|
} else {
|
|
if (alpha != 255) {
|
|
// Multiply color by alpha
|
|
fColor = GrColorPackRGBA(SkMulDiv255Round(GrColorUnpackR(fColor), alpha),
|
|
SkMulDiv255Round(GrColorUnpackG(fColor), alpha),
|
|
SkMulDiv255Round(GrColorUnpackB(fColor), alpha),
|
|
SkMulDiv255Round(GrColorUnpackA(fColor), alpha));
|
|
// We don't need to change fIsSingleComponent in this case
|
|
}
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void mulByKnownFourComponents(GrColor color) {
|
|
SkDEBUGCODE(this->validate());
|
|
uint32_t a;
|
|
if (GetAlphaAndCheckSingleChannel(color, &a)) {
|
|
this->mulByKnownSingleComponent(a);
|
|
} else {
|
|
if (color != 0xffffffff) {
|
|
fColor = GrColorPackRGBA(
|
|
SkMulDiv255Round(GrColorUnpackR(fColor), GrColorUnpackR(color)),
|
|
SkMulDiv255Round(GrColorUnpackG(fColor), GrColorUnpackG(color)),
|
|
SkMulDiv255Round(GrColorUnpackB(fColor), GrColorUnpackB(color)),
|
|
SkMulDiv255Round(GrColorUnpackA(fColor), a));
|
|
if (kRGBA_GrColorComponentFlags == fValidFlags) {
|
|
fIsSingleComponent = GetAlphaAndCheckSingleChannel(fColor, &a);
|
|
}
|
|
}
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
// Ignores the incoming color's RGB and muls its alpha by color.
|
|
void mulAlphaByKnownFourComponents(GrColor color) {
|
|
SkDEBUGCODE(this->validate());
|
|
uint32_t a;
|
|
if (GetAlphaAndCheckSingleChannel(color, &a)) {
|
|
this->mulAlphaByKnownSingleComponent(a);
|
|
} else if (fValidFlags & kA_GrColorComponentFlag) {
|
|
GrColor preAlpha = GrColorUnpackA(fColor);
|
|
if (0 == preAlpha) {
|
|
this->internalSetToTransparentBlack();
|
|
} else {
|
|
// We know that color has different component values
|
|
fIsSingleComponent = false;
|
|
fColor = GrColorPackRGBA(
|
|
SkMulDiv255Round(preAlpha, GrColorUnpackR(color)),
|
|
SkMulDiv255Round(preAlpha, GrColorUnpackG(color)),
|
|
SkMulDiv255Round(preAlpha, GrColorUnpackB(color)),
|
|
SkMulDiv255Round(preAlpha, a));
|
|
fValidFlags = kRGBA_GrColorComponentFlags;
|
|
}
|
|
} else {
|
|
fIsSingleComponent = false;
|
|
fValidFlags = kNone_GrColorComponentFlags;
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
// Ignores the incoming color's RGB and muls its alpha by the alpha param and sets all channels
|
|
// equal to that value.
|
|
void mulAlphaByKnownSingleComponent(uint8_t alpha) {
|
|
SkDEBUGCODE(this->validate());
|
|
if (0 == alpha || this->hasZeroAlpha()) {
|
|
this->internalSetToTransparentBlack();
|
|
} else {
|
|
if (fValidFlags & kA_GrColorComponentFlag) {
|
|
GrColor a = GrColorUnpackA(fColor);
|
|
a = SkMulDiv255Round(alpha, a);
|
|
fColor = GrColorPackRGBA(a, a, a, a);
|
|
fValidFlags = kRGBA_GrColorComponentFlags;
|
|
} else {
|
|
fValidFlags = kNone_GrColorComponentFlags;
|
|
}
|
|
fIsSingleComponent = true;
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void premulFourChannelColor() {
|
|
SkDEBUGCODE(this->validate());
|
|
SkASSERT(!fIsSingleComponent);
|
|
fNonMulStageFound = true;
|
|
if (!(fValidFlags & kA_GrColorComponentFlag)) {
|
|
fValidFlags = kNone_GrColorComponentFlags;
|
|
} else {
|
|
fColor = GrPremulColor(fColor);
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void invalidateComponents(GrColorComponentFlags invalidateFlags, ReadInput readsInput) {
|
|
SkDEBUGCODE(this->validate());
|
|
fValidFlags = (fValidFlags & ~invalidateFlags);
|
|
fIsSingleComponent = false;
|
|
fNonMulStageFound = true;
|
|
if (kWillNot_ReadInput == readsInput) {
|
|
fWillUseInputColor = false;
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void setToOther(GrColorComponentFlags validFlags, GrColor color, ReadInput readsInput) {
|
|
SkDEBUGCODE(this->validate());
|
|
fValidFlags = validFlags;
|
|
fColor = color;
|
|
fIsSingleComponent = false;
|
|
fNonMulStageFound = true;
|
|
if (kWillNot_ReadInput == readsInput) {
|
|
fWillUseInputColor = false;
|
|
}
|
|
if (kRGBA_GrColorComponentFlags == fValidFlags) {
|
|
uint32_t a;
|
|
if (GetAlphaAndCheckSingleChannel(color, &a)) {
|
|
fIsSingleComponent = true;
|
|
}
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
void setToUnknown(ReadInput readsInput) {
|
|
SkDEBUGCODE(this->validate());
|
|
this->internalSetToUnknown();
|
|
fNonMulStageFound= true;
|
|
if (kWillNot_ReadInput == readsInput) {
|
|
fWillUseInputColor = false;
|
|
}
|
|
SkDEBUGCODE(this->validate());
|
|
}
|
|
|
|
// Temporary setter to handle LCD text correctly until we improve texture pixel config queries
|
|
// and thus can rely solely on number of coverage components for RGA vs single channel coverage.
|
|
void setUsingLCDCoverage() {
|
|
fIsLCDCoverage = true;
|
|
}
|
|
|
|
GrColor color() const { return fColor; }
|
|
GrColorComponentFlags validFlags() const { return fValidFlags; }
|
|
bool willUseInputColor() const { return fWillUseInputColor; }
|
|
|
|
/**
|
|
* If isSingleComponent is true, then the flag values for r, g, b, and a must all be the
|
|
* same. If the flags are all set then all color components must be equal.
|
|
*/
|
|
SkDEBUGCODE(void validate() const;)
|
|
|
|
private:
|
|
friend class GrProcOptInfo;
|
|
|
|
/** Extracts the alpha channel and returns true if r,g,b == a. */
|
|
static bool GetAlphaAndCheckSingleChannel(GrColor color, uint32_t* alpha) {
|
|
*alpha = GrColorUnpackA(color);
|
|
return *alpha == GrColorUnpackR(color) && *alpha == GrColorUnpackG(color) &&
|
|
*alpha == GrColorUnpackB(color);
|
|
}
|
|
|
|
void reset(GrColor color, GrColorComponentFlags flags, bool isSingleComponent) {
|
|
fColor = color;
|
|
fValidFlags = flags;
|
|
fIsSingleComponent = isSingleComponent;
|
|
fNonMulStageFound = false;
|
|
fWillUseInputColor = true;
|
|
}
|
|
|
|
void reset(const GrPipelineInput& input) {
|
|
fColor = input.fColor;
|
|
fValidFlags = input.fValidFlags;
|
|
fIsSingleComponent = input.fIsSingleComponent;
|
|
fNonMulStageFound = false;
|
|
fWillUseInputColor = true;
|
|
fIsLCDCoverage = input.fIsLCDCoverage;
|
|
}
|
|
|
|
void internalSetToTransparentBlack() {
|
|
fValidFlags = kRGBA_GrColorComponentFlags;
|
|
fColor = 0;
|
|
fIsSingleComponent = true;
|
|
}
|
|
|
|
void internalSetToUnknown() {
|
|
fValidFlags = kNone_GrColorComponentFlags;
|
|
fIsSingleComponent = false;
|
|
}
|
|
|
|
bool hasZeroAlpha() const {
|
|
return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpackA(fColor));
|
|
}
|
|
|
|
bool isOpaque() const {
|
|
return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
|
|
}
|
|
|
|
bool isSolidWhite() const {
|
|
return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
|
|
}
|
|
|
|
bool isSingleComponent() const { return fIsSingleComponent; }
|
|
|
|
void resetWillUseInputColor() { fWillUseInputColor = true; }
|
|
|
|
bool allStagesMulInput() const { return !fNonMulStageFound; }
|
|
void resetNonMulStageFound() { fNonMulStageFound = false; }
|
|
|
|
bool isLCDCoverage() const { return fIsLCDCoverage; }
|
|
|
|
SkDEBUGCODE(bool colorComponentsAllEqual() const;)
|
|
/**
|
|
* If alpha is valid, check that any valid R,G,B values are <= A
|
|
*/
|
|
SkDEBUGCODE(bool validPreMulColor() const;)
|
|
|
|
GrColor fColor;
|
|
GrColorComponentFlags fValidFlags;
|
|
bool fIsSingleComponent;
|
|
bool fNonMulStageFound;
|
|
bool fWillUseInputColor;
|
|
bool fIsLCDCoverage; // Temorary data member until texture pixel configs are updated
|
|
|
|
};
|
|
|
|
#endif
|
|
|