1 /*
2 * Copyright (C) 2011 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 <gtest/gtest.h>
18
19 #include <SurfaceFlingerProperties.h>
20 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
21
22 #include <configstore/Utils.h>
23 #include <utils/String8.h>
24
25 #include <EGL/egl.h>
26 #include <gui/Surface.h>
27 #include <gui/IConsumerListener.h>
28 #include <gui/IProducerListener.h>
29 #include <gui/IGraphicBufferConsumer.h>
30 #include <gui/BufferQueue.h>
31
hasEglExtension(EGLDisplay dpy,const char * extensionName)32 bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
33 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
34 size_t cropExtLen = strlen(extensionName);
35 size_t extsLen = strlen(exts);
36 bool equal = !strcmp(extensionName, exts);
37 android::String8 extString(extensionName);
38 android::String8 space(" ");
39 bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
40 bool atEnd = (cropExtLen + 1) < extsLen &&
41 !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
42 bool inMiddle = strstr(exts, space + extString + space);
43 return equal || atStart || atEnd || inMiddle;
44 }
45
46 namespace android {
47
48 #define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
49
50 // retrieve wide-color setting from configstore
51 using namespace android::hardware::configstore;
52 using namespace android::hardware::configstore::V1_0;
53
54 #define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT))
55
56 static bool hasWideColorDisplay = android::sysprop::has_wide_color_display(false);
57
58 static bool hasHdrDisplay = android::sysprop::has_HDR_display(false);
59
60 class EGLTest : public ::testing::Test {
61 public:
62 void get8BitConfig(EGLConfig& config);
63 void setSurfaceSmpteMetadata(EGLSurface surface);
64 void checkSurfaceSmpteMetadata(EGLSurface eglSurface);
65
66 protected:
67 EGLDisplay mEglDisplay;
68
69 protected:
EGLTest()70 EGLTest() :
71 mEglDisplay(EGL_NO_DISPLAY) {
72 }
73
SetUp()74 virtual void SetUp() {
75 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
76 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
77 ASSERT_EQ(EGL_SUCCESS, eglGetError());
78
79 EGLint majorVersion;
80 EGLint minorVersion;
81 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
82 ASSERT_EQ(EGL_SUCCESS, eglGetError());
83 RecordProperty("EglVersionMajor", majorVersion);
84 RecordProperty("EglVersionMajor", minorVersion);
85 }
86
TearDown()87 virtual void TearDown() {
88 EGLBoolean success = eglTerminate(mEglDisplay);
89 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
90 ASSERT_EQ(EGL_SUCCESS, eglGetError());
91 }
92 };
93
TEST_F(EGLTest,DISABLED_EGLConfigEightBitFirst)94 TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) {
95
96 EGLint numConfigs;
97 EGLConfig config;
98 EGLBoolean success;
99 EGLint attrs[] = {
100 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
101 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
102 EGL_NONE
103 };
104
105 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
106 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
107 ASSERT_EQ(EGL_SUCCESS, eglGetError());
108 ASSERT_GE(numConfigs, 1);
109
110 EGLint components[3];
111
112 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
113 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
114 ASSERT_EQ(EGL_SUCCESS, eglGetError());
115 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
116 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
117 ASSERT_EQ(EGL_SUCCESS, eglGetError());
118 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
119 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
120 ASSERT_EQ(EGL_SUCCESS, eglGetError());
121
122 EXPECT_GE(components[0], 8);
123 EXPECT_GE(components[1], 8);
124 EXPECT_GE(components[2], 8);
125 }
126
TEST_F(EGLTest,EGLTerminateSucceedsWithRemainingObjects)127 TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) {
128 EGLint numConfigs;
129 EGLConfig config;
130 EGLint attrs[] = {
131 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
132 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
133 EGL_RED_SIZE, 8,
134 EGL_GREEN_SIZE, 8,
135 EGL_BLUE_SIZE, 8,
136 EGL_ALPHA_SIZE, 8,
137 EGL_NONE
138 };
139 EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
140
141 struct MockConsumer : public BnConsumerListener {
142 void onFrameAvailable(const BufferItem& /* item */) override {}
143 void onBuffersReleased() override {}
144 void onSidebandStreamChanged() override {}
145 };
146
147 // Create a EGLSurface
148 sp<IGraphicBufferProducer> producer;
149 sp<IGraphicBufferConsumer> consumer;
150 BufferQueue::createBufferQueue(&producer, &consumer);
151 consumer->consumerConnect(new MockConsumer, false);
152 sp<Surface> mSTC = new Surface(producer);
153 sp<ANativeWindow> mANW = mSTC;
154
155 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config,
156 mANW.get(), NULL);
157 ASSERT_EQ(EGL_SUCCESS, eglGetError());
158 ASSERT_NE(EGL_NO_SURFACE, eglSurface) ;
159
160 // do not destroy eglSurface
161 // eglTerminate is called in the tear down and should destroy it for us
162 }
163
TEST_F(EGLTest,EGLConfigRGBA8888First)164 TEST_F(EGLTest, EGLConfigRGBA8888First) {
165
166 EGLint numConfigs;
167 EGLConfig config;
168 EGLBoolean success;
169 EGLint attrs[] = {
170 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
171 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
172 EGL_RED_SIZE, 8,
173 EGL_GREEN_SIZE, 8,
174 EGL_BLUE_SIZE, 8,
175 EGL_ALPHA_SIZE, 8,
176 EGL_NONE
177 };
178
179 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
180 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
181 ASSERT_EQ(EGL_SUCCESS, eglGetError());
182 ASSERT_GE(numConfigs, 1);
183
184 EGLint components[4];
185
186 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
187 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
188 ASSERT_EQ(EGL_SUCCESS, eglGetError());
189 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
190 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
191 ASSERT_EQ(EGL_SUCCESS, eglGetError());
192 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
193 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
194 ASSERT_EQ(EGL_SUCCESS, eglGetError());
195 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
196 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
197 ASSERT_EQ(EGL_SUCCESS, eglGetError());
198
199 EXPECT_GE(components[0], 8);
200 EXPECT_GE(components[1], 8);
201 EXPECT_GE(components[2], 8);
202 EXPECT_GE(components[3], 8);
203 }
204
TEST_F(EGLTest,EGLDisplayP3)205 TEST_F(EGLTest, EGLDisplayP3) {
206 EGLint numConfigs;
207 EGLConfig config;
208 EGLBoolean success;
209
210 if (!hasWideColorDisplay) {
211 // skip this test if device does not have wide-color display
212 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
213 return;
214 }
215
216 // Test that display-p3 extensions exist
217 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
218 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
219 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
220
221 // Use 8-bit to keep forcus on Display-P3 aspect
222 EGLint attrs[] = {
223 // clang-format off
224 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
225 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
226 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
227 EGL_RED_SIZE, 8,
228 EGL_GREEN_SIZE, 8,
229 EGL_BLUE_SIZE, 8,
230 EGL_ALPHA_SIZE, 8,
231 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
232 EGL_NONE, EGL_NONE
233 // clang-format on
234 };
235 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
236 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
237 ASSERT_EQ(1, numConfigs);
238
239 EGLint components[4];
240 EGLint value;
241 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
242
243 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
244 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
245 ASSERT_EQ(EGL_SUCCESS, eglGetError());
246 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
247 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
248 ASSERT_EQ(EGL_SUCCESS, eglGetError());
249 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
250 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
251 ASSERT_EQ(EGL_SUCCESS, eglGetError());
252 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
253 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
254 ASSERT_EQ(EGL_SUCCESS, eglGetError());
255
256 EXPECT_EQ(components[0], 8);
257 EXPECT_EQ(components[1], 8);
258 EXPECT_EQ(components[2], 8);
259 EXPECT_EQ(components[3], 8);
260
261 struct MockConsumer : public BnConsumerListener {
262 void onFrameAvailable(const BufferItem& /* item */) override {}
263 void onBuffersReleased() override {}
264 void onSidebandStreamChanged() override {}
265 };
266
267 // Create a EGLSurface
268 sp<IGraphicBufferProducer> producer;
269 sp<IGraphicBufferConsumer> consumer;
270 BufferQueue::createBufferQueue(&producer, &consumer);
271 consumer->consumerConnect(new MockConsumer, false);
272 sp<Surface> mSTC = new Surface(producer);
273 sp<ANativeWindow> mANW = mSTC;
274 EGLint winAttrs[] = {
275 // clang-format off
276 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
277 EGL_NONE, EGL_NONE
278 // clang-format on
279 };
280
281 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
282 ASSERT_EQ(EGL_SUCCESS, eglGetError());
283 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
284
285 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
286 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
287 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
288
289 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
290 }
291
TEST_F(EGLTest,EGLDisplayP3Passthrough)292 TEST_F(EGLTest, EGLDisplayP3Passthrough) {
293 EGLConfig config;
294 EGLBoolean success;
295
296 if (!hasWideColorDisplay) {
297 // skip this test if device does not have wide-color display
298 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
299 return;
300 }
301
302 // Test that display-p3 extensions exist
303 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
304 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
305 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
306
307 get8BitConfig(config);
308
309 struct MockConsumer : public BnConsumerListener {
310 void onFrameAvailable(const BufferItem& /* item */) override {}
311 void onBuffersReleased() override {}
312 void onSidebandStreamChanged() override {}
313 };
314
315 // Create a EGLSurface
316 sp<IGraphicBufferProducer> producer;
317 sp<IGraphicBufferConsumer> consumer;
318 BufferQueue::createBufferQueue(&producer, &consumer);
319 consumer->consumerConnect(new MockConsumer, false);
320 sp<Surface> mSTC = new Surface(producer);
321 sp<ANativeWindow> mANW = mSTC;
322 EGLint winAttrs[] = {
323 // clang-format off
324 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT,
325 EGL_NONE, EGL_NONE
326 // clang-format on
327 };
328
329 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
330 ASSERT_EQ(EGL_SUCCESS, eglGetError());
331 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
332
333 android_dataspace dataspace =
334 static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
335 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
336
337 EGLint value;
338 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
339 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
340 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT, value);
341
342 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
343 }
344
TEST_F(EGLTest,EGLDisplayP31010102)345 TEST_F(EGLTest, EGLDisplayP31010102) {
346 // This test has been failing since:
347 // libEGL: When driver doesn't understand P3, map sRGB-encoded P3 to sRGB
348 // https://android-review.git.corp.google.com/c/platform/frameworks/native/+/793504
349 GTEST_SKIP() << "Skipping broken test. See b/120714942 and b/117104367";
350
351 EGLint numConfigs;
352 EGLConfig config;
353 EGLBoolean success;
354
355 if (!hasWideColorDisplay) {
356 // skip this test if device does not have wide-color display
357 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
358 return;
359 }
360
361 // Test that display-p3 extensions exist
362 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
363 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
364 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
365
366 // Use 8-bit to keep forcus on Display-P3 aspect
367 EGLint attrs[] = {
368 // clang-format off
369 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
370 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
371 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
372 EGL_RED_SIZE, 10,
373 EGL_GREEN_SIZE, 10,
374 EGL_BLUE_SIZE, 10,
375 EGL_ALPHA_SIZE, 2,
376 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
377 EGL_NONE, EGL_NONE
378 // clang-format on
379 };
380 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
381 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
382 ASSERT_EQ(1, numConfigs);
383
384 EGLint components[4];
385 EGLint value;
386 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
387
388 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
389 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
390 ASSERT_EQ(EGL_SUCCESS, eglGetError());
391 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
392 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
393 ASSERT_EQ(EGL_SUCCESS, eglGetError());
394 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
395 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
396 ASSERT_EQ(EGL_SUCCESS, eglGetError());
397 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
398 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
399 ASSERT_EQ(EGL_SUCCESS, eglGetError());
400
401 EXPECT_EQ(components[0], 10);
402 EXPECT_EQ(components[1], 10);
403 EXPECT_EQ(components[2], 10);
404 EXPECT_EQ(components[3], 2);
405
406 struct MockConsumer : public BnConsumerListener {
407 void onFrameAvailable(const BufferItem& /* item */) override {}
408 void onBuffersReleased() override {}
409 void onSidebandStreamChanged() override {}
410 };
411
412 // Create a EGLSurface
413 sp<IGraphicBufferProducer> producer;
414 sp<IGraphicBufferConsumer> consumer;
415 BufferQueue::createBufferQueue(&producer, &consumer);
416 consumer->consumerConnect(new MockConsumer, false);
417 sp<Surface> mSTC = new Surface(producer);
418 sp<ANativeWindow> mANW = mSTC;
419 EGLint winAttrs[] = {
420 // clang-format off
421 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
422 EGL_NONE, EGL_NONE
423 // clang-format on
424 };
425
426 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
427 ASSERT_EQ(EGL_SUCCESS, eglGetError());
428 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
429
430 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
431 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
432 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
433
434 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
435 }
436
get8BitConfig(EGLConfig & config)437 void EGLTest::get8BitConfig(EGLConfig& config) {
438 EGLint numConfigs;
439 EGLBoolean success;
440
441 // Use 8-bit to keep focus on colorspace aspect
442 const EGLint attrs[] = {
443 // clang-format off
444 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
445 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
446 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
447 EGL_RED_SIZE, 8,
448 EGL_GREEN_SIZE, 8,
449 EGL_BLUE_SIZE, 8,
450 EGL_ALPHA_SIZE, 8,
451 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
452 EGL_NONE,
453 // clang-format on
454 };
455 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
456 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
457 ASSERT_EQ(1, numConfigs);
458
459 EGLint components[4];
460 EGLint value;
461 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
462
463 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
464 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
465 ASSERT_EQ(EGL_SUCCESS, eglGetError());
466 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
467 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
468 ASSERT_EQ(EGL_SUCCESS, eglGetError());
469 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
470 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
471 ASSERT_EQ(EGL_SUCCESS, eglGetError());
472 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
473 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
474 ASSERT_EQ(EGL_SUCCESS, eglGetError());
475
476 // Verify component sizes on config match what was asked for.
477 EXPECT_EQ(components[0], 8);
478 EXPECT_EQ(components[1], 8);
479 EXPECT_EQ(components[2], 8);
480 EXPECT_EQ(components[3], 8);
481 }
482
setSurfaceSmpteMetadata(EGLSurface surface)483 void EGLTest::setSurfaceSmpteMetadata(EGLSurface surface) {
484 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
485 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT,
486 METADATA_SCALE(0.640));
487 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT,
488 METADATA_SCALE(0.330));
489 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT,
490 METADATA_SCALE(0.290));
491 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT,
492 METADATA_SCALE(0.600));
493 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT,
494 METADATA_SCALE(0.150));
495 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT,
496 METADATA_SCALE(0.060));
497 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_X_EXT,
498 METADATA_SCALE(0.3127));
499 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_Y_EXT,
500 METADATA_SCALE(0.3290));
501 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT,
502 METADATA_SCALE(300));
503 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MIN_LUMINANCE_EXT,
504 METADATA_SCALE(0.7));
505 }
506
507 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
508 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT,
509 METADATA_SCALE(300));
510 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT,
511 METADATA_SCALE(75));
512 }
513 }
514
checkSurfaceSmpteMetadata(EGLSurface eglSurface)515 void EGLTest::checkSurfaceSmpteMetadata(EGLSurface eglSurface) {
516 EGLBoolean success;
517 EGLint value;
518
519 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
520 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, &value);
521 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
522 ASSERT_EQ(METADATA_SCALE(0.640), value);
523 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, &value);
524 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
525 ASSERT_EQ(METADATA_SCALE(0.330), value);
526 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, &value);
527 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
528 ASSERT_EQ(METADATA_SCALE(0.290), value);
529 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, &value);
530 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
531 ASSERT_EQ(METADATA_SCALE(0.600), value);
532 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, &value);
533 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
534 ASSERT_EQ(METADATA_SCALE(0.150), value);
535 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, &value);
536 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
537 ASSERT_EQ(METADATA_SCALE(0.060), value);
538 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_X_EXT, &value);
539 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
540 ASSERT_EQ(METADATA_SCALE(0.3127), value);
541 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, &value);
542 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
543 ASSERT_EQ(METADATA_SCALE(0.3290), value);
544 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, &value);
545 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
546 ASSERT_EQ(METADATA_SCALE(300.0), value);
547 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, &value);
548 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
549 ASSERT_EQ(METADATA_SCALE(0.7), value);
550 }
551
552 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
553 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, &value);
554 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
555 ASSERT_EQ(METADATA_SCALE(300.0), value);
556 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, &value);
557 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
558 ASSERT_EQ(METADATA_SCALE(75.0), value);
559 }
560 }
561
TEST_F(EGLTest,EGLBT2020Linear)562 TEST_F(EGLTest, EGLBT2020Linear) {
563 EGLConfig config;
564 EGLBoolean success;
565
566 if (!hasHdrDisplay) {
567 // skip this test if device does not have HDR display
568 RecordProperty("hasHdrDisplay", false);
569 return;
570 }
571
572 // Test that bt2020 linear extension exists
573 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"))
574 << "EGL_EXT_gl_colorspace_bt2020_linear extension not available";
575
576 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
577
578 struct MockConsumer : public BnConsumerListener {
579 void onFrameAvailable(const BufferItem& /* item */) override {}
580 void onBuffersReleased() override {}
581 void onSidebandStreamChanged() override {}
582 };
583
584 // Create a EGLSurface
585 sp<IGraphicBufferProducer> producer;
586 sp<IGraphicBufferConsumer> consumer;
587 BufferQueue::createBufferQueue(&producer, &consumer);
588 consumer->consumerConnect(new MockConsumer, false);
589 sp<Surface> mSTC = new Surface(producer);
590 sp<ANativeWindow> mANW = mSTC;
591
592 std::vector<EGLint> winAttrs;
593 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
594 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
595
596 winAttrs.push_back(EGL_NONE);
597
598 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
599 ASSERT_EQ(EGL_SUCCESS, eglGetError());
600 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
601
602 EGLint value;
603 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
604 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
605 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
606
607 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
608
609 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
610
611 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
612 }
613
TEST_F(EGLTest,EGLBT2020PQ)614 TEST_F(EGLTest, EGLBT2020PQ) {
615 EGLConfig config;
616 EGLBoolean success;
617
618 if (!hasHdrDisplay) {
619 // skip this test if device does not have HDR display
620 RecordProperty("hasHdrDisplay", false);
621 return;
622 }
623
624 // Test that bt2020-pq extension exists
625 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"))
626 << "EGL_EXT_gl_colorspace_bt2020_pq extension not available";
627
628 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
629
630 struct MockConsumer : public BnConsumerListener {
631 void onFrameAvailable(const BufferItem& /* item */) override {}
632 void onBuffersReleased() override {}
633 void onSidebandStreamChanged() override {}
634 };
635
636 // Create a EGLSurface
637 sp<IGraphicBufferProducer> producer;
638 sp<IGraphicBufferConsumer> consumer;
639 BufferQueue::createBufferQueue(&producer, &consumer);
640 consumer->consumerConnect(new MockConsumer, false);
641 sp<Surface> mSTC = new Surface(producer);
642 sp<ANativeWindow> mANW = mSTC;
643 std::vector<EGLint> winAttrs;
644 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
645 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
646 winAttrs.push_back(EGL_NONE);
647
648 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
649 ASSERT_EQ(EGL_SUCCESS, eglGetError());
650 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
651
652 EGLint value;
653 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
654 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
655 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
656
657 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
658
659 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
660
661 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
662 }
663
TEST_F(EGLTest,EGLConfigFP16)664 TEST_F(EGLTest, EGLConfigFP16) {
665 EGLint numConfigs;
666 EGLConfig config;
667 EGLBoolean success;
668
669 if (!hasWideColorDisplay) {
670 // skip this test if device does not have wide-color display
671 RecordProperty("hasWideColorDisplay", false);
672 return;
673 }
674
675 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
676
677 const EGLint attrs[] = {
678 // clang-format off
679 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
680 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
681 EGL_RED_SIZE, 16,
682 EGL_GREEN_SIZE, 16,
683 EGL_BLUE_SIZE, 16,
684 EGL_ALPHA_SIZE, 16,
685 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
686 EGL_NONE,
687 // clang-format on
688 };
689 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
690 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
691 ASSERT_EQ(1, numConfigs);
692
693 EGLint components[4];
694
695 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
696 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
697 ASSERT_EQ(EGL_SUCCESS, eglGetError());
698 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
699 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
700 ASSERT_EQ(EGL_SUCCESS, eglGetError());
701 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
702 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
703 ASSERT_EQ(EGL_SUCCESS, eglGetError());
704 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
705 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
706 ASSERT_EQ(EGL_SUCCESS, eglGetError());
707
708 EXPECT_GE(components[0], 16);
709 EXPECT_GE(components[1], 16);
710 EXPECT_GE(components[2], 16);
711 EXPECT_GE(components[3], 16);
712
713 struct MockConsumer : public BnConsumerListener {
714 void onFrameAvailable(const BufferItem& /* item */) override {}
715 void onBuffersReleased() override {}
716 void onSidebandStreamChanged() override {}
717 };
718
719 sp<IGraphicBufferProducer> producer;
720 sp<IGraphicBufferConsumer> consumer;
721 BufferQueue::createBufferQueue(&producer, &consumer);
722 consumer->consumerConnect(new MockConsumer, false);
723 sp<Surface> mSTC = new Surface(producer);
724 sp<ANativeWindow> mANW = mSTC;
725
726 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
727 ASSERT_EQ(EGL_SUCCESS, eglGetError());
728 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
729
730 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
731 }
732
TEST_F(EGLTest,EGLNoConfigContext)733 TEST_F(EGLTest, EGLNoConfigContext) {
734 if (!hasWideColorDisplay) {
735 // skip this test if device does not have wide-color display
736 RecordProperty("hasWideColorDisplay", false);
737 return;
738 }
739
740 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
741
742 struct MockConsumer : public BnConsumerListener {
743 void onFrameAvailable(const BufferItem& /* item */) override {}
744 void onBuffersReleased() override {}
745 void onSidebandStreamChanged() override {}
746 };
747
748 std::vector<EGLint> contextAttributes;
749 contextAttributes.reserve(4);
750 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
751 contextAttributes.push_back(2);
752 contextAttributes.push_back(EGL_NONE);
753 contextAttributes.push_back(EGL_NONE);
754
755 EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
756 contextAttributes.data());
757 EXPECT_NE(EGL_NO_CONTEXT, eglContext);
758 EXPECT_EQ(EGL_SUCCESS, eglGetError());
759
760 if (eglContext != EGL_NO_CONTEXT) {
761 eglDestroyContext(mEglDisplay, eglContext);
762 }
763 }
764
765 // Emulate what a native application would do to create a
766 // 10:10:10:2 surface.
TEST_F(EGLTest,EGLConfig1010102)767 TEST_F(EGLTest, EGLConfig1010102) {
768 EGLint numConfigs;
769 EGLConfig config;
770 EGLBoolean success;
771
772 if (!hasWideColorDisplay) {
773 // skip this test if device does not have wide-color display
774 RecordProperty("hasWideColorDisplay", false);
775 return;
776 }
777
778 const EGLint attrs[] = {
779 // clang-format off
780 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
781 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
782 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
783 EGL_RED_SIZE, 10,
784 EGL_GREEN_SIZE, 10,
785 EGL_BLUE_SIZE, 10,
786 EGL_ALPHA_SIZE, 2,
787 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
788 EGL_NONE, EGL_NONE
789 // clang-format on
790 };
791 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
792 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
793 ASSERT_EQ(1, numConfigs);
794
795 EGLint components[4];
796 EGLint value;
797 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
798
799 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
800 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
801 ASSERT_EQ(EGL_SUCCESS, eglGetError());
802 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
803 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
804 ASSERT_EQ(EGL_SUCCESS, eglGetError());
805 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
806 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
807 ASSERT_EQ(EGL_SUCCESS, eglGetError());
808 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
809 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
810 ASSERT_EQ(EGL_SUCCESS, eglGetError());
811
812 EXPECT_EQ(components[0], 10);
813 EXPECT_EQ(components[1], 10);
814 EXPECT_EQ(components[2], 10);
815 EXPECT_EQ(components[3], 2);
816
817 struct MockConsumer : public BnConsumerListener {
818 void onFrameAvailable(const BufferItem& /* item */) override {}
819 void onBuffersReleased() override {}
820 void onSidebandStreamChanged() override {}
821 };
822
823 // Create a EGLSurface
824 sp<IGraphicBufferProducer> producer;
825 sp<IGraphicBufferConsumer> consumer;
826 BufferQueue::createBufferQueue(&producer, &consumer);
827 consumer->consumerConnect(new MockConsumer, false);
828 sp<Surface> mSTC = new Surface(producer);
829 sp<ANativeWindow> mANW = mSTC;
830
831 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
832 ASSERT_EQ(EGL_SUCCESS, eglGetError());
833 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
834
835 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
836 }
837
TEST_F(EGLTest,EGLInvalidColorspaceAttribute)838 TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
839 EGLConfig config;
840
841 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
842
843 struct MockConsumer : public BnConsumerListener {
844 void onFrameAvailable(const BufferItem& /* item */) override {}
845 void onBuffersReleased() override {}
846 void onSidebandStreamChanged() override {}
847 };
848
849 // Create a EGLSurface
850 sp<IGraphicBufferProducer> producer;
851 sp<IGraphicBufferConsumer> consumer;
852 BufferQueue::createBufferQueue(&producer, &consumer);
853 consumer->consumerConnect(new MockConsumer, false);
854 sp<Surface> mSTC = new Surface(producer);
855 sp<ANativeWindow> mANW = mSTC;
856
857 EGLint winAttrs[] = {
858 // clang-format off
859 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
860 EGL_NONE,
861 // clang-format on
862 };
863
864 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
865 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
866 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
867 }
868
TEST_F(EGLTest,EGLUnsupportedColorspaceFormatCombo)869 TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
870 EGLint numConfigs;
871 EGLConfig config;
872 EGLBoolean success;
873
874 if (!hasWideColorDisplay) {
875 // skip this test if device does not have wide-color display
876 RecordProperty("hasWideColorDisplay", false);
877 return;
878 }
879
880 const EGLint attrs[] = {
881 // clang-format off
882 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
883 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
884 EGL_RED_SIZE, 16,
885 EGL_GREEN_SIZE, 16,
886 EGL_BLUE_SIZE, 16,
887 EGL_ALPHA_SIZE, 16,
888 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
889 EGL_NONE,
890 // clang-format on
891 };
892 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
893 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
894 ASSERT_EQ(1, numConfigs);
895
896 struct MockConsumer : public BnConsumerListener {
897 void onFrameAvailable(const BufferItem& /* item */) override {}
898 void onBuffersReleased() override {}
899 void onSidebandStreamChanged() override {}
900 };
901
902 // Create a EGLSurface
903 sp<IGraphicBufferProducer> producer;
904 sp<IGraphicBufferConsumer> consumer;
905 BufferQueue::createBufferQueue(&producer, &consumer);
906 consumer->consumerConnect(new MockConsumer, false);
907 sp<Surface> mSTC = new Surface(producer);
908 sp<ANativeWindow> mANW = mSTC;
909
910 const EGLint winAttrs[] = {
911 // clang-format off
912 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
913 EGL_NONE,
914 // clang-format on
915 };
916
917 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
918 ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
919 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
920 }
921
TEST_F(EGLTest,EGLCreateWindowFailAndSucceed)922 TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
923 EGLConfig config;
924
925 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
926
927 struct MockConsumer : public BnConsumerListener {
928 void onFrameAvailable(const BufferItem& /* item */) override {}
929 void onBuffersReleased() override {}
930 void onSidebandStreamChanged() override {}
931 };
932
933 // Create a EGLSurface
934 sp<IGraphicBufferProducer> producer;
935 sp<IGraphicBufferConsumer> consumer;
936 BufferQueue::createBufferQueue(&producer, &consumer);
937 consumer->consumerConnect(new MockConsumer, false);
938 sp<Surface> mSTC = new Surface(producer);
939 sp<ANativeWindow> mANW = mSTC;
940
941 EGLint winAttrs[] = {
942 // clang-format off
943 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
944 EGL_NONE,
945 // clang-format on
946 };
947
948 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
949 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
950 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
951
952 // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
953 // in the first failed attempt (e.g. native_window_api_disconnect).
954 winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
955 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
956 ASSERT_EQ(EGL_SUCCESS, eglGetError());
957 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
958
959 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
960 }
961
TEST_F(EGLTest,EGLCreateWindowTwoColorspaces)962 TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
963 EGLConfig config;
964
965 if (!hasWideColorDisplay) {
966 // skip this test if device does not have wide-color display
967 RecordProperty("hasWideColorDisplay", false);
968 return;
969 }
970
971 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
972
973 struct MockConsumer : public BnConsumerListener {
974 void onFrameAvailable(const BufferItem& /* item */) override {}
975 void onBuffersReleased() override {}
976 void onSidebandStreamChanged() override {}
977 };
978
979 // Create a EGLSurface
980 sp<IGraphicBufferProducer> producer;
981 sp<IGraphicBufferConsumer> consumer;
982 BufferQueue::createBufferQueue(&producer, &consumer);
983 consumer->consumerConnect(new MockConsumer, false);
984 sp<Surface> mSTC = new Surface(producer);
985 sp<ANativeWindow> mANW = mSTC;
986
987 const EGLint winAttrs[] = {
988 // clang-format off
989 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
990 EGL_NONE,
991 // clang-format on
992 };
993
994 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
995 ASSERT_EQ(EGL_SUCCESS, eglGetError());
996 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
997
998 android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
999 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
1000
1001 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1002
1003 // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
1004 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
1005 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1006 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
1007
1008 dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
1009 // Make sure the dataspace has been reset to UNKNOWN
1010 ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
1011
1012 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1013 }
1014 }
1015