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;
65template <
float (*CONVERT)(
float)>
static bool check_conversion(uint32_t input, uint32_t output,
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));
74 float lower = std::max(0.f, (
float) inputComponent -
error);
75 float upper = std::min(255.f, (
float) inputComponent +
error);
76 lower = CONVERT(lower / 255.f);
77 upper = CONVERT(upper / 255.f);
78 SkASSERT(lower >= 0.f && lower <= 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));
99 float lower = std::max(0.f, (
float) inputComponent -
error);
100 float upper = std::min(255.f, (
float) inputComponent +
error);
101 lower = FORWARD(lower / 255.f);
102 upper = FORWARD(upper / 255.f);
103 SkASSERT(lower >= 0.f && lower <= 255.f);
104 SkASSERT(upper >= 0.f && upper <= 255.f);
107 lower = std::max(0.f, (
float) lowerComponent -
error);
108 upper = std::min(255.f, (
float) upperComponent +
error);
109 lower = BACKWARD(lowerComponent / 255.f);
110 upper = BACKWARD(upperComponent / 255.f);
111 SkASSERT(lower >= 0.f && lower <= 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";
198 case Encoding::kLinear:
return "linear";
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) {
245 GrCPixmap dataPM(writeII, data.get(),
kW*
sizeof(uint32_t));
246 if (!surfaceContext->writePixels(dContext, dataPM, {0, 0})) {
255 testName.printf(
"write %s data to a %s context and read as %s.",
encoding_as_str(writeEncoding),
258 error, testName.c_str());
267 auto context = ctxInfo.directContext();
269 GrRenderable::kNo).isValid()) {
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)
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)
#define DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info, ctsEnforcement)
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
SkISize dimensions() const
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)