116921ec30a81976129d507b1148c93a322e61a4fbsalomon/*
216921ec30a81976129d507b1148c93a322e61a4fbsalomon * Copyright 2015 Google Inc.
316921ec30a81976129d507b1148c93a322e61a4fbsalomon *
416921ec30a81976129d507b1148c93a322e61a4fbsalomon * Use of this source code is governed by a BSD-style license that can be
516921ec30a81976129d507b1148c93a322e61a4fbsalomon * found in the LICENSE file.
616921ec30a81976129d507b1148c93a322e61a4fbsalomon */
716921ec30a81976129d507b1148c93a322e61a4fbsalomon
816921ec30a81976129d507b1148c93a322e61a4fbsalomon#include "Test.h"
916921ec30a81976129d507b1148c93a322e61a4fbsalomon#if SK_SUPPORT_GPU
101530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#include "GrCaps.h"
111530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#include "GrContext.h"
1216921ec30a81976129d507b1148c93a322e61a4fbsalomon#include "SkCanvas.h"
1316921ec30a81976129d507b1148c93a322e61a4fbsalomon#include "SkSurface.h"
1416921ec30a81976129d507b1148c93a322e61a4fbsalomon
1516921ec30a81976129d507b1148c93a322e61a4fbsalomon// using anonymous namespace because these functions are used as template params.
1616921ec30a81976129d507b1148c93a322e61a4fbsalomonnamespace {
1716921ec30a81976129d507b1148c93a322e61a4fbsalomon/** convert 0..1 srgb value to 0..1 linear */
1816921ec30a81976129d507b1148c93a322e61a4fbsalomonfloat srgb_to_linear(float srgb) {
1916921ec30a81976129d507b1148c93a322e61a4fbsalomon    if (srgb <= 0.04045f) {
2016921ec30a81976129d507b1148c93a322e61a4fbsalomon        return srgb / 12.92f;
2116921ec30a81976129d507b1148c93a322e61a4fbsalomon    } else {
2216921ec30a81976129d507b1148c93a322e61a4fbsalomon        return powf((srgb + 0.055f) / 1.055f, 2.4f);
2316921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
2416921ec30a81976129d507b1148c93a322e61a4fbsalomon}
2516921ec30a81976129d507b1148c93a322e61a4fbsalomon
2616921ec30a81976129d507b1148c93a322e61a4fbsalomon/** convert 0..1 linear value to 0..1 srgb */
2716921ec30a81976129d507b1148c93a322e61a4fbsalomonfloat linear_to_srgb(float linear) {
2816921ec30a81976129d507b1148c93a322e61a4fbsalomon    if (linear <= 0.0031308) {
2916921ec30a81976129d507b1148c93a322e61a4fbsalomon        return linear * 12.92f;
3016921ec30a81976129d507b1148c93a322e61a4fbsalomon    } else {
3116921ec30a81976129d507b1148c93a322e61a4fbsalomon        return 1.055f * powf(linear, 1.f / 2.4f) - 0.055f;
3216921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
3316921ec30a81976129d507b1148c93a322e61a4fbsalomon}
3416921ec30a81976129d507b1148c93a322e61a4fbsalomon}
3516921ec30a81976129d507b1148c93a322e61a4fbsalomon
3616921ec30a81976129d507b1148c93a322e61a4fbsalomon/** tests a conversion with an error tolerance */
3716921ec30a81976129d507b1148c93a322e61a4fbsalomontemplate <float (*CONVERT)(float)> static bool check_conversion(uint32_t input, uint32_t output,
3816921ec30a81976129d507b1148c93a322e61a4fbsalomon                                                                float error) {
3916921ec30a81976129d507b1148c93a322e61a4fbsalomon    // alpha should always be exactly preserved.
4016921ec30a81976129d507b1148c93a322e61a4fbsalomon    if ((input & 0xff000000) != (output & 0xff000000)) {
4116921ec30a81976129d507b1148c93a322e61a4fbsalomon        return false;
4216921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
4316921ec30a81976129d507b1148c93a322e61a4fbsalomon
4416921ec30a81976129d507b1148c93a322e61a4fbsalomon    for (int c = 0; c < 3; ++c) {
4516921ec30a81976129d507b1148c93a322e61a4fbsalomon        uint8_t inputComponent = (uint8_t) ((input & (0xff << (c*8))) >> (c*8));
4616921ec30a81976129d507b1148c93a322e61a4fbsalomon        float lower = SkTMax(0.f, (float) inputComponent - error);
4716921ec30a81976129d507b1148c93a322e61a4fbsalomon        float upper = SkTMin(255.f, (float) inputComponent + error);
4816921ec30a81976129d507b1148c93a322e61a4fbsalomon        lower = CONVERT(lower / 255.f);
4916921ec30a81976129d507b1148c93a322e61a4fbsalomon        upper = CONVERT(upper / 255.f);
5016921ec30a81976129d507b1148c93a322e61a4fbsalomon        SkASSERT(lower >= 0.f && lower <= 255.f);
5116921ec30a81976129d507b1148c93a322e61a4fbsalomon        SkASSERT(upper >= 0.f && upper <= 255.f);
5216921ec30a81976129d507b1148c93a322e61a4fbsalomon        uint8_t outputComponent = (output & (0xff << (c*8))) >> (c*8);
5316921ec30a81976129d507b1148c93a322e61a4fbsalomon        if (outputComponent < SkScalarFloorToInt(lower * 255.f) ||
5416921ec30a81976129d507b1148c93a322e61a4fbsalomon            outputComponent > SkScalarCeilToInt(upper * 255.f)) {
5516921ec30a81976129d507b1148c93a322e61a4fbsalomon            return false;
5616921ec30a81976129d507b1148c93a322e61a4fbsalomon        }
5716921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
5816921ec30a81976129d507b1148c93a322e61a4fbsalomon    return true;
5916921ec30a81976129d507b1148c93a322e61a4fbsalomon}
6016921ec30a81976129d507b1148c93a322e61a4fbsalomon
6116921ec30a81976129d507b1148c93a322e61a4fbsalomon/** tests a forward and backward conversion with an error tolerance */
6216921ec30a81976129d507b1148c93a322e61a4fbsalomontemplate <float (*FORWARD)(float), float (*BACKWARD)(float)>
6316921ec30a81976129d507b1148c93a322e61a4fbsalomonstatic bool check_double_conversion(uint32_t input, uint32_t output, float error) {
6416921ec30a81976129d507b1148c93a322e61a4fbsalomon    // alpha should always be exactly preserved.
6516921ec30a81976129d507b1148c93a322e61a4fbsalomon    if ((input & 0xff000000) != (output & 0xff000000)) {
6616921ec30a81976129d507b1148c93a322e61a4fbsalomon        return false;
6716921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
6816921ec30a81976129d507b1148c93a322e61a4fbsalomon
6916921ec30a81976129d507b1148c93a322e61a4fbsalomon    for (int c = 0; c < 3; ++c) {
7016921ec30a81976129d507b1148c93a322e61a4fbsalomon        uint8_t inputComponent = (uint8_t) ((input & (0xff << (c*8))) >> (c*8));
7116921ec30a81976129d507b1148c93a322e61a4fbsalomon        float lower = SkTMax(0.f, (float) inputComponent - error);
7216921ec30a81976129d507b1148c93a322e61a4fbsalomon        float upper = SkTMin(255.f, (float) inputComponent + error);
7316921ec30a81976129d507b1148c93a322e61a4fbsalomon        lower = FORWARD(lower / 255.f);
7416921ec30a81976129d507b1148c93a322e61a4fbsalomon        upper = FORWARD(upper / 255.f);
7516921ec30a81976129d507b1148c93a322e61a4fbsalomon        SkASSERT(lower >= 0.f && lower <= 255.f);
7616921ec30a81976129d507b1148c93a322e61a4fbsalomon        SkASSERT(upper >= 0.f && upper <= 255.f);
7716921ec30a81976129d507b1148c93a322e61a4fbsalomon        uint8_t upperComponent = SkScalarCeilToInt(upper * 255.f);
7816921ec30a81976129d507b1148c93a322e61a4fbsalomon        uint8_t lowerComponent = SkScalarFloorToInt(lower * 255.f);
7916921ec30a81976129d507b1148c93a322e61a4fbsalomon        lower = SkTMax(0.f, (float) lowerComponent - error);
8016921ec30a81976129d507b1148c93a322e61a4fbsalomon        upper = SkTMin(255.f, (float) upperComponent + error);
8116921ec30a81976129d507b1148c93a322e61a4fbsalomon        lower = BACKWARD(lowerComponent / 255.f);
8216921ec30a81976129d507b1148c93a322e61a4fbsalomon        upper = BACKWARD(upperComponent / 255.f);
8316921ec30a81976129d507b1148c93a322e61a4fbsalomon        SkASSERT(lower >= 0.f && lower <= 255.f);
8416921ec30a81976129d507b1148c93a322e61a4fbsalomon        SkASSERT(upper >= 0.f && upper <= 255.f);
8516921ec30a81976129d507b1148c93a322e61a4fbsalomon        upperComponent = SkScalarCeilToInt(upper * 255.f);
8616921ec30a81976129d507b1148c93a322e61a4fbsalomon        lowerComponent = SkScalarFloorToInt(lower * 255.f);
8716921ec30a81976129d507b1148c93a322e61a4fbsalomon
8816921ec30a81976129d507b1148c93a322e61a4fbsalomon        uint8_t outputComponent = (output & (0xff << (c*8))) >> (c*8);
8916921ec30a81976129d507b1148c93a322e61a4fbsalomon        if (outputComponent < lowerComponent || outputComponent > upperComponent) {
9016921ec30a81976129d507b1148c93a322e61a4fbsalomon            return false;
9116921ec30a81976129d507b1148c93a322e61a4fbsalomon        }
9216921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
9316921ec30a81976129d507b1148c93a322e61a4fbsalomon    return true;
9416921ec30a81976129d507b1148c93a322e61a4fbsalomon}
9516921ec30a81976129d507b1148c93a322e61a4fbsalomon
9616921ec30a81976129d507b1148c93a322e61a4fbsalomonstatic bool check_srgb_to_linear_conversion(uint32_t srgb, uint32_t linear, float error) {
9716921ec30a81976129d507b1148c93a322e61a4fbsalomon    return check_conversion<srgb_to_linear>(srgb, linear, error);
9816921ec30a81976129d507b1148c93a322e61a4fbsalomon}
9916921ec30a81976129d507b1148c93a322e61a4fbsalomon
10016921ec30a81976129d507b1148c93a322e61a4fbsalomonstatic bool check_linear_to_srgb_conversion(uint32_t linear, uint32_t srgb, float error) {
10116921ec30a81976129d507b1148c93a322e61a4fbsalomon    return check_conversion<linear_to_srgb>(linear, srgb, error);
10216921ec30a81976129d507b1148c93a322e61a4fbsalomon}
10316921ec30a81976129d507b1148c93a322e61a4fbsalomon
10416921ec30a81976129d507b1148c93a322e61a4fbsalomonstatic bool check_linear_to_srgb_to_linear_conversion(uint32_t input, uint32_t output, float error) {
10516921ec30a81976129d507b1148c93a322e61a4fbsalomon    return check_double_conversion<linear_to_srgb, srgb_to_linear>(input, output, error);
10616921ec30a81976129d507b1148c93a322e61a4fbsalomon}
10716921ec30a81976129d507b1148c93a322e61a4fbsalomon
10816921ec30a81976129d507b1148c93a322e61a4fbsalomonstatic bool check_srgb_to_linear_to_srgb_conversion(uint32_t input, uint32_t output, float error) {
10916921ec30a81976129d507b1148c93a322e61a4fbsalomon    return check_double_conversion<srgb_to_linear, linear_to_srgb>(input, output, error);
11016921ec30a81976129d507b1148c93a322e61a4fbsalomon}
11116921ec30a81976129d507b1148c93a322e61a4fbsalomon
11216921ec30a81976129d507b1148c93a322e61a4fbsalomontypedef bool (*CheckFn) (uint32_t orig, uint32_t actual, float error);
11316921ec30a81976129d507b1148c93a322e61a4fbsalomon
11416921ec30a81976129d507b1148c93a322e61a4fbsalomonvoid read_and_check_pixels(skiatest::Reporter* reporter, GrTexture* texture, uint32_t* origData,
11516921ec30a81976129d507b1148c93a322e61a4fbsalomon                           GrPixelConfig readConfig, CheckFn checker, float error,
11616921ec30a81976129d507b1148c93a322e61a4fbsalomon                           const char* subtestName) {
11716921ec30a81976129d507b1148c93a322e61a4fbsalomon    int w = texture->width();
11816921ec30a81976129d507b1148c93a322e61a4fbsalomon    int h = texture->height();
11916921ec30a81976129d507b1148c93a322e61a4fbsalomon    SkAutoTMalloc<uint32_t> readData(w * h);
12016921ec30a81976129d507b1148c93a322e61a4fbsalomon    memset(readData.get(), 0, sizeof(uint32_t) * w * h);
12116921ec30a81976129d507b1148c93a322e61a4fbsalomon    if (!texture->readPixels(0, 0, w, h, readConfig, readData.get())) {
12216921ec30a81976129d507b1148c93a322e61a4fbsalomon        ERRORF(reporter, "Could not read pixels for %s.", subtestName);
12316921ec30a81976129d507b1148c93a322e61a4fbsalomon        return;
12416921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
12516921ec30a81976129d507b1148c93a322e61a4fbsalomon    for (int j = 0; j < h; ++j) {
12616921ec30a81976129d507b1148c93a322e61a4fbsalomon        for (int i = 0; i < w; ++i) {
12716921ec30a81976129d507b1148c93a322e61a4fbsalomon            uint32_t orig = origData[j * w + i];
12816921ec30a81976129d507b1148c93a322e61a4fbsalomon            uint32_t read = readData[j * w + i];
12916921ec30a81976129d507b1148c93a322e61a4fbsalomon
13016921ec30a81976129d507b1148c93a322e61a4fbsalomon            if (!checker(orig, read, error)) {
13116921ec30a81976129d507b1148c93a322e61a4fbsalomon                ERRORF(reporter, "Expected 0x%08x, read back as 0x%08x in %s at %d, %d).",
13216921ec30a81976129d507b1148c93a322e61a4fbsalomon                       orig, read, subtestName, i, j);
13316921ec30a81976129d507b1148c93a322e61a4fbsalomon                return;
13416921ec30a81976129d507b1148c93a322e61a4fbsalomon            }
13516921ec30a81976129d507b1148c93a322e61a4fbsalomon        }
13616921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
13716921ec30a81976129d507b1148c93a322e61a4fbsalomon}
13816921ec30a81976129d507b1148c93a322e61a4fbsalomon
13916921ec30a81976129d507b1148c93a322e61a4fbsalomon// TODO: Add tests for copySurface between srgb/linear textures. Add tests for unpremul/premul
14016921ec30a81976129d507b1148c93a322e61a4fbsalomon// conversion during read/write along with srgb/linear conversions.
1411530283c483cb88aa725bce50a6d193dd00ee570kkinnunenDEF_GPUTEST_FOR_RENDERING_CONTEXTS(SRGBReadWritePixels, reporter, context) {
1427d974f5e4f8ded8834b58f560ac6e03aed370310benjaminwagner#if defined(GOOGLE3)
1437d974f5e4f8ded8834b58f560ac6e03aed370310benjaminwagner    // Stack frame size is limited in GOOGLE3.
1447d974f5e4f8ded8834b58f560ac6e03aed370310benjaminwagner    static const int kW = 63;
1457d974f5e4f8ded8834b58f560ac6e03aed370310benjaminwagner    static const int kH = 63;
1467d974f5e4f8ded8834b58f560ac6e03aed370310benjaminwagner#else
14716921ec30a81976129d507b1148c93a322e61a4fbsalomon    static const int kW = 255;
14816921ec30a81976129d507b1148c93a322e61a4fbsalomon    static const int kH = 255;
1497d974f5e4f8ded8834b58f560ac6e03aed370310benjaminwagner#endif
15016921ec30a81976129d507b1148c93a322e61a4fbsalomon    uint32_t origData[kW * kH];
15116921ec30a81976129d507b1148c93a322e61a4fbsalomon    for (int j = 0; j < kH; ++j) {
15216921ec30a81976129d507b1148c93a322e61a4fbsalomon        for (int i = 0; i < kW; ++i) {
15316921ec30a81976129d507b1148c93a322e61a4fbsalomon            origData[j * kW + i] = (j << 24) | (i << 16) | (i << 8) | i;
15416921ec30a81976129d507b1148c93a322e61a4fbsalomon        }
15516921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
15616921ec30a81976129d507b1148c93a322e61a4fbsalomon
1571530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    GrSurfaceDesc desc;
1581530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fFlags = kRenderTarget_GrSurfaceFlag;
1591530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fWidth = kW;
1601530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fHeight = kH;
1611530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    desc.fConfig = kSRGBA_8888_GrPixelConfig;
1621530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    if (context->caps()->isConfigRenderable(desc.fConfig, false) &&
1631530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        context->caps()->isConfigTexturable(desc.fConfig)) {
1645ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        SkAutoTUnref<GrTexture> tex(context->textureProvider()->createTexture(
1655ec26ae9bfca635ccc98283aad5deda11519d826bsalomon                desc, SkBudgeted::kNo));
1661530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        if (!tex) {
1671530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            ERRORF(reporter, "Could not create SRGBA texture.");
1681530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            return;
16916921ec30a81976129d507b1148c93a322e61a4fbsalomon        }
17016921ec30a81976129d507b1148c93a322e61a4fbsalomon
1711530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        float error = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.2f  : 0.5f;
1721530283c483cb88aa725bce50a6d193dd00ee570kkinnunen
1731530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        // Write srgba data and read as srgba and then as rgba
1741530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        if (tex->writePixels(0, 0, kW, kH, kSRGBA_8888_GrPixelConfig, origData)) {
1751530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            // For the all-srgba case, we allow a small error only for devices that have
1761530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            // precision variation because the srgba data gets converted to linear and back in
1771530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            // the shader.
1781530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            float smallError = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.f :
1791530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                    0.0f;
1801530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            read_and_check_pixels(reporter, tex, origData, kSRGBA_8888_GrPixelConfig,
1811530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  check_srgb_to_linear_to_srgb_conversion, smallError,
1821530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  "write/read srgba to srgba texture");
1831530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            read_and_check_pixels(reporter, tex, origData, kRGBA_8888_GrPixelConfig,
1841530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  check_srgb_to_linear_conversion, error,
1851530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  "write srgba/read rgba with srgba texture");
1861530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        } else {
1871530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            ERRORF(reporter, "Could not write srgba data to srgba texture.");
1881530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        }
18916921ec30a81976129d507b1148c93a322e61a4fbsalomon
1901530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        // Now verify that we can write linear data
1911530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        if (tex->writePixels(0, 0, kW, kH, kRGBA_8888_GrPixelConfig, origData)) {
1921530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            // We allow more error on GPUs with lower precision shader variables.
1931530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            read_and_check_pixels(reporter, tex, origData, kSRGBA_8888_GrPixelConfig,
1941530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  check_linear_to_srgb_conversion, error,
1951530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  "write rgba/read srgba with srgba texture");
1961530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            read_and_check_pixels(reporter, tex, origData, kRGBA_8888_GrPixelConfig,
1971530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  check_linear_to_srgb_to_linear_conversion, error,
1981530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  "write/read rgba with srgba texture");
1991530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        } else {
2001530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            ERRORF(reporter, "Could not write rgba data to srgba texture.");
2011530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        }
20216921ec30a81976129d507b1148c93a322e61a4fbsalomon
2031530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        desc.fConfig = kRGBA_8888_GrPixelConfig;
2045ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        tex.reset(context->textureProvider()->createTexture(desc, SkBudgeted::kNo));
2051530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        if (!tex) {
2061530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            ERRORF(reporter, "Could not create RGBA texture.");
2071530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            return;
2081530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        }
20916921ec30a81976129d507b1148c93a322e61a4fbsalomon
2101530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        // Write srgba data to a rgba texture and read back as srgba and rgba
2111530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        if (tex->writePixels(0, 0, kW, kH, kSRGBA_8888_GrPixelConfig, origData)) {
2121530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            read_and_check_pixels(reporter, tex, origData, kSRGBA_8888_GrPixelConfig,
2131530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  check_srgb_to_linear_to_srgb_conversion, error,
2141530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  "write/read srgba to rgba texture");
2151530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            read_and_check_pixels(reporter, tex, origData, kRGBA_8888_GrPixelConfig,
2161530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  check_srgb_to_linear_conversion, error,
2171530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  "write srgba/read rgba to rgba texture");
2181530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        } else {
2191530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            ERRORF(reporter, "Could not write srgba data to rgba texture.");
2201530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        }
22116921ec30a81976129d507b1148c93a322e61a4fbsalomon
2221530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        // Write rgba data to a rgba texture and read back as srgba
2231530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        if (tex->writePixels(0, 0, kW, kH, kRGBA_8888_GrPixelConfig, origData)) {
2241530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            read_and_check_pixels(reporter, tex, origData, kSRGBA_8888_GrPixelConfig,
2251530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  check_linear_to_srgb_conversion, 1.2f,
2261530283c483cb88aa725bce50a6d193dd00ee570kkinnunen                                  "write rgba/read srgba to rgba texture");
2271530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        } else {
2281530283c483cb88aa725bce50a6d193dd00ee570kkinnunen            ERRORF(reporter, "Could not write rgba data to rgba texture.");
2291530283c483cb88aa725bce50a6d193dd00ee570kkinnunen        }
23016921ec30a81976129d507b1148c93a322e61a4fbsalomon    }
23116921ec30a81976129d507b1148c93a322e61a4fbsalomon}
23216921ec30a81976129d507b1148c93a322e61a4fbsalomon#endif
233