blob: 839a5cab2f2176a9062da3f2e693504c90060c0a [file] [log] [blame]
Mathias Agopian2f739f82011-07-07 14:54:30 -07001/*
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>
Tom Murphya1742962024-04-28 13:09:04 +000018#include <gmock/gmock.h>
Mathias Agopian2f739f82011-07-07 14:54:30 -070019
Sundong Ahn204fb1f2020-04-23 21:56:36 +090020#include <SurfaceFlingerProperties.h>
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060021#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
22
23#include <configstore/Utils.h>
Mathias Agopian2f739f82011-07-07 14:54:30 -070024#include <utils/String8.h>
25
26#include <EGL/egl.h>
Mathias Agopiane3c697f2013-02-14 17:11:02 -080027#include <gui/Surface.h>
Mathias Agopian2b5dd402017-02-07 17:36:19 -080028#include <gui/IConsumerListener.h>
29#include <gui/IProducerListener.h>
30#include <gui/IGraphicBufferConsumer.h>
31#include <gui/BufferQueue.h>
Mathias Agopian2f739f82011-07-07 14:54:30 -070032
Tom Murphya1742962024-04-28 13:09:04 +000033#include "egl_display.h"
34
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060035bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060036 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060037 size_t cropExtLen = strlen(extensionName);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060038 size_t extsLen = strlen(exts);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060039 bool equal = !strcmp(extensionName, exts);
40 android::String8 extString(extensionName);
41 android::String8 space(" ");
42 bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060043 bool atEnd = (cropExtLen + 1) < extsLen &&
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060044 !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
45 bool inMiddle = strstr(exts, space + extString + space);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060046 return equal || atStart || atEnd || inMiddle;
47}
48
Mathias Agopian2f739f82011-07-07 14:54:30 -070049namespace android {
50
Kalle Raita4cf36372017-01-13 10:18:36 -080051#define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
52
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060053// retrieve wide-color setting from configstore
54using namespace android::hardware::configstore;
Jaesoo Lee3b746b32017-05-02 22:19:39 +090055using namespace android::hardware::configstore::V1_0;
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060056
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -080057#define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT))
58
Sundong Ahn204fb1f2020-04-23 21:56:36 +090059static bool hasWideColorDisplay = android::sysprop::has_wide_color_display(false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060060
Sundong Ahn204fb1f2020-04-23 21:56:36 +090061static bool hasHdrDisplay = android::sysprop::has_HDR_display(false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -070062
Mathias Agopian2f739f82011-07-07 14:54:30 -070063class EGLTest : public ::testing::Test {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -070064public:
65 void get8BitConfig(EGLConfig& config);
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -070066 void setSurfaceSmpteMetadata(EGLSurface surface);
67 void checkSurfaceSmpteMetadata(EGLSurface eglSurface);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -070068
Mathias Agopian2f739f82011-07-07 14:54:30 -070069protected:
70 EGLDisplay mEglDisplay;
71
72protected:
73 EGLTest() :
74 mEglDisplay(EGL_NO_DISPLAY) {
75 }
76
77 virtual void SetUp() {
78 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
79 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
80 ASSERT_EQ(EGL_SUCCESS, eglGetError());
81
82 EGLint majorVersion;
83 EGLint minorVersion;
84 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
85 ASSERT_EQ(EGL_SUCCESS, eglGetError());
86 RecordProperty("EglVersionMajor", majorVersion);
87 RecordProperty("EglVersionMajor", minorVersion);
88 }
89
90 virtual void TearDown() {
91 EGLBoolean success = eglTerminate(mEglDisplay);
Kalle Raita4cf36372017-01-13 10:18:36 -080092 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -070093 ASSERT_EQ(EGL_SUCCESS, eglGetError());
94 }
95};
96
97TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) {
98
99 EGLint numConfigs;
100 EGLConfig config;
101 EGLBoolean success;
102 EGLint attrs[] = {
103 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
104 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
105 EGL_NONE
106 };
107
108 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
Kalle Raita4cf36372017-01-13 10:18:36 -0800109 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700110 ASSERT_EQ(EGL_SUCCESS, eglGetError());
111 ASSERT_GE(numConfigs, 1);
112
113 EGLint components[3];
114
115 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800116 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700117 ASSERT_EQ(EGL_SUCCESS, eglGetError());
118 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800119 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700120 ASSERT_EQ(EGL_SUCCESS, eglGetError());
121 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800122 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700123 ASSERT_EQ(EGL_SUCCESS, eglGetError());
124
125 EXPECT_GE(components[0], 8);
126 EXPECT_GE(components[1], 8);
127 EXPECT_GE(components[2], 8);
128}
129
Daniel Lam1cbcb982012-04-16 22:21:02 -0700130TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) {
131 EGLint numConfigs;
132 EGLConfig config;
133 EGLint attrs[] = {
134 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
135 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
136 EGL_RED_SIZE, 8,
137 EGL_GREEN_SIZE, 8,
138 EGL_BLUE_SIZE, 8,
139 EGL_ALPHA_SIZE, 8,
140 EGL_NONE
141 };
142 EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
143
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700144 struct MockConsumer : public BnConsumerListener {
Brian Anderson5ea5e592016-12-01 16:54:33 -0800145 void onFrameAvailable(const BufferItem& /* item */) override {}
146 void onBuffersReleased() override {}
147 void onSidebandStreamChanged() override {}
Mathias Agopian595264f2013-07-16 22:56:09 -0700148 };
149
Daniel Lam1cbcb982012-04-16 22:21:02 -0700150 // Create a EGLSurface
Dan Stoza5603a2f2014-04-07 13:41:37 -0700151 sp<IGraphicBufferProducer> producer;
152 sp<IGraphicBufferConsumer> consumer;
153 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700154 consumer->consumerConnect(new MockConsumer, false);
Dan Stoza5603a2f2014-04-07 13:41:37 -0700155 sp<Surface> mSTC = new Surface(producer);
Daniel Lam1cbcb982012-04-16 22:21:02 -0700156 sp<ANativeWindow> mANW = mSTC;
157
158 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config,
159 mANW.get(), NULL);
160 ASSERT_EQ(EGL_SUCCESS, eglGetError());
161 ASSERT_NE(EGL_NO_SURFACE, eglSurface) ;
162
163 // do not destroy eglSurface
164 // eglTerminate is called in the tear down and should destroy it for us
165}
166
Mathias Agopian2f739f82011-07-07 14:54:30 -0700167TEST_F(EGLTest, EGLConfigRGBA8888First) {
168
169 EGLint numConfigs;
170 EGLConfig config;
171 EGLBoolean success;
172 EGLint attrs[] = {
173 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
174 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
175 EGL_RED_SIZE, 8,
176 EGL_GREEN_SIZE, 8,
177 EGL_BLUE_SIZE, 8,
178 EGL_ALPHA_SIZE, 8,
179 EGL_NONE
180 };
181
182 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
Kalle Raita4cf36372017-01-13 10:18:36 -0800183 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700184 ASSERT_EQ(EGL_SUCCESS, eglGetError());
185 ASSERT_GE(numConfigs, 1);
186
187 EGLint components[4];
188
189 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800190 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700191 ASSERT_EQ(EGL_SUCCESS, eglGetError());
192 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800193 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700194 ASSERT_EQ(EGL_SUCCESS, eglGetError());
195 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800196 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700197 ASSERT_EQ(EGL_SUCCESS, eglGetError());
198 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800199 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700200 ASSERT_EQ(EGL_SUCCESS, eglGetError());
201
202 EXPECT_GE(components[0], 8);
203 EXPECT_GE(components[1], 8);
204 EXPECT_GE(components[2], 8);
205 EXPECT_GE(components[3], 8);
206}
207
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600208TEST_F(EGLTest, EGLDisplayP3) {
209 EGLint numConfigs;
210 EGLConfig config;
211 EGLBoolean success;
212
213 if (!hasWideColorDisplay) {
214 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchtere4177262017-07-10 16:34:25 -0600215 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600216 return;
217 }
218
219 // Test that display-p3 extensions exist
220 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
221 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
Peiyong Line0ff3772018-12-08 22:23:20 -0800222 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600223
224 // Use 8-bit to keep forcus on Display-P3 aspect
225 EGLint attrs[] = {
226 // clang-format off
227 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
228 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
229 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
230 EGL_RED_SIZE, 8,
231 EGL_GREEN_SIZE, 8,
232 EGL_BLUE_SIZE, 8,
233 EGL_ALPHA_SIZE, 8,
234 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
235 EGL_NONE, EGL_NONE
236 // clang-format on
237 };
238 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
239 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
240 ASSERT_EQ(1, numConfigs);
241
242 EGLint components[4];
243 EGLint value;
244 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
245
246 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
247 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
248 ASSERT_EQ(EGL_SUCCESS, eglGetError());
249 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
250 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
251 ASSERT_EQ(EGL_SUCCESS, eglGetError());
252 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
253 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
254 ASSERT_EQ(EGL_SUCCESS, eglGetError());
255 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
256 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
257 ASSERT_EQ(EGL_SUCCESS, eglGetError());
258
259 EXPECT_EQ(components[0], 8);
260 EXPECT_EQ(components[1], 8);
261 EXPECT_EQ(components[2], 8);
262 EXPECT_EQ(components[3], 8);
263
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700264 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600265 void onFrameAvailable(const BufferItem& /* item */) override {}
266 void onBuffersReleased() override {}
267 void onSidebandStreamChanged() override {}
268 };
269
270 // Create a EGLSurface
271 sp<IGraphicBufferProducer> producer;
272 sp<IGraphicBufferConsumer> consumer;
273 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700274 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600275 sp<Surface> mSTC = new Surface(producer);
276 sp<ANativeWindow> mANW = mSTC;
277 EGLint winAttrs[] = {
278 // clang-format off
279 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
280 EGL_NONE, EGL_NONE
281 // clang-format on
282 };
283
284 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
285 ASSERT_EQ(EGL_SUCCESS, eglGetError());
286 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
287
288 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
289 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
290 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
291
292 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
293}
294
Peiyong Line0ff3772018-12-08 22:23:20 -0800295TEST_F(EGLTest, EGLDisplayP3Passthrough) {
296 EGLConfig config;
297 EGLBoolean success;
298
299 if (!hasWideColorDisplay) {
300 // skip this test if device does not have wide-color display
301 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
302 return;
303 }
304
305 // Test that display-p3 extensions exist
306 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
307 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
308 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
309
310 get8BitConfig(config);
311
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700312 struct MockConsumer : public BnConsumerListener {
Peiyong Line0ff3772018-12-08 22:23:20 -0800313 void onFrameAvailable(const BufferItem& /* item */) override {}
314 void onBuffersReleased() override {}
315 void onSidebandStreamChanged() override {}
316 };
317
318 // Create a EGLSurface
319 sp<IGraphicBufferProducer> producer;
320 sp<IGraphicBufferConsumer> consumer;
321 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700322 consumer->consumerConnect(new MockConsumer, false);
Peiyong Line0ff3772018-12-08 22:23:20 -0800323 sp<Surface> mSTC = new Surface(producer);
324 sp<ANativeWindow> mANW = mSTC;
325 EGLint winAttrs[] = {
326 // clang-format off
327 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT,
328 EGL_NONE, EGL_NONE
329 // clang-format on
330 };
331
332 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
333 ASSERT_EQ(EGL_SUCCESS, eglGetError());
334 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
335
336 android_dataspace dataspace =
337 static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
338 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
339
340 EGLint value;
341 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
342 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
343 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT, value);
344
345 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
346}
347
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600348TEST_F(EGLTest, EGLDisplayP31010102) {
Cody Northrop2a66e542022-12-19 15:32:11 -0700349 // This test has been failing since:
350 // libEGL: When driver doesn't understand P3, map sRGB-encoded P3 to sRGB
351 // https://android-review.git.corp.google.com/c/platform/frameworks/native/+/793504
352 GTEST_SKIP() << "Skipping broken test. See b/120714942 and b/117104367";
353
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600354 EGLint numConfigs;
355 EGLConfig config;
356 EGLBoolean success;
357
358 if (!hasWideColorDisplay) {
359 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchtere4177262017-07-10 16:34:25 -0600360 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600361 return;
362 }
363
364 // Test that display-p3 extensions exist
365 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
366 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
Peiyong Line0ff3772018-12-08 22:23:20 -0800367 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600368
369 // Use 8-bit to keep forcus on Display-P3 aspect
370 EGLint attrs[] = {
371 // clang-format off
372 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
373 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
374 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
375 EGL_RED_SIZE, 10,
376 EGL_GREEN_SIZE, 10,
377 EGL_BLUE_SIZE, 10,
378 EGL_ALPHA_SIZE, 2,
379 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
380 EGL_NONE, EGL_NONE
381 // clang-format on
382 };
383 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
384 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
385 ASSERT_EQ(1, numConfigs);
386
387 EGLint components[4];
388 EGLint value;
389 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
390
391 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
392 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
393 ASSERT_EQ(EGL_SUCCESS, eglGetError());
394 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
395 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
396 ASSERT_EQ(EGL_SUCCESS, eglGetError());
397 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
398 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
399 ASSERT_EQ(EGL_SUCCESS, eglGetError());
400 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
401 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
402 ASSERT_EQ(EGL_SUCCESS, eglGetError());
403
404 EXPECT_EQ(components[0], 10);
405 EXPECT_EQ(components[1], 10);
406 EXPECT_EQ(components[2], 10);
407 EXPECT_EQ(components[3], 2);
408
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700409 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600410 void onFrameAvailable(const BufferItem& /* item */) override {}
411 void onBuffersReleased() override {}
412 void onSidebandStreamChanged() override {}
413 };
414
415 // Create a EGLSurface
416 sp<IGraphicBufferProducer> producer;
417 sp<IGraphicBufferConsumer> consumer;
418 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700419 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600420 sp<Surface> mSTC = new Surface(producer);
421 sp<ANativeWindow> mANW = mSTC;
422 EGLint winAttrs[] = {
423 // clang-format off
424 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
425 EGL_NONE, EGL_NONE
426 // clang-format on
427 };
428
429 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
430 ASSERT_EQ(EGL_SUCCESS, eglGetError());
431 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
432
433 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
434 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
435 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
436
437 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
438}
439
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700440void EGLTest::get8BitConfig(EGLConfig& config) {
441 EGLint numConfigs;
442 EGLBoolean success;
443
444 // Use 8-bit to keep focus on colorspace aspect
445 const EGLint attrs[] = {
446 // clang-format off
447 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
448 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
449 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
450 EGL_RED_SIZE, 8,
451 EGL_GREEN_SIZE, 8,
452 EGL_BLUE_SIZE, 8,
453 EGL_ALPHA_SIZE, 8,
454 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
455 EGL_NONE,
456 // clang-format on
457 };
458 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
459 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
460 ASSERT_EQ(1, numConfigs);
461
462 EGLint components[4];
463 EGLint value;
464 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
465
466 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
467 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
468 ASSERT_EQ(EGL_SUCCESS, eglGetError());
469 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
470 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
471 ASSERT_EQ(EGL_SUCCESS, eglGetError());
472 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
473 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
474 ASSERT_EQ(EGL_SUCCESS, eglGetError());
475 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
476 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
477 ASSERT_EQ(EGL_SUCCESS, eglGetError());
478
479 // Verify component sizes on config match what was asked for.
480 EXPECT_EQ(components[0], 8);
481 EXPECT_EQ(components[1], 8);
482 EXPECT_EQ(components[2], 8);
483 EXPECT_EQ(components[3], 8);
484}
485
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700486void EGLTest::setSurfaceSmpteMetadata(EGLSurface surface) {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700487 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700488 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT,
489 METADATA_SCALE(0.640));
490 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT,
491 METADATA_SCALE(0.330));
492 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT,
493 METADATA_SCALE(0.290));
494 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT,
495 METADATA_SCALE(0.600));
496 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT,
497 METADATA_SCALE(0.150));
498 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT,
499 METADATA_SCALE(0.060));
500 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_X_EXT,
501 METADATA_SCALE(0.3127));
502 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_Y_EXT,
503 METADATA_SCALE(0.3290));
504 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT,
505 METADATA_SCALE(300));
506 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MIN_LUMINANCE_EXT,
507 METADATA_SCALE(0.7));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700508 }
509
510 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700511 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT,
512 METADATA_SCALE(300));
513 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT,
514 METADATA_SCALE(75));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700515 }
516}
517
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700518void EGLTest::checkSurfaceSmpteMetadata(EGLSurface eglSurface) {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700519 EGLBoolean success;
520 EGLint value;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700521
522 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
523 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, &value);
524 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800525 ASSERT_EQ(METADATA_SCALE(0.640), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700526 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, &value);
527 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800528 ASSERT_EQ(METADATA_SCALE(0.330), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700529 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, &value);
530 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800531 ASSERT_EQ(METADATA_SCALE(0.290), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700532 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, &value);
533 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800534 ASSERT_EQ(METADATA_SCALE(0.600), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700535 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, &value);
536 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800537 ASSERT_EQ(METADATA_SCALE(0.150), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700538 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, &value);
539 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800540 ASSERT_EQ(METADATA_SCALE(0.060), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700541 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_X_EXT, &value);
542 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800543 ASSERT_EQ(METADATA_SCALE(0.3127), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700544 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, &value);
545 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800546 ASSERT_EQ(METADATA_SCALE(0.3290), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700547 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, &value);
548 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800549 ASSERT_EQ(METADATA_SCALE(300.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700550 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, &value);
551 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800552 ASSERT_EQ(METADATA_SCALE(0.7), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700553 }
554
555 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
556 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, &value);
557 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800558 ASSERT_EQ(METADATA_SCALE(300.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700559 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, &value);
560 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800561 ASSERT_EQ(METADATA_SCALE(75.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700562 }
563}
564
565TEST_F(EGLTest, EGLBT2020Linear) {
566 EGLConfig config;
567 EGLBoolean success;
568
569 if (!hasHdrDisplay) {
570 // skip this test if device does not have HDR display
571 RecordProperty("hasHdrDisplay", false);
572 return;
573 }
574
575 // Test that bt2020 linear extension exists
576 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"))
577 << "EGL_EXT_gl_colorspace_bt2020_linear extension not available";
578
579 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
580
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700581 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700582 void onFrameAvailable(const BufferItem& /* item */) override {}
583 void onBuffersReleased() override {}
584 void onSidebandStreamChanged() override {}
585 };
586
587 // Create a EGLSurface
588 sp<IGraphicBufferProducer> producer;
589 sp<IGraphicBufferConsumer> consumer;
590 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700591 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700592 sp<Surface> mSTC = new Surface(producer);
593 sp<ANativeWindow> mANW = mSTC;
594
595 std::vector<EGLint> winAttrs;
596 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
597 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
598
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700599 winAttrs.push_back(EGL_NONE);
600
601 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
602 ASSERT_EQ(EGL_SUCCESS, eglGetError());
603 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
604
605 EGLint value;
606 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
607 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
608 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
609
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700610 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
611
612 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700613
614 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
615}
616
617TEST_F(EGLTest, EGLBT2020PQ) {
618 EGLConfig config;
619 EGLBoolean success;
620
621 if (!hasHdrDisplay) {
622 // skip this test if device does not have HDR display
623 RecordProperty("hasHdrDisplay", false);
624 return;
625 }
626
627 // Test that bt2020-pq extension exists
628 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"))
629 << "EGL_EXT_gl_colorspace_bt2020_pq extension not available";
630
631 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
632
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700633 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700634 void onFrameAvailable(const BufferItem& /* item */) override {}
635 void onBuffersReleased() override {}
636 void onSidebandStreamChanged() override {}
637 };
638
639 // Create a EGLSurface
640 sp<IGraphicBufferProducer> producer;
641 sp<IGraphicBufferConsumer> consumer;
642 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700643 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700644 sp<Surface> mSTC = new Surface(producer);
645 sp<ANativeWindow> mANW = mSTC;
646 std::vector<EGLint> winAttrs;
647 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
648 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700649 winAttrs.push_back(EGL_NONE);
650
651 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
652 ASSERT_EQ(EGL_SUCCESS, eglGetError());
653 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
654
655 EGLint value;
656 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
657 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
658 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
659
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700660 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
661
662 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700663
664 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
665}
666
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600667TEST_F(EGLTest, EGLConfigFP16) {
668 EGLint numConfigs;
669 EGLConfig config;
670 EGLBoolean success;
Mathias Agopian2f739f82011-07-07 14:54:30 -0700671
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600672 if (!hasWideColorDisplay) {
673 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700674 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600675 return;
676 }
677
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600678 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600679
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700680 const EGLint attrs[] = {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600681 // clang-format off
682 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
683 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
684 EGL_RED_SIZE, 16,
685 EGL_GREEN_SIZE, 16,
686 EGL_BLUE_SIZE, 16,
687 EGL_ALPHA_SIZE, 16,
688 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700689 EGL_NONE,
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600690 // clang-format on
691 };
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600692 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
693 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
694 ASSERT_EQ(1, numConfigs);
695
696 EGLint components[4];
697
698 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
699 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
700 ASSERT_EQ(EGL_SUCCESS, eglGetError());
701 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
702 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
703 ASSERT_EQ(EGL_SUCCESS, eglGetError());
704 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
705 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
706 ASSERT_EQ(EGL_SUCCESS, eglGetError());
707 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
708 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
709 ASSERT_EQ(EGL_SUCCESS, eglGetError());
710
711 EXPECT_GE(components[0], 16);
712 EXPECT_GE(components[1], 16);
713 EXPECT_GE(components[2], 16);
714 EXPECT_GE(components[3], 16);
715
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700716 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600717 void onFrameAvailable(const BufferItem& /* item */) override {}
718 void onBuffersReleased() override {}
719 void onSidebandStreamChanged() override {}
720 };
721
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600722 sp<IGraphicBufferProducer> producer;
723 sp<IGraphicBufferConsumer> consumer;
724 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700725 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600726 sp<Surface> mSTC = new Surface(producer);
727 sp<ANativeWindow> mANW = mSTC;
728
729 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
730 ASSERT_EQ(EGL_SUCCESS, eglGetError());
731 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
732
733 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
734}
735
Courtney Goeltzenleuchterd99694b2017-07-10 16:30:42 -0600736TEST_F(EGLTest, EGLNoConfigContext) {
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600737 if (!hasWideColorDisplay) {
738 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700739 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600740 return;
741 }
742
743 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
744
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700745 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600746 void onFrameAvailable(const BufferItem& /* item */) override {}
747 void onBuffersReleased() override {}
748 void onSidebandStreamChanged() override {}
749 };
750
751 std::vector<EGLint> contextAttributes;
752 contextAttributes.reserve(4);
753 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
754 contextAttributes.push_back(2);
755 contextAttributes.push_back(EGL_NONE);
756 contextAttributes.push_back(EGL_NONE);
757
758 EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
759 contextAttributes.data());
760 EXPECT_NE(EGL_NO_CONTEXT, eglContext);
761 EXPECT_EQ(EGL_SUCCESS, eglGetError());
762
763 if (eglContext != EGL_NO_CONTEXT) {
764 eglDestroyContext(mEglDisplay, eglContext);
765 }
766}
767
Tom Murphy3013feb2024-08-23 10:05:32 +0000768// Verify that eglCreateContext works when EGL_TELEMETRY_HINT_ANDROID is used with
769// NO_HINT = 0, SKIP_TELEMETRY = 1 and an invalid of value of 2
770TEST_F(EGLTest, EGLContextTelemetryHintExt) {
771 for (int i = 0; i < 3; i++) {
772 EGLConfig config;
773 get8BitConfig(config);
774 std::vector<EGLint> contextAttributes;
775 contextAttributes.reserve(4);
776 contextAttributes.push_back(EGL_TELEMETRY_HINT_ANDROID);
777 contextAttributes.push_back(i);
778 contextAttributes.push_back(EGL_NONE);
779 contextAttributes.push_back(EGL_NONE);
780
781 EGLContext eglContext = eglCreateContext(mEglDisplay, config, EGL_NO_CONTEXT,
782 contextAttributes.data());
783 EXPECT_NE(EGL_NO_CONTEXT, eglContext);
784 EXPECT_EQ(EGL_SUCCESS, eglGetError());
785
786 if (eglContext != EGL_NO_CONTEXT) {
787 eglDestroyContext(mEglDisplay, eglContext);
788 }
789 }
790}
791
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600792// Emulate what a native application would do to create a
793// 10:10:10:2 surface.
794TEST_F(EGLTest, EGLConfig1010102) {
795 EGLint numConfigs;
796 EGLConfig config;
797 EGLBoolean success;
798
799 if (!hasWideColorDisplay) {
800 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700801 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600802 return;
803 }
804
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700805 const EGLint attrs[] = {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600806 // clang-format off
807 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
808 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
809 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
810 EGL_RED_SIZE, 10,
811 EGL_GREEN_SIZE, 10,
812 EGL_BLUE_SIZE, 10,
813 EGL_ALPHA_SIZE, 2,
814 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
815 EGL_NONE, EGL_NONE
816 // clang-format on
817 };
818 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
819 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
820 ASSERT_EQ(1, numConfigs);
821
822 EGLint components[4];
823 EGLint value;
824 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
825
826 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
827 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
828 ASSERT_EQ(EGL_SUCCESS, eglGetError());
829 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
830 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
831 ASSERT_EQ(EGL_SUCCESS, eglGetError());
832 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
833 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
834 ASSERT_EQ(EGL_SUCCESS, eglGetError());
835 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
836 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
837 ASSERT_EQ(EGL_SUCCESS, eglGetError());
838
839 EXPECT_EQ(components[0], 10);
840 EXPECT_EQ(components[1], 10);
841 EXPECT_EQ(components[2], 10);
842 EXPECT_EQ(components[3], 2);
843
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700844 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600845 void onFrameAvailable(const BufferItem& /* item */) override {}
846 void onBuffersReleased() override {}
847 void onSidebandStreamChanged() override {}
848 };
849
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600850 // Create a EGLSurface
851 sp<IGraphicBufferProducer> producer;
852 sp<IGraphicBufferConsumer> consumer;
853 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700854 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600855 sp<Surface> mSTC = new Surface(producer);
856 sp<ANativeWindow> mANW = mSTC;
857
858 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
859 ASSERT_EQ(EGL_SUCCESS, eglGetError());
860 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
861
862 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
863}
Weiwan Liu3ca92972018-09-28 15:44:12 -0700864
865TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
866 EGLConfig config;
867
868 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
869
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700870 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700871 void onFrameAvailable(const BufferItem& /* item */) override {}
872 void onBuffersReleased() override {}
873 void onSidebandStreamChanged() override {}
874 };
875
876 // Create a EGLSurface
877 sp<IGraphicBufferProducer> producer;
878 sp<IGraphicBufferConsumer> consumer;
879 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700880 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700881 sp<Surface> mSTC = new Surface(producer);
882 sp<ANativeWindow> mANW = mSTC;
883
884 EGLint winAttrs[] = {
885 // clang-format off
886 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
887 EGL_NONE,
888 // clang-format on
889 };
890
891 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
892 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
893 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
894}
895
896TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
897 EGLint numConfigs;
898 EGLConfig config;
899 EGLBoolean success;
900
Cody Northrop2a66e542022-12-19 15:32:11 -0700901 if (!hasWideColorDisplay) {
902 // skip this test if device does not have wide-color display
903 RecordProperty("hasWideColorDisplay", false);
904 return;
905 }
906
Weiwan Liu3ca92972018-09-28 15:44:12 -0700907 const EGLint attrs[] = {
908 // clang-format off
909 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
910 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
911 EGL_RED_SIZE, 16,
912 EGL_GREEN_SIZE, 16,
913 EGL_BLUE_SIZE, 16,
914 EGL_ALPHA_SIZE, 16,
915 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
916 EGL_NONE,
917 // clang-format on
918 };
919 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
920 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
921 ASSERT_EQ(1, numConfigs);
922
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700923 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700924 void onFrameAvailable(const BufferItem& /* item */) override {}
925 void onBuffersReleased() override {}
926 void onSidebandStreamChanged() override {}
927 };
928
929 // Create a EGLSurface
930 sp<IGraphicBufferProducer> producer;
931 sp<IGraphicBufferConsumer> consumer;
932 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700933 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700934 sp<Surface> mSTC = new Surface(producer);
935 sp<ANativeWindow> mANW = mSTC;
936
937 const EGLint winAttrs[] = {
938 // clang-format off
939 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
940 EGL_NONE,
941 // clang-format on
942 };
943
944 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
945 ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
946 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
947}
948
949TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
950 EGLConfig config;
951
952 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
953
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700954 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700955 void onFrameAvailable(const BufferItem& /* item */) override {}
956 void onBuffersReleased() override {}
957 void onSidebandStreamChanged() override {}
958 };
959
960 // Create a EGLSurface
961 sp<IGraphicBufferProducer> producer;
962 sp<IGraphicBufferConsumer> consumer;
963 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700964 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700965 sp<Surface> mSTC = new Surface(producer);
966 sp<ANativeWindow> mANW = mSTC;
967
968 EGLint winAttrs[] = {
969 // clang-format off
970 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
971 EGL_NONE,
972 // clang-format on
973 };
974
975 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
976 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
977 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
978
979 // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
980 // in the first failed attempt (e.g. native_window_api_disconnect).
981 winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
982 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
983 ASSERT_EQ(EGL_SUCCESS, eglGetError());
984 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
985
986 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
987}
988
989TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
990 EGLConfig config;
991
Cody Northrop2a66e542022-12-19 15:32:11 -0700992 if (!hasWideColorDisplay) {
993 // skip this test if device does not have wide-color display
994 RecordProperty("hasWideColorDisplay", false);
995 return;
996 }
997
Weiwan Liu3ca92972018-09-28 15:44:12 -0700998 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
999
Yiwei Zhang26169cd2020-07-28 15:46:12 -07001000 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -07001001 void onFrameAvailable(const BufferItem& /* item */) override {}
1002 void onBuffersReleased() override {}
1003 void onSidebandStreamChanged() override {}
1004 };
1005
1006 // Create a EGLSurface
1007 sp<IGraphicBufferProducer> producer;
1008 sp<IGraphicBufferConsumer> consumer;
1009 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -07001010 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -07001011 sp<Surface> mSTC = new Surface(producer);
1012 sp<ANativeWindow> mANW = mSTC;
1013
1014 const EGLint winAttrs[] = {
1015 // clang-format off
1016 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
1017 EGL_NONE,
1018 // clang-format on
1019 };
1020
1021 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
1022 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1023 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
1024
1025 android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
1026 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
1027
1028 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1029
1030 // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
1031 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
1032 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1033 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
1034
1035 dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
1036 // Make sure the dataspace has been reset to UNKNOWN
1037 ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
1038
1039 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1040}
Tom Murphya1742962024-04-28 13:09:04 +00001041
1042TEST_F(EGLTest, EGLCheckExtensionString) {
1043 // check that the format of the extension string is correct
1044
1045 egl_display_t* display = egl_display_t::get(mEglDisplay);
1046 ASSERT_NE(display, nullptr);
1047
1048 std::string extensionStrRegex = "((EGL_ANDROID_front_buffer_auto_refresh|"
1049 "EGL_ANDROID_get_native_client_buffer|"
1050 "EGL_ANDROID_presentation_time|"
1051 "EGL_EXT_surface_CTA861_3_metadata|"
1052 "EGL_EXT_surface_SMPTE2086_metadata|"
1053 "EGL_KHR_get_all_proc_addresses|"
1054 "EGL_KHR_swap_buffers_with_damage|"
1055 "EGL_ANDROID_get_frame_timestamps|"
1056 "EGL_EXT_gl_colorspace_scrgb|"
1057 "EGL_EXT_gl_colorspace_scrgb_linear|"
1058 "EGL_EXT_gl_colorspace_display_p3_linear|"
1059 "EGL_EXT_gl_colorspace_display_p3|"
1060 "EGL_EXT_gl_colorspace_display_p3_passthrough|"
1061 "EGL_EXT_gl_colorspace_bt2020_hlg|"
1062 "EGL_EXT_gl_colorspace_bt2020_linear|"
1063 "EGL_EXT_gl_colorspace_bt2020_pq|"
1064 "EGL_ANDROID_image_native_buffer|"
1065 "EGL_ANDROID_native_fence_sync|"
1066 "EGL_ANDROID_recordable|"
1067 "EGL_EXT_create_context_robustness|"
1068 "EGL_EXT_image_gl_colorspace|"
1069 "EGL_EXT_pixel_format_float|"
1070 "EGL_EXT_protected_content|"
1071 "EGL_EXT_yuv_surface|"
1072 "EGL_IMG_context_priority|"
1073 "EGL_KHR_config_attribs|"
1074 "EGL_KHR_create_context|"
1075 "EGL_KHR_fence_sync|"
1076 "EGL_KHR_gl_colorspace|"
1077 "EGL_KHR_gl_renderbuffer_image|"
1078 "EGL_KHR_gl_texture_2D_image|"
1079 "EGL_KHR_gl_texture_3D_image|"
1080 "EGL_KHR_gl_texture_cubemap_image|"
1081 "EGL_KHR_image|"
1082 "EGL_KHR_image_base|"
1083 "EGL_KHR_mutable_render_buffer|"
1084 "EGL_KHR_no_config_context|"
1085 "EGL_KHR_partial_update|"
1086 "EGL_KHR_surfaceless_context|"
1087 "EGL_KHR_wait_sync|"
1088 "EGL_EXT_buffer_age|"
1089 "EGL_KHR_reusable_sync|"
1090 "EGL_NV_context_priority_realtime) )+";
1091 EXPECT_THAT(display->getExtensionString(), testing::MatchesRegex(extensionStrRegex));
1092}
1093
Mathias Agopian2f739f82011-07-07 14:54:30 -07001094}