blob: 2c0d93b58d5a6859982c82c59dffc262a2c4fe96 [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
263// Emulate what a native application would do to create a
264// 10:10:10:2 surface.
265TEST_F(EGLTest, EGLConfig1010102) {
266 EGLint numConfigs;
267 EGLConfig config;
268 EGLBoolean success;
269
270 if (!hasWideColorDisplay) {
271 // skip this test if device does not have wide-color display
272 return;
273 }
274
275 EGLint attrs[] = {
276 // clang-format off
277 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
278 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
279 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
280 EGL_RED_SIZE, 10,
281 EGL_GREEN_SIZE, 10,
282 EGL_BLUE_SIZE, 10,
283 EGL_ALPHA_SIZE, 2,
284 EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
285 EGL_NONE, EGL_NONE
286 // clang-format on
287 };
288 success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
289 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
290 ASSERT_EQ(1, numConfigs);
291
292 EGLint components[4];
293 EGLint value;
294 eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
295
296 success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
297 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
298 ASSERT_EQ(EGL_SUCCESS, eglGetError());
299 success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
300 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
301 ASSERT_EQ(EGL_SUCCESS, eglGetError());
302 success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
303 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
304 ASSERT_EQ(EGL_SUCCESS, eglGetError());
305 success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
306 ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
307 ASSERT_EQ(EGL_SUCCESS, eglGetError());
308
309 EXPECT_EQ(components[0], 10);
310 EXPECT_EQ(components[1], 10);
311 EXPECT_EQ(components[2], 10);
312 EXPECT_EQ(components[3], 2);
313
314 struct DummyConsumer : public BnConsumerListener {
315 void onFrameAvailable(const BufferItem& /* item */) override {}
316 void onBuffersReleased() override {}
317 void onSidebandStreamChanged() override {}
318 };
319
Courtney Goeltzenleuchterf29f2872017-03-28 17:29:52 -0600320 // Create a EGLSurface
321 sp<IGraphicBufferProducer> producer;
322 sp<IGraphicBufferConsumer> consumer;
323 BufferQueue::createBufferQueue(&producer, &consumer);
324 consumer->consumerConnect(new DummyConsumer, false);
325 sp<Surface> mSTC = new Surface(producer);
326 sp<ANativeWindow> mANW = mSTC;
327
328 EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
329 ASSERT_EQ(EGL_SUCCESS, eglGetError());
330 ASSERT_NE(EGL_NO_SURFACE, eglSurface);
331
332 EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
333}
Mathias Agopian2f739f82011-07-07 14:54:30 -0700334}