Add helpers to deal with byte vs. half-float vertex colors

GrVertexColor stores either kind of color, and GrVertexWriter does the
right thing. SkColor4fPrepForDst helps to automate the conversion and
pinning. This ensures that colors are already pinned if the device has
no support for half-floats. This way, ops never need to worry about caps,
they can just check if all colors they're batching are normalized.

Bug: skia:
Change-Id: Ie0c15d3b16c6fc93a7f11d284029d77d482a6283
Reviewed-on: https://skia-review.googlesource.com/c/171725
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Brian Osman 2018-11-19 11:56:57 -05:00 committed by Skia Commit-Bot
parent dfc738b38c
commit 5c8a6b3238
5 changed files with 84 additions and 4 deletions

View File

@ -14,6 +14,7 @@
#include "SkColor.h"
#include "SkColorData.h"
#include "SkColorPriv.h"
#include "SkHalf.h"
/**
* GrColor is 4 bytes for R, G, B, A, in a specific order defined below. Whether the color is
@ -91,4 +92,28 @@ static inline bool SkPMColor4fFitsInBytes(const SkPMColor4f& color) {
color.fB >= 0.0f && color.fB <= 1.0f;
}
/**
* GrVertexColor is a helper for writing colors to a vertex attribute. It stores either GrColor
* or four half-float channels, depending on the wideColor parameter. GrVertexWriter will write
* the correct amount of data. Note that the GP needs to have been constructed with the correct
* attribute type for colors, to match the usage here.
*/
class GrVertexColor {
public:
GrVertexColor(const SkPMColor4f& color, bool wideColor)
: fWideColor(wideColor) {
if (wideColor) {
SkFloatToHalf_finite_ftz(Sk4f::Load(color.vec())).store(&fColor);
} else {
fColor[0] = color.toBytes_RGBA();
}
}
private:
friend struct GrVertexWriter;
uint32_t fColor[2];
bool fWideColor;
};
#endif

View File

@ -1066,6 +1066,35 @@ static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {
return false;
}
static inline bool GrPixelConfigIsFloatingPoint(GrPixelConfig config) {
switch (config) {
case kUnknown_GrPixelConfig:
case kAlpha_8_GrPixelConfig:
case kAlpha_8_as_Alpha_GrPixelConfig:
case kAlpha_8_as_Red_GrPixelConfig:
case kGray_8_GrPixelConfig:
case kGray_8_as_Lum_GrPixelConfig:
case kGray_8_as_Red_GrPixelConfig:
case kRGB_565_GrPixelConfig:
case kRGBA_4444_GrPixelConfig:
case kRGB_888_GrPixelConfig:
case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig:
case kSRGBA_8888_GrPixelConfig:
case kSBGRA_8888_GrPixelConfig:
case kRGBA_1010102_GrPixelConfig:
return false;
case kRGBA_float_GrPixelConfig:
case kRG_float_GrPixelConfig:
case kAlpha_half_GrPixelConfig:
case kAlpha_half_as_Red_GrPixelConfig:
case kRGBA_half_GrPixelConfig:
return true;
}
SK_ABORT("Invalid pixel config.");
return false;
}
/**
* Precision qualifier that should be used with a sampler.
*/

View File

@ -45,6 +45,15 @@ struct GrVertexWriter {
this->write(remainder...);
}
template <typename... Args>
void write(const GrVertexColor& color, const Args&... remainder) {
this->write(color.fColor[0]);
if (color.fWideColor) {
this->write(color.fColor[1]);
}
this->write(remainder...);
}
void write() {}
/**

View File

@ -260,6 +260,21 @@ SkPMColor4f SkColorToPMColor4f(SkColor c, const GrColorSpaceInfo& colorSpaceInfo
return color.premul();
}
SkColor4f SkColor4fPrepForDst(SkColor4f color, const GrColorSpaceInfo& colorSpaceInfo,
const GrCaps& caps) {
if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) {
color = xform->apply(color);
}
if (!GrPixelConfigIsFloatingPoint(colorSpaceInfo.config()) ||
!caps.halfFloatVertexAttributeSupport()) {
color = { SkTPin(color.fR, 0.0f, 1.0f),
SkTPin(color.fG, 0.0f, 1.0f),
SkTPin(color.fB, 0.0f, 1.0f),
color.fA };
}
return color;
}
///////////////////////////////////////////////////////////////////////////////
GrPixelConfig SkColorType2GrPixelConfig(const SkColorType type) {
@ -355,10 +370,8 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
SkBlendMode* primColorMode,
GrPaint* grPaint) {
// Convert SkPaint color to 4f format in the destination color space
SkColor4f origColor = skPaint.getColor4f();
if (auto* xform = colorSpaceInfo.colorSpaceXformFromSRGB()) {
origColor = xform->apply(origColor);
}
SkColor4f origColor = SkColor4fPrepForDst(skPaint.getColor4f(), colorSpaceInfo,
*context->contextPriv().caps());
const GrFPArgs fpArgs(context, &viewM, skPaint.getFilterQuality(), &colorSpaceInfo);

View File

@ -60,6 +60,10 @@ static inline GrColor SkColorToUnpremulGrColor(SkColor c) {
/** Similar, but using SkPMColor4f. */
SkPMColor4f SkColorToPMColor4f(SkColor, const GrColorSpaceInfo&);
/** Converts an SkColor4f to the destination color space. Pins the color if the destination is
normalized, or the device does not support half-float vertex attributes. */
SkColor4f SkColor4fPrepForDst(SkColor4f, const GrColorSpaceInfo&, const GrCaps&);
////////////////////////////////////////////////////////////////////////////////
// Paint conversion