blob: bbd786d155f3cbe83f5206a399431477c6da9cb1 [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) {
346 EGLint numConfigs;
347 EGLConfig config;
348 EGLBoolean success;
349
350 if (!hasWideColorDisplay) {
351 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchtere4177262017-07-10 16:34:25 -0600352 std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600353 return;
354 }
355
356 // Test that display-p3 extensions exist
357 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3"));
358 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_linear"));
Peiyong Line0ff3772018-12-08 22:23:20 -0800359 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_display_p3_passthrough"));
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600360
361 // Use 8-bit to keep forcus on Display-P3 aspect
362 EGLint attrs[] = {
363 // clang-format off
364 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
365 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
366 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
367 EGL_RED_SIZE, 10,
368 EGL_GREEN_SIZE, 10,
369 EGL_BLUE_SIZE, 10,
370 EGL_ALPHA_SIZE, 2,
371 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
372 EGL_NONE, EGL_NONE
373 // clang-format on
374 };
375 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
376 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
377 ASSERT_EQ(1, numConfigs);
378
379 EGLint components[4];
380 EGLint value;
381 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
382
383 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
384 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
385 ASSERT_EQ(EGL_SUCCESS, eglGetError());
386 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
387 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
388 ASSERT_EQ(EGL_SUCCESS, eglGetError());
389 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
390 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
391 ASSERT_EQ(EGL_SUCCESS, eglGetError());
392 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
393 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
394 ASSERT_EQ(EGL_SUCCESS, eglGetError());
395
396 EXPECT_EQ(components[0], 10);
397 EXPECT_EQ(components[1], 10);
398 EXPECT_EQ(components[2], 10);
399 EXPECT_EQ(components[3], 2);
400
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700401 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600402 void onFrameAvailable(const BufferItem& /* item */) override {}
403 void onBuffersReleased() override {}
404 void onSidebandStreamChanged() override {}
405 };
406
407 // Create a EGLSurface
408 sp<IGraphicBufferProducer> producer;
409 sp<IGraphicBufferConsumer> consumer;
410 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700411 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter2c325e22017-04-25 14:40:42 -0600412 sp<Surface> mSTC = new Surface(producer);
413 sp<ANativeWindow> mANW = mSTC;
414 EGLint winAttrs[] = {
415 // clang-format off
416 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
417 EGL_NONE, EGL_NONE
418 // clang-format on
419 };
420
421 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
422 ASSERT_EQ(EGL_SUCCESS, eglGetError());
423 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
424
425 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
426 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
427 ASSERT_EQ(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, value);
428
429 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
430}
431
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700432void EGLTest::get8BitConfig(EGLConfig& config) {
433 EGLint numConfigs;
434 EGLBoolean success;
435
436 // Use 8-bit to keep focus on colorspace aspect
437 const EGLint attrs[] = {
438 // clang-format off
439 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
440 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
441 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
442 EGL_RED_SIZE, 8,
443 EGL_GREEN_SIZE, 8,
444 EGL_BLUE_SIZE, 8,
445 EGL_ALPHA_SIZE, 8,
446 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
447 EGL_NONE,
448 // clang-format on
449 };
450 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
451 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
452 ASSERT_EQ(1, numConfigs);
453
454 EGLint components[4];
455 EGLint value;
456 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
457
458 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
459 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
460 ASSERT_EQ(EGL_SUCCESS, eglGetError());
461 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
462 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
463 ASSERT_EQ(EGL_SUCCESS, eglGetError());
464 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
465 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
466 ASSERT_EQ(EGL_SUCCESS, eglGetError());
467 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
468 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
469 ASSERT_EQ(EGL_SUCCESS, eglGetError());
470
471 // Verify component sizes on config match what was asked for.
472 EXPECT_EQ(components[0], 8);
473 EXPECT_EQ(components[1], 8);
474 EXPECT_EQ(components[2], 8);
475 EXPECT_EQ(components[3], 8);
476}
477
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700478void EGLTest::setSurfaceSmpteMetadata(EGLSurface surface) {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700479 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700480 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT,
481 METADATA_SCALE(0.640));
482 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT,
483 METADATA_SCALE(0.330));
484 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT,
485 METADATA_SCALE(0.290));
486 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT,
487 METADATA_SCALE(0.600));
488 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT,
489 METADATA_SCALE(0.150));
490 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT,
491 METADATA_SCALE(0.060));
492 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_X_EXT,
493 METADATA_SCALE(0.3127));
494 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_WHITE_POINT_Y_EXT,
495 METADATA_SCALE(0.3290));
496 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MAX_LUMINANCE_EXT,
497 METADATA_SCALE(300));
498 eglSurfaceAttrib(mEglDisplay, surface, EGL_SMPTE2086_MIN_LUMINANCE_EXT,
499 METADATA_SCALE(0.7));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700500 }
501
502 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700503 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT,
504 METADATA_SCALE(300));
505 eglSurfaceAttrib(mEglDisplay, surface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT,
506 METADATA_SCALE(75));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700507 }
508}
509
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700510void EGLTest::checkSurfaceSmpteMetadata(EGLSurface eglSurface) {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700511 EGLBoolean success;
512 EGLint value;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700513
514 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
515 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, &value);
516 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800517 ASSERT_EQ(METADATA_SCALE(0.640), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700518 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, &value);
519 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800520 ASSERT_EQ(METADATA_SCALE(0.330), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700521 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, &value);
522 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800523 ASSERT_EQ(METADATA_SCALE(0.290), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700524 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, &value);
525 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800526 ASSERT_EQ(METADATA_SCALE(0.600), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700527 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, &value);
528 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800529 ASSERT_EQ(METADATA_SCALE(0.150), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700530 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, &value);
531 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800532 ASSERT_EQ(METADATA_SCALE(0.060), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700533 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_X_EXT, &value);
534 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800535 ASSERT_EQ(METADATA_SCALE(0.3127), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700536 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, &value);
537 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800538 ASSERT_EQ(METADATA_SCALE(0.3290), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700539 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, &value);
540 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800541 ASSERT_EQ(METADATA_SCALE(300.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700542 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, &value);
543 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800544 ASSERT_EQ(METADATA_SCALE(0.7), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700545 }
546
547 if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
548 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, &value);
549 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800550 ASSERT_EQ(METADATA_SCALE(300.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700551 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, &value);
552 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800553 ASSERT_EQ(METADATA_SCALE(75.0), value);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700554 }
555}
556
557TEST_F(EGLTest, EGLBT2020Linear) {
558 EGLConfig config;
559 EGLBoolean success;
560
561 if (!hasHdrDisplay) {
562 // skip this test if device does not have HDR display
563 RecordProperty("hasHdrDisplay", false);
564 return;
565 }
566
567 // Test that bt2020 linear extension exists
568 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"))
569 << "EGL_EXT_gl_colorspace_bt2020_linear extension not available";
570
571 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
572
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700573 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700574 void onFrameAvailable(const BufferItem& /* item */) override {}
575 void onBuffersReleased() override {}
576 void onSidebandStreamChanged() override {}
577 };
578
579 // Create a EGLSurface
580 sp<IGraphicBufferProducer> producer;
581 sp<IGraphicBufferConsumer> consumer;
582 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700583 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700584 sp<Surface> mSTC = new Surface(producer);
585 sp<ANativeWindow> mANW = mSTC;
586
587 std::vector<EGLint> winAttrs;
588 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
589 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
590
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700591 winAttrs.push_back(EGL_NONE);
592
593 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
594 ASSERT_EQ(EGL_SUCCESS, eglGetError());
595 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
596
597 EGLint value;
598 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
599 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
600 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
601
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700602 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
603
604 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700605
606 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
607}
608
609TEST_F(EGLTest, EGLBT2020PQ) {
610 EGLConfig config;
611 EGLBoolean success;
612
613 if (!hasHdrDisplay) {
614 // skip this test if device does not have HDR display
615 RecordProperty("hasHdrDisplay", false);
616 return;
617 }
618
619 // Test that bt2020-pq extension exists
620 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"))
621 << "EGL_EXT_gl_colorspace_bt2020_pq extension not available";
622
623 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
624
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700625 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700626 void onFrameAvailable(const BufferItem& /* item */) override {}
627 void onBuffersReleased() override {}
628 void onSidebandStreamChanged() override {}
629 };
630
631 // Create a EGLSurface
632 sp<IGraphicBufferProducer> producer;
633 sp<IGraphicBufferConsumer> consumer;
634 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700635 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700636 sp<Surface> mSTC = new Surface(producer);
637 sp<ANativeWindow> mANW = mSTC;
638 std::vector<EGLint> winAttrs;
639 winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
640 winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700641 winAttrs.push_back(EGL_NONE);
642
643 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
644 ASSERT_EQ(EGL_SUCCESS, eglGetError());
645 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
646
647 EGLint value;
648 success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
649 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
650 ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
651
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700652 ASSERT_NO_FATAL_FAILURE(setSurfaceSmpteMetadata(eglSurface));
653
654 ASSERT_NO_FATAL_FAILURE(checkSurfaceSmpteMetadata(eglSurface));
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700655
656 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
657}
658
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600659TEST_F(EGLTest, EGLConfigFP16) {
660 EGLint numConfigs;
661 EGLConfig config;
662 EGLBoolean success;
Mathias Agopian2f739f82011-07-07 14:54:30 -0700663
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600664 if (!hasWideColorDisplay) {
665 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700666 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600667 return;
668 }
669
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600670 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600671
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700672 const EGLint attrs[] = {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600673 // clang-format off
674 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
675 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
676 EGL_RED_SIZE, 16,
677 EGL_GREEN_SIZE, 16,
678 EGL_BLUE_SIZE, 16,
679 EGL_ALPHA_SIZE, 16,
680 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700681 EGL_NONE,
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600682 // clang-format on
683 };
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600684 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
685 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
686 ASSERT_EQ(1, numConfigs);
687
688 EGLint components[4];
689
690 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
691 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
692 ASSERT_EQ(EGL_SUCCESS, eglGetError());
693 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
694 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
695 ASSERT_EQ(EGL_SUCCESS, eglGetError());
696 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
697 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
698 ASSERT_EQ(EGL_SUCCESS, eglGetError());
699 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
700 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
701 ASSERT_EQ(EGL_SUCCESS, eglGetError());
702
703 EXPECT_GE(components[0], 16);
704 EXPECT_GE(components[1], 16);
705 EXPECT_GE(components[2], 16);
706 EXPECT_GE(components[3], 16);
707
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700708 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600709 void onFrameAvailable(const BufferItem& /* item */) override {}
710 void onBuffersReleased() override {}
711 void onSidebandStreamChanged() override {}
712 };
713
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600714 sp<IGraphicBufferProducer> producer;
715 sp<IGraphicBufferConsumer> consumer;
716 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700717 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600718 sp<Surface> mSTC = new Surface(producer);
719 sp<ANativeWindow> mANW = mSTC;
720
721 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
722 ASSERT_EQ(EGL_SUCCESS, eglGetError());
723 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
724
725 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
726}
727
Courtney Goeltzenleuchterd99694b2017-07-10 16:30:42 -0600728TEST_F(EGLTest, EGLNoConfigContext) {
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600729 if (!hasWideColorDisplay) {
730 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700731 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600732 return;
733 }
734
735 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
736
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700737 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600738 void onFrameAvailable(const BufferItem& /* item */) override {}
739 void onBuffersReleased() override {}
740 void onSidebandStreamChanged() override {}
741 };
742
743 std::vector<EGLint> contextAttributes;
744 contextAttributes.reserve(4);
745 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
746 contextAttributes.push_back(2);
747 contextAttributes.push_back(EGL_NONE);
748 contextAttributes.push_back(EGL_NONE);
749
750 EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
751 contextAttributes.data());
752 EXPECT_NE(EGL_NO_CONTEXT, eglContext);
753 EXPECT_EQ(EGL_SUCCESS, eglGetError());
754
755 if (eglContext != EGL_NO_CONTEXT) {
756 eglDestroyContext(mEglDisplay, eglContext);
757 }
758}
759
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600760// Emulate what a native application would do to create a
761// 10:10:10:2 surface.
762TEST_F(EGLTest, EGLConfig1010102) {
763 EGLint numConfigs;
764 EGLConfig config;
765 EGLBoolean success;
766
767 if (!hasWideColorDisplay) {
768 // skip this test if device does not have wide-color display
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700769 RecordProperty("hasWideColorDisplay", false);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600770 return;
771 }
772
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700773 const EGLint attrs[] = {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600774 // clang-format off
775 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
776 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
777 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
778 EGL_RED_SIZE, 10,
779 EGL_GREEN_SIZE, 10,
780 EGL_BLUE_SIZE, 10,
781 EGL_ALPHA_SIZE, 2,
782 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
783 EGL_NONE, EGL_NONE
784 // clang-format on
785 };
786 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
787 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
788 ASSERT_EQ(1, numConfigs);
789
790 EGLint components[4];
791 EGLint value;
792 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
793
794 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
795 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
796 ASSERT_EQ(EGL_SUCCESS, eglGetError());
797 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
798 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
799 ASSERT_EQ(EGL_SUCCESS, eglGetError());
800 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
801 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
802 ASSERT_EQ(EGL_SUCCESS, eglGetError());
803 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
804 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
805 ASSERT_EQ(EGL_SUCCESS, eglGetError());
806
807 EXPECT_EQ(components[0], 10);
808 EXPECT_EQ(components[1], 10);
809 EXPECT_EQ(components[2], 10);
810 EXPECT_EQ(components[3], 2);
811
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700812 struct MockConsumer : public BnConsumerListener {
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600813 void onFrameAvailable(const BufferItem& /* item */) override {}
814 void onBuffersReleased() override {}
815 void onSidebandStreamChanged() override {}
816 };
817
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600818 // Create a EGLSurface
819 sp<IGraphicBufferProducer> producer;
820 sp<IGraphicBufferConsumer> consumer;
821 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700822 consumer->consumerConnect(new MockConsumer, false);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600823 sp<Surface> mSTC = new Surface(producer);
824 sp<ANativeWindow> mANW = mSTC;
825
826 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
827 ASSERT_EQ(EGL_SUCCESS, eglGetError());
828 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
829
830 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
831}
Weiwan Liu3ca92972018-09-28 15:44:12 -0700832
833TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
834 EGLConfig config;
835
836 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
837
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700838 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700839 void onFrameAvailable(const BufferItem& /* item */) override {}
840 void onBuffersReleased() override {}
841 void onSidebandStreamChanged() override {}
842 };
843
844 // Create a EGLSurface
845 sp<IGraphicBufferProducer> producer;
846 sp<IGraphicBufferConsumer> consumer;
847 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700848 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700849 sp<Surface> mSTC = new Surface(producer);
850 sp<ANativeWindow> mANW = mSTC;
851
852 EGLint winAttrs[] = {
853 // clang-format off
854 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
855 EGL_NONE,
856 // clang-format on
857 };
858
859 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
860 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
861 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
862}
863
864TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
865 EGLint numConfigs;
866 EGLConfig config;
867 EGLBoolean success;
868
869 const EGLint attrs[] = {
870 // clang-format off
871 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
872 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
873 EGL_RED_SIZE, 16,
874 EGL_GREEN_SIZE, 16,
875 EGL_BLUE_SIZE, 16,
876 EGL_ALPHA_SIZE, 16,
877 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
878 EGL_NONE,
879 // clang-format on
880 };
881 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
882 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
883 ASSERT_EQ(1, numConfigs);
884
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700885 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700886 void onFrameAvailable(const BufferItem& /* item */) override {}
887 void onBuffersReleased() override {}
888 void onSidebandStreamChanged() override {}
889 };
890
891 // Create a EGLSurface
892 sp<IGraphicBufferProducer> producer;
893 sp<IGraphicBufferConsumer> consumer;
894 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700895 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700896 sp<Surface> mSTC = new Surface(producer);
897 sp<ANativeWindow> mANW = mSTC;
898
899 const EGLint winAttrs[] = {
900 // clang-format off
901 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
902 EGL_NONE,
903 // clang-format on
904 };
905
906 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
907 ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
908 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
909}
910
911TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
912 EGLConfig config;
913
914 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
915
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700916 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700917 void onFrameAvailable(const BufferItem& /* item */) override {}
918 void onBuffersReleased() override {}
919 void onSidebandStreamChanged() override {}
920 };
921
922 // Create a EGLSurface
923 sp<IGraphicBufferProducer> producer;
924 sp<IGraphicBufferConsumer> consumer;
925 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700926 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700927 sp<Surface> mSTC = new Surface(producer);
928 sp<ANativeWindow> mANW = mSTC;
929
930 EGLint winAttrs[] = {
931 // clang-format off
932 EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
933 EGL_NONE,
934 // clang-format on
935 };
936
937 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
938 ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
939 ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
940
941 // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
942 // in the first failed attempt (e.g. native_window_api_disconnect).
943 winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
944 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
945 ASSERT_EQ(EGL_SUCCESS, eglGetError());
946 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
947
948 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
949}
950
951TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
952 EGLConfig config;
953
954 ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
955
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700956 struct MockConsumer : public BnConsumerListener {
Weiwan Liu3ca92972018-09-28 15:44:12 -0700957 void onFrameAvailable(const BufferItem& /* item */) override {}
958 void onBuffersReleased() override {}
959 void onSidebandStreamChanged() override {}
960 };
961
962 // Create a EGLSurface
963 sp<IGraphicBufferProducer> producer;
964 sp<IGraphicBufferConsumer> consumer;
965 BufferQueue::createBufferQueue(&producer, &consumer);
Yiwei Zhang26169cd2020-07-28 15:46:12 -0700966 consumer->consumerConnect(new MockConsumer, false);
Weiwan Liu3ca92972018-09-28 15:44:12 -0700967 sp<Surface> mSTC = new Surface(producer);
968 sp<ANativeWindow> mANW = mSTC;
969
970 const EGLint winAttrs[] = {
971 // clang-format off
972 EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
973 EGL_NONE,
974 // clang-format on
975 };
976
977 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
978 ASSERT_EQ(EGL_SUCCESS, eglGetError());
979 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
980
981 android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
982 ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
983
984 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
985
986 // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
987 eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
988 ASSERT_EQ(EGL_SUCCESS, eglGetError());
989 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
990
991 dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
992 // Make sure the dataspace has been reset to UNKNOWN
993 ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
994
995 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
996}
Mathias Agopian2f739f82011-07-07 14:54:30 -0700997}