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