return GrColorPackRGBA(r, g, b, a);
}
+
+/**
+* Similarly, GrColor4f is 4 floats for R, G, B, A, in that order. And like GrColor, whether
+* the color is premultiplied or not depends on the context.
+*/
+struct GrColor4f {
+ float fRGBA[4];
+
+ GrColor4f() {}
+ GrColor4f(float r, float g, float b, float a) {
+ fRGBA[0] = r;
+ fRGBA[1] = g;
+ fRGBA[2] = b;
+ fRGBA[3] = a;
+ }
+
+ static GrColor4f FromGrColor(GrColor color) {
+ GrColor4f result;
+ GrColorToRGBAFloat(color, result.fRGBA);
+ return result;
+ }
+
+ static GrColor4f FromSkColor4f(const SkColor4f& color) {
+ return GrColor4f(color.fR, color.fG, color.fB, color.fA);
+ }
+
+ GrColor toGrColor() const {
+ return GrColorPackRGBA(
+ SkTPin<unsigned>(static_cast<unsigned>(fRGBA[0] * 255.0f + 0.5f), 0, 255),
+ SkTPin<unsigned>(static_cast<unsigned>(fRGBA[1] * 255.0f + 0.5f), 0, 255),
+ SkTPin<unsigned>(static_cast<unsigned>(fRGBA[2] * 255.0f + 0.5f), 0, 255),
+ SkTPin<unsigned>(static_cast<unsigned>(fRGBA[3] * 255.0f + 0.5f), 0, 255));
+ }
+
+ SkColor4f toSkColor4f() const {
+ return SkColor4f { fRGBA[0], fRGBA[1], fRGBA[2], fRGBA[3] };
+ }
+
+ GrColor4f opaque() const {
+ return GrColor4f(fRGBA[0], fRGBA[1], fRGBA[2], 1.0f);
+ }
+
+ GrColor4f premul() const {
+ float a = fRGBA[3];
+ return GrColor4f(fRGBA[0] * a, fRGBA[1] * a, fRGBA[2] * a, a);
+ }
+};
+
/**
* Flags used for bitfields of color components. They are defined so that the bit order reflects the
* GrColor shift order.
/**
* The initial color of the drawn primitive. Defaults to solid white.
*/
- void setColor(GrColor color) { fColor = color; }
- GrColor getColor() const { return fColor; }
+ void setColor4f(const GrColor4f& color) { fColor = color; }
+ const GrColor4f& getColor4f() const { return fColor; }
+
+ /**
+ * Legacy getter, until all code handles 4f directly.
+ */
+ GrColor getColor() const { return fColor.toGrColor(); }
/**
* Should primitives be anti-aliased or not. Defaults to false.
bool fDisableOutputConversionToSRGB;
bool fAllowSRGBInputs;
- GrColor fColor;
+ GrColor4f fColor;
};
#endif
: fAntiAlias(false)
, fDisableOutputConversionToSRGB(false)
, fAllowSRGBInputs(false)
- , fColor(GrColor_WHITE) {}
+ , fColor(GrColor4f::FromGrColor(GrColor_WHITE)) {}
void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) {
fXPFactory = GrCoverageSetOpXPFactory::Make(regionOp, invertCoverage);
GrProcOptInfo colorProcInfo;
colorProcInfo.calcWithInitialValues(
sk_sp_address_as_pointer_address(fColorFragmentProcessors.begin()),
- this->numColorFragmentProcessors(), fColor, kRGBA_GrColorComponentFlags, false);
+ this->numColorFragmentProcessors(), this->getColor(), kRGBA_GrColorComponentFlags, false);
GrXPFactory::InvariantBlendedColor blendedColor;
if (fXPFactory) {
#include "SkMessageBus.h"
#include "SkMipMap.h"
#include "SkPixelRef.h"
+#include "SkPM4fPriv.h"
#include "SkResourceCache.h"
#include "SkTemplates.h"
#include "SkYUVPlanesCache.h"
grPaint->setAntiAlias(skPaint.isAntiAlias());
grPaint->setAllowSRGBInputs(allowSRGBInputs);
+ // Raw translation of the SkPaint color to our 4f format:
+ GrColor4f origColor = GrColor4f::FromGrColor(SkColorToUnpremulGrColor(skPaint.getColor()));
+
+ // Linearize, if the color is meant to be in sRGB gamma:
+ if (allowSRGBInputs) {
+ origColor.fRGBA[0] = exact_srgb_to_linear(origColor.fRGBA[0]);
+ origColor.fRGBA[1] = exact_srgb_to_linear(origColor.fRGBA[1]);
+ origColor.fRGBA[2] = exact_srgb_to_linear(origColor.fRGBA[2]);
+ }
+
// Setup the initial color considering the shader, the SkPaint color, and the presence or not
// of per-vertex colors.
sk_sp<GrFragmentProcessor> shaderFP;
// The geometry processor will insert the primitive color to start the color chain, so
// the GrPaint color will be ignored.
- GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor());
+ GrColor shaderInput = origColor.opaque().toGrColor();
+ // SRGBTODO: Preserve 4f on this code path
shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
if (primitiveIsSrc) {
shaderFP = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(shaderFP),
grPaint->addColorFragmentProcessor(shaderFP);
}
+ // We can ignore origColor here - alpha is unchanged by gamma
GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
if (GrColor_WHITE != paintAlpha) {
grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
}
} else {
// The shader's FP sees the paint unpremul color
- grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()));
+ grPaint->setColor4f(origColor);
grPaint->addColorFragmentProcessor(std::move(shaderFP));
}
} else {
if (primColorMode) {
// There is a blend between the primitive color and the paint color. The blend considers
// the opaque paint color. The paint's alpha is applied to the post-blended color.
+ // SRGBTODO: Preserve 4f on this code path
sk_sp<GrFragmentProcessor> processor(
- GrConstColorProcessor::Make(SkColorToOpaqueGrColor(skPaint.getColor()),
+ GrConstColorProcessor::Make(origColor.opaque().toGrColor(),
GrConstColorProcessor::kIgnore_InputMode));
if (primitiveIsSrc) {
processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor),
grPaint->addColorFragmentProcessor(std::move(processor));
}
- grPaint->setColor(SkColorToOpaqueGrColor(skPaint.getColor()));
+ grPaint->setColor4f(origColor.opaque());
+ // We can ignore origColor here - alpha is unchanged by gamma
GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
if (GrColor_WHITE != paintAlpha) {
grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
}
} else {
// No shader, no primitive color.
- grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor()));
+ grPaint->setColor4f(origColor.premul());
applyColorFilterToPaintColor = true;
}
}
SkColorFilter* colorFilter = skPaint.getColorFilter();
if (colorFilter) {
if (applyColorFilterToPaintColor) {
- grPaint->setColor(SkColorToPremulGrColor(colorFilter->filterColor(skPaint.getColor())));
+ grPaint->setColor4f(GrColor4f::FromSkColor4f(
+ colorFilter->filterColor4f(origColor.toSkColor4f())).premul());
} else {
sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context));
if (cfFP) {