blob: 503d7dffdb7a832b58352b619efd133b91aa1024 [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
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600768// Emulate what a native application would do to create a
769// 10:10:10:2 surface.
770TEST_F(EGLTest, EGLConfig1010102) {
771 EGLint numConfigs;
772 EGLConfig config;
773 EGLBoolean success;
774
775 if (!hasWideColorDisplay) {
776 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700777 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600778 return;
779 }
780
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700781 const EGLint attrs[] = {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600782 // clang-format off
783 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
784 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
785 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
786 EGL_RED_SIZE, 10,
787 EGL_GREEN_SIZE, 10,
788 EGL_BLUE_SIZE, 10,
789 EGL_ALPHA_SIZE, 2,
790 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
791 EGL_NONE, EGL_NONE
792 // clang-format on
793 };
794 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
795 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
796 ASSERT_EQ(1, numConfigs);
797
798 EGLint components[4];
799 EGLint value;
800 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
801
802 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
803 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
804 ASSERT_EQ(EGL_SUCCESS, eglGetError());
805 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
806 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
807 ASSERT_EQ(EGL_SUCCESS, eglGetError());
808 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
809 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
810 ASSERT_EQ(EGL_SUCCESS, eglGetError());
811 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
812 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
813 ASSERT_EQ(EGL_SUCCESS, eglGetError());
814
815 EXPECT_EQ(components[0], 10);
816 EXPECT_EQ(components[1], 10);
817 EXPECT_EQ(components[2], 10);
818 EXPECT_EQ(components[3], 2);
819
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700820 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600821 void onFrameAvailable(const BufferItem& /* item */) override {}
822 void onBuffersReleased() override {}
823 void onSidebandStreamChanged() override {}
824 };
825
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600826 // Create a EGLSurface
827 sp<IGraphicBufferProducer> producer;
828 sp<IGraphicBufferConsumer> consumer;
829 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700830 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600831 sp<Surface> mSTC = new Surface(producer);
832 sp<ANativeWindow> mANW = mSTC;
833
834 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
835 ASSERT_EQ(EGL_SUCCESS, eglGetError());
836 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
837
838 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
839}
Weiwan Liu3ca92972018-09-28 15:44:12 -0700840
841TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
842 EGLConfig config;
843
844 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
845
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700846 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700847 void onFrameAvailable(const BufferItem& /* item */) override {}
848 void onBuffersReleased() override {}
849 void onSidebandStreamChanged() override {}
850 };
851
852 // Create a EGLSurface
853 sp<IGraphicBufferProducer> producer;
854 sp<IGraphicBufferConsumer> consumer;
855 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700856 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700857 sp<Surface> mSTC = new Surface(producer);
858 sp<ANativeWindow> mANW = mSTC;
859
860 EGLint winAttrs[] = {
861 // clang-format off
862 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
863 EGL_NONE,
864 // clang-format on
865 };
866
867 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
868 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
869 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
870}
871
872TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
873 EGLint numConfigs;
874 EGLConfig config;
875 EGLBoolean success;
876
Cody Northrop2a66e542022-12-19 15:32:11 -0700877 if (!hasWideColorDisplay) {
878 // skip this test if device does not have wide-color display
879 RecordProperty("hasWideColorDisplay", false);
880 return;
881 }
882
Weiwan Liu3ca92972018-09-28 15:44:12 -0700883 const EGLint attrs[] = {
884 // clang-format off
885 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
886 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
887 EGL_RED_SIZE, 16,
888 EGL_GREEN_SIZE, 16,
889 EGL_BLUE_SIZE, 16,
890 EGL_ALPHA_SIZE, 16,
891 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
892 EGL_NONE,
893 // clang-format on
894 };
895 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
896 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
897 ASSERT_EQ(1, numConfigs);
898
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700899 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700900 void onFrameAvailable(const BufferItem& /* item */) override {}
901 void onBuffersReleased() override {}
902 void onSidebandStreamChanged() override {}
903 };
904
905 // Create a EGLSurface
906 sp<IGraphicBufferProducer> producer;
907 sp<IGraphicBufferConsumer> consumer;
908 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700909 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700910 sp<Surface> mSTC = new Surface(producer);
911 sp<ANativeWindow> mANW = mSTC;
912
913 const EGLint winAttrs[] = {
914 // clang-format off
915 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
916 EGL_NONE,
917 // clang-format on
918 };
919
920 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
921 ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
922 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
923}
924
925TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
926 EGLConfig config;
927
928 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
929
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700930 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700931 void onFrameAvailable(const BufferItem& /* item */) override {}
932 void onBuffersReleased() override {}
933 void onSidebandStreamChanged() override {}
934 };
935
936 // Create a EGLSurface
937 sp<IGraphicBufferProducer> producer;
938 sp<IGraphicBufferConsumer> consumer;
939 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700940 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700941 sp<Surface> mSTC = new Surface(producer);
942 sp<ANativeWindow> mANW = mSTC;
943
944 EGLint winAttrs[] = {
945 // clang-format off
946 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
947 EGL_NONE,
948 // clang-format on
949 };
950
951 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
952 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
953 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
954
955 // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
956 // in the first failed attempt (e.g. native_window_api_disconnect).
957 winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
958 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
959 ASSERT_EQ(EGL_SUCCESS, eglGetError());
960 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
961
962 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
963}
964
965TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
966 EGLConfig config;
967
Cody Northrop2a66e542022-12-19 15:32:11 -0700968 if (!hasWideColorDisplay) {
969 // skip this test if device does not have wide-color display
970 RecordProperty("hasWideColorDisplay", false);
971 return;
972 }
973
Weiwan Liu3ca92972018-09-28 15:44:12 -0700974 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
975
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700976 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700977 void onFrameAvailable(const BufferItem& /* item */) override {}
978 void onBuffersReleased() override {}
979 void onSidebandStreamChanged() override {}
980 };
981
982 // Create a EGLSurface
983 sp<IGraphicBufferProducer> producer;
984 sp<IGraphicBufferConsumer> consumer;
985 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700986 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700987 sp<Surface> mSTC = new Surface(producer);
988 sp<ANativeWindow> mANW = mSTC;
989
990 const EGLint winAttrs[] = {
991 // clang-format off
992 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
993 EGL_NONE,
994 // clang-format on
995 };
996
997 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
998 ASSERT_EQ(EGL_SUCCESS, eglGetError());
999 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
1000
1001 android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
1002 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
1003
1004 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1005
1006 // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
1007 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
1008 ASSERT_EQ(EGL_SUCCESS, eglGetError());
1009 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
1010
1011 dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
1012 // Make sure the dataspace has been reset to UNKNOWN
1013 ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
1014
1015 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
1016}
Tom Murphya1742962024-04-28 13:09:04 +00001017
1018TEST_F(EGLTest, EGLCheckExtensionString) {
1019 // check that the format of the extension string is correct
1020
1021 egl_display_t* display = egl_display_t::get(mEglDisplay);
1022 ASSERT_NE(display, nullptr);
1023
1024 std::string extensionStrRegex = "((EGL_ANDROID_front_buffer_auto_refresh|"
1025 "EGL_ANDROID_get_native_client_buffer|"
1026 "EGL_ANDROID_presentation_time|"
1027 "EGL_EXT_surface_CTA861_3_metadata|"
1028 "EGL_EXT_surface_SMPTE2086_metadata|"
1029 "EGL_KHR_get_all_proc_addresses|"
1030 "EGL_KHR_swap_buffers_with_damage|"
1031 "EGL_ANDROID_get_frame_timestamps|"
1032 "EGL_EXT_gl_colorspace_scrgb|"
1033 "EGL_EXT_gl_colorspace_scrgb_linear|"
1034 "EGL_EXT_gl_colorspace_display_p3_linear|"
1035 "EGL_EXT_gl_colorspace_display_p3|"
1036 "EGL_EXT_gl_colorspace_display_p3_passthrough|"
1037 "EGL_EXT_gl_colorspace_bt2020_hlg|"
1038 "EGL_EXT_gl_colorspace_bt2020_linear|"
1039 "EGL_EXT_gl_colorspace_bt2020_pq|"
1040 "EGL_ANDROID_image_native_buffer|"
1041 "EGL_ANDROID_native_fence_sync|"
1042 "EGL_ANDROID_recordable|"
1043 "EGL_EXT_create_context_robustness|"
1044 "EGL_EXT_image_gl_colorspace|"
1045 "EGL_EXT_pixel_format_float|"
1046 "EGL_EXT_protected_content|"
1047 "EGL_EXT_yuv_surface|"
1048 "EGL_IMG_context_priority|"
1049 "EGL_KHR_config_attribs|"
1050 "EGL_KHR_create_context|"
1051 "EGL_KHR_fence_sync|"
1052 "EGL_KHR_gl_colorspace|"
1053 "EGL_KHR_gl_renderbuffer_image|"
1054 "EGL_KHR_gl_texture_2D_image|"
1055 "EGL_KHR_gl_texture_3D_image|"
1056 "EGL_KHR_gl_texture_cubemap_image|"
1057 "EGL_KHR_image|"
1058 "EGL_KHR_image_base|"
1059 "EGL_KHR_mutable_render_buffer|"
1060 "EGL_KHR_no_config_context|"
1061 "EGL_KHR_partial_update|"
1062 "EGL_KHR_surfaceless_context|"
1063 "EGL_KHR_wait_sync|"
1064 "EGL_EXT_buffer_age|"
1065 "EGL_KHR_reusable_sync|"
1066 "EGL_NV_context_priority_realtime) )+";
1067 EXPECT_THAT(display->getExtensionString(), testing::MatchesRegex(extensionStrRegex));
1068}
1069
Mathias Agopian2f739f82011-07-07 14:54:30 -07001070}