37#include <initializer_list>
47 if (srgb <= 0.04045f) {
50 return powf((srgb + 0.055f) / 1.055f, 2.4f);
59 return 1.055f * powf(
linear, 1.f / 2.4f) - 0.055f;
68 if ((input & 0xff000000) != (
output & 0xff000000)) {
72 for (
int c = 0; c < 3; ++c) {
73 uint8_t inputComponent = (uint8_t) ((input & (0xff << (c*8))) >> (c*8));
75 float upper =
std::min(255.f, (
float) inputComponent +
error);
77 upper = CONVERT(upper / 255.f);
79 SkASSERT(upper >= 0.f && upper <= 255.f);
80 uint8_t outputComponent = (
output & (0xff << (c*8))) >> (c*8);
90template <
float (*FORWARD)(
float),
float (*BACKWARD)(
float)>
93 if ((input & 0xff000000) != (
output & 0xff000000)) {
97 for (
int c = 0; c < 3; ++c) {
98 uint8_t inputComponent = (uint8_t) ((input & (0xff << (c*8))) >> (c*8));
100 float upper =
std::min(255.f, (
float) inputComponent +
error);
102 upper = FORWARD(upper / 255.f);
104 SkASSERT(upper >= 0.f && upper <= 255.f);
109 lower = BACKWARD(lowerComponent / 255.f);
110 upper = BACKWARD(upperComponent / 255.f);
112 SkASSERT(upper >= 0.f && upper <= 255.f);
116 uint8_t outputComponent = (
output & (0xff << (c*8))) >> (c*8);
117 if (outputComponent < lowerComponent || outputComponent > upperComponent) {
125 return check_conversion<srgb_to_linear>(srgb,
linear,
error);
129 return check_conversion<linear_to_srgb>(
linear, srgb,
error);
133 return check_double_conversion<linear_to_srgb, srgb_to_linear>(input,
output,
error);
137 return check_double_conversion<srgb_to_linear, linear_to_srgb>(input,
output,
error);
154 const char* subtestName) {
157 memset(readPM.
addr(), 0,
sizeof(uint32_t)*
w*
h);
159 if (!sc->
readPixels(dContext, readPM, {0, 0})) {
164 for (
int j = 0; j <
h; ++j) {
165 for (
int i = 0;
i <
w; ++
i) {
166 uint32_t orig = origData[j *
w +
i];
167 uint32_t
read =
static_cast<uint32_t*
>(readPM.
addr())[j *
w +
i];
170 ERRORF(
reporter,
"Original 0x%08x, read back as 0x%08x in %s at %d, %d).", orig,
171 read, subtestName,
i, j);
188 case Encoding::kUntagged:
return nullptr;
197 case Encoding::kUntagged:
return "untagged";
199 case Encoding::kSRGB:
return "sRGB";
204static constexpr int kW = 255;
205static constexpr int kH = 255;
208 std::unique_ptr<uint32_t[]>
data(
new uint32_t[
kW *
kH]);
209 for (
int j = 0; j <
kH; ++j) {
210 for (
int i = 0;
i <
kW; ++
i) {
211 data[j *
kW +
i] = (0xFF << 24) | (
i << 16) | (
i << 8) |
i;
235static void test_write_read(Encoding contextEncoding, Encoding writeEncoding, Encoding readEncoding,
239 if (!surfaceContext) {
246 if (!surfaceContext->writePixels(dContext, dataPM, {0, 0})) {
267 auto context = ctxInfo.directContext();
273 float error = context->priv().caps()->shaderCaps()->fHalfIs32Bits ? 0.5f : 1.2f;
277 float smallError = context->priv().caps()->shaderCaps()->fHalfIs32Bits ? 0.0f : 1.f;
283 test_write_read(Encoding::kSRGB, Encoding::kSRGB, Encoding::kSRGB, smallError,
294 test_write_read(Encoding::kSRGB, Encoding::kUntagged, Encoding::kSRGB, smallError,
311 for (
auto writeEncoding : {Encoding::kSRGB, Encoding::kUntagged,
Encoding::kLinear}) {
static float linear_to_srgb(float linear)
static float srgb_to_linear(float srgb)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
@ kBottomLeft_GrSurfaceOrigin
#define check(reporter, ref, unref, make, kill)
static bool check_srgb_to_linear_conversion(uint32_t srgb, uint32_t linear, float error)
static const char * encoding_as_str(Encoding encoding)
static std::unique_ptr< uint32_t[]> make_data()
static bool check_linear_to_srgb_to_linear_conversion(uint32_t input, uint32_t output, float error)
static bool check_linear_to_srgb_conversion(uint32_t linear, uint32_t srgb, float error)
static bool check_no_conversion(uint32_t input, uint32_t output, float error)
static bool check_double_conversion(uint32_t input, uint32_t output, float error)
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SRGBReadWritePixels, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
static bool check_srgb_to_linear_to_srgb_conversion(uint32_t input, uint32_t output, float error)
bool(* CheckFn)(uint32_t orig, uint32_t actual, float error)
void read_and_check_pixels(skiatest::Reporter *reporter, GrDirectContext *dContext, skgpu::ganesh::SurfaceContext *sc, uint32_t *origData, const SkImageInfo &dstInfo, CheckFn checker, float error, const char *subtestName)
static bool check_conversion(uint32_t input, uint32_t output, float error)
static sk_sp< SkColorSpace > encoding_as_color_space(Encoding encoding)
static std::unique_ptr< skgpu::ganesh::SurfaceContext > make_surface_context(Encoding contextEncoding, GrRecordingContext *rContext, skiatest::Reporter *reporter)
static void test_write_read(Encoding contextEncoding, Encoding writeEncoding, Encoding readEncoding, float error, CheckFn check, GrDirectContext *dContext, skiatest::Reporter *reporter)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
static bool read(SkStream *stream, void *buffer, size_t amount)
#define SkScalarCeilToInt(x)
#define SkScalarFloorToInt(x)
std::unique_ptr< skgpu::ganesh::SurfaceContext > CreateSurfaceContext(GrRecordingContext *rContext, const GrImageInfo &info, SkBackingFit fit, GrSurfaceOrigin origin, GrRenderable renderable, int sampleCount, skgpu::Mipmapped mipmapped, GrProtected isProtected, skgpu::Budgeted budgeted)
static GrPixmap Allocate(const GrImageInfo &info)
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkColorSpace > MakeSRGBLinear()
bool readPixels(GrDirectContext *dContext, GrPixmap dst, SkIPoint srcPt)
const uint8_t uint32_t uint32_t GError ** error
static float max(float r, float g, float b)
static float min(float r, float g, float b)
static constexpr skcms_TransferFunction kLinear
SkISize dimensions() const
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
std::shared_ptr< const fml::Mapping > data
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)