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 |