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