blob: b2f868326443061161d56a4bed254df07fab8216 [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
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060019#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
20
21#include <configstore/Utils.h>
Mathias Agopian2f739f82011-07-07 14:54:30 -070022#include <utils/String8.h>
23
24#include <EGL/egl.h>
Mathias Agopiane3c697f2013-02-14 17:11:02 -080025#include <gui/Surface.h>
Mathias Agopian2b5dd402017-02-07 17:36:19 -080026#include <gui/IConsumerListener.h>
27#include <gui/IProducerListener.h>
28#include <gui/IGraphicBufferConsumer.h>
29#include <gui/BufferQueue.h>
Mathias Agopian2f739f82011-07-07 14:54:30 -070030
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060031bool hasEglExtension(EGLDisplay dpy, const char* extensionName) {
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060032 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060033 size_t cropExtLen = strlen(extensionName);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060034 size_t extsLen = strlen(exts);
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060035 bool equal = !strcmp(extensionName, exts);
36 android::String8 extString(extensionName);
37 android::String8 space(" ");
38 bool atStart = !strncmp(extString + space, exts, cropExtLen + 1);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060039 bool atEnd = (cropExtLen + 1) < extsLen &&
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -060040 !strcmp(space + extString, exts + extsLen - (cropExtLen + 1));
41 bool inMiddle = strstr(exts, space + extString + space);
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060042 return equal || atStart || atEnd || inMiddle;
43}
44
Mathias Agopian2f739f82011-07-07 14:54:30 -070045namespace android {
46
Kalle Raita4cf36372017-01-13 10:18:36 -080047#define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
48
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -060049// retrieve wide-color setting from configstore
50using namespace android::hardware::configstore;
51
52static bool hasWideColorDisplay =
53 getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
54
Mathias Agopian2f739f82011-07-07 14:54:30 -070055class EGLTest : public ::testing::Test {
56protected:
57 EGLDisplay mEglDisplay;
58
59protected:
60 EGLTest() :
61 mEglDisplay(EGL_NO_DISPLAY) {
62 }
63
64 virtual void SetUp() {
65 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
66 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
67 ASSERT_EQ(EGL_SUCCESS, eglGetError());
68
69 EGLint majorVersion;
70 EGLint minorVersion;
71 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
72 ASSERT_EQ(EGL_SUCCESS, eglGetError());
73 RecordProperty("EglVersionMajor", majorVersion);
74 RecordProperty("EglVersionMajor", minorVersion);
75 }
76
77 virtual void TearDown() {
78 EGLBoolean success = eglTerminate(mEglDisplay);
Kalle Raita4cf36372017-01-13 10:18:36 -080079 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -070080 ASSERT_EQ(EGL_SUCCESS, eglGetError());
81 }
82};
83
84TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) {
85
86 EGLint numConfigs;
87 EGLConfig config;
88 EGLBoolean success;
89 EGLint attrs[] = {
90 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
91 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
92 EGL_NONE
93 };
94
95 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
Kalle Raita4cf36372017-01-13 10:18:36 -080096 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -070097 ASSERT_EQ(EGL_SUCCESS, eglGetError());
98 ASSERT_GE(numConfigs, 1);
99
100 EGLint components[3];
101
102 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800103 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700104 ASSERT_EQ(EGL_SUCCESS, eglGetError());
105 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
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 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
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
112 EXPECT_GE(components[0], 8);
113 EXPECT_GE(components[1], 8);
114 EXPECT_GE(components[2], 8);
115}
116
Daniel Lam1cbcb982012-04-16 22:21:02 -0700117TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) {
118 EGLint numConfigs;
119 EGLConfig config;
120 EGLint attrs[] = {
121 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
122 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
123 EGL_RED_SIZE, 8,
124 EGL_GREEN_SIZE, 8,
125 EGL_BLUE_SIZE, 8,
126 EGL_ALPHA_SIZE, 8,
127 EGL_NONE
128 };
129 EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
130
Mathias Agopiana4e19522013-07-31 20:09:53 -0700131 struct DummyConsumer : public BnConsumerListener {
Brian Anderson5ea5e592016-12-01 16:54:33 -0800132 void onFrameAvailable(const BufferItem& /* item */) override {}
133 void onBuffersReleased() override {}
134 void onSidebandStreamChanged() override {}
Mathias Agopian595264f2013-07-16 22:56:09 -0700135 };
136
Daniel Lam1cbcb982012-04-16 22:21:02 -0700137 // Create a EGLSurface
Dan Stoza5603a2f2014-04-07 13:41:37 -0700138 sp<IGraphicBufferProducer> producer;
139 sp<IGraphicBufferConsumer> consumer;
140 BufferQueue::createBufferQueue(&producer, &consumer);
141 consumer->consumerConnect(new DummyConsumer, false);
142 sp<Surface> mSTC = new Surface(producer);
Daniel Lam1cbcb982012-04-16 22:21:02 -0700143 sp<ANativeWindow> mANW = mSTC;
144
145 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config,
146 mANW.get(), NULL);
147 ASSERT_EQ(EGL_SUCCESS, eglGetError());
148 ASSERT_NE(EGL_NO_SURFACE, eglSurface) ;
149
150 // do not destroy eglSurface
151 // eglTerminate is called in the tear down and should destroy it for us
152}
153
Mathias Agopian2f739f82011-07-07 14:54:30 -0700154TEST_F(EGLTest, EGLConfigRGBA8888First) {
155
156 EGLint numConfigs;
157 EGLConfig config;
158 EGLBoolean success;
159 EGLint attrs[] = {
160 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
161 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
162 EGL_RED_SIZE, 8,
163 EGL_GREEN_SIZE, 8,
164 EGL_BLUE_SIZE, 8,
165 EGL_ALPHA_SIZE, 8,
166 EGL_NONE
167 };
168
169 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
Kalle Raita4cf36372017-01-13 10:18:36 -0800170 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700171 ASSERT_EQ(EGL_SUCCESS, eglGetError());
172 ASSERT_GE(numConfigs, 1);
173
174 EGLint components[4];
175
176 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800177 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700178 ASSERT_EQ(EGL_SUCCESS, eglGetError());
179 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
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 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
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 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
Kalle Raita4cf36372017-01-13 10:18:36 -0800186 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
Mathias Agopian2f739f82011-07-07 14:54:30 -0700187 ASSERT_EQ(EGL_SUCCESS, eglGetError());
188
189 EXPECT_GE(components[0], 8);
190 EXPECT_GE(components[1], 8);
191 EXPECT_GE(components[2], 8);
192 EXPECT_GE(components[3], 8);
193}
194
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600195TEST_F(EGLTest, EGLConfigFP16) {
196 EGLint numConfigs;
197 EGLConfig config;
198 EGLBoolean success;
Mathias Agopian2f739f82011-07-07 14:54:30 -0700199
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600200 if (!hasWideColorDisplay) {
201 // skip this test if device does not have wide-color display
202 return;
203 }
204
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600205 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600206
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600207 EGLint attrs[] = {
208 // clang-format off
209 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
210 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
211 EGL_RED_SIZE, 16,
212 EGL_GREEN_SIZE, 16,
213 EGL_BLUE_SIZE, 16,
214 EGL_ALPHA_SIZE, 16,
215 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
216 EGL_NONE, EGL_NONE
217 // clang-format on
218 };
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600219 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
220 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
221 ASSERT_EQ(1, numConfigs);
222
223 EGLint components[4];
224
225 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
226 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
227 ASSERT_EQ(EGL_SUCCESS, eglGetError());
228 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
229 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
230 ASSERT_EQ(EGL_SUCCESS, eglGetError());
231 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
232 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
233 ASSERT_EQ(EGL_SUCCESS, eglGetError());
234 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
235 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
236 ASSERT_EQ(EGL_SUCCESS, eglGetError());
237
238 EXPECT_GE(components[0], 16);
239 EXPECT_GE(components[1], 16);
240 EXPECT_GE(components[2], 16);
241 EXPECT_GE(components[3], 16);
242
243 struct DummyConsumer : public BnConsumerListener {
244 void onFrameAvailable(const BufferItem& /* item */) override {}
245 void onBuffersReleased() override {}
246 void onSidebandStreamChanged() override {}
247 };
248
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600249 sp<IGraphicBufferProducer> producer;
250 sp<IGraphicBufferConsumer> consumer;
251 BufferQueue::createBufferQueue(&producer, &consumer);
252 consumer->consumerConnect(new DummyConsumer, false);
253 sp<Surface> mSTC = new Surface(producer);
254 sp<ANativeWindow> mANW = mSTC;
255
256 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
257 ASSERT_EQ(EGL_SUCCESS, eglGetError());
258 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
259
260 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
261}
262
Courtney Goeltzenleuchterf7ed1b42017-04-17 17:27:47 -0600263TEST_F(EGLTest, EGL_KHR_no_config_context) {
264 if (!hasWideColorDisplay) {
265 // skip this test if device does not have wide-color display
266 return;
267 }
268
269 ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_KHR_no_config_context"));
270
271 struct DummyConsumer : public BnConsumerListener {
272 void onFrameAvailable(const BufferItem& /* item */) override {}
273 void onBuffersReleased() override {}
274 void onSidebandStreamChanged() override {}
275 };
276
277 std::vector<EGLint> contextAttributes;
278 contextAttributes.reserve(4);
279 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
280 contextAttributes.push_back(2);
281 contextAttributes.push_back(EGL_NONE);
282 contextAttributes.push_back(EGL_NONE);
283
284 EGLContext eglContext = eglCreateContext(mEglDisplay, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
285 contextAttributes.data());
286 EXPECT_NE(EGL_NO_CONTEXT, eglContext);
287 EXPECT_EQ(EGL_SUCCESS, eglGetError());
288
289 if (eglContext != EGL_NO_CONTEXT) {
290 eglDestroyContext(mEglDisplay, eglContext);
291 }
292}
293
Courtney Goeltzenleuchterd118ea92017-04-17 17:33:52 -0600294// Emulate what a native application would do to create a
295// 10:10:10:2 surface.
296TEST_F(EGLTest, EGLConfig1010102) {
297 EGLint numConfigs;
298 EGLConfig config;
299 EGLBoolean success;
300
301 if (!hasWideColorDisplay) {
302 // skip this test if device does not have wide-color display
303 return;
304 }
305
306 EGLint attrs[] = {
307 // clang-format off
308 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
309 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
310 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
311 EGL_RED_SIZE, 10,
312 EGL_GREEN_SIZE, 10,
313 EGL_BLUE_SIZE, 10,
314 EGL_ALPHA_SIZE, 2,
315 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
316 EGL_NONE, EGL_NONE
317 // clang-format on
318 };
319 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
320 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
321 ASSERT_EQ(1, numConfigs);
322
323 EGLint components[4];
324 EGLint value;
325 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
326
327 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
328 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
329 ASSERT_EQ(EGL_SUCCESS, eglGetError());
330 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
331 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
332 ASSERT_EQ(EGL_SUCCESS, eglGetError());
333 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
334 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
335 ASSERT_EQ(EGL_SUCCESS, eglGetError());
336 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
337 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
338 ASSERT_EQ(EGL_SUCCESS, eglGetError());
339
340 EXPECT_EQ(components[0], 10);
341 EXPECT_EQ(components[1], 10);
342 EXPECT_EQ(components[2], 10);
343 EXPECT_EQ(components[3], 2);
344
345 struct DummyConsumer : public BnConsumerListener {
346 void onFrameAvailable(const BufferItem& /* item */) override {}
347 void onBuffersReleased() override {}
348 void onSidebandStreamChanged() override {}
349 };
350
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600351 // Create a EGLSurface
352 sp<IGraphicBufferProducer> producer;
353 sp<IGraphicBufferConsumer> consumer;
354 BufferQueue::createBufferQueue(&producer, &consumer);
355 consumer->consumerConnect(new DummyConsumer, false);
356 sp<Surface> mSTC = new Surface(producer);
357 sp<ANativeWindow> mANW = mSTC;
358
359 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
360 ASSERT_EQ(EGL_SUCCESS, eglGetError());
361 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
362
363 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
364}
Mathias Agopian2f739f82011-07-07 14:54:30 -0700365}