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 <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> 20 21 #include <configstore/Utils.h> 22 #include <utils/String8.h> 23 24 #include <EGL/egl.h> 25 #include <gui/Surface.h> 26 #include <gui/IConsumerListener.h> 27 #include <gui/IProducerListener.h> 28 #include <gui/IGraphicBufferConsumer.h> 29 #include <gui/BufferQueue.h> 30 31 bool hasEglExtension(EGLDisplay dpy, const char* extensionName) { 32 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS); 33 size_t cropExtLen = strlen(extensionName); 34 size_t extsLen = strlen(exts); 35 bool equal = !strcmp(extensionName, exts); 36 android::String8 extString(extensionName); 37 android::String8 space(" "); 38 bool atStart = !strncmp(extString + space, exts, cropExtLen + 1); 39 bool atEnd = (cropExtLen + 1) < extsLen && 40 !strcmp(space + extString, exts + extsLen - (cropExtLen + 1)); 41 bool inMiddle = strstr(exts, space + extString + space); 42 return equal || atStart || atEnd || inMiddle; 43 } 44 45 namespace android { 46 47 #define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE) 48 49 // retrieve wide-color setting from configstore 50 using namespace android::hardware::configstore; 51 using namespace android::hardware::configstore::V1_0; 52 53 #define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT)) 54 55 static bool hasWideColorDisplay = 56 getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false); 57 58 static bool hasHdrDisplay = 59 getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false); 60 61 class EGLTest : public ::testing::Test { 62 public: 63 void get8BitConfig(EGLConfig& config); 64 void setSurfaceSmpteMetadata(EGLSurface surface); 65 void checkSurfaceSmpteMetadata(EGLSurface eglSurface); 66 67 protected: 68 EGLDisplay mEglDisplay; 69 70 protected: 71 EGLTest() : 72 mEglDisplay(EGL_NO_DISPLAY) { 73 } 74 75 virtual void SetUp() { 76 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 77 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); 78 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 79 80 EGLint majorVersion; 81 EGLint minorVersion; 82 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); 83 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 84 RecordProperty("EglVersionMajor", majorVersion); 85 RecordProperty("EglVersionMajor", minorVersion); 86 } 87 88 virtual void TearDown() { 89 EGLBoolean success = eglTerminate(mEglDisplay); 90 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 91 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 92 } 93 }; 94 95 TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) { 96 97 EGLint numConfigs; 98 EGLConfig config; 99 EGLBoolean success; 100 EGLint attrs[] = { 101 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 102 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 103 EGL_NONE 104 }; 105 106 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); 107 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 108 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 109 ASSERT_GE(numConfigs, 1); 110 111 EGLint components[3]; 112 113 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); 114 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 115 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 116 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); 117 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 118 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 119 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); 120 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 121 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 122 123 EXPECT_GE(components[0], 8); 124 EXPECT_GE(components[1], 8); 125 EXPECT_GE(components[2], 8); 126 } 127 128 TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) { 129 EGLint numConfigs; 130 EGLConfig config; 131 EGLint attrs[] = { 132 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 133 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 134 EGL_RED_SIZE, 8, 135 EGL_GREEN_SIZE, 8, 136 EGL_BLUE_SIZE, 8, 137 EGL_ALPHA_SIZE, 8, 138 EGL_NONE 139 }; 140 EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs)); 141 142 struct DummyConsumer : public BnConsumerListener { 143 void onFrameAvailable(const BufferItem& /* item */) override {} 144 void onBuffersReleased() override {} 145 void onSidebandStreamChanged() override {} 146 }; 147 148 // Create a EGLSurface 149 sp<IGraphicBufferProducer> producer; 150 sp<IGraphicBufferConsumer> consumer; 151 BufferQueue::createBufferQueue(&producer, &consumer); 152 consumer->consumerConnect(new DummyConsumer, false); 153 sp<Surface> mSTC = new Surface(producer); 154 sp<ANativeWindow> mANW = mSTC; 155 156 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, 157 mANW.get(), NULL); 158 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 159 ASSERT_NE(EGL_NO_SURFACE, eglSurface) ; 160 161 // do not destroy eglSurface 162 // eglTerminate is called in the tear down and should destroy it for us 163 } 164 165 TEST_F(EGLTest, EGLConfigRGBA8888First) { 166 167 EGLint numConfigs; 168 EGLConfig config; 169 EGLBoolean success; 170 EGLint attrs[] = { 171 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 172 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 173 EGL_RED_SIZE, 8, 174 EGL_GREEN_SIZE, 8, 175 EGL_BLUE_SIZE, 8, 176 EGL_ALPHA_SIZE, 8, 177 EGL_NONE 178 }; 179 180 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); 181 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 182 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 183 ASSERT_GE(numConfigs, 1); 184 185 EGLint components[4]; 186 187 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); 188 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 189 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 190 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); 191 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 192 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 193 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); 194 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 195 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 196 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]); 197 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 198 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 199 200 EXPECT_GE(components[0], 8); 201 EXPECT_GE(components[1], 8); 202 EXPECT_GE(components[2], 8); 203 EXPECT_GE(components[3], 8); 204 } 205 206 TEST_F(EGLTest, EGLDisplayP3) { 207 EGLint numConfigs; 208 EGLConfig config; 209 EGLBoolean success; 210 211 if (!hasWideColorDisplay) { 212 // skip this test if device does not have wide-color display 213 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl; 214 return; 215 } 216 217 // Test that display-p3 extensions exist 218 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3")); 219 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear")); 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 DummyConsumer : 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 DummyConsumer, 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 292 TEST_F(EGLTest, EGLDisplayP31010102) { 293 EGLint numConfigs; 294 EGLConfig config; 295 EGLBoolean success; 296 297 if (!hasWideColorDisplay) { 298 // skip this test if device does not have wide-color display 299 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl; 300 return; 301 } 302 303 // Test that display-p3 extensions exist 304 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3")); 305 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear")); 306 307 // Use 8-bit to keep forcus on Display-P3 aspect 308 EGLint attrs[] = { 309 // clang-format off 310 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 311 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 312 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, 313 EGL_RED_SIZE, 10, 314 EGL_GREEN_SIZE, 10, 315 EGL_BLUE_SIZE, 10, 316 EGL_ALPHA_SIZE, 2, 317 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, 318 EGL_NONE, EGL_NONE 319 // clang-format on 320 }; 321 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); 322 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 323 ASSERT_EQ(1, numConfigs); 324 325 EGLint components[4]; 326 EGLint value; 327 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value); 328 329 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); 330 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 331 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 332 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); 333 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 334 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 335 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); 336 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 337 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 338 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]); 339 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 340 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 341 342 EXPECT_EQ(components[0], 10); 343 EXPECT_EQ(components[1], 10); 344 EXPECT_EQ(components[2], 10); 345 EXPECT_EQ(components[3], 2); 346 347 struct DummyConsumer : public BnConsumerListener { 348 void onFrameAvailable(const BufferItem& /* item */) override {} 349 void onBuffersReleased() override {} 350 void onSidebandStreamChanged() override {} 351 }; 352 353 // Create a EGLSurface 354 sp<IGraphicBufferProducer> producer; 355 sp<IGraphicBufferConsumer> consumer; 356 BufferQueue::createBufferQueue(&producer, &consumer); 357 consumer->consumerConnect(new DummyConsumer, false); 358 sp<Surface> mSTC = new Surface(producer); 359 sp<ANativeWindow> mANW = mSTC; 360 EGLint winAttrs[] = { 361 // clang-format off 362 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT, 363 EGL_NONE, EGL_NONE 364 // clang-format on 365 }; 366 367 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs); 368 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 369 ASSERT_NE(EGL_NO_SURFACE, eglSurface); 370 371 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value); 372 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 373 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value); 374 375 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface)); 376 } 377 378 void EGLTest::get8BitConfig(EGLConfig& config) { 379 EGLint numConfigs; 380 EGLBoolean success; 381 382 // Use 8-bit to keep focus on colorspace aspect 383 const EGLint attrs[] = { 384 // clang-format off 385 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 386 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 387 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, 388 EGL_RED_SIZE, 8, 389 EGL_GREEN_SIZE, 8, 390 EGL_BLUE_SIZE, 8, 391 EGL_ALPHA_SIZE, 8, 392 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, 393 EGL_NONE, 394 // clang-format on 395 }; 396 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); 397 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 398 ASSERT_EQ(1, numConfigs); 399 400 EGLint components[4]; 401 EGLint value; 402 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value); 403 404 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); 405 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 406 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 407 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); 408 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 409 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 410 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); 411 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 412 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 413 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]); 414 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 415 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 416 417 // Verify component sizes on config match what was asked for. 418 EXPECT_EQ(components[0], 8); 419 EXPECT_EQ(components[1], 8); 420 EXPECT_EQ(components[2], 8); 421 EXPECT_EQ(components[3], 8); 422 } 423 424 void EGLTest::setSurfaceSmpteMetadata(EGLSurface surface) { 425 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) { 426 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, 427 METADATA_SCALE(0.640)); 428 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, 429 METADATA_SCALE(0.330)); 430 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, 431 METADATA_SCALE(0.290)); 432 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, 433 METADATA_SCALE(0.600)); 434 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, 435 METADATA_SCALE(0.150)); 436 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, 437 METADATA_SCALE(0.060)); 438 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_X_EXT, 439 METADATA_SCALE(0.3127)); 440 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, 441 METADATA_SCALE(0.3290)); 442 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, 443 METADATA_SCALE(300)); 444 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, 445 METADATA_SCALE(0.7)); 446 } 447 448 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) { 449 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, 450 METADATA_SCALE(300)); 451 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, 452 METADATA_SCALE(75)); 453 } 454 } 455 456 void EGLTest::checkSurfaceSmpteMetadata(EGLSurface eglSurface) { 457 EGLBoolean success; 458 EGLint value; 459 460 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) { 461 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, &value); 462 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 463 ASSERT_EQ(METADATA_SCALE(0.640), value); 464 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, &value); 465 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 466 ASSERT_EQ(METADATA_SCALE(0.330), value); 467 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, &value); 468 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 469 ASSERT_EQ(METADATA_SCALE(0.290), value); 470 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, &value); 471 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 472 ASSERT_EQ(METADATA_SCALE(0.600), value); 473 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, &value); 474 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 475 ASSERT_EQ(METADATA_SCALE(0.150), value); 476 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, &value); 477 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 478 ASSERT_EQ(METADATA_SCALE(0.060), value); 479 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_X_EXT, &value); 480 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 481 ASSERT_EQ(METADATA_SCALE(0.3127), value); 482 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, &value); 483 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 484 ASSERT_EQ(METADATA_SCALE(0.3290), value); 485 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, &value); 486 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 487 ASSERT_EQ(METADATA_SCALE(300.0), value); 488 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, &value); 489 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 490 ASSERT_EQ(METADATA_SCALE(0.7), value); 491 } 492 493 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) { 494 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, &value); 495 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 496 ASSERT_EQ(METADATA_SCALE(300.0), value); 497 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, &value); 498 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 499 ASSERT_EQ(METADATA_SCALE(75.0), value); 500 } 501 } 502 503 TEST_F(EGLTest, EGLBT2020Linear) { 504 EGLConfig config; 505 EGLBoolean success; 506 507 if (!hasHdrDisplay) { 508 // skip this test if device does not have HDR display 509 RecordProperty("hasHdrDisplay", false); 510 return; 511 } 512 513 // Test that bt2020 linear extension exists 514 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear")) 515 << "EGL_EXT_gl_colorspace_bt2020_linear extension not available"; 516 517 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config)); 518 519 struct DummyConsumer : public BnConsumerListener { 520 void onFrameAvailable(const BufferItem& /* item */) override {} 521 void onBuffersReleased() override {} 522 void onSidebandStreamChanged() override {} 523 }; 524 525 // Create a EGLSurface 526 sp<IGraphicBufferProducer> producer; 527 sp<IGraphicBufferConsumer> consumer; 528 BufferQueue::createBufferQueue(&producer, &consumer); 529 consumer->consumerConnect(new DummyConsumer, false); 530 sp<Surface> mSTC = new Surface(producer); 531 sp<ANativeWindow> mANW = mSTC; 532 533 std::vector<EGLint> winAttrs; 534 winAttrs.push_back(EGL_GL_COLORSPACE_KHR); 535 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT); 536 537 winAttrs.push_back(EGL_NONE); 538 539 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data()); 540 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 541 ASSERT_NE(EGL_NO_SURFACE, eglSurface); 542 543 EGLint value; 544 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value); 545 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 546 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value); 547 548 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface)); 549 550 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface)); 551 552 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface)); 553 } 554 555 TEST_F(EGLTest, EGLBT2020PQ) { 556 EGLConfig config; 557 EGLBoolean success; 558 559 if (!hasHdrDisplay) { 560 // skip this test if device does not have HDR display 561 RecordProperty("hasHdrDisplay", false); 562 return; 563 } 564 565 // Test that bt2020-pq extension exists 566 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq")) 567 << "EGL_EXT_gl_colorspace_bt2020_pq extension not available"; 568 569 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config)); 570 571 struct DummyConsumer : public BnConsumerListener { 572 void onFrameAvailable(const BufferItem& /* item */) override {} 573 void onBuffersReleased() override {} 574 void onSidebandStreamChanged() override {} 575 }; 576 577 // Create a EGLSurface 578 sp<IGraphicBufferProducer> producer; 579 sp<IGraphicBufferConsumer> consumer; 580 BufferQueue::createBufferQueue(&producer, &consumer); 581 consumer->consumerConnect(new DummyConsumer, false); 582 sp<Surface> mSTC = new Surface(producer); 583 sp<ANativeWindow> mANW = mSTC; 584 std::vector<EGLint> winAttrs; 585 winAttrs.push_back(EGL_GL_COLORSPACE_KHR); 586 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT); 587 winAttrs.push_back(EGL_NONE); 588 589 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data()); 590 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 591 ASSERT_NE(EGL_NO_SURFACE, eglSurface); 592 593 EGLint value; 594 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value); 595 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 596 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value); 597 598 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface)); 599 600 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface)); 601 602 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface)); 603 } 604 605 TEST_F(EGLTest, EGLConfigFP16) { 606 EGLint numConfigs; 607 EGLConfig config; 608 EGLBoolean success; 609 610 if (!hasWideColorDisplay) { 611 // skip this test if device does not have wide-color display 612 RecordProperty("hasWideColorDisplay", false); 613 return; 614 } 615 616 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float")); 617 618 const EGLint attrs[] = { 619 // clang-format off 620 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 621 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 622 EGL_RED_SIZE, 16, 623 EGL_GREEN_SIZE, 16, 624 EGL_BLUE_SIZE, 16, 625 EGL_ALPHA_SIZE, 16, 626 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT, 627 EGL_NONE, 628 // clang-format on 629 }; 630 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); 631 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 632 ASSERT_EQ(1, numConfigs); 633 634 EGLint components[4]; 635 636 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); 637 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 638 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 639 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); 640 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 641 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 642 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); 643 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 644 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 645 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]); 646 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 647 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 648 649 EXPECT_GE(components[0], 16); 650 EXPECT_GE(components[1], 16); 651 EXPECT_GE(components[2], 16); 652 EXPECT_GE(components[3], 16); 653 654 struct DummyConsumer : public BnConsumerListener { 655 void onFrameAvailable(const BufferItem& /* item */) override {} 656 void onBuffersReleased() override {} 657 void onSidebandStreamChanged() override {} 658 }; 659 660 sp<IGraphicBufferProducer> producer; 661 sp<IGraphicBufferConsumer> consumer; 662 BufferQueue::createBufferQueue(&producer, &consumer); 663 consumer->consumerConnect(new DummyConsumer, false); 664 sp<Surface> mSTC = new Surface(producer); 665 sp<ANativeWindow> mANW = mSTC; 666 667 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL); 668 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 669 ASSERT_NE(EGL_NO_SURFACE, eglSurface); 670 671 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface)); 672 } 673 674 TEST_F(EGLTest, EGLNoConfigContext) { 675 if (!hasWideColorDisplay) { 676 // skip this test if device does not have wide-color display 677 RecordProperty("hasWideColorDisplay", false); 678 return; 679 } 680 681 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context")); 682 683 struct DummyConsumer : public BnConsumerListener { 684 void onFrameAvailable(const BufferItem& /* item */) override {} 685 void onBuffersReleased() override {} 686 void onSidebandStreamChanged() override {} 687 }; 688 689 std::vector<EGLint> contextAttributes; 690 contextAttributes.reserve(4); 691 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION); 692 contextAttributes.push_back(2); 693 contextAttributes.push_back(EGL_NONE); 694 contextAttributes.push_back(EGL_NONE); 695 696 EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT, 697 contextAttributes.data()); 698 EXPECT_NE(EGL_NO_CONTEXT, eglContext); 699 EXPECT_EQ(EGL_SUCCESS, eglGetError()); 700 701 if (eglContext != EGL_NO_CONTEXT) { 702 eglDestroyContext(mEglDisplay, eglContext); 703 } 704 } 705 706 // Emulate what a native application would do to create a 707 // 10:10:10:2 surface. 708 TEST_F(EGLTest, EGLConfig1010102) { 709 EGLint numConfigs; 710 EGLConfig config; 711 EGLBoolean success; 712 713 if (!hasWideColorDisplay) { 714 // skip this test if device does not have wide-color display 715 RecordProperty("hasWideColorDisplay", false); 716 return; 717 } 718 719 const EGLint attrs[] = { 720 // clang-format off 721 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 722 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 723 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, 724 EGL_RED_SIZE, 10, 725 EGL_GREEN_SIZE, 10, 726 EGL_BLUE_SIZE, 10, 727 EGL_ALPHA_SIZE, 2, 728 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, 729 EGL_NONE, EGL_NONE 730 // clang-format on 731 }; 732 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs); 733 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 734 ASSERT_EQ(1, numConfigs); 735 736 EGLint components[4]; 737 EGLint value; 738 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value); 739 740 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]); 741 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 742 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 743 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]); 744 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 745 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 746 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]); 747 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 748 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 749 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]); 750 ASSERT_EQ(EGL_UNSIGNED_TRUE, success); 751 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 752 753 EXPECT_EQ(components[0], 10); 754 EXPECT_EQ(components[1], 10); 755 EXPECT_EQ(components[2], 10); 756 EXPECT_EQ(components[3], 2); 757 758 struct DummyConsumer : public BnConsumerListener { 759 void onFrameAvailable(const BufferItem& /* item */) override {} 760 void onBuffersReleased() override {} 761 void onSidebandStreamChanged() override {} 762 }; 763 764 // Create a EGLSurface 765 sp<IGraphicBufferProducer> producer; 766 sp<IGraphicBufferConsumer> consumer; 767 BufferQueue::createBufferQueue(&producer, &consumer); 768 consumer->consumerConnect(new DummyConsumer, false); 769 sp<Surface> mSTC = new Surface(producer); 770 sp<ANativeWindow> mANW = mSTC; 771 772 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL); 773 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 774 ASSERT_NE(EGL_NO_SURFACE, eglSurface); 775 776 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface)); 777 } 778 } 779