1 /*
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 
19 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
20 
21 #include <configstore/Utils.h>
22 #include <utils/String8.h>
23 
24 #include <EGL/egl.h>
25 #include <gui/Surface.h>
26 #include <gui/IConsumerListener.h>
27 #include <gui/IProducerListener.h>
28 #include <gui/IGraphicBufferConsumer.h>
29 #include <gui/BufferQueue.h>
30 
31 #define PIXEL_FORMAT_FLOAT "EGL_EXT_pixel_format_float"
32 
hasEglPixelFormatFloat()33 bool hasEglPixelFormatFloat() {
34     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
35     const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
36     size_t cropExtLen = strlen(PIXEL_FORMAT_FLOAT);
37     size_t extsLen = strlen(exts);
38     bool equal = !strcmp(PIXEL_FORMAT_FLOAT, exts);
39     bool atStart = !strncmp(PIXEL_FORMAT_FLOAT " ", exts, cropExtLen + 1);
40     bool atEnd = (cropExtLen + 1) < extsLen &&
41             !strcmp(" " PIXEL_FORMAT_FLOAT, exts + extsLen - (cropExtLen + 1));
42     bool inMiddle = strstr(exts, " " PIXEL_FORMAT_FLOAT " ");
43     return equal || atStart || atEnd || inMiddle;
44 }
45 
46 namespace android {
47 
48 #define EGL_UNSIGNED_TRUE static_cast<EGLBoolean>(EGL_TRUE)
49 
50 // retrieve wide-color setting from configstore
51 using namespace android::hardware::configstore;
52 using namespace android::hardware::configstore::V1_0;
53 
54 static bool hasWideColorDisplay =
55         getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
56 
57 class EGLTest : public ::testing::Test {
58 protected:
59     EGLDisplay mEglDisplay;
60 
61 protected:
EGLTest()62     EGLTest() :
63             mEglDisplay(EGL_NO_DISPLAY) {
64     }
65 
SetUp()66     virtual void SetUp() {
67         mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
68         ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
69         ASSERT_EQ(EGL_SUCCESS, eglGetError());
70 
71         EGLint majorVersion;
72         EGLint minorVersion;
73         EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
74         ASSERT_EQ(EGL_SUCCESS, eglGetError());
75         RecordProperty("EglVersionMajor", majorVersion);
76         RecordProperty("EglVersionMajor", minorVersion);
77     }
78 
TearDown()79     virtual void TearDown() {
80         EGLBoolean success = eglTerminate(mEglDisplay);
81         ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
82         ASSERT_EQ(EGL_SUCCESS, eglGetError());
83     }
84 };
85 
TEST_F(EGLTest,DISABLED_EGLConfigEightBitFirst)86 TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) {
87 
88     EGLint numConfigs;
89     EGLConfig config;
90     EGLBoolean success;
91     EGLint attrs[] = {
92             EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
93             EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
94             EGL_NONE
95     };
96 
97     success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
98     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
99     ASSERT_EQ(EGL_SUCCESS, eglGetError());
100     ASSERT_GE(numConfigs, 1);
101 
102     EGLint components[3];
103 
104     success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
105     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
106     ASSERT_EQ(EGL_SUCCESS, eglGetError());
107     success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
108     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
109     ASSERT_EQ(EGL_SUCCESS, eglGetError());
110     success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
111     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
112     ASSERT_EQ(EGL_SUCCESS, eglGetError());
113 
114     EXPECT_GE(components[0], 8);
115     EXPECT_GE(components[1], 8);
116     EXPECT_GE(components[2], 8);
117 }
118 
TEST_F(EGLTest,EGLTerminateSucceedsWithRemainingObjects)119 TEST_F(EGLTest, EGLTerminateSucceedsWithRemainingObjects) {
120     EGLint numConfigs;
121     EGLConfig config;
122     EGLint attrs[] = {
123         EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
124         EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
125         EGL_RED_SIZE,           8,
126         EGL_GREEN_SIZE,         8,
127         EGL_BLUE_SIZE,          8,
128         EGL_ALPHA_SIZE,         8,
129         EGL_NONE
130     };
131     EXPECT_TRUE(eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs));
132 
133     struct DummyConsumer : public BnConsumerListener {
134         void onFrameAvailable(const BufferItem& /* item */) override {}
135         void onBuffersReleased() override {}
136         void onSidebandStreamChanged() override {}
137     };
138 
139     // Create a EGLSurface
140     sp<IGraphicBufferProducer> producer;
141     sp<IGraphicBufferConsumer> consumer;
142     BufferQueue::createBufferQueue(&producer, &consumer);
143     consumer->consumerConnect(new DummyConsumer, false);
144     sp<Surface> mSTC = new Surface(producer);
145     sp<ANativeWindow> mANW = mSTC;
146 
147     EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config,
148                                 mANW.get(), NULL);
149     ASSERT_EQ(EGL_SUCCESS, eglGetError());
150     ASSERT_NE(EGL_NO_SURFACE, eglSurface) ;
151 
152     // do not destroy eglSurface
153     // eglTerminate is called in the tear down and should destroy it for us
154 }
155 
TEST_F(EGLTest,EGLConfigRGBA8888First)156 TEST_F(EGLTest, EGLConfigRGBA8888First) {
157 
158     EGLint numConfigs;
159     EGLConfig config;
160     EGLBoolean success;
161     EGLint attrs[] = {
162             EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
163             EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
164             EGL_RED_SIZE,           8,
165             EGL_GREEN_SIZE,         8,
166             EGL_BLUE_SIZE,          8,
167             EGL_ALPHA_SIZE,         8,
168             EGL_NONE
169     };
170 
171     success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
172     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
173     ASSERT_EQ(EGL_SUCCESS, eglGetError());
174     ASSERT_GE(numConfigs, 1);
175 
176     EGLint components[4];
177 
178     success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
179     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
180     ASSERT_EQ(EGL_SUCCESS, eglGetError());
181     success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
182     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
183     ASSERT_EQ(EGL_SUCCESS, eglGetError());
184     success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
185     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
186     ASSERT_EQ(EGL_SUCCESS, eglGetError());
187     success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
188     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
189     ASSERT_EQ(EGL_SUCCESS, eglGetError());
190 
191     EXPECT_GE(components[0], 8);
192     EXPECT_GE(components[1], 8);
193     EXPECT_GE(components[2], 8);
194     EXPECT_GE(components[3], 8);
195 }
196 
TEST_F(EGLTest,EGLConfigFP16)197 TEST_F(EGLTest, EGLConfigFP16) {
198     EGLint numConfigs;
199     EGLConfig config;
200     EGLBoolean success;
201 
202     if (!hasWideColorDisplay) {
203         // skip this test if device does not have wide-color display
204         return;
205     }
206 
207     ASSERT_TRUE(hasEglPixelFormatFloat());
208 
209     EGLint attrs[] = {EGL_SURFACE_TYPE,
210                       EGL_WINDOW_BIT,
211                       EGL_RENDERABLE_TYPE,
212                       EGL_OPENGL_ES2_BIT,
213                       EGL_RED_SIZE,
214                       16,
215                       EGL_GREEN_SIZE,
216                       16,
217                       EGL_BLUE_SIZE,
218                       16,
219                       EGL_ALPHA_SIZE,
220                       16,
221                       EGL_COLOR_COMPONENT_TYPE_EXT,
222                       EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
223                       EGL_NONE};
224     success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
225     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
226     ASSERT_EQ(1, numConfigs);
227 
228     EGLint components[4];
229 
230     success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
231     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
232     ASSERT_EQ(EGL_SUCCESS, eglGetError());
233     success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
234     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
235     ASSERT_EQ(EGL_SUCCESS, eglGetError());
236     success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
237     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
238     ASSERT_EQ(EGL_SUCCESS, eglGetError());
239     success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
240     ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
241     ASSERT_EQ(EGL_SUCCESS, eglGetError());
242 
243     EXPECT_GE(components[0], 16);
244     EXPECT_GE(components[1], 16);
245     EXPECT_GE(components[2], 16);
246     EXPECT_GE(components[3], 16);
247 
248     struct DummyConsumer : public BnConsumerListener {
249         void onFrameAvailable(const BufferItem& /* item */) override {}
250         void onBuffersReleased() override {}
251         void onSidebandStreamChanged() override {}
252     };
253 
254     // Create a EGLSurface
255     sp<IGraphicBufferProducer> producer;
256     sp<IGraphicBufferConsumer> consumer;
257     BufferQueue::createBufferQueue(&producer, &consumer);
258     consumer->consumerConnect(new DummyConsumer, false);
259     sp<Surface> mSTC = new Surface(producer);
260     sp<ANativeWindow> mANW = mSTC;
261 
262     EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
263     ASSERT_EQ(EGL_SUCCESS, eglGetError());
264     ASSERT_NE(EGL_NO_SURFACE, eglSurface);
265 
266     EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
267 }
268 }
269