blob: cbe4ef9c408af1d5d1290727e5b37b598bdf055b [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>
18
Sundong Ahn204fb1f2020-04-23 21:56:36 +090019#include <SurfaceFlingerProperties.h>
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060020#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
21
22#include <configstore/Utils.h>
Mathias Agopian2f739f82011-07-07 14:54:30 -070023#include <utils/String8.h>
24
25#include <EGL/egl.h>
Mathias Agopiane3c697f2013-02-14 17:11:02 -080026#include <gui/Surface.h>
Mathias Agopian2b5dd402017-02-07 17:36:19 -080027#include <gui/IConsumerListener.h>
28#include <gui/IProducerListener.h>
29#include <gui/IGraphicBufferConsumer.h>
30#include <gui/BufferQueue.h>
Mathias Agopian2f739f82011-07-07 14:54:30 -070031
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060032bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060033 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060034 size_t cropExtLen = strlen(extensionName);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060035 size_t extsLen = strlen(exts);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060036 bool equal = !strcmp(extensionName, exts);
37 android::String8 extString(extensionName);
38 android::String8 space(" ");
39 bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060040 bool atEnd = (cropExtLen + 1) < extsLen &&
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060041 !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
42 bool inMiddle = strstr(exts, space + extString + space);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060043 return equal || atStart || atEnd || inMiddle;
44}
45
Mathias Agopian2f739f82011-07-07 14:54:30 -070046namespace android {
47
Kalle Raita4cf36372017-01-13 10:18:36 -080048#define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
49
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060050// retrieve wide-color setting from configstore
51using namespace android::hardware::configstore;
Jaesoo Lee3b746b32017-05-02 22:19:39 +090052using namespace android::hardware::configstore::V1_0;
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060053
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -080054#define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT))
55
Sundong Ahn204fb1f2020-04-23 21:56:36 +090056static bool hasWideColorDisplay = android::sysprop::has_wide_color_display(false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060057
Sundong Ahn204fb1f2020-04-23 21:56:36 +090058static bool hasHdrDisplay = android::sysprop::has_HDR_display(false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -070059
Mathias Agopian2f739f82011-07-07 14:54:30 -070060class EGLTest : public ::testing::Test {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -070061public:
62 void get8BitConfig(EGLConfig& config);
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -070063 void setSurfaceSmpteMetadata(EGLSurface surface);
64 void checkSurfaceSmpteMetadata(EGLSurface eglSurface);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -070065
Mathias Agopian2f739f82011-07-07 14:54:30 -070066protected:
67 EGLDisplay mEglDisplay;
68
69protected:
70 EGLTest() :
71 mEglDisplay(EGL_NO_DISPLAY) {
72 }
73
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
87 virtual void TearDown() {
88 EGLBoolean success = eglTerminate(mEglDisplay);
Kalle Raita4cf36372017-01-13 10:18:36 -080089 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -070090 ASSERT_EQ(EGL_SUCCESS, eglGetError());
91 }
92};
93
94TEST_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);
Kalle Raita4cf36372017-01-13 10:18:36 -0800106 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700107 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]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800113 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700114 ASSERT_EQ(EGL_SUCCESS, eglGetError());
115 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
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_BLUE_SIZE, &components[2]);
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
122 EXPECT_GE(components[0], 8);
123 EXPECT_GE(components[1], 8);
124 EXPECT_GE(components[2], 8);
125}
126
Daniel Lam1cbcb982012-04-16 22:21:02 -0700127TEST_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
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700141 struct MockConsumer : public BnConsumerListener {
Brian Anderson5ea5e592016-12-01 16:54:33 -0800142 void onFrameAvailable(const BufferItem& /* item */) override {}
143 void onBuffersReleased() override {}
144 void onSidebandStreamChanged() override {}
Mathias Agopian595264f2013-07-16 22:56:09 -0700145 };
146
Daniel Lam1cbcb982012-04-16 22:21:02 -0700147 // Create a EGLSurface
Dan Stoza5603a2f2014-04-07 13:41:37 -0700148 sp<IGraphicBufferProducer> producer;
149 sp<IGraphicBufferConsumer> consumer;
150 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700151 consumer->consumerConnect(new MockConsumer, false);
Dan Stoza5603a2f2014-04-07 13:41:37 -0700152 sp<Surface> mSTC = new Surface(producer);
Daniel Lam1cbcb982012-04-16 22:21:02 -0700153 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
Mathias Agopian2f739f82011-07-07 14:54:30 -0700164TEST_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);
Kalle Raita4cf36372017-01-13 10:18:36 -0800180 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700181 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]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800187 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700188 ASSERT_EQ(EGL_SUCCESS, eglGetError());
189 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
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_BLUE_SIZE, &components[2]);
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_ALPHA_SIZE, &components[3]);
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
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
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600205TEST_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
Courtney Goeltzenleuchtere4177262017-07-10 16:34:25 -0600212 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600213 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"));
Peiyong Line0ff3772018-12-08 22:23:20 -0800219 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600220
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
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700261 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600262 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);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700271 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600272 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
Peiyong Line0ff3772018-12-08 22:23:20 -0800292TEST_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
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700309 struct MockConsumer : public BnConsumerListener {
Peiyong Line0ff3772018-12-08 22:23:20 -0800310 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);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700319 consumer->consumerConnect(new MockConsumer, false);
Peiyong Line0ff3772018-12-08 22:23:20 -0800320 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
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600345TEST_F(EGLTest, EGLDisplayP31010102) {
Cody Northrop2a66e542022-12-19 15:32:11 -0700346 // This test has been failing since:
347 // libEGL: When driver doesn't understand P3, map sRGB-encoded P3 to sRGB
348 // https://android-review.git.corp.google.com/c/platform/frameworks/native/+/793504
349 GTEST_SKIP() << "Skipping broken test. See b/120714942 and b/117104367";
350
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600351 EGLint numConfigs;
352 EGLConfig config;
353 EGLBoolean success;
354
355 if (!hasWideColorDisplay) {
356 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchtere4177262017-07-10 16:34:25 -0600357 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600358 return;
359 }
360
361 // Test that display-p3 extensions exist
362 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
363 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
Peiyong Line0ff3772018-12-08 22:23:20 -0800364 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600365
366 // Use 8-bit to keep forcus on Display-P3 aspect
367 EGLint attrs[] = {
368 // clang-format off
369 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
370 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
371 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
372 EGL_RED_SIZE, 10,
373 EGL_GREEN_SIZE, 10,
374 EGL_BLUE_SIZE, 10,
375 EGL_ALPHA_SIZE, 2,
376 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
377 EGL_NONE, EGL_NONE
378 // clang-format on
379 };
380 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
381 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
382 ASSERT_EQ(1, numConfigs);
383
384 EGLint components[4];
385 EGLint value;
386 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
387
388 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
389 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
390 ASSERT_EQ(EGL_SUCCESS, eglGetError());
391 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
392 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
393 ASSERT_EQ(EGL_SUCCESS, eglGetError());
394 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
395 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
396 ASSERT_EQ(EGL_SUCCESS, eglGetError());
397 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
398 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
399 ASSERT_EQ(EGL_SUCCESS, eglGetError());
400
401 EXPECT_EQ(components[0], 10);
402 EXPECT_EQ(components[1], 10);
403 EXPECT_EQ(components[2], 10);
404 EXPECT_EQ(components[3], 2);
405
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700406 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600407 void onFrameAvailable(const BufferItem& /* item */) override {}
408 void onBuffersReleased() override {}
409 void onSidebandStreamChanged() override {}
410 };
411
412 // Create a EGLSurface
413 sp<IGraphicBufferProducer> producer;
414 sp<IGraphicBufferConsumer> consumer;
415 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700416 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600417 sp<Surface> mSTC = new Surface(producer);
418 sp<ANativeWindow> mANW = mSTC;
419 EGLint winAttrs[] = {
420 // clang-format off
421 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
422 EGL_NONE, EGL_NONE
423 // clang-format on
424 };
425
426 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
427 ASSERT_EQ(EGL_SUCCESS, eglGetError());
428 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
429
430 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
431 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
432 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
433
434 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
435}
436
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700437void EGLTest::get8BitConfig(EGLConfig& config) {
438 EGLint numConfigs;
439 EGLBoolean success;
440
441 // Use 8-bit to keep focus on colorspace aspect
442 const EGLint attrs[] = {
443 // clang-format off
444 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
445 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
446 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
447 EGL_RED_SIZE, 8,
448 EGL_GREEN_SIZE, 8,
449 EGL_BLUE_SIZE, 8,
450 EGL_ALPHA_SIZE, 8,
451 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
452 EGL_NONE,
453 // clang-format on
454 };
455 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
456 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
457 ASSERT_EQ(1, numConfigs);
458
459 EGLint components[4];
460 EGLint value;
461 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
462
463 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
464 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
465 ASSERT_EQ(EGL_SUCCESS, eglGetError());
466 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
467 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
468 ASSERT_EQ(EGL_SUCCESS, eglGetError());
469 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
470 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
471 ASSERT_EQ(EGL_SUCCESS, eglGetError());
472 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
473 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
474 ASSERT_EQ(EGL_SUCCESS, eglGetError());
475
476 // Verify component sizes on config match what was asked for.
477 EXPECT_EQ(components[0], 8);
478 EXPECT_EQ(components[1], 8);
479 EXPECT_EQ(components[2], 8);
480 EXPECT_EQ(components[3], 8);
481}
482
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700483void EGLTest::setSurfaceSmpteMetadata(EGLSurface surface) {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700484 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700485 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT,
486 METADATA_SCALE(0.640));
487 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT,
488 METADATA_SCALE(0.330));
489 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT,
490 METADATA_SCALE(0.290));
491 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT,
492 METADATA_SCALE(0.600));
493 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT,
494 METADATA_SCALE(0.150));
495 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT,
496 METADATA_SCALE(0.060));
497 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_X_EXT,
498 METADATA_SCALE(0.3127));
499 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_Y_EXT,
500 METADATA_SCALE(0.3290));
501 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT,
502 METADATA_SCALE(300));
503 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MIN_LUMINANCE_EXT,
504 METADATA_SCALE(0.7));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700505 }
506
507 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700508 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT,
509 METADATA_SCALE(300));
510 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT,
511 METADATA_SCALE(75));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700512 }
513}
514
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700515void EGLTest::checkSurfaceSmpteMetadata(EGLSurface eglSurface) {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700516 EGLBoolean success;
517 EGLint value;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700518
519 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
520 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, &value);
521 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800522 ASSERT_EQ(METADATA_SCALE(0.640), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700523 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, &value);
524 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800525 ASSERT_EQ(METADATA_SCALE(0.330), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700526 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, &value);
527 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800528 ASSERT_EQ(METADATA_SCALE(0.290), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700529 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, &value);
530 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800531 ASSERT_EQ(METADATA_SCALE(0.600), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700532 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, &value);
533 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800534 ASSERT_EQ(METADATA_SCALE(0.150), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700535 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, &value);
536 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800537 ASSERT_EQ(METADATA_SCALE(0.060), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700538 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_X_EXT, &value);
539 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800540 ASSERT_EQ(METADATA_SCALE(0.3127), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700541 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, &value);
542 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800543 ASSERT_EQ(METADATA_SCALE(0.3290), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700544 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, &value);
545 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800546 ASSERT_EQ(METADATA_SCALE(300.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700547 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, &value);
548 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800549 ASSERT_EQ(METADATA_SCALE(0.7), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700550 }
551
552 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
553 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, &value);
554 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800555 ASSERT_EQ(METADATA_SCALE(300.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700556 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, &value);
557 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800558 ASSERT_EQ(METADATA_SCALE(75.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700559 }
560}
561
562TEST_F(EGLTest, EGLBT2020Linear) {
563 EGLConfig config;
564 EGLBoolean success;
565
566 if (!hasHdrDisplay) {
567 // skip this test if device does not have HDR display
568 RecordProperty("hasHdrDisplay", false);
569 return;
570 }
571
572 // Test that bt2020 linear extension exists
573 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"))
574 << "EGL_EXT_gl_colorspace_bt2020_linear extension not available";
575
576 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
577
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700578 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700579 void onFrameAvailable(const BufferItem& /* item */) override {}
580 void onBuffersReleased() override {}
581 void onSidebandStreamChanged() override {}
582 };
583
584 // Create a EGLSurface
585 sp<IGraphicBufferProducer> producer;
586 sp<IGraphicBufferConsumer> consumer;
587 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700588 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700589 sp<Surface> mSTC = new Surface(producer);
590 sp<ANativeWindow> mANW = mSTC;
591
592 std::vector<EGLint> winAttrs;
593 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
594 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
595
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700596 winAttrs.push_back(EGL_NONE);
597
598 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
599 ASSERT_EQ(EGL_SUCCESS, eglGetError());
600 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
601
602 EGLint value;
603 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
604 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
605 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
606
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700607 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
608
609 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700610
611 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
612}
613
614TEST_F(EGLTest, EGLBT2020PQ) {
615 EGLConfig config;
616 EGLBoolean success;
617
618 if (!hasHdrDisplay) {
619 // skip this test if device does not have HDR display
620 RecordProperty("hasHdrDisplay", false);
621 return;
622 }
623
624 // Test that bt2020-pq extension exists
625 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"))
626 << "EGL_EXT_gl_colorspace_bt2020_pq extension not available";
627
628 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
629
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700630 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700631 void onFrameAvailable(const BufferItem& /* item */) override {}
632 void onBuffersReleased() override {}
633 void onSidebandStreamChanged() override {}
634 };
635
636 // Create a EGLSurface
637 sp<IGraphicBufferProducer> producer;
638 sp<IGraphicBufferConsumer> consumer;
639 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700640 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700641 sp<Surface> mSTC = new Surface(producer);
642 sp<ANativeWindow> mANW = mSTC;
643 std::vector<EGLint> winAttrs;
644 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
645 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700646 winAttrs.push_back(EGL_NONE);
647
648 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
649 ASSERT_EQ(EGL_SUCCESS, eglGetError());
650 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
651
652 EGLint value;
653 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
654 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
655 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
656
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700657 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
658
659 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700660
661 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
662}
663
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600664TEST_F(EGLTest, EGLConfigFP16) {
665 EGLint numConfigs;
666 EGLConfig config;
667 EGLBoolean success;
Mathias Agopian2f739f82011-07-07 14:54:30 -0700668
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600669 if (!hasWideColorDisplay) {
670 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700671 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600672 return;
673 }
674
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600675 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600676
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700677 const EGLint attrs[] = {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600678 // clang-format off
679 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
680 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
681 EGL_RED_SIZE, 16,
682 EGL_GREEN_SIZE, 16,
683 EGL_BLUE_SIZE, 16,
684 EGL_ALPHA_SIZE, 16,
685 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700686 EGL_NONE,
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600687 // clang-format on
688 };
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600689 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
690 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
691 ASSERT_EQ(1, numConfigs);
692
693 EGLint components[4];
694
695 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
696 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
697 ASSERT_EQ(EGL_SUCCESS, eglGetError());
698 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
699 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
700 ASSERT_EQ(EGL_SUCCESS, eglGetError());
701 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
702 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
703 ASSERT_EQ(EGL_SUCCESS, eglGetError());
704 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
705 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
706 ASSERT_EQ(EGL_SUCCESS, eglGetError());
707
708 EXPECT_GE(components[0], 16);
709 EXPECT_GE(components[1], 16);
710 EXPECT_GE(components[2], 16);
711 EXPECT_GE(components[3], 16);
712
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700713 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600714 void onFrameAvailable(const BufferItem& /* item */) override {}
715 void onBuffersReleased() override {}
716 void onSidebandStreamChanged() override {}
717 };
718
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600719 sp<IGraphicBufferProducer> producer;
720 sp<IGraphicBufferConsumer> consumer;
721 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700722 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600723 sp<Surface> mSTC = new Surface(producer);
724 sp<ANativeWindow> mANW = mSTC;
725
726 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
727 ASSERT_EQ(EGL_SUCCESS, eglGetError());
728 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
729
730 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
731}
732
Courtney Goeltzenleuchterd99694b2017-07-10 16:30:42 -0600733TEST_F(EGLTest, EGLNoConfigContext) {
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600734 if (!hasWideColorDisplay) {
735 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700736 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600737 return;
738 }
739
740 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
741
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700742 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600743 void onFrameAvailable(const BufferItem& /* item */) override {}
744 void onBuffersReleased() override {}
745 void onSidebandStreamChanged() override {}
746 };
747
748 std::vector<EGLint> contextAttributes;
749 contextAttributes.reserve(4);
750 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
751 contextAttributes.push_back(2);
752 contextAttributes.push_back(EGL_NONE);
753 contextAttributes.push_back(EGL_NONE);
754
755 EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
756 contextAttributes.data());
757 EXPECT_NE(EGL_NO_CONTEXT, eglContext);
758 EXPECT_EQ(EGL_SUCCESS, eglGetError());
759
760 if (eglContext != EGL_NO_CONTEXT) {
761 eglDestroyContext(mEglDisplay, eglContext);
762 }
763}
764
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600765// Emulate what a native application would do to create a
766// 10:10:10:2 surface.
767TEST_F(EGLTest, EGLConfig1010102) {
768 EGLint numConfigs;
769 EGLConfig config;
770 EGLBoolean success;
771
772 if (!hasWideColorDisplay) {
773 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700774 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600775 return;
776 }
777
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700778 const EGLint attrs[] = {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600779 // clang-format off
780 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
781 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
782 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
783 EGL_RED_SIZE, 10,
784 EGL_GREEN_SIZE, 10,
785 EGL_BLUE_SIZE, 10,
786 EGL_ALPHA_SIZE, 2,
787 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
788 EGL_NONE, EGL_NONE
789 // clang-format on
790 };
791 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
792 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
793 ASSERT_EQ(1, numConfigs);
794
795 EGLint components[4];
796 EGLint value;
797 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
798
799 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
800 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
801 ASSERT_EQ(EGL_SUCCESS, eglGetError());
802 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
803 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
804 ASSERT_EQ(EGL_SUCCESS, eglGetError());
805 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
806 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
807 ASSERT_EQ(EGL_SUCCESS, eglGetError());
808 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
809 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
810 ASSERT_EQ(EGL_SUCCESS, eglGetError());
811
812 EXPECT_EQ(components[0], 10);
813 EXPECT_EQ(components[1], 10);
814 EXPECT_EQ(components[2], 10);
815 EXPECT_EQ(components[3], 2);
816
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700817 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600818 void onFrameAvailable(const BufferItem& /* item */) override {}
819 void onBuffersReleased() override {}
820 void onSidebandStreamChanged() override {}
821 };
822
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600823 // Create a EGLSurface
824 sp<IGraphicBufferProducer> producer;
825 sp<IGraphicBufferConsumer> consumer;
826 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700827 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600828 sp<Surface> mSTC = new Surface(producer);
829 sp<ANativeWindow> mANW = mSTC;
830
831 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
832 ASSERT_EQ(EGL_SUCCESS, eglGetError());
833 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
834
835 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
836}
Weiwan Liu3ca92972018-09-28 15:44:12 -0700837
838TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
839 EGLConfig config;
840
841 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
842
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700843 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700844 void onFrameAvailable(const BufferItem& /* item */) override {}
845 void onBuffersReleased() override {}
846 void onSidebandStreamChanged() override {}
847 };
848
849 // Create a EGLSurface
850 sp<IGraphicBufferProducer> producer;
851 sp<IGraphicBufferConsumer> consumer;
852 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700853 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700854 sp<Surface> mSTC = new Surface(producer);
855 sp<ANativeWindow> mANW = mSTC;
856
857 EGLint winAttrs[] = {
858 // clang-format off
859 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
860 EGL_NONE,
861 // clang-format on
862 };
863
864 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
865 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
866 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
867}
868
869TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
870 EGLint numConfigs;
871 EGLConfig config;
872 EGLBoolean success;
873
Cody Northrop2a66e542022-12-19 15:32:11 -0700874 if (!hasWideColorDisplay) {
875 // skip this test if device does not have wide-color display
876 RecordProperty("hasWideColorDisplay", false);
877 return;
878 }
879
Weiwan Liu3ca92972018-09-28 15:44:12 -0700880 const EGLint attrs[] = {
881 // clang-format off
882 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
883 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
884 EGL_RED_SIZE, 16,
885 EGL_GREEN_SIZE, 16,
886 EGL_BLUE_SIZE, 16,
887 EGL_ALPHA_SIZE, 16,
888 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
889 EGL_NONE,
890 // clang-format on
891 };
892 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
893 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
894 ASSERT_EQ(1, numConfigs);
895
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700896 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700897 void onFrameAvailable(const BufferItem& /* item */) override {}
898 void onBuffersReleased() override {}
899 void onSidebandStreamChanged() override {}
900 };
901
902 // Create a EGLSurface
903 sp<IGraphicBufferProducer> producer;
904 sp<IGraphicBufferConsumer> consumer;
905 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700906 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700907 sp<Surface> mSTC = new Surface(producer);
908 sp<ANativeWindow> mANW = mSTC;
909
910 const EGLint winAttrs[] = {
911 // clang-format off
912 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
913 EGL_NONE,
914 // clang-format on
915 };
916
917 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
918 ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
919 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
920}
921
922TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
923 EGLConfig config;
924
925 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
926
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700927 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700928 void onFrameAvailable(const BufferItem& /* item */) override {}
929 void onBuffersReleased() override {}
930 void onSidebandStreamChanged() override {}
931 };
932
933 // Create a EGLSurface
934 sp<IGraphicBufferProducer> producer;
935 sp<IGraphicBufferConsumer> consumer;
936 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700937 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700938 sp<Surface> mSTC = new Surface(producer);
939 sp<ANativeWindow> mANW = mSTC;
940
941 EGLint winAttrs[] = {
942 // clang-format off
943 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
944 EGL_NONE,
945 // clang-format on
946 };
947
948 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
949 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
950 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
951
952 // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
953 // in the first failed attempt (e.g. native_window_api_disconnect).
954 winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
955 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
956 ASSERT_EQ(EGL_SUCCESS, eglGetError());
957 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
958
959 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
960}
961
962TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
963 EGLConfig config;
964
Cody Northrop2a66e542022-12-19 15:32:11 -0700965 if (!hasWideColorDisplay) {
966 // skip this test if device does not have wide-color display
967 RecordProperty("hasWideColorDisplay", false);
968 return;
969 }
970
Weiwan Liu3ca92972018-09-28 15:44:12 -0700971 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
972
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700973 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700974 void onFrameAvailable(const BufferItem& /* item */) override {}
975 void onBuffersReleased() override {}
976 void onSidebandStreamChanged() override {}
977 };
978
979 // Create a EGLSurface
980 sp<IGraphicBufferProducer> producer;
981 sp<IGraphicBufferConsumer> consumer;
982 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700983 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700984 sp<Surface> mSTC = new Surface(producer);
985 sp<ANativeWindow> mANW = mSTC;
986
987 const EGLint winAttrs[] = {
988 // clang-format off
989 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
990 EGL_NONE,
991 // clang-format on
992 };
993
994 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
995 ASSERT_EQ(EGL_SUCCESS, eglGetError());
996 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
997
998 android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
999 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
1000
1001 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1002
1003 // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
1004 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
1005 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1006 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
1007
1008 dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
1009 // Make sure the dataspace has been reset to UNKNOWN
1010 ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
1011
1012 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1013}
Mathias Agopian2f739f82011-07-07 14:54:30 -07001014}