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 EGLint numConfigs;
347 EGLConfig config;
348 EGLBoolean success;
349
350 if (!hasWideColorDisplay) {
351 // skip this test if device does not have wide-color display
352 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
353 return;
354 }
355
356 // Test that display-p3 extensions exist
357 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
358 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
359 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
360
361 // Use 8-bit to keep forcus on Display-P3 aspect
362 EGLint attrs[] = {
363 // clang-format off
364 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
365 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
366 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
367 EGL_RED_SIZE, 10,
368 EGL_GREEN_SIZE, 10,
369 EGL_BLUE_SIZE, 10,
370 EGL_ALPHA_SIZE, 2,
371 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
372 EGL_NONE, EGL_NONE
373 // clang-format on
374 };
375 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
376 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
377 ASSERT_EQ(1, numConfigs);
378
379 EGLint components[4];
380 EGLint value;
381 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
382
383 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
384 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
385 ASSERT_EQ(EGL_SUCCESS, eglGetError());
386 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
387 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
388 ASSERT_EQ(EGL_SUCCESS, eglGetError());
389 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
390 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
391 ASSERT_EQ(EGL_SUCCESS, eglGetError());
392 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
393 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
394 ASSERT_EQ(EGL_SUCCESS, eglGetError());
395
396 EXPECT_EQ(components[0], 10);
397 EXPECT_EQ(components[1], 10);
398 EXPECT_EQ(components[2], 10);
399 EXPECT_EQ(components[3], 2);
400
401 struct MockConsumer : public BnConsumerListener {
402 void onFrameAvailable(const BufferItem& /* item */) override {}
403 void onBuffersReleased() override {}
404 void onSidebandStreamChanged() override {}
405 };
406
407 // Create a EGLSurface
408 sp<IGraphicBufferProducer> producer;
409 sp<IGraphicBufferConsumer> consumer;
410 BufferQueue::createBufferQueue(&producer, &consumer);
411 consumer->consumerConnect(new MockConsumer, false);
412 sp<Surface> mSTC = new Surface(producer);
413 sp<ANativeWindow> mANW = mSTC;
414 EGLint winAttrs[] = {
415 // clang-format off
416 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
417 EGL_NONE, EGL_NONE
418 // clang-format on
419 };
420
421 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
422 ASSERT_EQ(EGL_SUCCESS, eglGetError());
423 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
424
425 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
426 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
427 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
428
429 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
430 }
431
get8BitConfig(EGLConfig & config)432 void EGLTest::get8BitConfig(EGLConfig& config) {
433 EGLint numConfigs;
434 EGLBoolean success;
435
436 // Use 8-bit to keep focus on colorspace aspect
437 const EGLint attrs[] = {
438 // clang-format off
439 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
440 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
441 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
442 EGL_RED_SIZE, 8,
443 EGL_GREEN_SIZE, 8,
444 EGL_BLUE_SIZE, 8,
445 EGL_ALPHA_SIZE, 8,
446 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
447 EGL_NONE,
448 // clang-format on
449 };
450 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
451 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
452 ASSERT_EQ(1, numConfigs);
453
454 EGLint components[4];
455 EGLint value;
456 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
457
458 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
459 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
460 ASSERT_EQ(EGL_SUCCESS, eglGetError());
461 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
462 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
463 ASSERT_EQ(EGL_SUCCESS, eglGetError());
464 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
465 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
466 ASSERT_EQ(EGL_SUCCESS, eglGetError());
467 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
468 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
469 ASSERT_EQ(EGL_SUCCESS, eglGetError());
470
471 // Verify component sizes on config match what was asked for.
472 EXPECT_EQ(components[0], 8);
473 EXPECT_EQ(components[1], 8);
474 EXPECT_EQ(components[2], 8);
475 EXPECT_EQ(components[3], 8);
476 }
477
setSurfaceSmpteMetadata(EGLSurface surface)478 void EGLTest::setSurfaceSmpteMetadata(EGLSurface surface) {
479 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
480 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT,
481 METADATA_SCALE(0.640));
482 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT,
483 METADATA_SCALE(0.330));
484 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT,
485 METADATA_SCALE(0.290));
486 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT,
487 METADATA_SCALE(0.600));
488 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT,
489 METADATA_SCALE(0.150));
490 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT,
491 METADATA_SCALE(0.060));
492 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_X_EXT,
493 METADATA_SCALE(0.3127));
494 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_Y_EXT,
495 METADATA_SCALE(0.3290));
496 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT,
497 METADATA_SCALE(300));
498 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MIN_LUMINANCE_EXT,
499 METADATA_SCALE(0.7));
500 }
501
502 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
503 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT,
504 METADATA_SCALE(300));
505 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT,
506 METADATA_SCALE(75));
507 }
508 }
509
checkSurfaceSmpteMetadata(EGLSurface eglSurface)510 void EGLTest::checkSurfaceSmpteMetadata(EGLSurface eglSurface) {
511 EGLBoolean success;
512 EGLint value;
513
514 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
515 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, &value);
516 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
517 ASSERT_EQ(METADATA_SCALE(0.640), value);
518 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, &value);
519 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
520 ASSERT_EQ(METADATA_SCALE(0.330), value);
521 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, &value);
522 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
523 ASSERT_EQ(METADATA_SCALE(0.290), value);
524 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, &value);
525 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
526 ASSERT_EQ(METADATA_SCALE(0.600), value);
527 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, &value);
528 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
529 ASSERT_EQ(METADATA_SCALE(0.150), value);
530 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, &value);
531 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
532 ASSERT_EQ(METADATA_SCALE(0.060), value);
533 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_X_EXT, &value);
534 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
535 ASSERT_EQ(METADATA_SCALE(0.3127), value);
536 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, &value);
537 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
538 ASSERT_EQ(METADATA_SCALE(0.3290), value);
539 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, &value);
540 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
541 ASSERT_EQ(METADATA_SCALE(300.0), value);
542 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, &value);
543 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
544 ASSERT_EQ(METADATA_SCALE(0.7), value);
545 }
546
547 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
548 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, &value);
549 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
550 ASSERT_EQ(METADATA_SCALE(300.0), value);
551 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, &value);
552 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
553 ASSERT_EQ(METADATA_SCALE(75.0), value);
554 }
555 }
556
TEST_F(EGLTest,EGLBT2020Linear)557 TEST_F(EGLTest, EGLBT2020Linear) {
558 EGLConfig config;
559 EGLBoolean success;
560
561 if (!hasHdrDisplay) {
562 // skip this test if device does not have HDR display
563 RecordProperty("hasHdrDisplay", false);
564 return;
565 }
566
567 // Test that bt2020 linear extension exists
568 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"))
569 << "EGL_EXT_gl_colorspace_bt2020_linear extension not available";
570
571 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
572
573 struct MockConsumer : public BnConsumerListener {
574 void onFrameAvailable(const BufferItem& /* item */) override {}
575 void onBuffersReleased() override {}
576 void onSidebandStreamChanged() override {}
577 };
578
579 // Create a EGLSurface
580 sp<IGraphicBufferProducer> producer;
581 sp<IGraphicBufferConsumer> consumer;
582 BufferQueue::createBufferQueue(&producer, &consumer);
583 consumer->consumerConnect(new MockConsumer, false);
584 sp<Surface> mSTC = new Surface(producer);
585 sp<ANativeWindow> mANW = mSTC;
586
587 std::vector<EGLint> winAttrs;
588 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
589 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
590
591 winAttrs.push_back(EGL_NONE);
592
593 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
594 ASSERT_EQ(EGL_SUCCESS, eglGetError());
595 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
596
597 EGLint value;
598 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
599 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
600 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
601
602 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
603
604 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
605
606 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
607 }
608
TEST_F(EGLTest,EGLBT2020PQ)609 TEST_F(EGLTest, EGLBT2020PQ) {
610 EGLConfig config;
611 EGLBoolean success;
612
613 if (!hasHdrDisplay) {
614 // skip this test if device does not have HDR display
615 RecordProperty("hasHdrDisplay", false);
616 return;
617 }
618
619 // Test that bt2020-pq extension exists
620 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"))
621 << "EGL_EXT_gl_colorspace_bt2020_pq extension not available";
622
623 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
624
625 struct MockConsumer : public BnConsumerListener {
626 void onFrameAvailable(const BufferItem& /* item */) override {}
627 void onBuffersReleased() override {}
628 void onSidebandStreamChanged() override {}
629 };
630
631 // Create a EGLSurface
632 sp<IGraphicBufferProducer> producer;
633 sp<IGraphicBufferConsumer> consumer;
634 BufferQueue::createBufferQueue(&producer, &consumer);
635 consumer->consumerConnect(new MockConsumer, false);
636 sp<Surface> mSTC = new Surface(producer);
637 sp<ANativeWindow> mANW = mSTC;
638 std::vector<EGLint> winAttrs;
639 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
640 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
641 winAttrs.push_back(EGL_NONE);
642
643 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
644 ASSERT_EQ(EGL_SUCCESS, eglGetError());
645 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
646
647 EGLint value;
648 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
649 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
650 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
651
652 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
653
654 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
655
656 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
657 }
658
TEST_F(EGLTest,EGLConfigFP16)659 TEST_F(EGLTest, EGLConfigFP16) {
660 EGLint numConfigs;
661 EGLConfig config;
662 EGLBoolean success;
663
664 if (!hasWideColorDisplay) {
665 // skip this test if device does not have wide-color display
666 RecordProperty("hasWideColorDisplay", false);
667 return;
668 }
669
670 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
671
672 const EGLint attrs[] = {
673 // clang-format off
674 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
675 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
676 EGL_RED_SIZE, 16,
677 EGL_GREEN_SIZE, 16,
678 EGL_BLUE_SIZE, 16,
679 EGL_ALPHA_SIZE, 16,
680 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
681 EGL_NONE,
682 // clang-format on
683 };
684 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
685 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
686 ASSERT_EQ(1, numConfigs);
687
688 EGLint components[4];
689
690 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
691 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
692 ASSERT_EQ(EGL_SUCCESS, eglGetError());
693 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
694 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
695 ASSERT_EQ(EGL_SUCCESS, eglGetError());
696 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
697 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
698 ASSERT_EQ(EGL_SUCCESS, eglGetError());
699 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
700 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
701 ASSERT_EQ(EGL_SUCCESS, eglGetError());
702
703 EXPECT_GE(components[0], 16);
704 EXPECT_GE(components[1], 16);
705 EXPECT_GE(components[2], 16);
706 EXPECT_GE(components[3], 16);
707
708 struct MockConsumer : public BnConsumerListener {
709 void onFrameAvailable(const BufferItem& /* item */) override {}
710 void onBuffersReleased() override {}
711 void onSidebandStreamChanged() override {}
712 };
713
714 sp<IGraphicBufferProducer> producer;
715 sp<IGraphicBufferConsumer> consumer;
716 BufferQueue::createBufferQueue(&producer, &consumer);
717 consumer->consumerConnect(new MockConsumer, false);
718 sp<Surface> mSTC = new Surface(producer);
719 sp<ANativeWindow> mANW = mSTC;
720
721 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
722 ASSERT_EQ(EGL_SUCCESS, eglGetError());
723 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
724
725 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
726 }
727
TEST_F(EGLTest,EGLNoConfigContext)728 TEST_F(EGLTest, EGLNoConfigContext) {
729 if (!hasWideColorDisplay) {
730 // skip this test if device does not have wide-color display
731 RecordProperty("hasWideColorDisplay", false);
732 return;
733 }
734
735 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
736
737 struct MockConsumer : public BnConsumerListener {
738 void onFrameAvailable(const BufferItem& /* item */) override {}
739 void onBuffersReleased() override {}
740 void onSidebandStreamChanged() override {}
741 };
742
743 std::vector<EGLint> contextAttributes;
744 contextAttributes.reserve(4);
745 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
746 contextAttributes.push_back(2);
747 contextAttributes.push_back(EGL_NONE);
748 contextAttributes.push_back(EGL_NONE);
749
750 EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
751 contextAttributes.data());
752 EXPECT_NE(EGL_NO_CONTEXT, eglContext);
753 EXPECT_EQ(EGL_SUCCESS, eglGetError());
754
755 if (eglContext != EGL_NO_CONTEXT) {
756 eglDestroyContext(mEglDisplay, eglContext);
757 }
758 }
759
760 // Emulate what a native application would do to create a
761 // 10:10:10:2 surface.
TEST_F(EGLTest,EGLConfig1010102)762 TEST_F(EGLTest, EGLConfig1010102) {
763 EGLint numConfigs;
764 EGLConfig config;
765 EGLBoolean success;
766
767 if (!hasWideColorDisplay) {
768 // skip this test if device does not have wide-color display
769 RecordProperty("hasWideColorDisplay", false);
770 return;
771 }
772
773 const EGLint attrs[] = {
774 // clang-format off
775 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
776 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
777 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
778 EGL_RED_SIZE, 10,
779 EGL_GREEN_SIZE, 10,
780 EGL_BLUE_SIZE, 10,
781 EGL_ALPHA_SIZE, 2,
782 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
783 EGL_NONE, EGL_NONE
784 // clang-format on
785 };
786 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
787 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
788 ASSERT_EQ(1, numConfigs);
789
790 EGLint components[4];
791 EGLint value;
792 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
793
794 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
795 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
796 ASSERT_EQ(EGL_SUCCESS, eglGetError());
797 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
798 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
799 ASSERT_EQ(EGL_SUCCESS, eglGetError());
800 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
801 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
802 ASSERT_EQ(EGL_SUCCESS, eglGetError());
803 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
804 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
805 ASSERT_EQ(EGL_SUCCESS, eglGetError());
806
807 EXPECT_EQ(components[0], 10);
808 EXPECT_EQ(components[1], 10);
809 EXPECT_EQ(components[2], 10);
810 EXPECT_EQ(components[3], 2);
811
812 struct MockConsumer : public BnConsumerListener {
813 void onFrameAvailable(const BufferItem& /* item */) override {}
814 void onBuffersReleased() override {}
815 void onSidebandStreamChanged() override {}
816 };
817
818 // Create a EGLSurface
819 sp<IGraphicBufferProducer> producer;
820 sp<IGraphicBufferConsumer> consumer;
821 BufferQueue::createBufferQueue(&producer, &consumer);
822 consumer->consumerConnect(new MockConsumer, false);
823 sp<Surface> mSTC = new Surface(producer);
824 sp<ANativeWindow> mANW = mSTC;
825
826 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
827 ASSERT_EQ(EGL_SUCCESS, eglGetError());
828 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
829
830 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
831 }
832
TEST_F(EGLTest,EGLInvalidColorspaceAttribute)833 TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
834 EGLConfig config;
835
836 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
837
838 struct MockConsumer : public BnConsumerListener {
839 void onFrameAvailable(const BufferItem& /* item */) override {}
840 void onBuffersReleased() override {}
841 void onSidebandStreamChanged() override {}
842 };
843
844 // Create a EGLSurface
845 sp<IGraphicBufferProducer> producer;
846 sp<IGraphicBufferConsumer> consumer;
847 BufferQueue::createBufferQueue(&producer, &consumer);
848 consumer->consumerConnect(new MockConsumer, false);
849 sp<Surface> mSTC = new Surface(producer);
850 sp<ANativeWindow> mANW = mSTC;
851
852 EGLint winAttrs[] = {
853 // clang-format off
854 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
855 EGL_NONE,
856 // clang-format on
857 };
858
859 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
860 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
861 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
862 }
863
TEST_F(EGLTest,EGLUnsupportedColorspaceFormatCombo)864 TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
865 EGLint numConfigs;
866 EGLConfig config;
867 EGLBoolean success;
868
869 const EGLint attrs[] = {
870 // clang-format off
871 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
872 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
873 EGL_RED_SIZE, 16,
874 EGL_GREEN_SIZE, 16,
875 EGL_BLUE_SIZE, 16,
876 EGL_ALPHA_SIZE, 16,
877 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
878 EGL_NONE,
879 // clang-format on
880 };
881 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
882 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
883 ASSERT_EQ(1, numConfigs);
884
885 struct MockConsumer : public BnConsumerListener {
886 void onFrameAvailable(const BufferItem& /* item */) override {}
887 void onBuffersReleased() override {}
888 void onSidebandStreamChanged() override {}
889 };
890
891 // Create a EGLSurface
892 sp<IGraphicBufferProducer> producer;
893 sp<IGraphicBufferConsumer> consumer;
894 BufferQueue::createBufferQueue(&producer, &consumer);
895 consumer->consumerConnect(new MockConsumer, false);
896 sp<Surface> mSTC = new Surface(producer);
897 sp<ANativeWindow> mANW = mSTC;
898
899 const EGLint winAttrs[] = {
900 // clang-format off
901 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
902 EGL_NONE,
903 // clang-format on
904 };
905
906 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
907 ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
908 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
909 }
910
TEST_F(EGLTest,EGLCreateWindowFailAndSucceed)911 TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
912 EGLConfig config;
913
914 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
915
916 struct MockConsumer : public BnConsumerListener {
917 void onFrameAvailable(const BufferItem& /* item */) override {}
918 void onBuffersReleased() override {}
919 void onSidebandStreamChanged() override {}
920 };
921
922 // Create a EGLSurface
923 sp<IGraphicBufferProducer> producer;
924 sp<IGraphicBufferConsumer> consumer;
925 BufferQueue::createBufferQueue(&producer, &consumer);
926 consumer->consumerConnect(new MockConsumer, false);
927 sp<Surface> mSTC = new Surface(producer);
928 sp<ANativeWindow> mANW = mSTC;
929
930 EGLint winAttrs[] = {
931 // clang-format off
932 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
933 EGL_NONE,
934 // clang-format on
935 };
936
937 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
938 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
939 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
940
941 // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
942 // in the first failed attempt (e.g. native_window_api_disconnect).
943 winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
944 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
945 ASSERT_EQ(EGL_SUCCESS, eglGetError());
946 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
947
948 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
949 }
950
TEST_F(EGLTest,EGLCreateWindowTwoColorspaces)951 TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
952 EGLConfig config;
953
954 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
955
956 struct MockConsumer : public BnConsumerListener {
957 void onFrameAvailable(const BufferItem& /* item */) override {}
958 void onBuffersReleased() override {}
959 void onSidebandStreamChanged() override {}
960 };
961
962 // Create a EGLSurface
963 sp<IGraphicBufferProducer> producer;
964 sp<IGraphicBufferConsumer> consumer;
965 BufferQueue::createBufferQueue(&producer, &consumer);
966 consumer->consumerConnect(new MockConsumer, false);
967 sp<Surface> mSTC = new Surface(producer);
968 sp<ANativeWindow> mANW = mSTC;
969
970 const EGLint winAttrs[] = {
971 // clang-format off
972 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
973 EGL_NONE,
974 // clang-format on
975 };
976
977 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
978 ASSERT_EQ(EGL_SUCCESS, eglGetError());
979 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
980
981 android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
982 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
983
984 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
985
986 // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
987 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
988 ASSERT_EQ(EGL_SUCCESS, eglGetError());
989 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
990
991 dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
992 // Make sure the dataspace has been reset to UNKNOWN
993 ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
994
995 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
996 }
997 }
998