| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "Test.h" | 8 #include "Test.h" |
| 9 | 9 |
| 10 // This test is specific to the GPU backend. | 10 // This test is specific to the GPU backend. |
| 11 #if SK_SUPPORT_GPU | 11 #if SK_SUPPORT_GPU |
| 12 | 12 |
| 13 #include "GrContext.h" | 13 #include "GrContext.h" |
| 14 #include "SkGpuDevice.h" | 14 #include "SkGpuDevice.h" |
| 15 | 15 |
| 16 // This was made indivisible by 4 to ensure we test setting GL_PACK_ALIGNMENT pr
operly. | 16 // This was made indivisible by 4 to ensure we test setting GL_PACK_ALIGNMENT pr
operly. |
| 17 static const int X_SIZE = 13; | 17 static const int X_SIZE = 13; |
| 18 static const int Y_SIZE = 13; | 18 static const int Y_SIZE = 13; |
| 19 | 19 |
| 20 static void validate_alpha_data(skiatest::Reporter* reporter, int w, int h, cons
t uint8_t* actual, |
| 21 size_t actualRowBytes, const uint8_t* expected,
SkString extraMsg) { |
| 22 for (int y = 0; y < h; ++y) { |
| 23 for (int x = 0; x < w; ++x) { |
| 24 uint8_t a = actual[y * actualRowBytes + x]; |
| 25 uint8_t e = expected[y * w + x]; |
| 26 if (e != a) { |
| 27 ERRORF(reporter, |
| 28 "Failed alpha readback. Expected: 0x%02x, Got: 0x%02x at
(%d,%d), %s", |
| 29 e, a, x, y, extraMsg.c_str()); |
| 30 return; |
| 31 } |
| 32 } |
| 33 } |
| 34 } |
| 35 |
| 20 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadWriteAlpha, reporter, context) { | 36 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ReadWriteAlpha, reporter, context) { |
| 21 unsigned char alphaData[X_SIZE][Y_SIZE]; | 37 unsigned char alphaData[X_SIZE * Y_SIZE]; |
| 22 | |
| 23 memset(alphaData, 0, X_SIZE * Y_SIZE); | |
| 24 | 38 |
| 25 bool match; | 39 bool match; |
| 26 unsigned char readback[X_SIZE][Y_SIZE]; | 40 |
| 41 static const size_t kRowBytes[] = {0, X_SIZE, X_SIZE + 1, 2 * X_SIZE - 1}; |
| 27 | 42 |
| 28 for (int rt = 0; rt < 2; ++rt) { | 43 for (int rt = 0; rt < 2; ++rt) { |
| 29 GrSurfaceDesc desc; | 44 GrSurfaceDesc desc; |
| 30 // let Skia know we will be using this texture as a render target | 45 // let Skia know we will be using this texture as a render target |
| 31 desc.fFlags = rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlag
s; | 46 desc.fFlags = rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlag
s; |
| 32 // it is a single channel texture | 47 // it is a single channel texture |
| 33 desc.fConfig = kAlpha_8_GrPixelConfig; | 48 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 34 desc.fWidth = X_SIZE; | 49 desc.fWidth = X_SIZE; |
| 35 desc.fHeight = Y_SIZE; | 50 desc.fHeight = Y_SIZE; |
| 36 | 51 |
| 37 // We are initializing the texture with zeros here | 52 // We are initializing the texture with zeros here |
| 53 memset(alphaData, 0, X_SIZE * Y_SIZE); |
| 38 SkAutoTUnref<GrTexture> texture( | 54 SkAutoTUnref<GrTexture> texture( |
| 39 context->textureProvider()->createTexture(desc, false, alphaData, 0)
); | 55 context->textureProvider()->createTexture(desc, false, alphaData, 0)
); |
| 40 if (!texture) { | 56 if (!texture) { |
| 41 if (!rt) { | 57 if (!rt) { |
| 42 ERRORF(reporter, "Could not create alpha texture."); | 58 ERRORF(reporter, "Could not create alpha texture."); |
| 43 } | 59 } |
| 44 continue; | 60 continue; |
| 45 } | 61 } |
| 46 | 62 |
| 47 // create a distinctive texture | 63 // create a distinctive texture |
| 48 for (int y = 0; y < Y_SIZE; ++y) { | 64 for (int y = 0; y < Y_SIZE; ++y) { |
| 49 for (int x = 0; x < X_SIZE; ++x) { | 65 for (int x = 0; x < X_SIZE; ++x) { |
| 50 alphaData[x][y] = y*X_SIZE+x; | 66 alphaData[y * X_SIZE + x] = y*X_SIZE+x; |
| 51 } | 67 } |
| 52 } | 68 } |
| 53 | 69 |
| 54 // upload the texture | 70 for (auto rowBytes : kRowBytes) { |
| 55 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, | 71 // upload the texture (do per-rowbytes iteration because we may over
write below). |
| 56 alphaData, 0); | 72 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, |
| 73 alphaData, 0); |
| 57 | 74 |
| 58 // clear readback to something non-zero so we can detect readback failur
es | 75 size_t nonZeroRowBytes = rowBytes ? rowBytes : X_SIZE; |
| 59 memset(readback, 0x1, X_SIZE * Y_SIZE); | 76 SkAutoTDeleteArray<uint8_t> readback(new uint8_t[nonZeroRowBytes * Y
_SIZE]); |
| 77 // clear readback to something non-zero so we can detect readback fa
ilures |
| 78 memset(readback.get(), 0x1, nonZeroRowBytes * Y_SIZE); |
| 60 | 79 |
| 61 // read the texture back | 80 // read the texture back |
| 62 texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, | 81 texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, |
| 63 readback, 0); | 82 readback.get(), rowBytes); |
| 64 | 83 |
| 65 // make sure the original & read back versions match | 84 // make sure the original & read back versions match |
| 66 match = true; | 85 SkString msg; |
| 86 msg.printf("rt:%d, rb:%zd", rt, rowBytes); |
| 87 validate_alpha_data(reporter, X_SIZE, Y_SIZE, readback.get(), nonZer
oRowBytes, |
| 88 alphaData, msg); |
| 67 | 89 |
| 68 for (int y = 0; y < Y_SIZE && match; ++y) { | 90 // Now try writing on the single channel texture (if we could create
as a RT). |
| 69 for (int x = 0; x < X_SIZE && match; ++x) { | 91 if (texture->asRenderTarget()) { |
| 70 if (alphaData[x][y] != readback[x][y]) { | 92 SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); |
| 71 SkDebugf("Failed alpha readback. Expected: 0x%02x, " | 93 SkAutoTUnref<SkBaseDevice> device(SkGpuDevice::Create( |
| 72 "Got: 0x%02x at (%d,%d), rt: %d", alphaData[x][y],
readback[x][y], x, | 94 texture->asRenderTarget(), &props, SkGpuDevice::kUninit_Init
Contents)); |
| 73 y, rt); | 95 SkCanvas canvas(device); |
| 74 match = false; | |
| 75 } | |
| 76 } | |
| 77 } | |
| 78 | 96 |
| 79 // Now try writing on the single channel texture (if we could create as
a RT). | 97 SkPaint paint; |
| 80 if (texture->asRenderTarget()) { | |
| 81 SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); | |
| 82 SkAutoTUnref<SkBaseDevice> device(SkGpuDevice::Create( | |
| 83 texture->asRenderTarget(), &props, SkGpuDevice::kUninit_InitCont
ents)); | |
| 84 SkCanvas canvas(device); | |
| 85 | 98 |
| 86 SkPaint paint; | 99 const SkRect rect = SkRect::MakeLTRB(-10, -10, X_SIZE + 10, Y_SI
ZE + 10); |
| 87 | 100 |
| 88 const SkRect rect = SkRect::MakeLTRB(-10, -10, X_SIZE + 10, Y_SIZE +
10); | 101 paint.setColor(SK_ColorWHITE); |
| 89 | 102 |
| 90 paint.setColor(SK_ColorWHITE); | 103 canvas.drawRect(rect, paint); |
| 91 | 104 |
| 92 canvas.drawRect(rect, paint); | 105 memset(readback.get(), 0x1, nonZeroRowBytes * Y_SIZE); |
| 106 texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfi
g, readback.get(), |
| 107 rowBytes); |
| 93 | 108 |
| 94 texture->readPixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, r
eadback, 0); | 109 match = true; |
| 95 | 110 for (int y = 0; y < Y_SIZE && match; ++y) { |
| 96 match = true; | 111 for (int x = 0; x < X_SIZE && match; ++x) { |
| 97 | 112 uint8_t rbValue = readback.get()[y * nonZeroRowBytes + x
]; |
| 98 for (int y = 0; y < Y_SIZE && match; ++y) { | 113 if (0xFF != rbValue) { |
| 99 for (int x = 0; x < X_SIZE && match; ++x) { | 114 ERRORF(reporter, |
| 100 if (0xFF != readback[x][y]) { | 115 "Failed alpha readback after clear. Expected:
0xFF, Got: 0x%02x" |
| 101 ERRORF(reporter, | 116 " at (%d,%d), rb:%zd", rbValue, x, y, rowByte
s); |
| 102 "Failed alpha readback after clear. Expected: 0xF
F, Got: 0x%02x at " | 117 match = false; |
| 103 "(%d,%d)", readback[x][y], x, y); | 118 } |
| 104 match = false; | |
| 105 } | 119 } |
| 106 } | 120 } |
| 107 } | 121 } |
| 108 } | 122 } |
| 109 } | 123 } |
| 110 | 124 |
| 111 static const GrPixelConfig kRGBAConfigs[] { | 125 static const GrPixelConfig kRGBAConfigs[] { |
| 112 kRGBA_8888_GrPixelConfig, | 126 kRGBA_8888_GrPixelConfig, |
| 113 kBGRA_8888_GrPixelConfig, | 127 kBGRA_8888_GrPixelConfig, |
| 114 kSRGBA_8888_GrPixelConfig | 128 kSRGBA_8888_GrPixelConfig |
| 115 }; | 129 }; |
| 116 | 130 |
| 131 for (int y = 0; y < Y_SIZE; ++y) { |
| 132 for (int x = 0; x < X_SIZE; ++x) { |
| 133 alphaData[y * X_SIZE + x] = y*X_SIZE+x; |
| 134 } |
| 135 } |
| 136 |
| 117 // Attempt to read back just alpha from a RGBA/BGRA texture. Once with a tex
ture-only src and | 137 // Attempt to read back just alpha from a RGBA/BGRA texture. Once with a tex
ture-only src and |
| 118 // once with a render target. | 138 // once with a render target. |
| 119 for (auto cfg : kRGBAConfigs) { | 139 for (auto cfg : kRGBAConfigs) { |
| 120 for (int rt = 0; rt < 2; ++rt) { | 140 for (int rt = 0; rt < 2; ++rt) { |
| 121 GrSurfaceDesc desc; | 141 GrSurfaceDesc desc; |
| 122 desc.fFlags = rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurface
Flags; | 142 desc.fFlags = rt ? kRenderTarget_GrSurfaceFlag : kNone_GrSurface
Flags; |
| 123 desc.fConfig = cfg; | 143 desc.fConfig = cfg; |
| 124 desc.fWidth = X_SIZE; | 144 desc.fWidth = X_SIZE; |
| 125 desc.fHeight = Y_SIZE; | 145 desc.fHeight = Y_SIZE; |
| 126 | 146 |
| 127 uint32_t rgbaData[X_SIZE][Y_SIZE]; | 147 uint32_t rgbaData[X_SIZE * Y_SIZE]; |
| 128 // Make the alpha channel of the rgba texture come from alphaData. | 148 // Make the alpha channel of the rgba texture come from alphaData. |
| 129 for (int y = 0; y < Y_SIZE; ++y) { | 149 for (int y = 0; y < Y_SIZE; ++y) { |
| 130 for (int x = 0; x < X_SIZE; ++x) { | 150 for (int x = 0; x < X_SIZE; ++x) { |
| 131 rgbaData[x][y] = GrColorPackRGBA(6, 7, 8, alphaData[x][y]); | 151 rgbaData[y * X_SIZE + x] = GrColorPackRGBA(6, 7, 8, alphaDat
a[y * X_SIZE + x]); |
| 132 } | 152 } |
| 133 } | 153 } |
| 134 SkAutoTUnref<GrTexture> texture( | 154 SkAutoTUnref<GrTexture> texture( |
| 135 context->textureProvider()->createTexture(desc, false, rgbaData,
0)); | 155 context->textureProvider()->createTexture(desc, false, rgbaData,
0)); |
| 136 if (!texture) { | 156 if (!texture) { |
| 137 // We always expect to be able to create a RGBA texture | 157 // We always expect to be able to create a RGBA texture |
| 138 if (!rt && kRGBA_8888_GrPixelConfig == desc.fConfig) { | 158 if (!rt && kRGBA_8888_GrPixelConfig == desc.fConfig) { |
| 139 ERRORF(reporter, "Failed to create RGBA texture."); | 159 ERRORF(reporter, "Failed to create RGBA texture."); |
| 140 } | 160 } |
| 141 continue; | 161 continue; |
| 142 } | 162 } |
| 143 | 163 |
| 144 // clear readback to something non-zero so we can detect readback fa
ilures | 164 for (auto rowBytes : kRowBytes) { |
| 145 memset(readback, 0x0, X_SIZE * Y_SIZE); | 165 size_t nonZeroRowBytes = rowBytes ? rowBytes : X_SIZE; |
| 146 | 166 |
| 147 // read the texture back | 167 SkAutoTDeleteArray<uint8_t> readback(new uint8_t[nonZeroRowBytes
* Y_SIZE]); |
| 148 texture->readPixels(0, 0, desc.fWidth, desc.fHeight, kAlpha_8_GrPixe
lConfig, readback, | 168 // Clear so we don't accidentally see values from previous itera
tion. |
| 149 0); | 169 memset(readback.get(), 0x0, nonZeroRowBytes * Y_SIZE); |
| 150 | 170 |
| 151 match = true; | 171 // read the texture back |
| 172 texture->readPixels(0, 0, desc.fWidth, desc.fHeight, kAlpha_8_Gr
PixelConfig, |
| 173 readback.get(), rowBytes); |
| 152 | 174 |
| 153 for (int y = 0; y < Y_SIZE && match; ++y) { | 175 // make sure the original & read back versions match |
| 154 for (int x = 0; x < X_SIZE && match; ++x) { | 176 SkString msg; |
| 155 if (alphaData[x][y] != readback[x][y]) { | 177 msg.printf("rt:%d, rb:%zd", rt, rowBytes); |
| 156 texture->readPixels(0, 0, desc.fWidth, desc.fHeight, | 178 validate_alpha_data(reporter, X_SIZE, Y_SIZE, readback.get(), no
nZeroRowBytes, |
| 157 kAlpha_8_GrPixelConfig, readback, 0)
; | 179 alphaData, msg); |
| 158 ERRORF(reporter, | |
| 159 "Failed alpha readback from cfg %d. Expected: 0x%
02x, Got: 0x%02x at" | |
| 160 " (%d,%d), rt:%d", desc.fConfig, alphaData[x][y],
readback[x][y], x, | |
| 161 y, rt); | |
| 162 match = false; | |
| 163 } | |
| 164 } | |
| 165 } | 180 } |
| 166 } | 181 } |
| 167 } | 182 } |
| 168 } | 183 } |
| 169 | 184 |
| 170 #endif | 185 #endif |
| OLD | NEW |