1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <EGL/egl.h>
18 #include <EGL/eglext.h>
19 #include <GLES2/gl2.h>
20 #include <GLES2/gl2ext.h>
21 #include <GLES3/gl32.h>
22
23 #include <array>
24 #include <cmath>
25 #include <iterator>
26 #include <set>
27 #include <sstream>
28 #include <string>
29 #include <vector>
30
31 #include <android/hardware_buffer.h>
32 #include <android/log.h>
33 #include <gtest/gtest.h>
34
35 #define NO_ERROR 0
36 #define LOG_TAG "AHBGLTest"
37 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
38
39 namespace android {
40 namespace {
41
42 // The 'stride' field is ignored by AHardwareBuffer_allocate, so we can use it
43 // to pass these flags.
44 enum TestFlags {
45 kGlFormat = 0x1, // The 'format' field specifies a GL format.
46 kUseSrgb = 0x2, // Whether to use the sRGB transfer function.
47 kExplicitYuvSampling = 0x4, // Whether to do explicit YUV conversion sampling,
48 // if false, GL will do conversions implicitly.
49 };
50
51 // Conversion from YUV to RGB used by GPU. This assumes BT.601 (partial) format.
52 // The matrix M is multiplied in (Y,U,V) = M * (R, G, B, 1) to obtain the final YUV value s.
53 // TODO(b/123041714): Assumes ITU_601 color space is used. Can we count on this? Spec is unclear for
54 // glReadPixels YUV -> RGB conversion.
55 const double kYuvToRgb[] = {
56 0.25678823529411765, 0.50412941176470580, 0.09790588235294118, 16.00,
57 -0.14822352941176470, -0.29099215686274510, 0.43921568627450980, 128.0,
58 0.43921568627450980, -0.36778823529411764, -0.07142745098039215, 128.0
59 };
60
61 #define FORMAT_CASE(x) case AHARDWAREBUFFER_FORMAT_##x: return #x; break
62 #define GL_FORMAT_CASE(x) case x: return #x; break;
AHBFormatAsString(int32_t format)63 const char* AHBFormatAsString(int32_t format) {
64 switch (format) {
65 FORMAT_CASE(R8G8B8A8_UNORM);
66 FORMAT_CASE(R8G8B8X8_UNORM);
67 FORMAT_CASE(R8G8B8_UNORM);
68 FORMAT_CASE(R5G6B5_UNORM);
69 FORMAT_CASE(R16G16B16A16_FLOAT);
70 FORMAT_CASE(R10G10B10A2_UNORM);
71 FORMAT_CASE(BLOB);
72 FORMAT_CASE(D16_UNORM);
73 FORMAT_CASE(D24_UNORM);
74 FORMAT_CASE(D24_UNORM_S8_UINT);
75 FORMAT_CASE(D32_FLOAT);
76 FORMAT_CASE(D32_FLOAT_S8_UINT);
77 FORMAT_CASE(S8_UINT);
78 FORMAT_CASE(Y8Cb8Cr8_420);
79 FORMAT_CASE(R8_UNORM);
80 FORMAT_CASE(R16_UINT);
81 FORMAT_CASE(R16G16_UINT);
82 GL_FORMAT_CASE(GL_RGB8);
83 GL_FORMAT_CASE(GL_RGBA8);
84 GL_FORMAT_CASE(GL_RGB565);
85 GL_FORMAT_CASE(GL_SRGB8_ALPHA8);
86 GL_FORMAT_CASE(GL_RGBA16F);
87 GL_FORMAT_CASE(GL_RGB10_A2);
88 GL_FORMAT_CASE(GL_DEPTH_COMPONENT16);
89 GL_FORMAT_CASE(GL_DEPTH24_STENCIL8);
90 GL_FORMAT_CASE(GL_STENCIL_INDEX8);
91 GL_FORMAT_CASE(GL_R8);
92 GL_FORMAT_CASE(GL_R16UI);
93 GL_FORMAT_CASE(GL_RG16UI);
94 }
95 return "";
96 }
97
GetTestName(const::testing::TestParamInfo<AHardwareBuffer_Desc> & info)98 std::string GetTestName(const ::testing::TestParamInfo<AHardwareBuffer_Desc>& info) {
99 std::ostringstream name;
100 const char* format_string = AHBFormatAsString(info.param.format);
101 if (strlen(format_string) == 0) {
102 name << info.index;
103 } else {
104 name << format_string;
105 if (info.param.stride & kUseSrgb) {
106 name << "_sRGB";
107 }
108 if (info.param.stride & kExplicitYuvSampling) {
109 name << "_explicitYuvSampling";
110 }
111 }
112 return name.str();
113 }
114
115 union IntFloat {
116 uint32_t i;
117 float f;
118 };
119
120 // Copied from android.util.Half
121 // Used for reading directly from half-float buffers
FloatFromHalf(uint16_t bits)122 float FloatFromHalf(uint16_t bits) {
123 uint32_t s = bits & 0x8000;
124 uint32_t e = (bits & 0x7C00) >> 10;
125 uint32_t m = bits & 0x3FF;
126 uint32_t outE = 0;
127 uint32_t outM = 0;
128 if (e == 0) { // Denormal or 0
129 if (m != 0) {
130 // Convert denorm fp16 into normalized fp32
131 IntFloat uif;
132 uif.i = (126 << 23);
133 float denormal = uif.f;
134 uif.i += m;
135 float o = uif.f - denormal;
136 return s == 0 ? o : -o;
137 }
138 } else {
139 outM = m << 13;
140 if (e == 0x1f) { // Infinite or NaN
141 outE = 0xff;
142 } else {
143 outE = e - 15 + 127;
144 }
145 }
146 IntFloat result;
147 result.i = (s << 16) | (outE << 23) | outM;
148 return result.f;
149 }
150
151 // Copied from android.util.Half
152 // Used for writing directly into half-float buffers.
HalfFromFloat(float value)153 uint16_t HalfFromFloat(float value) {
154 uint32_t bits = *reinterpret_cast<uint32_t*>(&value); // convert to int bits
155 int32_t s = (bits >> 31);
156 int32_t e = (bits >> 23) & 0xFF;
157 int32_t m = bits & 0x7FFFFF;
158
159 int32_t outE = 0;
160 int32_t outM = 0;
161
162 if (e == 0xff) { // Infinite or NaN
163 outE = 0x1f;
164 outM = m != 0 ? 0x200 : 0;
165 } else {
166 e = e - 127 + 15;
167 if (e >= 0x1f) { // Overflow
168 outE = 0x31;
169 } else if (e <= 0) { // Underflow
170 if (e < -10) {
171 // The absolute fp32 value is less than MIN_VALUE, flush to +/-0
172 } else {
173 // The fp32 value is a normalized float less than MIN_NORMAL,
174 // we convert to a denorm fp16
175 m = (m | 0x800000) >> (1 - e);
176 if ((m & 0x1000) != 0) m += 0x2000;
177 outM = m >> 13;
178 }
179 } else {
180 outE = e;
181 outM = m >> 13;
182 if ((m & 0x1000) != 0) {
183 // Round to nearest "0.5" up
184 int out = (outE << 10) | outM;
185 out++;
186 return static_cast<uint16_t>(out | (s << 15));
187 }
188 }
189 }
190 return static_cast<uint16_t>((s << 15) | (outE << 10) | outM);
191 }
192
193 // Utility function to ensure converted values are clamped to [0...255].
ClampToUInt8(float value)194 uint8_t ClampToUInt8(float value) {
195 return static_cast<uint8_t>(value <= 0.0 ? 0 : (value >= 255.0 ? 255 : value));
196 }
197
MipLevelCount(uint32_t width,uint32_t height)198 int MipLevelCount(uint32_t width, uint32_t height) {
199 return 1 + static_cast<int>(std::floor(std::log2(static_cast<float>(std::max(width, height)))));
200 }
201
RoundUpToPowerOf2(uint32_t value)202 uint32_t RoundUpToPowerOf2(uint32_t value) {
203 return value == 0u ? value : 1u << (32 - __builtin_clz(value - 1));
204 }
205
206 // Returns true only if the format has a dedicated alpha channel
FormatHasAlpha(uint32_t format)207 bool FormatHasAlpha(uint32_t format) {
208 switch (format) {
209 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
210 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
211 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
212 // This may look scary, but fortunately AHardwareBuffer formats and GL pixel formats
213 // do not overlap.
214 case GL_RGBA8:
215 case GL_RGB10_A2:
216 case GL_RGBA16F:
217 case GL_SRGB8_ALPHA8:
218 return true;
219 default: return false;
220 }
221 }
222
223 // Returns true only if the format has its components specified in some floating point format.
FormatIsFloat(uint32_t format)224 bool FormatIsFloat(uint32_t format) {
225 return format == AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT || format == GL_RGBA16F;
226 }
227
228 // Returns true only if the format is a YUV format.
FormatIsYuv(uint32_t format)229 bool FormatIsYuv(uint32_t format) {
230 // Update with more YUV cases here if more formats become available
231 return format == AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420;
232 }
233
UploadData(const AHardwareBuffer_Desc & desc,GLenum format,GLenum type,const void * data)234 void UploadData(const AHardwareBuffer_Desc& desc, GLenum format, GLenum type, const void* data) {
235 if (desc.layers <= 1) {
236 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, desc.width, desc.height, format, type, data);
237 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "glTexSubImage2D failed";
238 } else {
239 for (uint32_t layer = 0; layer < desc.layers; ++layer) {
240 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, desc.width, desc.height, 1,
241 format, type, data);
242 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "glTexSubImage3D failed";
243 }
244 }
245 }
246
247 // Uploads opaque red to the currently bound texture.
UploadRedPixels(const AHardwareBuffer_Desc & desc)248 void UploadRedPixels(const AHardwareBuffer_Desc& desc) {
249 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
250 const bool use_srgb = desc.stride & kUseSrgb;
251 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
252 switch (desc.format) {
253 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
254 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
255 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
256 case GL_RGB565:
257 case GL_RGB8: {
258 // GL_RGB565 supports uploading GL_UNSIGNED_BYTE data.
259 const int size = desc.width * desc.height * 3;
260 std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
261 for (int i = 0; i < size; i += 3) {
262 pixels[i] = use_srgb ? 188 : 255;
263 pixels[i + 1] = 0;
264 pixels[i + 2] = 0;
265 }
266 UploadData(desc, GL_RGB, GL_UNSIGNED_BYTE, pixels.get());
267 break;
268 }
269 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
270 case GL_RGBA8:
271 case GL_SRGB8_ALPHA8: {
272 const int size = desc.width * desc.height * 4;
273 std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
274 for (int i = 0; i < size; i += 4) {
275 pixels[i] = use_srgb ? 188 : 255;
276 pixels[i + 1] = 0;
277 pixels[i + 2] = 0;
278 pixels[i + 3] = use_srgb ? 128 : 255;
279 }
280 UploadData(desc, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
281 break;
282 }
283 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
284 case GL_RGBA16F: {
285 const int size = desc.width * desc.height * 4;
286 std::unique_ptr<float[]> pixels(new float[size]);
287 for (int i = 0; i < size; i += 4) {
288 pixels[i] = 1.f;
289 pixels[i + 1] = 0.f;
290 pixels[i + 2] = 0.f;
291 pixels[i + 3] = 1.f;
292 }
293 UploadData(desc, GL_RGBA, GL_FLOAT, pixels.get());
294 break;
295 }
296 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
297 case GL_RGB10_A2: {
298 const int size = desc.width * desc.height;
299 std::unique_ptr<uint32_t[]> pixels(new uint32_t[size]);
300 for (int i = 0; i < size; ++i) {
301 // Opaque red is top 2 bits and bottom 10 bits set.
302 pixels[i] = 0xc00003ff;
303 }
304 UploadData(desc, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV_EXT, pixels.get());
305 break;
306 }
307 default: FAIL() << "Unrecognized AHardwareBuffer format"; break;
308 }
309 }
310
311 // A pre-defined list of colors that will be used for testing
312 enum GoldenColor {
313 kZero, // all zero, i.e., transparent black
314 kBlack, // opaque black
315 kWhite, // opaque white
316 kRed, // opaque red
317 kGreen, // opaque green
318 kBlue, // opaque blue
319 kRed50, // 50% premultiplied red, i.e., (0.5, 0, 0, 0.5)
320 kRed50Srgb, // 50% premultiplied red under sRGB transfer function
321 kRed50Alpha100, // Opaque 50% red
322 };
323
324 // A golden color at a specified position (given in pixel coordinates)
325 struct GoldenPixel {
326 int x;
327 int y;
328 GoldenColor color;
329 };
330
331 // Compares a golden pixel against an actual pixel given the 4 color values. The values must
332 // match exactly.
333 template <typename T>
CheckGoldenPixel(int x,int y,const std::array<T,4> & golden,const std::array<T,4> & actual)334 void CheckGoldenPixel(int x, int y, const std::array<T, 4>& golden,
335 const std::array<T, 4>& actual) {
336 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
337 EXPECT_EQ(golden, actual) << "Pixel doesn't match at X=" << x << ", Y=" << y;
338 }
339
340 // Compares an actual pixel against a range of pixel values specified by a minimum and maximum
341 // 4-component pixel value.
342 template <typename T>
CheckGoldenPixel(int x,int y,const std::array<T,4> & minimum,const std::array<T,4> & maximum,const std::array<T,4> & actual)343 void CheckGoldenPixel(int x, int y, const std::array<T, 4>& minimum,
344 const std::array<T, 4>& maximum, const std::array<T, 4>& actual) {
345 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
346 bool in_range = true;
347 for (int i = 0; i < 4; ++i) {
348 if (actual[i] < minimum[i] || actual[i] > maximum[i]) {
349 in_range = false;
350 break;
351 }
352 }
353 // Prefix with '+' so that uint8_t values are printed out as integers
354 EXPECT_TRUE(in_range) << "Pixel out of acceptable range at X=" << x << ", Y=" << y
355 << "; actual value: {" << +actual[0] << ", " << +actual[1] << ", "
356 << +actual[2] << ", " << +actual[3]
357 << "}, minimum: {" << +minimum[0] << ", " << +minimum[1] << ", "
358 << +minimum[2] << ", " << +minimum[3]
359 << "}, maximum: {" << +maximum[0] << ", " << +maximum[1] << ", "
360 << +maximum[2] << ", " << +maximum[3]
361 << "}";
362 }
363
364 // Given a golden color, format, and maximum allowed error, returns a 4-component pixel (as well as
365 // a maximum where it makes sense). Returns true, if the golden_max_out parameter was set, and
366 // the return values indicate a range.
GetGoldenColor(const GoldenColor & golden,uint32_t format,int32_t max_err,std::array<uint8_t,4> * golden_pixel_out,std::array<uint8_t,4> * golden_max_out)367 bool GetGoldenColor(const GoldenColor& golden, uint32_t format, int32_t max_err,
368 std::array<uint8_t, 4>* golden_pixel_out,
369 std::array<uint8_t, 4>* golden_max_out) {
370 bool use_range = false;
371 // Adjust color values.
372 std::array<uint8_t, 4>& golden_pixel = *golden_pixel_out;
373 std::array<uint8_t, 4>& golden_max = *golden_max_out;
374 golden_pixel[0] = golden_pixel[1] = golden_pixel[2] = 0;
375 golden_max[0] = golden_max[1] = golden_max[2] = 0;
376 golden_pixel[3] = 255;
377 golden_max[3] = 255;
378 switch (golden) {
379 case kRed: golden_pixel[0] = 255; break;
380 case kRed50:
381 case kRed50Alpha100:
382 use_range = true;
383 golden_pixel[0] = 127;
384 golden_max[0] = 128;
385 break;
386 case kRed50Srgb:
387 use_range = true;
388 golden_pixel[0] = 187;
389 golden_max[0] = 188;
390 break;
391 case kGreen: golden_pixel[1] = 255; break;
392 case kBlue: golden_pixel[2] = 255; break;
393 case kZero: if (FormatHasAlpha(format)) golden_pixel[3] = 0; break;
394 case kWhite: golden_pixel[0] = 255; golden_pixel[1] = 255; golden_pixel[2] = 255; break;
395 case kBlack: break;
396 default:
397 ADD_FAILURE() << "Unrecognized golden pixel color";
398 return false;
399 }
400 // Adjust alpha.
401 if (golden == kRed50 || golden == kRed50Srgb) {
402 if (format == GL_RGB10_A2 || format == AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM) {
403 golden_pixel[3] = 85;
404 golden_max[3] = 170;
405 } else if (FormatHasAlpha(format)) {
406 golden_pixel[3] = 127;
407 golden_max[3] = 128;
408 }
409 }
410 // Adjust color range for RGB565.
411 if ((golden == kRed50 || golden == kRed50Alpha100) &&
412 (format == GL_RGB565 || format == AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM)) {
413 golden_pixel[0] = 123;
414 golden_max[0] = 132;
415 }
416 // Convert to YUV if this is a YUV format
417 if (FormatIsYuv(format)) {
418 const uint8_t r = golden_pixel[0];
419 const uint8_t g = golden_pixel[1];
420 const uint8_t b = golden_pixel[2];
421 const float y = kYuvToRgb[0] * r + kYuvToRgb[1] * g + kYuvToRgb[2] * b + kYuvToRgb[3];
422 const float u = kYuvToRgb[4] * r + kYuvToRgb[5] * g + kYuvToRgb[6] * b + kYuvToRgb[7];
423 const float v = kYuvToRgb[8] * r + kYuvToRgb[9] * g + kYuvToRgb[10] * b + kYuvToRgb[11];
424 golden_pixel[0] = ClampToUInt8(y);
425 golden_pixel[1] = ClampToUInt8(u);
426 golden_pixel[2] = ClampToUInt8(v);
427 }
428 // Apply error bounds
429 if (max_err != 0) {
430 for (int i = 0; i < 4; ++i) {
431 golden_pixel[i] = ClampToUInt8(golden_pixel[i] - max_err);
432 golden_max[i] = ClampToUInt8(golden_pixel[i] + max_err);
433 }
434 use_range = true;
435 }
436 return use_range;
437 }
438
439 // Get a golden color for range-less values.
GetGoldenColor(const GoldenColor & golden,uint32_t format,std::array<uint8_t,4> * golden_pixel_out)440 void GetGoldenColor(const GoldenColor& golden, uint32_t format,
441 std::array<uint8_t, 4>* golden_pixel_out) {
442 std::array<uint8_t, 4> ignore;
443 GetGoldenColor(golden, format, 0, golden_pixel_out, &ignore);
444 }
445
446 // Get a golden color for floating point values.
GetGoldenColor(const GoldenColor & golden,std::array<float,4> * golden_pixel_out)447 void GetGoldenColor(const GoldenColor& golden, std::array<float, 4>* golden_pixel_out) {
448 std::array<float, 4>& golden_pixel = *golden_pixel_out;
449 golden_pixel[0] = golden_pixel[1] = golden_pixel[2] = 0.f;
450 golden_pixel[3] = 1.f;
451 switch (golden) {
452 case kRed: golden_pixel[0] = 1.f; break;
453 case kRed50: golden_pixel[0] = 0.5f; golden_pixel[3] = 0.5f; break;
454 case kGreen: golden_pixel[1] = 1.f; break;
455 case kBlue: golden_pixel[2] = 1.f; break;
456 case kZero: golden_pixel[3] = 0.f; break;
457 case kWhite: golden_pixel[0] = 1.f; golden_pixel[1] = 1.f; golden_pixel[2] = 1.f; break;
458 case kBlack: break;
459 default: FAIL() << "Unrecognized golden pixel color";
460 }
461 }
462
463 // Checks a pixel against a golden pixel of the specified format with the given error bounds.
CheckGoldenPixel(const GoldenPixel & golden,const std::array<uint8_t,4> & pixel,uint32_t format,int32_t max_err)464 void CheckGoldenPixel(const GoldenPixel& golden, const std::array<uint8_t, 4>& pixel,
465 uint32_t format, int32_t max_err) {
466 std::array<uint8_t, 4> golden_pixel;
467 std::array<uint8_t, 4> golden_max;
468 if (GetGoldenColor(golden.color, format, max_err, &golden_pixel, &golden_max)) {
469 CheckGoldenPixel(golden.x, golden.y, golden_pixel, golden_max, pixel);
470 } else {
471 CheckGoldenPixel(golden.x, golden.y, golden_pixel, pixel);
472 }
473 }
474
475 // Checks a pixel against a golden pixel of the specified format with no room for error.
CheckGoldenPixel(const GoldenPixel & golden,const std::array<uint8_t,4> & pixel,uint32_t format)476 void CheckGoldenPixel(const GoldenPixel& golden, const std::array<uint8_t, 4>& pixel,
477 uint32_t format) {
478 CheckGoldenPixel(golden, pixel, format, 0);
479 }
480
481 // Checks a floating point pixel against a golden pixel.
CheckGoldenPixel(const GoldenPixel & golden,const std::array<float,4> & pixel)482 void CheckGoldenPixel(const GoldenPixel& golden, const std::array<float, 4>& pixel) {
483 std::array<float, 4> golden_pixel;
484 GetGoldenColor(golden.color, &golden_pixel);
485 CheckGoldenPixel(golden.x, golden.y, golden_pixel, pixel);
486 }
487
488 // Using glReadPixels, reads out the individual pixel values of each golden pixel location, and
489 // compares each against the golden color.
CheckGoldenPixels(const std::vector<GoldenPixel> & goldens,uint32_t format,int16_t max_err=0)490 void CheckGoldenPixels(const std::vector<GoldenPixel>& goldens,
491 uint32_t format,
492 int16_t max_err = 0) {
493 // We currently do not test any float formats that don't have alpha.
494 EXPECT_TRUE(FormatIsFloat(format) ? FormatHasAlpha(format) : true);
495 if (FormatIsYuv(format)) {
496 format = GL_RGB8; // YUV formats are read out as RGB for glReadPixels
497 max_err = 255; // Conversion method is unknown, so we cannot assume
498 // anything about the actual colors
499 }
500 glPixelStorei(GL_PACK_ALIGNMENT, 1);
501 // In OpenGL, Y axis grows up, so bottom = minimum Y coordinate.
502 int bottom = INT_MAX, left = INT_MAX, right = 0, top = 0;
503 for (const GoldenPixel& golden : goldens) {
504 left = std::min(left, golden.x);
505 right = std::max(right, golden.x);
506 bottom = std::min(bottom, golden.y);
507 top = std::max(top, golden.y);
508 if (FormatIsFloat(format)) {
509 std::array<float, 4> pixel = {0.5f, 0.5f, 0.5f, 0.5f};
510 glReadPixels(golden.x, golden.y, 1, 1, GL_RGBA, GL_FLOAT, pixel.data());
511 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "Could not read pixel at " << golden.x << "," << golden.y;
512 CheckGoldenPixel(golden, pixel);
513 } else {
514 std::array<uint8_t, 4> pixel = {127, 127, 127, 127};
515 glReadPixels(golden.x, golden.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel.data());
516 CheckGoldenPixel(golden, pixel, format, max_err);
517 }
518 }
519 // Repeat the test, but read back all the necessary pixels in a single glReadPixels call.
520 const int width = right - left + 1;
521 const int height = top - bottom + 1;
522 if (FormatIsFloat(format)) {
523 std::unique_ptr<float[]> pixels(new float[width * height * 4]);
524 glReadPixels(left, bottom, width, height, GL_RGBA, GL_FLOAT, pixels.get());
525 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
526 for (const GoldenPixel& golden : goldens) {
527 float* pixel = pixels.get() + ((golden.y - bottom) * width + golden.x - left) * 4;
528 std::array<float, 4> pixel_array;
529 memcpy(pixel_array.data(), pixel, 4 * sizeof(float));
530 CheckGoldenPixel(golden, pixel_array);
531 }
532 } else {
533 std::unique_ptr<uint8_t[]> pixels(new uint8_t[width * height * 4]);
534 glReadPixels(left, bottom, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
535 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
536 for (const GoldenPixel& golden : goldens) {
537 uint8_t* pixel = pixels.get() + ((golden.y - bottom) * width + golden.x - left) * 4;
538 std::array<uint8_t, 4> pixel_array;
539 memcpy(pixel_array.data(), pixel, 4);
540 CheckGoldenPixel(golden, pixel_array, format, max_err);
541 }
542 }
543 }
544
545 // Using direct memory access by locking the buffer, accesses the individual pixel values of each
546 // golden pixel location, and compares each against the golden color. This variant works for RGBA
547 // layouts only.
CheckCpuGoldenPixelsRgba(const std::vector<GoldenPixel> & goldens,AHardwareBuffer * buffer,const AHardwareBuffer_Desc & desc)548 void CheckCpuGoldenPixelsRgba(const std::vector<GoldenPixel>& goldens,
549 AHardwareBuffer* buffer,
550 const AHardwareBuffer_Desc& desc) {
551 void* data = nullptr;
552 int result = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1, nullptr,
553 &data);
554 ASSERT_EQ(NO_ERROR, result) << "AHardwareBuffer_lock failed with error " << result;
555 for (const GoldenPixel& golden : goldens) {
556 ptrdiff_t row_offset = golden.y * desc.stride;
557 switch (desc.format) {
558 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
559 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: {
560 uint8_t* pixel = reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 4;
561 std::array<uint8_t, 4> pixel_to_check;
562 memcpy(pixel_to_check.data(), pixel, 4);
563 if (desc.format == AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM) {
564 pixel_to_check[3] = 255;
565 }
566 CheckGoldenPixel(golden, pixel_to_check, desc.format);
567 break;
568 }
569 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM: {
570 uint8_t* pixel = reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 3;
571 std::array<uint8_t, 4> pixel_to_check;
572 memcpy(pixel_to_check.data(), pixel, 3);
573 pixel_to_check[3] = 255;
574 CheckGoldenPixel(golden, pixel_to_check, desc.format);
575 break;
576 }
577 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: {
578 uint16_t* pixel = reinterpret_cast<uint16_t*>(
579 reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 2);
580 std::array<uint8_t, 4> pixel_to_check = {
581 static_cast<uint8_t>(((*pixel & 0xF800) >> 11) * (255./31.)),
582 static_cast<uint8_t>(((*pixel & 0x07E0) >> 5) * (255./63.)),
583 static_cast<uint8_t>((*pixel & 0x001F) * (255./31.)),
584 255,
585 };
586 CheckGoldenPixel(golden, pixel_to_check, desc.format);
587 break;
588 }
589 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT: {
590 uint16_t* pixel = reinterpret_cast<uint16_t*>(
591 reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 8);
592 std::array<float, 4> pixel_to_check;
593 for (int i = 0; i < 4; ++i) {
594 pixel_to_check[i] = FloatFromHalf(pixel[i]);
595 }
596 CheckGoldenPixel(golden, pixel_to_check);
597 break;
598 }
599 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: {
600 uint32_t* pixel = reinterpret_cast<uint32_t*>(
601 reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 4);
602 std::array<uint8_t, 4> pixel_to_check = {
603 static_cast<uint8_t>((*pixel & 0x000003FF) * (255./1023.)),
604 static_cast<uint8_t>(((*pixel & 0x000FFC00) >> 10) * (255./1023.)),
605 static_cast<uint8_t>(((*pixel & 0x3FF00000) >> 20) * (255./1023.)),
606 static_cast<uint8_t>(((*pixel & 0xC0000000) >> 30) * (255./3.)),
607 };
608 CheckGoldenPixel(golden, pixel_to_check, desc.format);
609 break;
610 }
611 default: FAIL() << "Unrecognized AHardwareBuffer format"; break;
612 }
613 }
614 AHardwareBuffer_unlock(buffer, nullptr);
615 }
616
617 // Using direct memory access by locking the buffer, accesses the individual pixel values of each
618 // golden pixel location, and compares each against the golden color. This variant works for YUV
619 // layouts only.
CheckCpuGoldenPixelsYuv(const std::vector<GoldenPixel> & goldens,AHardwareBuffer * buffer,const AHardwareBuffer_Desc & desc)620 void CheckCpuGoldenPixelsYuv(const std::vector<GoldenPixel>& goldens,
621 AHardwareBuffer* buffer,
622 const AHardwareBuffer_Desc& desc) {
623 AHardwareBuffer_Planes planes_info;
624 int result = AHardwareBuffer_lockPlanes(buffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1,
625 nullptr, &planes_info);
626 ASSERT_EQ(NO_ERROR, result) << "AHardwareBuffer_lock failed with error " << result;
627 for (const GoldenPixel& golden : goldens) {
628 switch (desc.format) {
629 case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: {
630 ASSERT_EQ(3U, planes_info.planeCount) << "Unexpected number of planes in YUV data: "
631 << planes_info.planeCount;
632 AHardwareBuffer_Plane* planes = planes_info.planes;
633 ptrdiff_t y_offset = golden.y * planes[0].rowStride
634 + golden.x * planes[0].pixelStride;
635 ptrdiff_t u_offset = (golden.y / 2) * planes[1].rowStride
636 + (golden.x / 2) * planes[1].pixelStride;
637 ptrdiff_t v_offset = (golden.y / 2) * planes[2].rowStride
638 + (golden.x / 2) * planes[2].pixelStride;
639 // Check colors in YUV space (which desc.format is)
640 std::array<uint8_t, 4> pixel_to_check = {
641 *(reinterpret_cast<uint8_t*>(planes[0].data) + y_offset),
642 *(reinterpret_cast<uint8_t*>(planes[1].data) + u_offset),
643 *(reinterpret_cast<uint8_t*>(planes[2].data) + v_offset),
644 255
645 };
646 CheckGoldenPixel(golden, pixel_to_check, desc.format);
647 }
648 break;
649 default: FAIL() << "Unrecognized AHardwareBuffer format"; break;
650 }
651 }
652 AHardwareBuffer_unlock(buffer, nullptr);
653 }
654
655 // Using direct memory access by locking the buffer, accesses the individual pixel values of each
656 // golden pixel location, and compares each against the golden color. This variant forwards to the
657 // appropriate RGBA or YUV variants.
CheckCpuGoldenPixels(const std::vector<GoldenPixel> & goldens,AHardwareBuffer * buffer)658 void CheckCpuGoldenPixels(const std::vector<GoldenPixel>& goldens,
659 AHardwareBuffer* buffer) {
660 AHardwareBuffer_Desc desc;
661 AHardwareBuffer_describe(buffer, &desc);
662 if (FormatIsYuv(desc.format)) {
663 CheckCpuGoldenPixelsYuv(goldens, buffer, desc);
664 } else {
665 CheckCpuGoldenPixelsRgba(goldens, buffer, desc);
666 }
667 }
668
669 // Draws the following checkerboard pattern using glScissor and glClear.
670 // The number after the color is the stencil value and the floating point number is the depth value.
671 // The pattern is asymmetric to detect coordinate system mixups.
672 // +-----+-----+ (W, H)
673 // | OR1 | OB2 |
674 // | 0.5 | 0.0 |
675 // +-----+-----+ Tb = transparent black
676 // | Tb0 | OG3 | OR = opaque red
677 // | 1.0 | 1.0 | OG = opaque green
678 // (0, 0) +-----+-----+ OB = opaque blue
679 //
DrawCheckerboard(int width,int height,uint32_t format)680 void DrawCheckerboard(int width, int height, uint32_t format) {
681 glEnable(GL_SCISSOR_TEST);
682 const GLbitfield all_bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
683 std::array<uint8_t, 4> color;
684
685 GetGoldenColor(kZero, format, &color);
686 glClearColor(color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
687 glClearDepthf(1.0f);
688 glClearStencil(0);
689 glScissor(0, 0, width, height);
690 glClear(all_bits);
691
692 GetGoldenColor(kRed, format, &color);
693 glClearColor(color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
694 glClearDepthf(0.5f);
695 glClearStencil(1);
696 glScissor(0, height / 2, width / 2, height / 2);
697 glClear(all_bits);
698
699 GetGoldenColor(kGreen, format, &color);
700 glClearColor(color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
701 glClearDepthf(1.0f);
702 glClearStencil(3);
703 glScissor(width / 2, 0, width / 2, height / 2);
704 glClear(all_bits);
705
706 GetGoldenColor(kBlue, format, &color);
707 glClearColor(color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
708 glClearDepthf(0.f);
709 glClearStencil(2);
710 glScissor(width / 2, height / 2, width / 2, height / 2);
711 glClear(all_bits);
712
713 glDisable(GL_SCISSOR_TEST);
714 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
715 }
716
717 // Using direct memory access, writes each specified golden pixel to the correct memory address
718 // inside the given buffer. This variant is compatible with RGBA color buffers only.
WriteGoldenPixelsRgba(AHardwareBuffer * buffer,const AHardwareBuffer_Desc & desc,const std::vector<GoldenPixel> & goldens)719 void WriteGoldenPixelsRgba(AHardwareBuffer* buffer,
720 const AHardwareBuffer_Desc& desc,
721 const std::vector<GoldenPixel>& goldens) {
722 void* data = nullptr;
723 int result = AHardwareBuffer_lock(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1, nullptr,
724 &data);
725 ASSERT_EQ(NO_ERROR, result) << "AHardwareBuffer_lock failed with error " << result;
726 std::array<uint8_t, 4> golden_color;
727 std::array<float, 4> golden_float;
728 for (const GoldenPixel& golden : goldens) {
729 ptrdiff_t row_offset = golden.y * desc.stride;
730 switch (desc.format) {
731 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
732 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: {
733 uint8_t* pixel = reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 4;
734 GetGoldenColor(golden.color, desc.format, &golden_color);
735 memcpy(pixel, golden_color.data(), 4);
736 break;
737 }
738 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM: {
739 uint8_t* pixel = reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 3;
740 GetGoldenColor(golden.color, desc.format, &golden_color);
741 memcpy(pixel, golden_color.data(), 3);
742 break;
743 }
744 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: {
745 uint16_t* pixel = reinterpret_cast<uint16_t*>(
746 reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 2);
747 GetGoldenColor(golden.color, desc.format, &golden_color);
748 uint16_t golden_565 =
749 static_cast<uint8_t>(golden_color[0] * (31./255.)) << 11
750 | static_cast<uint8_t>(golden_color[1] * (63./255.)) << 5
751 | static_cast<uint8_t>(golden_color[2] * (31./255.));
752 *pixel = golden_565;
753 break;
754 }
755 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT: {
756 uint16_t* pixel = reinterpret_cast<uint16_t*>(
757 reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 8);
758 GetGoldenColor(golden.color, &golden_float);
759 for (int i = 0; i < 4; ++i) {
760 pixel[i] = HalfFromFloat(golden_float[i]);
761 }
762 break;
763 }
764 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: {
765 uint32_t* pixel = reinterpret_cast<uint32_t*>(
766 reinterpret_cast<uint8_t*>(data) + (row_offset + golden.x) * 4);
767 GetGoldenColor(golden.color, desc.format, &golden_color);
768 uint32_t golden_10102 =
769 static_cast<uint16_t>(golden_color[0] * (1023./255.))
770 | static_cast<uint16_t>(golden_color[1] * (1023./255.)) << 10
771 | static_cast<uint16_t>(golden_color[2] * (1023./255.)) << 20
772 | static_cast<uint16_t>(golden_color[3] * (3./255.)) << 30;
773 *pixel = golden_10102;
774 break;
775 }
776 default: FAIL() << "Unrecognized AHardwareBuffer format"; break;
777 }
778 }
779 AHardwareBuffer_unlock(buffer, nullptr);
780 }
781
782 // Using direct memory access, writes each specified golden pixel to the correct memory address
783 // inside the given buffer. This variant is compatible with YUV color buffers only.
WriteGoldenPixelsYuv(AHardwareBuffer * buffer,const AHardwareBuffer_Desc & desc,const std::vector<GoldenPixel> & goldens)784 void WriteGoldenPixelsYuv(AHardwareBuffer* buffer,
785 const AHardwareBuffer_Desc& desc,
786 const std::vector<GoldenPixel>& goldens) {
787 AHardwareBuffer_Planes planes_info;
788 int result = AHardwareBuffer_lockPlanes(buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1,
789 nullptr, &planes_info);
790 ASSERT_EQ(NO_ERROR, result) << "AHardwareBuffer_lock failed with error " << result;
791 std::array<uint8_t, 4> golden_color;
792 for (const GoldenPixel& golden : goldens) {
793 switch (desc.format) {
794 case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: {
795 ASSERT_EQ(3U, planes_info.planeCount) << "Unexpected number of planes in YUV data: "
796 << planes_info.planeCount;
797 AHardwareBuffer_Plane* planes = planes_info.planes;
798
799 ptrdiff_t y_offset = golden.y * planes[0].rowStride
800 + golden.x * planes[0].pixelStride;
801 ptrdiff_t u_offset = (golden.y / 2) * planes[1].rowStride
802 + (golden.x / 2) * planes[1].pixelStride;
803 ptrdiff_t v_offset = (golden.y / 2) * planes[2].rowStride
804 + (golden.x / 2) * planes[2].pixelStride;
805
806 GetGoldenColor(golden.color, desc.format, &golden_color);
807 uint8_t* const y_ptr = reinterpret_cast<uint8_t*>(planes[0].data) + y_offset;
808 uint8_t* const u_ptr = reinterpret_cast<uint8_t*>(planes[1].data) + u_offset;
809 uint8_t* const v_ptr = reinterpret_cast<uint8_t*>(planes[2].data) + v_offset;
810 *y_ptr = golden_color[0];
811 *u_ptr = golden_color[1];
812 *v_ptr = golden_color[2];
813 }
814 break;
815 default: FAIL() << "Unrecognized AHardwareBuffer format"; break;
816 }
817 }
818 AHardwareBuffer_unlock(buffer, nullptr);
819 }
820
821 // Writes the following checkerboard pattern directly to a buffer.
822 // The pattern is asymmetric to detect coordinate system mixups.
823 // +-----+-----+ (W, H)
824 // | OR | OB |
825 // | | |
826 // +-----+-----+ Tb = transparent black
827 // | Tb | OG | OR = opaque red
828 // | | | OG = opaque green
829 // (0, 0) +-----+-----+ OB = opaque blue
830 //
WriteCheckerBoard(AHardwareBuffer * buffer)831 void WriteCheckerBoard(AHardwareBuffer* buffer) {
832 AHardwareBuffer_Desc desc;
833 AHardwareBuffer_describe(buffer, &desc);
834
835 // Write golden values in same manner as checkerboard on GPU
836 std::vector<GoldenPixel> goldens(desc.width * desc.height);
837 const uint32_t h2 = desc.height / 2;
838 const uint32_t w2 = desc.width / 2;
839 for (uint32_t y = h2; y < desc.height; ++y) {
840 for (uint32_t x = 0; x < w2; ++x) {
841 const uint32_t offset = y * desc.width + x;
842 goldens[offset].x = x;
843 goldens[offset].y = y;
844 goldens[offset].color = kRed;
845 }
846 }
847 for (uint32_t y = h2; y < desc.height; ++y) {
848 for (uint32_t x = w2; x < desc.width; ++x) {
849 const uint32_t offset = y * desc.width + x;
850 goldens[offset].x = x;
851 goldens[offset].y = y;
852 goldens[offset].color = kBlue;
853 }
854 }
855 for (uint32_t y = 0; y < h2; ++y) {
856 for (uint32_t x = 0; x < w2; ++x) {
857 const uint32_t offset = y * desc.width + x;
858 goldens[offset].x = x;
859 goldens[offset].y = y;
860 goldens[offset].color = kZero;
861 }
862 }
863 for (uint32_t y = 0; y < h2; ++y) {
864 for (uint32_t x = w2; x < desc.width; ++x) {
865 const uint32_t offset = y * desc.width + x;
866 goldens[offset].x = x;
867 goldens[offset].y = y;
868 goldens[offset].color = kGreen;
869 }
870 }
871
872 if (FormatIsYuv(desc.format)) {
873 WriteGoldenPixelsYuv(buffer, desc, goldens);
874 } else {
875 WriteGoldenPixelsRgba(buffer, desc, goldens);
876 }
877 }
878
879 const char* kVertexShader = R"glsl(#version 100
880 attribute vec2 aPosition;
881 attribute float aDepth;
882 uniform mediump float uScale;
883 varying mediump vec2 vTexCoords;
884 void main() {
885 vTexCoords = (vec2(1.0) + aPosition) * 0.5;
886 gl_Position.xy = aPosition * uScale;
887 gl_Position.z = aDepth;
888 gl_Position.w = 1.0;
889 }
890 )glsl";
891
892 const char* kTextureFragmentShader = R"glsl(#version 100
893 precision mediump float;
894 varying mediump vec2 vTexCoords;
895 uniform lowp sampler2D uTexture;
896 void main() {
897 gl_FragColor = texture2D(uTexture, vTexCoords);
898 }
899 )glsl";
900
901 const char* kExternalTextureFragmentShader = R"glsl(#version 100
902 #extension GL_OES_EGL_image_external : require
903 precision mediump float;
904 varying mediump vec2 vTexCoords;
905 uniform samplerExternalOES uTexture;
906 void main() {
907 gl_FragColor = texture2D(uTexture, vTexCoords);
908 }
909 )glsl";
910
911 const char* kYuvTextureFragmentShader = R"glsl(#version 300 es
912 #extension GL_EXT_YUV_target : require
913 precision mediump float;
914 uniform __samplerExternal2DY2YEXT uTexture;
915 in vec2 vTexCoords;
916 out vec4 outColor;
917 void main() {
918 vec3 srcYuv = texture(uTexture, vTexCoords).xyz;
919 outColor = vec4(yuv_2_rgb(srcYuv, itu_601), 1.0);
920 }
921 )glsl";
922
923 const char* kCubeMapFragmentShader = R"glsl(#version 100
924 precision mediump float;
925 varying mediump vec2 vTexCoords;
926 uniform lowp samplerCube uTexture;
927 uniform mediump vec3 uFaceVector;
928 void main() {
929 vec2 scaledTexCoords = (2.0 * vTexCoords) - vec2(1.0);
930 vec3 coords = uFaceVector;
931 if (uFaceVector.x > 0.0) {
932 coords.z = -scaledTexCoords.x;
933 coords.y = -scaledTexCoords.y;
934 }
935 if (uFaceVector.x < 0.0) {
936 coords.z = scaledTexCoords.x;
937 coords.y = -scaledTexCoords.y;
938 }
939 if (uFaceVector.y > 0.0) {
940 coords.x = scaledTexCoords.x;
941 coords.z = scaledTexCoords.y;
942 }
943 if (uFaceVector.y < 0.0) {
944 coords.x = scaledTexCoords.x;
945 coords.z = -scaledTexCoords.y;
946 }
947 if (uFaceVector.z > 0.0) {
948 coords.x = scaledTexCoords.x;
949 coords.y = -scaledTexCoords.y;
950 }
951 if (uFaceVector.z < 0.0) {
952 coords.x = -scaledTexCoords.x;
953 coords.y = -scaledTexCoords.y;
954 }
955 gl_FragColor = textureCube(uTexture, coords);
956 }
957 )glsl";
958
959 const char* kColorFragmentShader = R"glsl(#version 100
960 precision mediump float;
961 uniform lowp vec4 uColor;
962 void main() {
963 gl_FragColor = uColor;
964 }
965 )glsl";
966
967 const char* kVertexShaderEs3x = R"glsl(
968 in vec2 aPosition;
969 in float aDepth;
970 uniform mediump float uScale;
971 out mediump vec2 vTexCoords;
972 void main() {
973 vTexCoords = (vec2(1.0) + aPosition) * 0.5;
974 gl_Position.xy = aPosition * uScale;
975 gl_Position.z = aDepth;
976 gl_Position.w = 1.0;
977 }
978 )glsl";
979
980 const char* kSsboComputeShaderEs31 = R"glsl(#version 310 es
981 layout(local_size_x = 1) in;
982 layout(std430, binding=0) buffer Output {
983 uint data[];
984 } bOutput;
985 void main() {
986 bOutput.data[gl_GlobalInvocationID.x] =
987 gl_GlobalInvocationID.x * 3u;
988 }
989 )glsl";
990
991 const char* kArrayFragmentShaderEs30 = R"glsl(#version 300 es
992 precision mediump float;
993 in mediump vec2 vTexCoords;
994 uniform lowp sampler2DArray uTexture;
995 uniform mediump float uLayer;
996 out mediump vec4 color;
997 void main() {
998 color = texture(uTexture, vec3(vTexCoords, uLayer));
999 }
1000 )glsl";
1001
1002 const char* kCubeMapArrayFragmentShaderEs32 = R"glsl(#version 320 es
1003 precision mediump float;
1004 in mediump vec2 vTexCoords;
1005 uniform lowp samplerCubeArray uTexture;
1006 uniform mediump float uLayer;
1007 uniform mediump vec3 uFaceVector;
1008 out mediump vec4 color;
1009 void main() {
1010 vec2 scaledTexCoords = (2.0 * vTexCoords) - vec2(1.0);
1011 vec4 coords = vec4(uFaceVector, uLayer);
1012 if (uFaceVector.x > 0.0) {
1013 coords.z = -scaledTexCoords.x;
1014 coords.y = -scaledTexCoords.y;
1015 }
1016 if (uFaceVector.x < 0.0) {
1017 coords.z = scaledTexCoords.x;
1018 coords.y = -scaledTexCoords.y;
1019 }
1020 if (uFaceVector.y > 0.0) {
1021 coords.x = scaledTexCoords.x;
1022 coords.z = scaledTexCoords.y;
1023 }
1024 if (uFaceVector.y < 0.0) {
1025 coords.x = scaledTexCoords.x;
1026 coords.z = -scaledTexCoords.y;
1027 }
1028 if (uFaceVector.z > 0.0) {
1029 coords.x = scaledTexCoords.x;
1030 coords.y = -scaledTexCoords.y;
1031 }
1032 if (uFaceVector.z < 0.0) {
1033 coords.x = -scaledTexCoords.x;
1034 coords.y = -scaledTexCoords.y;
1035 }
1036 color = texture(uTexture, coords);
1037 }
1038 )glsl";
1039
1040 const char* kStencilFragmentShaderEs30 = R"glsl(#version 300 es
1041 precision mediump float;
1042 in mediump vec2 vTexCoords;
1043 uniform lowp usampler2D uTexture;
1044 out mediump vec4 color;
1045 void main() {
1046 uvec4 stencil = texture(uTexture, vTexCoords);
1047 color.r = stencil.x == 1u ? 1.0 : 0.0;
1048 color.g = stencil.x == 3u ? 1.0 : 0.0;
1049 color.b = stencil.x == 2u ? 1.0 : 0.0;
1050 color.a = stencil.x == 0u ? 0.0 : 1.0;
1051 }
1052 )glsl";
1053
1054 const char* kStencilArrayFragmentShaderEs30 = R"glsl(#version 300 es
1055 precision mediump float;
1056 in mediump vec2 vTexCoords;
1057 uniform lowp usampler2DArray uTexture;
1058 uniform mediump float uLayer;
1059 out mediump vec4 color;
1060 void main() {
1061 uvec4 stencil = texture(uTexture, vec3(vTexCoords, uLayer));
1062 color.r = stencil.x == 1u ? 1.0 : 0.0;
1063 color.g = stencil.x == 3u ? 1.0 : 0.0;
1064 color.b = stencil.x == 2u ? 1.0 : 0.0;
1065 color.a = stencil.x == 0u ? 0.0 : 1.0;
1066 }
1067 )glsl";
1068
GetTextureVertexShader(uint32_t format,uint32_t flags)1069 std::string GetTextureVertexShader(uint32_t format, uint32_t flags) {
1070 return FormatIsYuv(format) && (flags & kExplicitYuvSampling)
1071 ? std::string("#version 300 es") + kVertexShaderEs3x
1072 : kVertexShader;
1073 }
1074
GetTextureFragmentShader(uint32_t format,uint32_t flags)1075 std::string GetTextureFragmentShader(uint32_t format, uint32_t flags) {
1076 return FormatIsYuv(format)
1077 ? ((flags & kExplicitYuvSampling)
1078 ? kYuvTextureFragmentShader
1079 : kExternalTextureFragmentShader)
1080 : kTextureFragmentShader;
1081 }
1082
GetMaxExpectedColorError(uint32_t format,uint32_t flags)1083 uint32_t GetMaxExpectedColorError(uint32_t format, uint32_t flags) {
1084 // If format is YUV, and we have no explicit sampling, then we do not
1085 // know how the color will be converted (spec is not specific), and the
1086 // maximum error allows for any value. We do not want to abort the test
1087 // as we still want to ensure rendering and read-outs succeed.
1088 // If we use explicit sampling, then we know the conversion method
1089 // (BT.601), but account for some imprecision (2).
1090 // Otherwise, we do not allow any deviation from the expected value.
1091 return FormatIsYuv(format)
1092 ? ((flags & kExplicitYuvSampling) ? 2 : 255)
1093 : 0;
1094 }
1095
1096 // Interleaved X and Y coordinates for 2 triangles forming a quad with CCW
1097 // orientation.
1098 const float kQuadPositions[] = {
1099 -1.f, -1.f, 1.f, 1.f, -1.f, 1.f,
1100 -1.f, -1.f, 1.f, -1.f, 1.f, 1.f,
1101 };
1102 const GLsizei kQuadVertexCount = 6;
1103
1104 // Interleaved X, Y and Z coordinates for 4 triangles forming a "pyramid" as
1105 // seen from above. The center vertex has Z=1, while the edge vertices have Z=-1.
1106 // It looks like this:
1107 //
1108 // +---+ 1, 1
1109 // |\ /|
1110 // | x |
1111 // |/ \|
1112 // -1, -1 +---+
1113 const float kPyramidPositions[] = {
1114 -1.f, -1.f, -1.f, 0.f, 0.f, 1.f, -1.f, 1.f, -1.f,
1115 -1.f, 1.f, -1.f, 0.f, 0.f, 1.f, 1.f, 1.f, -1.f,
1116 1.f, 1.f, -1.f, 0.f, 0.f, 1.f, 1.f, -1.f, -1.f,
1117 1.f, -1.f, -1.f, 0.f, 0.f, 1.f, -1.f, -1.f, -1.f,
1118 };
1119 const GLsizei kPyramidVertexCount = 12;
1120
1121 } // namespace
1122
1123 class AHardwareBufferGLTest : public ::testing::TestWithParam<AHardwareBuffer_Desc> {
1124 public:
1125 enum AttachmentType {
1126 kNone,
1127 kBufferAsTexture,
1128 kBufferAsRenderbuffer,
1129 kRenderbuffer,
1130 };
1131
1132 void SetUp() override;
1133 virtual bool SetUpBuffer(const AHardwareBuffer_Desc& desc);
1134 void SetUpProgram(const std::string& vertex_source, const std::string& fragment_source,
1135 const float* mesh, float scale, int texture_unit = 0);
1136 void SetUpTexture(const AHardwareBuffer_Desc& desc, int unit);
1137 void SetUpBufferObject(uint32_t size, GLenum target, GLbitfield flags);
1138 void SetUpFramebuffer(int width, int height, int layer, AttachmentType color,
1139 AttachmentType depth = kNone, AttachmentType stencil = kNone,
1140 AttachmentType depth_stencil = kNone, int level = 0);
1141 void TearDown() override;
1142
MakeCurrent(int which)1143 void MakeCurrent(int which) {
1144 if (GetParam().stride & kGlFormat) return;
1145 mWhich = which;
1146 eglMakeCurrent(mDisplay, mSurface, mSurface, mContext[mWhich]);
1147 }
MakeCurrentNone()1148 void MakeCurrentNone() {
1149 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
1150 }
HasEGLExtension(const std::string & s)1151 bool HasEGLExtension(const std::string& s) {
1152 return mEGLExtensions.find(s) != mEGLExtensions.end();
1153 }
HasGLExtension(const std::string & s)1154 bool HasGLExtension(const std::string& s) {
1155 return mGLExtensions.find(s) != mGLExtensions.end();
1156 }
IsFormatColorRenderable(uint32_t format,bool use_srgb)1157 bool IsFormatColorRenderable(uint32_t format, bool use_srgb) {
1158 if (use_srgb) {
1159 // According to the spec, GL_SRGB8 is not color-renderable.
1160 return format == AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM || format == GL_SRGB8_ALPHA8;
1161 } else {
1162 if (format == GL_RGBA16F || format == AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT) {
1163 return mGLVersion >= 32 || HasGLExtension("GL_EXT_color_buffer_float");
1164 }
1165 return true;
1166 }
1167 }
1168
1169 protected:
1170 std::set<std::string> mEGLExtensions;
1171 std::set<std::string> mGLExtensions;
1172 EGLDisplay mDisplay = EGL_NO_DISPLAY;
1173 EGLSurface mSurface = EGL_NO_SURFACE;
1174 EGLContext mContext[2] = { EGL_NO_CONTEXT, EGL_NO_CONTEXT };
1175 int mWhich = 0; // Which of the two EGL contexts is current.
1176 int mContextCount = 2; // Will be 2 in AHB test cases and 1 in pure GL test cases.
1177 int mGLVersion = 0; // major_version * 10 + minor_version
1178
1179 AHardwareBuffer* mBuffer = nullptr;
1180 EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
1181 GLenum mTexTarget = GL_NONE;
1182 GLuint mProgram = 0;
1183 GLint mColorLocation = -1;
1184 GLint mFaceVectorLocation = -1;
1185 GLuint mTextures[2] = { 0, 0 };
1186 GLuint mBufferObjects[2] = { 0, 0 };
1187 GLuint mFramebuffers[2] = { 0, 0 };
1188 GLint mMaxTextureUnits = 0;
1189 };
1190
SetUp()1191 void AHardwareBufferGLTest::SetUp() {
1192 mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1193 eglInitialize(mDisplay, NULL, NULL);
1194
1195 // Try creating an OpenGL ES 3.x context and fall back to 2.x if that fails.
1196 // Create two contexts for cross-context image sharing tests.
1197 EGLConfig first_config;
1198 EGLint config_attrib_list[] = {
1199 EGL_RED_SIZE, 8,
1200 EGL_GREEN_SIZE, 8,
1201 EGL_BLUE_SIZE, 8,
1202 EGL_ALPHA_SIZE, 8,
1203 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
1204 EGL_NONE
1205 };
1206 EGLint num_config = 0;
1207 eglChooseConfig(mDisplay, config_attrib_list, &first_config, 1, &num_config);
1208 if (num_config == 0) {
1209 // There are no configs with the ES 3.0 bit, fall back to ES 2.0.
1210 config_attrib_list[8] = EGL_NONE;
1211 config_attrib_list[9] = EGL_NONE;
1212 eglChooseConfig(mDisplay, config_attrib_list, &first_config, 1, &num_config);
1213 }
1214 ASSERT_GT(num_config, 0);
1215
1216 EGLint context_attrib_list[] = {
1217 EGL_CONTEXT_CLIENT_VERSION, 3,
1218 EGL_NONE
1219 };
1220 // Try creating an ES 3.0 context, but don't bother if there were no ES 3.0 compatible configs.
1221 if (config_attrib_list[9] != EGL_NONE) {
1222 mContext[0] = eglCreateContext(mDisplay, first_config, EGL_NO_CONTEXT, context_attrib_list);
1223 }
1224 // If we don't have a context yet, fall back to ES 2.0.
1225 if (mContext[0] == EGL_NO_CONTEXT) {
1226 context_attrib_list[1] = 2;
1227 mContext[0] = eglCreateContext(mDisplay, first_config, EGL_NO_CONTEXT, context_attrib_list);
1228 }
1229 mContext[1] = eglCreateContext(mDisplay, first_config, EGL_NO_CONTEXT, context_attrib_list);
1230 ASSERT_NE(EGL_NO_CONTEXT, mContext[0]);
1231 ASSERT_NE(EGL_NO_CONTEXT, mContext[1]);
1232
1233 // Parse EGL extension strings into a set for easier processing.
1234 std::istringstream eglext_stream(eglQueryString(mDisplay, EGL_EXTENSIONS));
1235 mEGLExtensions = std::set<std::string>{
1236 std::istream_iterator<std::string>{eglext_stream},
1237 std::istream_iterator<std::string>{}
1238 };
1239 // Create a 1x1 pbuffer surface if surfaceless contexts are not supported.
1240 if (!HasEGLExtension("EGL_KHR_surfaceless_context")) {
1241 EGLint const surface_attrib_list[] = {
1242 EGL_WIDTH, 1,
1243 EGL_HEIGHT, 1,
1244 EGL_NONE
1245 };
1246 mSurface = eglCreatePbufferSurface(mDisplay, first_config, surface_attrib_list);
1247 }
1248 EGLBoolean result = eglMakeCurrent(mDisplay, mSurface, mSurface, mContext[0]);
1249 ASSERT_EQ(EGLBoolean{EGL_TRUE}, result);
1250
1251 // Parse GL extension strings into a set for easier processing.
1252 std::istringstream glext_stream(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
1253 mGLExtensions = std::set<std::string>{
1254 std::istream_iterator<std::string>{glext_stream},
1255 std::istream_iterator<std::string>{}
1256 };
1257 // Parse GL version. Find the first dot, then treat the digit before it as the major version
1258 // and the digit after it as the minor version.
1259 std::string version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
1260 std::size_t dot_pos = version.find('.');
1261 ASSERT_TRUE(dot_pos > 0 && dot_pos < version.size() - 1);
1262 mGLVersion = (version[dot_pos - 1] - '0') * 10 + (version[dot_pos + 1] - '0');
1263 ASSERT_GE(mGLVersion, 20);
1264 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mMaxTextureUnits);
1265 }
1266
SetUpBuffer(const AHardwareBuffer_Desc & desc)1267 bool AHardwareBufferGLTest::SetUpBuffer(const AHardwareBuffer_Desc& desc) {
1268 const bool use_srgb = desc.stride & kUseSrgb;
1269 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) {
1270 if (desc.layers > 6) {
1271 if (mGLVersion < 32) {
1272 ALOGI("Test skipped: cube map arrays require GL ES 3.2, found %d.%d",
1273 mGLVersion / 10, mGLVersion % 10);
1274 return false;
1275 }
1276 mTexTarget = GL_TEXTURE_CUBE_MAP_ARRAY;
1277 } else {
1278 mTexTarget = GL_TEXTURE_CUBE_MAP;
1279 }
1280 } else {
1281 if (desc.layers > 1) {
1282 if (mGLVersion < 30) {
1283 ALOGI("Test skipped: texture arrays require GL ES 3.0, found %d.%d",
1284 mGLVersion / 10, mGLVersion % 10);
1285 return false;
1286 }
1287 mTexTarget = GL_TEXTURE_2D_ARRAY;
1288 } else {
1289 if (FormatIsYuv(desc.format)) {
1290 mTexTarget = GL_TEXTURE_EXTERNAL_OES;
1291 } else {
1292 mTexTarget = GL_TEXTURE_2D;
1293 }
1294 }
1295 }
1296 if ((desc.format == GL_RGB8 || desc.format == GL_RGBA8) &&
1297 (desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) &&
1298 mGLVersion < 30 && !HasGLExtension("GL_OES_rgb8_rgba8")) {
1299 ALOGI("Test skipped: GL_RGB8/GL_RGBA8 renderbuffers require GL ES 3.0 or "
1300 "GL_OES_rgb8_rgba8, but neither were found.");
1301 return false;
1302 }
1303 if (desc.format == GL_SRGB8_ALPHA8 && mGLVersion < 30 &&
1304 !HasGLExtension("GL_EXT_sRGB")) {
1305 ALOGI("Test skipped: GL_SRGB8_ALPHA8 requires GL ES 3.0 or GL_EXT_sRGB, "
1306 "but neither were found.");
1307 return false;
1308 }
1309 if (desc.format == GL_RGB10_A2 && mGLVersion < 30) {
1310 ALOGI("Test skipped: GL_RGB10_A2 requires GL ES 3.0, found %d.%d",
1311 mGLVersion / 10, mGLVersion % 10);
1312 return false;
1313 }
1314 if (desc.format == GL_RGBA16F && mGLVersion < 30) {
1315 ALOGI("Test skipped: GL_RGBA16F requires GL ES 3.0, found %d.%d",
1316 mGLVersion / 10, mGLVersion % 10);
1317 return false;
1318 }
1319 if (desc.format == GL_DEPTH_COMPONENT16 &&
1320 (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) &&
1321 mGLVersion < 30 && !HasGLExtension("GL_OES_depth_texture")) {
1322 ALOGI("Test skipped: depth textures require GL ES 3.0 or "
1323 "GL_OES_depth_texture, but neither were found.");
1324 return false;
1325 }
1326 if (desc.format == GL_DEPTH24_STENCIL8 &&
1327 (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) &&
1328 mGLVersion < 30 && !HasGLExtension("GL_OES_packed_depth_stencil")) {
1329 ALOGI("Test skipped: depth-stencil textures require GL ES 3.0 or "
1330 "GL_OES_packed_depth_stencil, but neither were found.");
1331 return false;
1332 }
1333 if (mTexTarget == GL_TEXTURE_EXTERNAL_OES &&
1334 (desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) &&
1335 !HasGLExtension("GL_OES_EGL_image_external")) {
1336 ALOGI("Test skipped: External textures are not supported but required "
1337 "by this test.");
1338 return false;
1339 }
1340 if (FormatIsYuv(desc.format) && !HasGLExtension("GL_EXT_YUV_target")) {
1341 ALOGI("Test skipped: The GL_EXT_YUV_target extension is required for "
1342 "operations in the YUV color space.");
1343 return false;
1344 }
1345 // For control cases using GL formats, the test should be run in a single
1346 // context, without using AHardwareBuffer. This simplifies verifying that
1347 // the test behaves as expected even if the AHardwareBuffer format under
1348 // test is not supported.
1349 if (desc.stride & kGlFormat) {
1350 mContextCount = 1;
1351 return true;
1352 }
1353
1354 // The code below will only execute if we are allocating a real AHardwareBuffer.
1355 if (use_srgb && !HasEGLExtension("EGL_EXT_image_gl_colorspace")) {
1356 ALOGI("Test skipped: sRGB hardware buffers require EGL_EXT_image_gl_colorspace");
1357 return false;
1358 }
1359 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP &&
1360 !HasGLExtension("GL_EXT_EGL_image_storage")) {
1361 ALOGI("Test skipped: cube map array hardware buffers require "
1362 "GL_EXT_EGL_image_storage");
1363 return false;
1364 }
1365 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE &&
1366 !HasGLExtension("GL_EXT_EGL_image_storage")) {
1367 ALOGI("Test skipped: mipmapped hardware buffers require "
1368 "GL_EXT_EGL_image_storage");
1369 return false;
1370 }
1371
1372 int result = AHardwareBuffer_allocate(&desc, &mBuffer);
1373
1374 ALOGI("Attempting to allocate format=%s width=%d height=%d layers=%d result=%d",
1375 AHBFormatAsString(desc.format), desc.width, desc.height, desc.layers, result);
1376
1377 // Skip if this format cannot be allocated.
1378 if (result != NO_ERROR) {
1379 EXPECT_FALSE(AHardwareBuffer_isSupported(&desc)) <<
1380 "AHardwareBuffer_isSupported returned true, but buffer allocation failed. "
1381 "Potential gralloc bug or resource exhaustion.";
1382 ALOGI("Test skipped: format %s could not be allocated",
1383 AHBFormatAsString(desc.format));
1384 return false;
1385 }
1386 EXPECT_TRUE(AHardwareBuffer_isSupported(&desc)) <<
1387 "AHardwareBuffer_isSupported returned false, but buffer allocation succeeded. "
1388 "This is most likely a bug in the gralloc implementation.";
1389
1390 // The code below will only execute if allocating an AHardwareBuffer succeeded.
1391 // Fail early if the buffer is mipmapped or a cube map, but the GL extension required
1392 // to actually access it from GL is not present.
1393 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP &&
1394 !HasGLExtension("GL_EXT_EGL_image_storage")) {
1395 ADD_FAILURE() << "Cube map AHardwareBuffer allocation succeeded, but the extension "
1396 "GL_EXT_EGL_image_storage is not present";
1397 return false;
1398 }
1399 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE &&
1400 !HasGLExtension("GL_EXT_EGL_image_storage")) {
1401 ADD_FAILURE() << "Mipmapped AHardwareBuffer allocation succeeded, but the extension "
1402 "GL_EXT_EGL_image_storage is not present";
1403 return false;
1404 }
1405
1406 // Do not create the EGLImage if this is a blob format.
1407 if (desc.format == AHARDWAREBUFFER_FORMAT_BLOB) return true;
1408
1409 EXPECT_TRUE(HasEGLExtension("EGL_ANDROID_image_native_buffer"));
1410
1411 EGLint attrib_list[3] = { EGL_NONE, EGL_NONE, EGL_NONE };
1412 if (use_srgb) {
1413 attrib_list[0] = EGL_GL_COLORSPACE_KHR;
1414 attrib_list[1] = EGL_GL_COLORSPACE_SRGB_KHR;
1415 }
1416 mEGLImage = eglCreateImageKHR(
1417 mDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
1418 eglGetNativeClientBufferANDROID(mBuffer), attrib_list);
1419 EXPECT_NE(EGL_NO_IMAGE_KHR, mEGLImage) <<
1420 "AHardwareBuffer allocation succeeded, but binding it to an EGLImage failed. "
1421 "This is usually caused by a version mismatch between the gralloc implementation and "
1422 "the OpenGL/EGL driver. Please contact your GPU vendor to resolve this problem.";
1423 return mEGLImage != EGL_NO_IMAGE_KHR;
1424 }
1425
SetUpProgram(const std::string & vertex_source,const std::string & fragment_source,const float * mesh,float scale,int texture_unit)1426 void AHardwareBufferGLTest::SetUpProgram(const std::string& vertex_source,
1427 const std::string& fragment_source,
1428 const float* mesh, float scale, int texture_unit) {
1429 ASSERT_EQ(0U, mProgram);
1430 GLint status = GL_FALSE;
1431 mProgram = glCreateProgram();
1432 GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
1433 const char* vertex_source_cstr = vertex_source.c_str();
1434 glShaderSource(vertex_shader, 1, &vertex_source_cstr, nullptr);
1435 glCompileShader(vertex_shader);
1436 glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status);
1437 ASSERT_EQ(GL_TRUE, status) << "Vertex shader compilation failed";
1438 GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
1439 const char* fragment_source_cstr = fragment_source.c_str();
1440 glShaderSource(fragment_shader, 1, &fragment_source_cstr, nullptr);
1441 glCompileShader(fragment_shader);
1442 glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status);
1443 ASSERT_EQ(GL_TRUE, status) << "Fragment shader compilation failed";
1444 glAttachShader(mProgram, vertex_shader);
1445 glAttachShader(mProgram, fragment_shader);
1446 glLinkProgram(mProgram);
1447 glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
1448 ASSERT_EQ(GL_TRUE, status) << "Shader program linking failed";
1449 glDetachShader(mProgram, vertex_shader);
1450 glDetachShader(mProgram, fragment_shader);
1451 glDeleteShader(vertex_shader);
1452 glDeleteShader(fragment_shader);
1453 glUseProgram(mProgram);
1454 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "GL error during shader program setup";
1455
1456 GLint a_position_location = glGetAttribLocation(mProgram, "aPosition");
1457 GLint a_depth_location = glGetAttribLocation(mProgram, "aDepth");
1458 if (mesh == kQuadPositions) {
1459 glVertexAttribPointer(a_position_location, 2, GL_FLOAT, GL_TRUE, 0, kQuadPositions);
1460 glVertexAttrib1f(a_depth_location, 0.f);
1461 glEnableVertexAttribArray(a_position_location);
1462 } else if (mesh == kPyramidPositions) {
1463 glVertexAttribPointer(a_position_location, 2, GL_FLOAT, GL_TRUE, 3 * sizeof(float),
1464 kPyramidPositions);
1465 glVertexAttribPointer(a_depth_location, 1, GL_FLOAT, GL_TRUE, 3 * sizeof(float),
1466 kPyramidPositions + 2);
1467 glEnableVertexAttribArray(a_position_location);
1468 glEnableVertexAttribArray(a_depth_location);
1469 } else {
1470 FAIL() << "Unknown mesh";
1471 }
1472 glUniform1f(glGetUniformLocation(mProgram, "uScale"), scale);
1473 mColorLocation = glGetUniformLocation(mProgram, "uColor");
1474 if (mColorLocation >= 0) {
1475 glUniform4f(mColorLocation, 1.f, 0.f, 0.f, 1.f);
1476 }
1477 GLint u_texture_location = glGetUniformLocation(mProgram, "uTexture");
1478 if (u_texture_location >= 0) {
1479 glUniform1i(u_texture_location, texture_unit);
1480 }
1481 GLint u_layer_location = glGetUniformLocation(mProgram, "uLayer");
1482 if (u_layer_location >= 0) {
1483 glUniform1f(u_layer_location, static_cast<float>(GetParam().layers - 1));
1484 }
1485 mFaceVectorLocation = glGetUniformLocation(mProgram, "uFaceVector");
1486 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "GL error during shader uniform setup";
1487 }
1488
SetUpTexture(const AHardwareBuffer_Desc & desc,int unit)1489 void AHardwareBufferGLTest::SetUpTexture(const AHardwareBuffer_Desc& desc, int unit) {
1490 GLuint& texture = mTextures[mWhich];
1491 glGenTextures(1, &texture);
1492 glActiveTexture(GL_TEXTURE0 + unit);
1493 glBindTexture(mTexTarget, texture);
1494 // If the texture does not have mipmaps, set a filter that does not require them.
1495 if (!(desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE)) {
1496 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1497 }
1498 if (desc.stride & kGlFormat) {
1499 int levels = 1;
1500 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE) {
1501 levels = MipLevelCount(desc.width, desc.height);
1502 }
1503 // kGlFormat is set in the stride field, so interpret desc.format as a GL format.
1504 if ((desc.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) ? desc.layers > 6 : desc.layers > 1) {
1505 glTexStorage3D(mTexTarget, levels, desc.format, desc.width, desc.height, desc.layers);
1506 } else if (mGLVersion >= 30) {
1507 glTexStorage2D(mTexTarget, levels, desc.format, desc.width, desc.height);
1508 } else {
1509 // Compatibility code for ES 2.0 goes here.
1510 GLenum internal_format = 0, format = 0, type = 0;
1511 switch (desc.format) {
1512 case GL_RGB8:
1513 internal_format = GL_RGB;
1514 format = GL_RGB;
1515 type = GL_UNSIGNED_BYTE;
1516 break;
1517 case GL_RGBA8:
1518 internal_format = GL_RGBA;
1519 format = GL_RGBA;
1520 type = GL_UNSIGNED_BYTE;
1521 break;
1522 case GL_SRGB8_ALPHA8:
1523 // Available through GL_EXT_sRGB.
1524 internal_format = GL_SRGB_ALPHA_EXT;
1525 format = GL_RGBA;
1526 type = GL_UNSIGNED_BYTE;
1527 break;
1528 case GL_RGB565:
1529 internal_format = GL_RGB;
1530 format = GL_RGB;
1531 type = GL_UNSIGNED_SHORT_5_6_5;
1532 break;
1533 case GL_DEPTH_COMPONENT16:
1534 // Available through GL_OES_depth_texture.
1535 // Note that these are treated as luminance textures, not as red textures.
1536 internal_format = GL_DEPTH_COMPONENT;
1537 format = GL_DEPTH_COMPONENT;
1538 type = GL_UNSIGNED_SHORT;
1539 break;
1540 case GL_DEPTH24_STENCIL8:
1541 // Available through GL_OES_packed_depth_stencil.
1542 internal_format = GL_DEPTH_STENCIL_OES;
1543 format = GL_DEPTH_STENCIL;
1544 type = GL_UNSIGNED_INT_24_8;
1545 break;
1546 default:
1547 FAIL() << "Unrecognized GL format"; break;
1548 }
1549 if (desc.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) {
1550 for (int face = 0; face < 6; ++face) {
1551 uint32_t width = desc.width;
1552 uint32_t height = desc.height;
1553 for (int level = 0; level < levels; ++level) {
1554 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, internal_format,
1555 width, height, 0, format, type, nullptr);
1556 width /= 2;
1557 height /= 2;
1558 }
1559 }
1560 } else {
1561 uint32_t width = desc.width;
1562 uint32_t height = desc.height;
1563 for (int level = 0; level < levels; ++level) {
1564 glTexImage2D(mTexTarget, level, internal_format, width, height, 0, format,
1565 type, nullptr);
1566 width /= 2;
1567 height /= 2;
1568 }
1569 }
1570 }
1571 } else {
1572 if (HasGLExtension("GL_EXT_EGL_image_storage")) {
1573 glEGLImageTargetTexStorageEXT(mTexTarget, static_cast<GLeglImageOES>(mEGLImage),
1574 nullptr);
1575 } else {
1576 glEGLImageTargetTexture2DOES(mTexTarget, static_cast<GLeglImageOES>(mEGLImage));
1577 }
1578 }
1579 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "GL error during texture setup";
1580 }
1581
SetUpBufferObject(uint32_t size,GLenum target,GLbitfield flags)1582 void AHardwareBufferGLTest::SetUpBufferObject(uint32_t size, GLenum target, GLbitfield flags) {
1583 glGenBuffers(1, &mBufferObjects[mWhich]);
1584 glBindBuffer(target, mBufferObjects[mWhich]);
1585 glBufferStorageExternalEXT(target, 0, size,
1586 eglGetNativeClientBufferANDROID(mBuffer), flags);
1587 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "GL error during buffer object setup";
1588 }
1589
SetUpFramebuffer(int width,int height,int layer,AttachmentType color,AttachmentType depth,AttachmentType stencil,AttachmentType depth_stencil,int level)1590 void AHardwareBufferGLTest::SetUpFramebuffer(int width, int height, int layer,
1591 AttachmentType color,
1592 AttachmentType depth,
1593 AttachmentType stencil,
1594 AttachmentType depth_stencil,
1595 int level) {
1596 AttachmentType attachment_types[] = { color, depth, stencil, depth_stencil };
1597 GLenum attachment_points[] = {
1598 GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT,
1599 GL_DEPTH_STENCIL_ATTACHMENT
1600 };
1601 GLenum default_formats[] = {
1602 GL_RGBA8, GL_DEPTH_COMPONENT16, GL_STENCIL_INDEX8, GL_DEPTH24_STENCIL8
1603 };
1604 GLuint& fbo = mFramebuffers[mWhich];
1605 GLbitfield clear_bits[] = {
1606 GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT,
1607 GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT
1608 };
1609
1610 glClearColor(0.f, 0.f, 0.f, 0.f);
1611 glClearDepthf(1.0f);
1612 glClearStencil(0);
1613 glGenFramebuffers(1, &fbo);
1614 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1615 for (int i = 0; i < 4; ++i) {
1616 switch (attachment_types[i]) {
1617 case kNone:
1618 break;
1619 case kBufferAsTexture:
1620 ASSERT_NE(0U, mTextures[mWhich]);
1621 if (mTexTarget == GL_TEXTURE_2D || mTexTarget == GL_TEXTURE_EXTERNAL_OES) {
1622 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment_points[i], mTexTarget,
1623 mTextures[mWhich], level);
1624 } else if (mTexTarget == GL_TEXTURE_CUBE_MAP) {
1625 glFramebufferTexture2D(GL_FRAMEBUFFER, attachment_points[i],
1626 GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer,
1627 mTextures[mWhich], level);
1628 } else {
1629 glFramebufferTextureLayer(GL_FRAMEBUFFER, attachment_points[i],
1630 mTextures[mWhich], level, layer);
1631 }
1632 break;
1633 case kBufferAsRenderbuffer: {
1634 ASSERT_EQ(0, layer);
1635 GLuint renderbuffer = 0;
1636 glGenRenderbuffers(1, &renderbuffer);
1637 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1638 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
1639 bool isGlFormat = GetParam().stride & kGlFormat;
1640 if (isGlFormat) {
1641 glRenderbufferStorage(GL_RENDERBUFFER, GetParam().format, width, height);
1642 } else {
1643 ASSERT_FALSE(FormatIsYuv(GetParam().format)) << "YUV renderbuffers unsupported";
1644 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
1645 static_cast<GLeglImageOES>(mEGLImage));
1646 }
1647 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment_points[i],
1648 GL_RENDERBUFFER, renderbuffer);
1649 if (isGlFormat)
1650 glClear(clear_bits[i]);
1651 break;
1652 }
1653 case kRenderbuffer: {
1654 ASSERT_EQ(0, layer);
1655 GLuint renderbuffer = 0;
1656 glGenRenderbuffers(1, &renderbuffer);
1657 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1658 glRenderbufferStorage(GL_RENDERBUFFER, default_formats[i], width, height);
1659 glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment_points[i],
1660 GL_RENDERBUFFER, renderbuffer);
1661 glClear(clear_bits[i]);
1662 break;
1663 }
1664 default: FAIL() << "Unrecognized binding type";
1665 }
1666 }
1667 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "GL error during framebuffer setup";
1668 ASSERT_EQ(GLenum{GL_FRAMEBUFFER_COMPLETE},
1669 glCheckFramebufferStatus(GL_FRAMEBUFFER)) << "Framebuffer not complete";
1670 glViewport(0, 0, width, height);
1671 }
1672
TearDown()1673 void AHardwareBufferGLTest::TearDown() {
1674 MakeCurrentNone();
1675 for (int i = 0; i < 2; ++i) {
1676 // All GL objects will be deleted along with the context.
1677 eglDestroyContext(mDisplay, mContext[i]);
1678 }
1679 if (mBuffer != nullptr) {
1680 eglDestroyImageKHR(mDisplay, mEGLImage);
1681 AHardwareBuffer_release(mBuffer);
1682 }
1683 if (mSurface != EGL_NO_SURFACE) {
1684 eglDestroySurface(mDisplay, mSurface);
1685 }
1686 eglTerminate(mDisplay);
1687 }
1688
1689
1690 class BlobTest : public AHardwareBufferGLTest {
1691 public:
SetUpBuffer(const AHardwareBuffer_Desc & desc)1692 bool SetUpBuffer(const AHardwareBuffer_Desc& desc) override {
1693 if (!HasGLExtension("GL_EXT_external_buffer")) {
1694 ALOGI("Test skipped: GL_EXT_external_buffer not present");
1695 return false;
1696 }
1697 return AHardwareBufferGLTest::SetUpBuffer(desc);
1698 }
1699 };
1700
1701 // Verifies that a blob buffer can be used to supply vertex attributes to a shader.
TEST_P(BlobTest,GpuDataBufferVertexBuffer)1702 TEST_P(BlobTest, GpuDataBufferVertexBuffer) {
1703 AHardwareBuffer_Desc desc = GetParam();
1704 desc.width = sizeof kQuadPositions;
1705 desc.usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
1706 if (!SetUpBuffer(desc)) return;
1707
1708 ASSERT_NO_FATAL_FAILURE(
1709 SetUpProgram(kVertexShader, kColorFragmentShader, kQuadPositions, 0.5f));
1710
1711 for (int i = 0; i < mContextCount; ++i) {
1712 MakeCurrent(i);
1713 ASSERT_NO_FATAL_FAILURE(
1714 SetUpBufferObject(desc.width, GL_ARRAY_BUFFER,
1715 GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT));
1716 }
1717 float* data = static_cast<float*>(
1718 glMapBufferRange(GL_ARRAY_BUFFER, 0, desc.width,
1719 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
1720 ASSERT_NE(data, nullptr) << "glMapBufferRange on a blob buffer failed";
1721 memcpy(data, kQuadPositions, desc.width);
1722 glUnmapBuffer(GL_ARRAY_BUFFER);
1723 glFinish();
1724
1725 MakeCurrent(0);
1726 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
1727 GLint a_position_location = glGetAttribLocation(mProgram, "aPosition");
1728 glVertexAttribPointer(a_position_location, 2, GL_FLOAT, GL_TRUE, 0, 0);
1729 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
1730 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
1731
1732 // Check the rendered pixels. There should be a red square in the middle.
1733 std::vector<GoldenPixel> goldens{
1734 {5, 35, kZero}, {15, 35, kZero}, {25, 35, kZero}, {35, 35, kZero},
1735 {5, 25, kZero}, {15, 25, kRed}, {25, 25, kRed}, {35, 25, kZero},
1736 {5, 15, kZero}, {15, 15, kRed}, {25, 15, kRed}, {35, 15, kZero},
1737 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kZero}, {35, 5, kZero},
1738 };
1739 CheckGoldenPixels(goldens, GL_RGBA8);
1740 }
1741
1742 // Verifies that a blob buffer can be directly accessed from the CPU.
TEST_P(BlobTest,GpuDataBufferCpuWrite)1743 TEST_P(BlobTest, GpuDataBufferCpuWrite) {
1744 AHardwareBuffer_Desc desc = GetParam();
1745 desc.width = sizeof kQuadPositions;
1746 desc.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
1747 if (!SetUpBuffer(desc)) return;
1748
1749 ASSERT_NO_FATAL_FAILURE(
1750 SetUpProgram(kVertexShader, kColorFragmentShader, kQuadPositions, 0.5f));
1751
1752 for (int i = 0; i < mContextCount; ++i) {
1753 MakeCurrent(i);
1754 ASSERT_NO_FATAL_FAILURE(
1755 SetUpBufferObject(desc.width, GL_ARRAY_BUFFER,
1756 GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT));
1757 }
1758
1759 // Clear the buffer to zero
1760 std::vector<float> zero_data(desc.width / sizeof(float), 0.f);
1761 glBufferSubData(GL_ARRAY_BUFFER, 0, desc.width, zero_data.data());
1762 glFinish();
1763
1764 // Upload actual data with CPU access
1765 float* data = nullptr;
1766 int result = AHardwareBuffer_lock(mBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY,
1767 -1, nullptr, reinterpret_cast<void**>(&data));
1768 ASSERT_EQ(NO_ERROR, result);
1769 memcpy(data, kQuadPositions, desc.width);
1770 AHardwareBuffer_unlock(mBuffer, nullptr);
1771
1772 // Render the buffer in the other context
1773 MakeCurrent(0);
1774 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
1775 GLint a_position_location = glGetAttribLocation(mProgram, "aPosition");
1776 glVertexAttribPointer(a_position_location, 2, GL_FLOAT, GL_TRUE, 0, 0);
1777 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
1778 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
1779
1780 // Check the rendered pixels. There should be a red square in the middle.
1781 std::vector<GoldenPixel> goldens{
1782 {5, 35, kZero}, {15, 35, kZero}, {25, 35, kZero}, {35, 35, kZero},
1783 {5, 25, kZero}, {15, 25, kRed}, {25, 25, kRed}, {35, 25, kZero},
1784 {5, 15, kZero}, {15, 15, kRed}, {25, 15, kRed}, {35, 15, kZero},
1785 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kZero}, {35, 5, kZero},
1786 };
1787 CheckGoldenPixels(goldens, GL_RGBA8);
1788 }
1789
1790 // Verifies that data written into a blob buffer from the GPU can be read on the CPU.
TEST_P(BlobTest,GpuDataBufferCpuRead)1791 TEST_P(BlobTest, GpuDataBufferCpuRead) {
1792 if (mGLVersion < 31) {
1793 ALOGI("Test skipped: shader storage buffer objects require ES 3.1+, found %d.%d",
1794 mGLVersion / 10, mGLVersion % 10);
1795 return;
1796 }
1797 const int kBufferElements = 16;
1798 AHardwareBuffer_Desc desc = GetParam();
1799 desc.width = kBufferElements * sizeof(int);
1800 desc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
1801 if (!SetUpBuffer(desc)) return;
1802
1803 for (int i = 0; i < mContextCount; ++i) {
1804 MakeCurrent(i);
1805 ASSERT_NO_FATAL_FAILURE(
1806 SetUpBufferObject(desc.width, GL_SHADER_STORAGE_BUFFER,
1807 GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_READ_BIT));
1808 }
1809
1810 // Clear the buffer to zero
1811 std::vector<unsigned int> expected_data(kBufferElements, 0U);
1812 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, desc.width, expected_data.data());
1813 glFinish();
1814
1815 // Write into the buffer with a compute shader
1816 GLint status = 0;
1817 mProgram = glCreateProgram();
1818 GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
1819 glShaderSource(shader, 1, &kSsboComputeShaderEs31, nullptr);
1820 glCompileShader(shader);
1821 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
1822 ASSERT_EQ(GL_TRUE, status) << "Compute shader compilation failed";
1823 glAttachShader(mProgram, shader);
1824 glLinkProgram(mProgram);
1825 glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
1826 ASSERT_EQ(GL_TRUE, status) << "Shader program linking failed";
1827 glDetachShader(mProgram, shader);
1828 glDeleteShader(shader);
1829 glUseProgram(mProgram);
1830 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "GL error during compute shader setup";
1831 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, mBufferObjects[mWhich]);
1832 glDispatchCompute(kBufferElements, 1, 1);
1833 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1834 glFinish();
1835 EXPECT_EQ(GLenum{GL_NO_ERROR}, glGetError()) << "GL error during compute shader execution";
1836
1837 // Inspect the data written into the buffer using CPU access.
1838 MakeCurrent(0);
1839 unsigned int* data = nullptr;
1840 int result = AHardwareBuffer_lock(mBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
1841 -1, nullptr, reinterpret_cast<void**>(&data));
1842 ASSERT_EQ(NO_ERROR, result) << "AHardwareBuffer_lock failed with error " << result;
1843 std::ostringstream s;
1844 for (int i = 0; i < kBufferElements; ++i) {
1845 expected_data[i] = static_cast<unsigned int>(i * 3);
1846 s << data[i] << ", ";
1847 }
1848 EXPECT_EQ(0, memcmp(expected_data.data(), data, desc.width)) << s.str();
1849 AHardwareBuffer_unlock(mBuffer, nullptr);
1850 }
1851
1852 // The first case tests an ordinary GL buffer, while the second one tests an AHB-backed buffer.
1853 INSTANTIATE_TEST_CASE_P(
1854 Blob, BlobTest,
1855 ::testing::Values(
1856 AHardwareBuffer_Desc{1, 1, 1, AHARDWAREBUFFER_FORMAT_BLOB, 0, 0, 0, 0}),
1857 &GetTestName);
1858
1859
1860 class ColorTest : public AHardwareBufferGLTest {
1861 public:
SetUpBuffer(const AHardwareBuffer_Desc & desc)1862 bool SetUpBuffer(const AHardwareBuffer_Desc& desc) override {
1863 if ((desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) &&
1864 !IsFormatColorRenderable(desc.format, desc.stride & kUseSrgb)) {
1865 ALOGI("Test skipped: requires GPU_COLOR_OUTPUT, but format is not color-renderable");
1866 return false;
1867 }
1868 return AHardwareBufferGLTest::SetUpBuffer(desc);
1869 }
1870 };
1871
1872 // Verify that when allocating an AHardwareBuffer succeeds with GPU_COLOR_OUTPUT,
1873 // it can be bound as a framebuffer attachment, glClear'ed and then read from
1874 // another context using glReadPixels.
TEST_P(ColorTest,GpuColorOutputIsRenderable)1875 TEST_P(ColorTest, GpuColorOutputIsRenderable) {
1876 AHardwareBuffer_Desc desc = GetParam();
1877 desc.width = 100;
1878 desc.height = 100;
1879 desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
1880 if (FormatIsYuv(desc.format)) {
1881 // YUV formats are only supported for textures, so add texture usage.
1882 desc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
1883 }
1884 // This test does not make sense for layered buffers - don't bother testing them.
1885 if (desc.layers > 1) return;
1886 if (!SetUpBuffer(desc)) return;
1887
1888 for (int i = 0; i < mContextCount; ++i) {
1889 MakeCurrent(i);
1890
1891 // YUV renderbuffers are unsupported, so we attach as a texture in this case.
1892 AttachmentType attachmentType;
1893 if (FormatIsYuv(desc.format)) {
1894 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, 1));
1895 attachmentType = kBufferAsTexture;
1896 } else {
1897 attachmentType = kBufferAsRenderbuffer;
1898 }
1899
1900 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(desc.width, desc.height, 0, attachmentType));
1901 }
1902
1903 // Draw a simple checkerboard pattern in the second context, which will
1904 // be current after the loop above, then read it in the first.
1905 DrawCheckerboard(desc.width, desc.height, desc.format);
1906 glFinish();
1907
1908 MakeCurrent(0);
1909 std::vector<GoldenPixel> goldens{
1910 {10, 90, kRed}, {40, 90, kRed}, {60, 90, kBlue}, {90, 90, kBlue},
1911 {10, 60, kRed}, {40, 60, kRed}, {60, 60, kBlue}, {90, 60, kBlue},
1912 {10, 40, kZero}, {40, 40, kZero}, {60, 40, kGreen}, {90, 40, kGreen},
1913 {10, 10, kZero}, {40, 10, kZero}, {60, 10, kGreen}, {90, 10, kGreen},
1914 };
1915 CheckGoldenPixels(goldens, desc.format);
1916 }
1917
1918 // Verifies that the content of GPU_COLOR_OUTPUT buffers can be read on the CPU directly by
1919 // locking the HardwareBuffer.
TEST_P(ColorTest,GpuColorOutputCpuRead)1920 TEST_P(ColorTest, GpuColorOutputCpuRead) {
1921 AHardwareBuffer_Desc desc = GetParam();
1922 desc.width = 16;
1923 desc.height = 16;
1924 desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_READ_RARELY;
1925 if (FormatIsYuv(desc.format)) {
1926 // YUV formats are only supported for textures, so add texture usage.
1927 desc.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
1928 }
1929 // This test does not make sense for GL formats. Layered buffers do not support CPU access.
1930 if ((desc.stride & kGlFormat) || desc.layers > 1) {
1931 ALOGI("Test skipped: Test is for single-layer HardwareBuffer formats only.");
1932 return;
1933 }
1934 if (!SetUpBuffer(desc)) return;
1935
1936 MakeCurrent(1);
1937
1938 // YUV renderbuffers are unsupported, so we attach as a texture in this case.
1939 AttachmentType attachmentType;
1940 if (FormatIsYuv(desc.format)) {
1941 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, 1));
1942 attachmentType = kBufferAsTexture;
1943 } else {
1944 attachmentType = kBufferAsRenderbuffer;
1945 }
1946
1947 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(desc.width, desc.height, 0, attachmentType));
1948
1949 // Draw a simple checkerboard pattern in the second context, which will
1950 // be current after the loop above, then read it in the first.
1951 DrawCheckerboard(desc.width, desc.height, desc.format);
1952 glFinish();
1953
1954 MakeCurrent(0);
1955 std::vector<GoldenPixel> goldens{
1956 {0, 15, kRed}, {7, 15, kRed}, {8, 15, kBlue}, {15, 15, kBlue},
1957 {0, 8, kRed}, {7, 8, kRed}, {8, 8, kBlue}, {15, 8, kBlue},
1958 {0, 7, kZero}, {7, 7, kZero}, {8, 7, kGreen}, {15, 7, kGreen},
1959 {0, 0, kZero}, {7, 0, kZero}, {8, 0, kGreen}, {15, 0, kGreen},
1960 };
1961
1962 // As we glCleared the colors, the YUV colors will simply be the RGB values
1963 CheckCpuGoldenPixels(goldens, mBuffer);
1964 }
1965
1966 // Verifies that the CPU can write directly to a HardwareBuffer, and the GPU can then read from
1967 // that buffer.
TEST_P(ColorTest,CpuWriteColorGpuRead)1968 TEST_P(ColorTest, CpuWriteColorGpuRead) {
1969 AHardwareBuffer_Desc desc = GetParam();
1970 desc.width = 16;
1971 desc.height = 16;
1972 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
1973 // This test does not make sense for GL formats. Layered buffers do not support CPU access.
1974 if ((desc.stride & kGlFormat) || desc.layers > 1) {
1975 ALOGI("Test skipped: Test is for single-layer HardwareBuffer formats only.");
1976 return;
1977 }
1978
1979 if (!SetUpBuffer(desc)) return;
1980
1981 // Write into buffer when no context is active
1982 MakeCurrentNone();
1983 WriteCheckerBoard(mBuffer);
1984
1985 // Now setup a texture in a context to sample from this buffer
1986 MakeCurrent(0);
1987 const int kTextureUnit = 6 % mMaxTextureUnits;
1988 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
1989 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1990 glTexParameteri(mTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1991
1992 // Draw a quad that samples from the texture.
1993 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(16, 16, 0, kRenderbuffer));
1994 glClearColor(0.f, 0.f, 0.f, 0.f);
1995 glClear(GL_COLOR_BUFFER_BIT);
1996
1997 std::string vertex_shader = GetTextureVertexShader(desc.format, desc.stride);
1998 std::string fragment_shader = GetTextureFragmentShader(desc.format, desc.stride);
1999 ASSERT_NO_FATAL_FAILURE(
2000 SetUpProgram(vertex_shader, fragment_shader, kQuadPositions,
2001 1.0f, kTextureUnit));
2002
2003 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2004 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2005
2006 // Check the rendered pixels.
2007 // Non-alpha formats will render black instead of zero
2008 GoldenColor dark = FormatHasAlpha(desc.format) ? kZero : kBlack;
2009 std::vector<GoldenPixel> goldens{
2010 {0, 15, kRed}, {7, 15, kRed}, {8, 15, kBlue}, {15, 15, kBlue},
2011 {0, 8, kRed}, {7, 8, kRed}, {8, 8, kBlue}, {15, 8, kBlue},
2012 {0, 7, dark}, {7, 7, dark}, {8, 7, kGreen}, {15, 7, kGreen},
2013 {0, 0, dark}, {7, 0, dark}, {8, 0, kGreen}, {15, 0, kGreen},
2014 };
2015 // If source was YUV, there may be some conversion imprecision, so we allow some error
2016 CheckGoldenPixels(goldens, GL_RGBA8, GetMaxExpectedColorError(desc.format, desc.stride));
2017 }
2018
2019 // Verify that when allocating an AHardwareBuffer succeeds with GPU_SAMPLED_IMAGE,
2020 // it can be bound as a texture, set to a color with glTexSubImage2D and sampled
2021 // from in a fragment shader.
TEST_P(ColorTest,GpuSampledImageCanBeSampled)2022 TEST_P(ColorTest, GpuSampledImageCanBeSampled) {
2023 AHardwareBuffer_Desc desc = GetParam();
2024 desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
2025
2026 // This test requires using glTexImage2d to assign image data. YUV formats do not
2027 // support this. Other tests using glClear and CPU access test the YUV variants.
2028 if (FormatIsYuv(desc.format)) {
2029 ALOGI("Test Skipped: YUV formats do not support glTexImage2d and variants.");
2030 return;
2031 }
2032
2033 if (!SetUpBuffer(desc)) return;
2034
2035 // Bind the EGLImage to textures in both contexts.
2036 const int kTextureUnit = 6 % mMaxTextureUnits;
2037 for (int i = 0; i < mContextCount; ++i) {
2038 MakeCurrent(i);
2039 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2040 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2041 glTexParameteri(mTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2042 }
2043 // In the second context, upload opaque red to the texture.
2044 ASSERT_NO_FATAL_FAILURE(UploadRedPixels(desc));
2045 glFinish();
2046
2047 // In the first context, draw a quad that samples from the texture.
2048 MakeCurrent(0);
2049 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
2050 glClearColor(0.f, 0.f, 0.f, 0.f);
2051 glClear(GL_COLOR_BUFFER_BIT);
2052
2053 if (desc.layers > 1) {
2054 ASSERT_NO_FATAL_FAILURE(
2055 SetUpProgram(std::string("#version 300 es") + kVertexShaderEs3x,
2056 kArrayFragmentShaderEs30, kQuadPositions, 0.5f, kTextureUnit));
2057 } else {
2058 std::string vertex_shader = GetTextureVertexShader(desc.format, desc.stride);
2059 std::string fragment_shader = GetTextureFragmentShader(desc.format, desc.stride);
2060 ASSERT_NO_FATAL_FAILURE(
2061 SetUpProgram(vertex_shader, fragment_shader, kQuadPositions,
2062 0.5f, kTextureUnit));
2063 }
2064 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2065 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2066
2067 // Check the rendered pixels. There should be a red square in the middle.
2068 GoldenColor color = kRed;
2069 if (desc.stride & kUseSrgb) {
2070 color = FormatHasAlpha(desc.format) ? kRed50 : kRed50Alpha100;
2071 }
2072 std::vector<GoldenPixel> goldens{
2073 {5, 35, kZero}, {15, 35, kZero}, {25, 35, kZero}, {35, 35, kZero},
2074 {5, 25, kZero}, {15, 25, color}, {25, 25, color}, {35, 25, kZero},
2075 {5, 15, kZero}, {15, 15, color}, {25, 15, color}, {35, 15, kZero},
2076 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kZero}, {35, 5, kZero},
2077 };
2078 CheckGoldenPixels(goldens, GL_RGBA8);
2079 }
2080
2081 // Verify that buffers which have both GPU_SAMPLED_IMAGE and GPU_COLOR_OUTPUT
2082 // can be both rendered and sampled as a texture.
TEST_P(ColorTest,GpuColorOutputAndSampledImage)2083 TEST_P(ColorTest, GpuColorOutputAndSampledImage) {
2084 AHardwareBuffer_Desc desc = GetParam();
2085 desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
2086 if (!SetUpBuffer(desc)) return;
2087
2088 // Bind the EGLImage to textures in both contexts.
2089 const int kTextureUnit = 1 % mMaxTextureUnits;
2090 for (int i = 0; i < mContextCount; ++i) {
2091 MakeCurrent(i);
2092 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2093 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2094 glTexParameteri(mTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2095 }
2096
2097 // In the second context, draw a checkerboard pattern.
2098 ASSERT_NO_FATAL_FAILURE(
2099 SetUpFramebuffer(desc.width, desc.height, desc.layers - 1, kBufferAsTexture));
2100 DrawCheckerboard(desc.width, desc.height, desc.format);
2101 glFinish();
2102
2103 // In the first context, draw a quad that samples from the texture.
2104 MakeCurrent(0);
2105 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
2106 glClearColor(0.f, 0.f, 0.f, 0.f);
2107 glClear(GL_COLOR_BUFFER_BIT);
2108
2109 if (desc.layers > 1) {
2110 ASSERT_NO_FATAL_FAILURE(
2111 SetUpProgram(std::string("#version 300 es") + kVertexShaderEs3x,
2112 kArrayFragmentShaderEs30, kQuadPositions, 0.5f, kTextureUnit));
2113 } else {
2114 std::string vertex_shader = GetTextureVertexShader(desc.format, desc.stride);
2115 std::string fragment_shader = GetTextureFragmentShader(desc.format, desc.stride);
2116 ASSERT_NO_FATAL_FAILURE(
2117 SetUpProgram(vertex_shader, fragment_shader, kQuadPositions,
2118 0.5f, kTextureUnit));
2119 }
2120 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2121 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2122
2123 // Check the rendered pixels. The lower left area of the checkerboard will
2124 // be either transparent or opaque black depending on whether the texture
2125 // format has an alpha channel.
2126 const GoldenColor kCBBlack = FormatHasAlpha(desc.format) ? kZero : kBlack;
2127 std::vector<GoldenPixel> goldens{
2128 {5, 35, kZero}, {15, 35, kZero}, {25, 35, kZero}, {35, 35, kZero},
2129 {5, 25, kZero}, {15, 25, kRed}, {25, 25, kBlue}, {35, 25, kZero},
2130 {5, 15, kZero}, {15, 15, kCBBlack}, {25, 15, kGreen}, {35, 15, kZero},
2131 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kZero}, {35, 5, kZero},
2132 };
2133 CheckGoldenPixels(goldens, GL_RGBA8, GetMaxExpectedColorError(desc.format, desc.stride));
2134 }
2135
TEST_P(ColorTest,MipmapComplete)2136 TEST_P(ColorTest, MipmapComplete) {
2137 if (mGLVersion < 30) {
2138 ALOGI("Test skipped: reading from nonzero level of a mipmap requires ES 3.0+, "
2139 "found %d.%d", mGLVersion / 10, mGLVersion % 10);
2140 return;
2141 }
2142 const int kNumTiles = 8;
2143 AHardwareBuffer_Desc desc = GetParam();
2144 // Ensure that the checkerboard tiles have equal size at every level of the mipmap.
2145 desc.width = std::max(8u, RoundUpToPowerOf2(desc.width));
2146 desc.height = std::max(8u, RoundUpToPowerOf2(desc.height));
2147 desc.usage =
2148 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
2149 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
2150 AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE;
2151 if (!SetUpBuffer(desc)) return;
2152
2153 const int kTextureUnit = 7 % mMaxTextureUnits;
2154 for (int i = 0; i < mContextCount; ++i) {
2155 MakeCurrent(i);
2156 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2157 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
2158 }
2159 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2160
2161 // Draw checkerboard for mipmapping.
2162 const int kTileWidth = desc.width / kNumTiles;
2163 const int kTileHeight = desc.height / kNumTiles;
2164 ASSERT_NO_FATAL_FAILURE(
2165 SetUpFramebuffer(desc.width, desc.height, desc.layers - 1, kBufferAsTexture));
2166 glEnable(GL_SCISSOR_TEST);
2167 for (int i = 0; i < kNumTiles; ++i) {
2168 for (int j = 0; j < kNumTiles; ++j) {
2169 const float v = (i & 1) ^ (j & 1) ? 1.f : 0.f;
2170 glClearColor(v, 0.f, 0.f, v);
2171 glScissor(i * kTileWidth, j * kTileHeight, kTileWidth, kTileHeight);
2172 glClear(GL_COLOR_BUFFER_BIT);
2173 }
2174 }
2175 glDisable(GL_SCISSOR_TEST);
2176 glGenerateMipmap(mTexTarget);
2177 glFinish();
2178 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2179
2180 MakeCurrent(0);
2181 ASSERT_NO_FATAL_FAILURE(
2182 SetUpFramebuffer(1, 1, desc.layers - 1, kBufferAsTexture, kNone, kNone, kNone,
2183 MipLevelCount(desc.width, desc.height) - 1));
2184 std::vector<GoldenPixel> goldens{{0, 0, (desc.stride & kUseSrgb) ? kRed50Srgb : kRed50}};
2185 CheckGoldenPixels(goldens, desc.format);
2186 }
2187
TEST_P(ColorTest,CubemapSampling)2188 TEST_P(ColorTest, CubemapSampling) {
2189 AHardwareBuffer_Desc desc = GetParam();
2190 desc.usage =
2191 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
2192 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
2193 AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
2194 desc.height = desc.width;
2195 desc.layers *= 6;
2196 if (!SetUpBuffer(desc)) return;
2197
2198 const int kTextureUnit = 4 % mMaxTextureUnits;
2199 for (int i = 0; i < mContextCount; ++i) {
2200 MakeCurrent(i);
2201 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2202 }
2203
2204 for (int i = 0; i < 6; ++i) {
2205 ASSERT_NO_FATAL_FAILURE(
2206 SetUpFramebuffer(desc.width, desc.height, desc.layers - 6 + i, kBufferAsTexture));
2207 DrawCheckerboard(desc.width, desc.height, desc.format);
2208 }
2209 glFinish();
2210
2211 MakeCurrent(0);
2212 if (desc.layers > 6) {
2213 ASSERT_NO_FATAL_FAILURE(
2214 SetUpProgram(std::string("#version 320 es") + kVertexShaderEs3x,
2215 kCubeMapArrayFragmentShaderEs32, kQuadPositions, 0.5f, kTextureUnit));
2216 } else {
2217 ASSERT_NO_FATAL_FAILURE(
2218 SetUpProgram(kVertexShader, kCubeMapFragmentShader, kQuadPositions, 0.5f, kTextureUnit));
2219 }
2220 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
2221 for (int i = 0; i < 6; ++i) {
2222 float face_vector[3] = {0.f, 0.f, 0.f};
2223 face_vector[i / 2] = (i % 2) ? -1.f : 1.f;
2224 glUniform3fv(mFaceVectorLocation, 1, face_vector);
2225 glClearColor(0.f, 0.f, 0.f, 0.f);
2226 glClear(GL_COLOR_BUFFER_BIT);
2227 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2228
2229 const GoldenColor kCBBlack = FormatHasAlpha(desc.format) ? kZero : kBlack;
2230 std::vector<GoldenPixel> goldens{
2231 {5, 35, kZero}, {15, 35, kZero}, {25, 35, kZero}, {35, 35, kZero},
2232 {5, 25, kZero}, {15, 25, kRed}, {25, 25, kBlue}, {35, 25, kZero},
2233 {5, 15, kZero}, {15, 15, kCBBlack}, {25, 15, kGreen}, {35, 15, kZero},
2234 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kZero}, {35, 5, kZero},
2235 };
2236 CheckGoldenPixels(goldens, GL_RGBA8);
2237 }
2238 }
2239
TEST_P(ColorTest,CubemapMipmaps)2240 TEST_P(ColorTest, CubemapMipmaps) {
2241 if (mGLVersion < 30) {
2242 ALOGI("Test skipped: reading from nonzero level of a mipmap requires ES 3.0+, "
2243 "found %d.%d", mGLVersion / 10, mGLVersion % 10);
2244 return;
2245 }
2246 const int kNumTiles = 8;
2247 AHardwareBuffer_Desc desc = GetParam();
2248 desc.usage =
2249 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
2250 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
2251 AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP |
2252 AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE;
2253 // Ensure that the checkerboard tiles have equal size at every level of the mipmap.
2254 desc.width = std::max(8u, RoundUpToPowerOf2(desc.width));
2255 desc.height = desc.width;
2256 desc.layers *= 6;
2257 if (!SetUpBuffer(desc)) return;
2258
2259 const int kTextureUnit = 5 % mMaxTextureUnits;
2260 for (int i = 0; i < mContextCount; ++i) {
2261 MakeCurrent(i);
2262 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2263 }
2264
2265 const int kTileSize = desc.width / kNumTiles;
2266 glEnable(GL_SCISSOR_TEST);
2267 for (int face = 0; face < 6; ++face) {
2268 ASSERT_NO_FATAL_FAILURE(
2269 SetUpFramebuffer(desc.width, desc.height, desc.layers - 6 + face, kBufferAsTexture));
2270 for (int i = 0; i < kNumTiles; ++i) {
2271 for (int j = 0; j < kNumTiles; ++j) {
2272 const float v = (i & 1) ^ (j & 1) ? 1.f : 0.f;
2273 glClearColor(v, 0.f, 0.f, v);
2274 glScissor(i * kTileSize, j * kTileSize, kTileSize, kTileSize);
2275 glClear(GL_COLOR_BUFFER_BIT);
2276 }
2277 }
2278 }
2279 glDisable(GL_SCISSOR_TEST);
2280 glGenerateMipmap(mTexTarget);
2281 glFinish();
2282
2283 MakeCurrent(0);
2284 for (int face = 0; face < 6; ++face) {
2285 ASSERT_NO_FATAL_FAILURE(
2286 SetUpFramebuffer(1, 1, desc.layers - 6 + face, kBufferAsTexture, kNone, kNone, kNone,
2287 MipLevelCount(desc.width, desc.height) - 1));
2288 std::vector<GoldenPixel> goldens{{0, 0, (desc.stride & kUseSrgb) ? kRed50Srgb : kRed50}};
2289 CheckGoldenPixels(goldens, desc.format);
2290 }
2291 }
2292
2293 // The 'stride' field is used to pass a combination of TestFlags.
2294 INSTANTIATE_TEST_CASE_P(
2295 SingleLayer, ColorTest,
2296 ::testing::Values(
2297 AHardwareBuffer_Desc{75, 33, 1, GL_RGB8, 0, kGlFormat, 0, 0},
2298 AHardwareBuffer_Desc{64, 80, 1, GL_RGBA8, 0, kGlFormat, 0, 0},
2299 AHardwareBuffer_Desc{49, 23, 1, GL_SRGB8_ALPHA8, 0, kGlFormat | kUseSrgb, 0, 0},
2300 AHardwareBuffer_Desc{63, 78, 1, GL_RGB565, 0, kGlFormat, 0, 0},
2301 AHardwareBuffer_Desc{42, 41, 1, GL_RGBA16F, 0, kGlFormat, 0, 0},
2302 AHardwareBuffer_Desc{37, 63, 1, GL_RGB10_A2, 0, kGlFormat, 0, 0},
2303 AHardwareBuffer_Desc{33, 20, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 0, 0, 0, 0},
2304 AHardwareBuffer_Desc{33, 20, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 0, kUseSrgb, 0, 0},
2305 AHardwareBuffer_Desc{20, 10, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, 0, 0, 0, 0},
2306 AHardwareBuffer_Desc{20, 10, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, 0, kUseSrgb, 0, 0},
2307 AHardwareBuffer_Desc{16, 20, 1, AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM, 0, 0, 0, 0},
2308 AHardwareBuffer_Desc{16, 20, 1, AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM, 0, kUseSrgb, 0, 0},
2309 AHardwareBuffer_Desc{10, 20, 1, AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM, 0, 0, 0, 0},
2310 AHardwareBuffer_Desc{10, 20, 1, AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT, 0, 0, 0, 0},
2311 AHardwareBuffer_Desc{10, 20, 1, AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM, 0, 0, 0, 0},
2312 AHardwareBuffer_Desc{64, 80, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, 0, 0, 0, 0},
2313 AHardwareBuffer_Desc{64, 80, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, 0,
2314 kExplicitYuvSampling, 0, 0}),
2315 &GetTestName);
2316
2317 INSTANTIATE_TEST_CASE_P(
2318 MultipleLayers, ColorTest,
2319 ::testing::Values(
2320 AHardwareBuffer_Desc{75, 33, 5, GL_RGB8, 0, kGlFormat, 0, 0},
2321 AHardwareBuffer_Desc{64, 80, 6, GL_RGBA8, 0, kGlFormat, 0, 0},
2322 AHardwareBuffer_Desc{33, 28, 4, GL_SRGB8_ALPHA8, 0, kGlFormat | kUseSrgb, 0, 0},
2323 AHardwareBuffer_Desc{42, 41, 3, GL_RGBA16F, 0, kGlFormat, 0, 0},
2324 AHardwareBuffer_Desc{63, 78, 3, GL_RGB565, 0, kGlFormat, 0, 0},
2325 AHardwareBuffer_Desc{37, 63, 4, GL_RGB10_A2, 0, kGlFormat, 0, 0},
2326 AHardwareBuffer_Desc{25, 77, 7, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 0, 0, 0, 0},
2327 AHardwareBuffer_Desc{25, 77, 7, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, 0, kUseSrgb, 0, 0},
2328 AHardwareBuffer_Desc{30, 30, 3, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, 0, 0, 0, 0},
2329 AHardwareBuffer_Desc{30, 30, 3, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, 0, kUseSrgb, 0, 0},
2330 AHardwareBuffer_Desc{50, 50, 4, AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM, 0, 0, 0, 0},
2331 AHardwareBuffer_Desc{50, 50, 4, AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM, 0, kUseSrgb, 0, 0},
2332 AHardwareBuffer_Desc{20, 10, 2, AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM, 0, 0, 0, 0},
2333 AHardwareBuffer_Desc{20, 20, 4, AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT, 0, 0, 0, 0},
2334 AHardwareBuffer_Desc{30, 20, 16, AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM, 0, 0, 0, 0}),
2335 &GetTestName);
2336
2337
2338 class DepthTest : public AHardwareBufferGLTest {};
2339
2340 // Verify that depth testing against a depth buffer rendered in another context
2341 // works correctly.
TEST_P(DepthTest,DepthAffectsDrawAcrossContexts)2342 TEST_P(DepthTest, DepthAffectsDrawAcrossContexts) {
2343 AHardwareBuffer_Desc desc = GetParam();
2344 desc.width = 40;
2345 desc.height = 40;
2346 desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
2347 // This test does not make sense for layered buffers - don't bother testing them.
2348 if (desc.layers > 1) return;
2349 if (!SetUpBuffer(desc)) return;
2350
2351 // Bind the EGLImage to renderbuffers and framebuffers in both contexts.
2352 // The depth buffer is shared, but the color buffer is not.
2353 for (int i = 0; i < mContextCount; ++i) {
2354 MakeCurrent(i);
2355 ASSERT_NO_FATAL_FAILURE(
2356 SetUpFramebuffer(40, 40, 0, kRenderbuffer, kBufferAsRenderbuffer));
2357 }
2358
2359 // In the second context, clear the depth buffer to a checkerboard pattern.
2360 DrawCheckerboard(40, 40, desc.format);
2361 glFinish();
2362
2363 // In the first context, clear the color buffer only, then draw a red pyramid.
2364 MakeCurrent(0);
2365 ASSERT_NO_FATAL_FAILURE(
2366 SetUpProgram(kVertexShader, kColorFragmentShader, kPyramidPositions, 1.f));
2367 glClearColor(0.f, 0.f, 0.f, 0.f);
2368 glClear(GL_COLOR_BUFFER_BIT);
2369 glEnable(GL_DEPTH_TEST);
2370 glDepthFunc(GL_LESS);
2371 glDrawArrays(GL_TRIANGLES, 0, kPyramidVertexCount);
2372 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2373
2374 // Check golden pixels.
2375 std::vector<GoldenPixel> goldens{
2376 {5, 35, kRed}, {15, 35, kRed}, {25, 35, kZero}, {35, 35, kZero},
2377 {5, 25, kRed}, {15, 25, kZero}, {25, 25, kZero}, {35, 25, kZero},
2378 {5, 15, kRed}, {15, 15, kRed}, {25, 15, kRed}, {35, 15, kRed},
2379 {5, 5, kRed}, {15, 5, kRed}, {25, 5, kRed}, {35, 5, kRed},
2380 };
2381 CheckGoldenPixels(goldens, GL_RGBA8);
2382 }
2383
2384 // Verify that depth buffers with usage GPU_SAMPLED_IMAGE can be used as textures.
TEST_P(DepthTest,DepthCanBeSampled)2385 TEST_P(DepthTest, DepthCanBeSampled) {
2386 AHardwareBuffer_Desc desc = GetParam();
2387 desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
2388 if (!SetUpBuffer(desc)) return;
2389
2390 // Bind the EGLImage to renderbuffers and framebuffers in both contexts.
2391 // The depth buffer is shared, but the color buffer is not.
2392 const int kTextureUnit = 3 % mMaxTextureUnits;
2393 for (int i = 0; i < 2; ++i) {
2394 MakeCurrent(i);
2395 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2396 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2397 glTexParameteri(mTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2398 }
2399
2400 // In the second context, attach the depth texture to the framebuffer and clear to 1.
2401 ASSERT_NO_FATAL_FAILURE(
2402 SetUpFramebuffer(desc.width, desc.height, desc.layers - 1, kNone, kBufferAsTexture));
2403 glClearDepthf(1.f);
2404 glClear(GL_DEPTH_BUFFER_BIT);
2405 glFinish();
2406
2407 // In the first context, draw a quad using the depth texture.
2408 MakeCurrent(0);
2409 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
2410 glClearColor(0.f, 0.f, 0.f, 0.f);
2411 glClear(GL_COLOR_BUFFER_BIT);
2412 if (desc.layers > 1) {
2413 ASSERT_NO_FATAL_FAILURE(
2414 SetUpProgram(std::string("#version 300 es") + kVertexShaderEs3x, kArrayFragmentShaderEs30,
2415 kQuadPositions, 0.5f, kTextureUnit));
2416 } else {
2417 std::string vertex_shader = GetTextureVertexShader(desc.format, desc.stride);
2418 std::string fragment_shader = GetTextureFragmentShader(desc.format, desc.stride);
2419 ASSERT_NO_FATAL_FAILURE(
2420 SetUpProgram(vertex_shader, fragment_shader, kQuadPositions, 0.5f, kTextureUnit));
2421 }
2422 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2423 glFinish();
2424 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2425
2426 // Check the rendered pixels. There should be a square in the middle.
2427 const GoldenColor kDepth = mGLVersion < 30 ? kWhite : kRed;
2428 std::vector<GoldenPixel> goldens{
2429 {5, 35, kZero}, {15, 35, kZero}, {25, 35, kZero}, {35, 35, kZero},
2430 {5, 25, kZero}, {15, 25, kDepth}, {25, 25, kDepth}, {35, 25, kZero},
2431 {5, 15, kZero}, {15, 15, kDepth}, {25, 15, kDepth}, {35, 15, kZero},
2432 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kZero}, {35, 5, kZero},
2433 };
2434 CheckGoldenPixels(goldens, GL_RGBA8);
2435 }
2436
TEST_P(DepthTest,DepthCubemapSampling)2437 TEST_P(DepthTest, DepthCubemapSampling) {
2438 AHardwareBuffer_Desc desc = GetParam();
2439 desc.usage =
2440 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
2441 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
2442 AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
2443 desc.height = desc.width;
2444 desc.layers *= 6;
2445 if (!SetUpBuffer(desc)) return;
2446
2447 const int kTextureUnit = 9 % mMaxTextureUnits;
2448 for (int i = 0; i < mContextCount; ++i) {
2449 MakeCurrent(i);
2450 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2451 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2452 glTexParameteri(mTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2453 }
2454
2455 glEnable(GL_SCISSOR_TEST);
2456 for (int i = 0; i < 6; ++i) {
2457 ASSERT_NO_FATAL_FAILURE(
2458 SetUpFramebuffer(desc.width, desc.height, desc.layers - 6 + i, kNone, kBufferAsTexture));
2459 glClearDepthf(0.f);
2460 glScissor(0, 0, desc.width, desc.height);
2461 glClear(GL_DEPTH_BUFFER_BIT);
2462 glClearDepthf(1.f);
2463 glScissor(0, 0, desc.width / 2, desc.height / 2);
2464 glClear(GL_DEPTH_BUFFER_BIT);
2465 glScissor(desc.width / 2, desc.height / 2, desc.width / 2, desc.height / 2);
2466 glClear(GL_DEPTH_BUFFER_BIT);
2467 }
2468 glDisable(GL_SCISSOR_TEST);
2469 glFinish();
2470 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2471
2472 MakeCurrent(0);
2473 if (desc.layers > 6) {
2474 ASSERT_NO_FATAL_FAILURE(
2475 SetUpProgram(std::string("#version 320 es") + kVertexShaderEs3x,
2476 kCubeMapArrayFragmentShaderEs32, kQuadPositions, 0.5f, kTextureUnit));
2477 } else {
2478 ASSERT_NO_FATAL_FAILURE(
2479 SetUpProgram(kVertexShader, kCubeMapFragmentShader, kQuadPositions, 0.5f, kTextureUnit));
2480 }
2481 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
2482 const GoldenColor kDepth = mGLVersion < 30 ? kWhite: kRed;
2483 for (int i = 0; i < 6; ++i) {
2484 float face_vector[3] = {0.f, 0.f, 0.f};
2485 face_vector[i / 2] = (i % 2) ? -1.f : 1.f;
2486 glUniform3fv(mFaceVectorLocation, 1, face_vector);
2487 glClearColor(0.f, 0.f, 0.f, 0.f);
2488 glClear(GL_COLOR_BUFFER_BIT);
2489 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2490 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2491
2492 std::vector<GoldenPixel> goldens{
2493 {5, 35, kZero}, {15, 35, kZero}, {25, 35, kZero}, {35, 35, kZero},
2494 {5, 25, kZero}, {15, 25, kBlack}, {25, 25, kDepth}, {35, 25, kZero},
2495 {5, 15, kZero}, {15, 15, kDepth}, {25, 15, kBlack}, {35, 15, kZero},
2496 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kZero}, {35, 5, kZero},
2497 };
2498 CheckGoldenPixels(goldens, GL_RGBA8);
2499 }
2500 }
2501
2502 // The 'stride' field is used to pass a combination of TestFlags.
2503 INSTANTIATE_TEST_CASE_P(
2504 SingleLayer, DepthTest,
2505 ::testing::Values(
2506 AHardwareBuffer_Desc{16, 24, 1, GL_DEPTH_COMPONENT16, 0, kGlFormat, 0, 0},
2507 AHardwareBuffer_Desc{16, 24, 1, AHARDWAREBUFFER_FORMAT_D16_UNORM, 0, 0, 0, 0},
2508 AHardwareBuffer_Desc{44, 21, 1, AHARDWAREBUFFER_FORMAT_D24_UNORM, 0, 0, 0, 0},
2509 AHardwareBuffer_Desc{57, 33, 1, AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT, 0, 0, 0, 0},
2510 AHardwareBuffer_Desc{20, 10, 1, AHARDWAREBUFFER_FORMAT_D32_FLOAT, 0, 0, 0, 0},
2511 AHardwareBuffer_Desc{57, 33, 1, AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT, 0, 0, 0, 0}),
2512 &GetTestName);
2513
2514
2515 INSTANTIATE_TEST_CASE_P(
2516 MultipleLayers, DepthTest,
2517 ::testing::Values(
2518 AHardwareBuffer_Desc{16, 24, 6, GL_DEPTH_COMPONENT16, 0, kGlFormat, 0, 0},
2519 AHardwareBuffer_Desc{16, 24, 6, AHARDWAREBUFFER_FORMAT_D16_UNORM, 0, 0, 0, 0},
2520 AHardwareBuffer_Desc{44, 21, 4, AHARDWAREBUFFER_FORMAT_D24_UNORM, 0, 0, 0, 0},
2521 AHardwareBuffer_Desc{57, 33, 7, AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT, 0, 0, 0, 0},
2522 AHardwareBuffer_Desc{20, 10, 5, AHARDWAREBUFFER_FORMAT_D32_FLOAT, 0, 0, 0, 0},
2523 AHardwareBuffer_Desc{57, 33, 3, AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT, 0, 0, 0, 0}),
2524 &GetTestName);
2525
2526
2527 class StencilTest : public AHardwareBufferGLTest {};
2528
2529 // Verify that stencil testing against a stencil buffer rendered in another context
2530 // works correctly.
TEST_P(StencilTest,StencilAffectsDrawAcrossContexts)2531 TEST_P(StencilTest, StencilAffectsDrawAcrossContexts) {
2532 AHardwareBuffer_Desc desc = GetParam();
2533 desc.width = 40;
2534 desc.height = 40;
2535 desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
2536 // This test does not make sense for layered buffers - don't bother testing them.
2537 if (desc.layers > 1) return;
2538 if (!SetUpBuffer(desc)) return;
2539
2540 // Bind the EGLImage to renderbuffers and framebuffers in both contexts.
2541 // The depth buffer is shared, but the color buffer is not.
2542 for (int i = 0; i < mContextCount; ++i) {
2543 MakeCurrent(i);
2544 ASSERT_NO_FATAL_FAILURE(
2545 SetUpFramebuffer(40, 40, 0, kRenderbuffer, kNone, kBufferAsRenderbuffer));
2546 }
2547
2548 // In the second context, clear the stencil buffer to a checkerboard pattern.
2549 DrawCheckerboard(40, 40, desc.format);
2550 glFinish();
2551 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2552
2553 // In the first context, clear the color buffer only, then draw a flat quad.
2554 MakeCurrent(0);
2555 ASSERT_NO_FATAL_FAILURE(
2556 SetUpProgram(kVertexShader, kColorFragmentShader, kQuadPositions, 1.f));
2557 glClearColor(0.f, 0.f, 0.f, 0.f);
2558 glClear(GL_COLOR_BUFFER_BIT);
2559 glEnable(GL_STENCIL_TEST);
2560 glStencilFunc(GL_ALWAYS, 0, 0xFF);
2561 glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
2562 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2563 glClear(GL_COLOR_BUFFER_BIT);
2564 glStencilFunc(GL_EQUAL, 2, 0xFF);
2565 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2566 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2567 glUniform4f(mColorLocation, 0.f, 1.f, 0.f, 1.f);
2568 glStencilFunc(GL_EQUAL, 4, 0xFF);
2569 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2570 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2571 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2572
2573 // Check golden pixels.
2574 std::vector<GoldenPixel> goldens{
2575 {5, 35, kRed}, {15, 35, kRed}, {25, 35, kZero}, {35, 35, kZero},
2576 {5, 25, kRed}, {15, 25, kRed}, {25, 25, kZero}, {35, 25, kZero},
2577 {5, 15, kZero}, {15, 15, kZero}, {25, 15, kGreen}, {35, 15, kGreen},
2578 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kGreen}, {35, 5, kGreen},
2579 };
2580 CheckGoldenPixels(goldens, GL_RGBA8);
2581 }
2582
2583 // Verify that stencil testing against a stencil buffer rendered in another context
2584 // works correctly.
TEST_P(StencilTest,StencilTexture)2585 TEST_P(StencilTest, StencilTexture) {
2586 AHardwareBuffer_Desc desc = GetParam();
2587 desc.usage = AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
2588 const bool kPureStencil =
2589 desc.format == GL_STENCIL_INDEX8 || desc.format == AHARDWAREBUFFER_FORMAT_S8_UINT;
2590 // Pure stencil textures are only supported with an extension. Note: we don't exit for the
2591 // AHB format here, because we want to ensure that buffer allocation fails with the
2592 // GPU_SAMPLED_IMAGE usage flag if the implementation doesn't support pure stencil textures.
2593 if (desc.format == GL_STENCIL_INDEX8 && !HasGLExtension("GL_OES_texture_stencil8")) return;
2594 // Stencil sampling from depth-stencil textures was introduced in ES 3.1.
2595 if (!kPureStencil && mGLVersion < 31) return;
2596 if (!SetUpBuffer(desc)) return;
2597
2598 const int kTextureUnit = 8 % mMaxTextureUnits;
2599 for (int i = 0; i < mContextCount; ++i) {
2600 MakeCurrent(i);
2601 ASSERT_NO_FATAL_FAILURE(SetUpTexture(desc, kTextureUnit));
2602 glTexParameteri(mTexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2603 glTexParameteri(mTexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2604 if (!kPureStencil) {
2605 glTexParameteri(mTexTarget, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
2606 }
2607 }
2608
2609 // In the second context, clear the stencil buffer to a checkerboard pattern.
2610 ASSERT_NO_FATAL_FAILURE(
2611 SetUpFramebuffer(desc.width, desc.height, desc.layers - 1,
2612 kNone, kNone, kBufferAsTexture));
2613 DrawCheckerboard(desc.width, desc.height, desc.format);
2614 glFinish();
2615 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2616
2617 // In the first context, reconstruct the checkerboard with a special shader.
2618 MakeCurrent(0);
2619 ASSERT_NO_FATAL_FAILURE(
2620 SetUpProgram(std::string("#version 300 es") + kVertexShaderEs3x,
2621 desc.layers > 1 ? kStencilArrayFragmentShaderEs30 : kStencilFragmentShaderEs30,
2622 kQuadPositions, 1.f, kTextureUnit));
2623 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(40, 40, 0, kRenderbuffer));
2624 glDrawArrays(GL_TRIANGLES, 0, kQuadVertexCount);
2625 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2626
2627 // Check golden pixels.
2628 std::vector<GoldenPixel> goldens{
2629 {5, 35, kRed}, {15, 35, kRed}, {25, 35, kBlue}, {35, 35, kBlue},
2630 {5, 25, kRed}, {15, 25, kRed}, {25, 25, kBlue}, {35, 25, kBlue},
2631 {5, 15, kZero}, {15, 15, kZero}, {25, 15, kGreen}, {35, 15, kGreen},
2632 {5, 5, kZero}, {15, 5, kZero}, {25, 5, kGreen}, {35, 5, kGreen},
2633 };
2634 CheckGoldenPixels(goldens, GL_RGBA8);
2635 }
2636
2637 // The 'stride' field is used to pass a combination of TestFlags.
2638 INSTANTIATE_TEST_CASE_P(
2639 SingleLayer, StencilTest,
2640 ::testing::Values(
2641 AHardwareBuffer_Desc{49, 57, 1, GL_STENCIL_INDEX8, 0, kGlFormat, 0, 0},
2642 AHardwareBuffer_Desc{36, 50, 1, GL_DEPTH24_STENCIL8, 0, kGlFormat, 0, 0},
2643 AHardwareBuffer_Desc{26, 29, 1, AHARDWAREBUFFER_FORMAT_S8_UINT, 0, 0, 0, 0},
2644 AHardwareBuffer_Desc{57, 33, 1, AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT, 0, 0, 0, 0},
2645 AHardwareBuffer_Desc{17, 23, 1, AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT, 0, 0, 0, 0}),
2646 &GetTestName);
2647
2648 INSTANTIATE_TEST_CASE_P(
2649 MultipleLayers, StencilTest,
2650 ::testing::Values(
2651 AHardwareBuffer_Desc{49, 57, 3, GL_STENCIL_INDEX8, 0, kGlFormat, 0, 0},
2652 AHardwareBuffer_Desc{36, 50, 6, GL_DEPTH24_STENCIL8, 0, kGlFormat, 0, 0},
2653 AHardwareBuffer_Desc{26, 29, 5, AHARDWAREBUFFER_FORMAT_S8_UINT, 0, 0, 0, 0},
2654 AHardwareBuffer_Desc{57, 33, 4, AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT, 0, 0, 0, 0},
2655 AHardwareBuffer_Desc{17, 23, 7, AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT, 0, 0, 0, 0}),
2656 &GetTestName);
2657
2658 class R8Test : public AHardwareBufferGLTest {};
2659
2660 // Verify that if we can allocate an R8 AHB we can render to it.
TEST_P(R8Test,Write)2661 TEST_P(R8Test, Write) {
2662 AHardwareBuffer_Desc desc = GetParam();
2663 desc.usage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
2664 if (!SetUpBuffer(desc)) {
2665 return;
2666 }
2667
2668 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(desc.width, desc.height, 0, kBufferAsRenderbuffer));
2669 ASSERT_NO_FATAL_FAILURE(
2670 SetUpProgram(kVertexShader, kColorFragmentShader, kPyramidPositions, 0.5f));
2671
2672 glDrawArrays(GL_TRIANGLES, 0, kPyramidVertexCount);
2673 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2674 }
2675
2676 INSTANTIATE_TEST_CASE_P(
2677 SingleLayer, R8Test,
2678 ::testing::Values(
2679 AHardwareBuffer_Desc{57, 33, 1, AHARDWAREBUFFER_FORMAT_R8_UNORM, 0, 0, 0, 0}),
2680 &GetTestName);
2681
2682 class R16UITest : public AHardwareBufferGLTest {};
2683
2684 // Verify that if we can allocate an R16_UINT AHB we can render to it.
TEST_P(R16UITest,Write)2685 TEST_P(R16UITest, Write) {
2686 AHardwareBuffer_Desc desc = GetParam();
2687 desc.usage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
2688 if (!SetUpBuffer(desc)) {
2689 return;
2690 }
2691
2692 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(desc.width, desc.height, 0, kBufferAsRenderbuffer));
2693 ASSERT_NO_FATAL_FAILURE(
2694 SetUpProgram(kVertexShader, kColorFragmentShader, kPyramidPositions, 0.5f));
2695
2696 glDrawArrays(GL_TRIANGLES, 0, kPyramidVertexCount);
2697 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2698 }
2699
2700 INSTANTIATE_TEST_CASE_P(
2701 SingleLayer, R16UITest,
2702 ::testing::Values(
2703 AHardwareBuffer_Desc{57, 33, 1, AHARDWAREBUFFER_FORMAT_R16_UINT, 0, 0, 0, 0}),
2704 &GetTestName);
2705
2706 class RG16UITest : public AHardwareBufferGLTest {};
2707
2708 // Verify that if we can allocate an R16G16_UINT AHB we can render to it.
TEST_P(RG16UITest,Write)2709 TEST_P(RG16UITest, Write) {
2710 AHardwareBuffer_Desc desc = GetParam();
2711 desc.usage = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
2712 if (!SetUpBuffer(desc)) {
2713 return;
2714 }
2715
2716 ASSERT_NO_FATAL_FAILURE(SetUpFramebuffer(desc.width, desc.height, 0, kBufferAsRenderbuffer));
2717 ASSERT_NO_FATAL_FAILURE(
2718 SetUpProgram(kVertexShader, kColorFragmentShader, kPyramidPositions, 0.5f));
2719
2720 glDrawArrays(GL_TRIANGLES, 0, kPyramidVertexCount);
2721 ASSERT_EQ(GLenum{GL_NO_ERROR}, glGetError());
2722 }
2723
2724 INSTANTIATE_TEST_CASE_P(
2725 SingleLayer, RG16UITest,
2726 ::testing::Values(
2727 AHardwareBuffer_Desc{57, 33, 1, AHARDWAREBUFFER_FORMAT_R16G16_UINT, 0, 0, 0, 0}),
2728 &GetTestName);
2729
2730 } // namespace android
2731