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 #include "FBConfig.h"
17 #include "FrameBuffer.h"
18 #include "EGLDispatch.h"
19 #include <stdio.h>
20
21 FBConfig **FBConfig::s_fbConfigs = NULL;
22 int FBConfig::s_numConfigs = 0;
23
24 const GLuint FBConfig::s_configAttribs[] = {
25 EGL_DEPTH_SIZE, // must be first - see getDepthSize()
26 EGL_STENCIL_SIZE, // must be second - see getStencilSize()
27 EGL_RENDERABLE_TYPE,// must be third - see getRenderableType()
28 EGL_SURFACE_TYPE, // must be fourth - see getSurfaceType()
29 EGL_CONFIG_ID, // must be fifth - see chooseConfig()
30 EGL_BUFFER_SIZE,
31 EGL_ALPHA_SIZE,
32 EGL_BLUE_SIZE,
33 EGL_GREEN_SIZE,
34 EGL_RED_SIZE,
35 EGL_CONFIG_CAVEAT,
36 EGL_LEVEL,
37 EGL_MAX_PBUFFER_HEIGHT,
38 EGL_MAX_PBUFFER_PIXELS,
39 EGL_MAX_PBUFFER_WIDTH,
40 EGL_NATIVE_RENDERABLE,
41 EGL_NATIVE_VISUAL_ID,
42 EGL_NATIVE_VISUAL_TYPE,
43 EGL_SAMPLES,
44 EGL_SAMPLE_BUFFERS,
45 EGL_TRANSPARENT_TYPE,
46 EGL_TRANSPARENT_BLUE_VALUE,
47 EGL_TRANSPARENT_GREEN_VALUE,
48 EGL_TRANSPARENT_RED_VALUE,
49 EGL_BIND_TO_TEXTURE_RGB,
50 EGL_BIND_TO_TEXTURE_RGBA,
51 EGL_MIN_SWAP_INTERVAL,
52 EGL_MAX_SWAP_INTERVAL,
53 EGL_LUMINANCE_SIZE,
54 EGL_ALPHA_MASK_SIZE,
55 EGL_COLOR_BUFFER_TYPE,
56 //EGL_MATCH_NATIVE_PIXMAP,
57 EGL_CONFORMANT
58 };
59
60 const int FBConfig::s_numConfigAttribs = sizeof(FBConfig::s_configAttribs) / sizeof(GLuint);
61
initConfigList(FrameBuffer * fb)62 InitConfigStatus FBConfig::initConfigList(FrameBuffer *fb)
63 {
64 InitConfigStatus ret = INIT_CONFIG_FAILED;
65
66 if (!fb) {
67 return ret;
68 }
69
70 EGLDisplay dpy = fb->getDisplay();
71
72 if (dpy == EGL_NO_DISPLAY) {
73 fprintf(stderr,"Could not get EGL Display\n");
74 return ret;
75 }
76
77 //
78 // Query the set of configs in the EGL backend
79 //
80 EGLint nConfigs;
81 if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
82 fprintf(stderr, "Could not get number of available configs\n");
83 return ret;
84 }
85 EGLConfig *configs = new EGLConfig[nConfigs];
86 s_egl.eglGetConfigs(dpy, configs, nConfigs, &nConfigs);
87
88 //
89 // copy the config attributes, filter out
90 // configs we do not want to support.
91 //
92 int j = 0;
93 s_fbConfigs = new FBConfig*[nConfigs];
94 for (int i=0; i<nConfigs; i++) {
95
96 //
97 // filter out configs which does not support pbuffers.
98 // we only support pbuffer configs since we use a pbuffer
99 // handle to bind a guest created window object.
100 //
101 EGLint surfaceType;
102 s_egl.eglGetConfigAttrib(dpy, configs[i],
103 EGL_SURFACE_TYPE, &surfaceType);
104 if (!(surfaceType & EGL_PBUFFER_BIT)) continue;
105
106 //
107 // Filter out not RGB configs
108 //
109 EGLint redSize, greenSize, blueSize;
110 s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE, &redSize);
111 s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE, &blueSize);
112 s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &greenSize);
113 if (redSize==0 || greenSize==0 || blueSize==0) continue;
114
115 s_fbConfigs[j++] = new FBConfig(dpy, configs[i]);
116 }
117 s_numConfigs = j;
118
119 delete[] configs;
120
121 return s_numConfigs > 0 ? INIT_CONFIG_PASSED : INIT_CONFIG_FAILED;
122 }
123
get(int p_config)124 const FBConfig *FBConfig::get(int p_config)
125 {
126 if (p_config >= 0 && p_config < s_numConfigs) {
127 return s_fbConfigs[p_config];
128 }
129 return NULL;
130 }
131
getNumConfigs()132 int FBConfig::getNumConfigs()
133 {
134 return s_numConfigs;
135 }
136
packConfigsInfo(GLuint * buffer)137 void FBConfig::packConfigsInfo(GLuint *buffer)
138 {
139 memcpy(buffer, s_configAttribs, s_numConfigAttribs * sizeof(GLuint));
140 for (int i=0; i<s_numConfigs; i++) {
141 memcpy(buffer+(i+1)*s_numConfigAttribs,
142 s_fbConfigs[i]->m_attribValues,
143 s_numConfigAttribs * sizeof(GLuint));
144 }
145 }
146
chooseConfig(FrameBuffer * fb,EGLint * attribs,uint32_t * configs,uint32_t configs_size)147 int FBConfig::chooseConfig(FrameBuffer *fb, EGLint * attribs, uint32_t * configs, uint32_t configs_size)
148 {
149 EGLDisplay dpy = fb->getDisplay();
150 int ret = 0;
151
152 if (dpy == EGL_NO_DISPLAY) {
153 fprintf(stderr,"Could not get EGL Display\n");
154 return ret;
155 }
156 //
157 // Query the num of configs in the EGL backend
158 //
159 EGLint nConfigs;
160 if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
161 fprintf(stderr, "Could not get number of available configs\n");
162 return ret;
163 }
164 //
165 // Query the max matching configs in the backend
166 //
167 EGLConfig *matchedConfigs = new EGLConfig[nConfigs];
168
169 //
170 //Until we have EGLImage implementation, we force pbuf configs
171 //
172 bool needToAddPbufAttr = true;
173 int attribCnt = 0;
174 EGLint * attrib_p = attribs;
175 if (attribs) {
176 while (attrib_p[0] != EGL_NONE) {
177 if (attrib_p[0] == EGL_SURFACE_TYPE) {
178 attrib_p[1] = EGL_PBUFFER_BIT; //replace whatever was there before
179 needToAddPbufAttr = false;
180 }
181 attrib_p += 2;
182 attribCnt += 2;
183 }
184 }
185 EGLint * newAttribs = new EGLint[attribCnt + 1 + ((needToAddPbufAttr) ? 2 : 0)];
186 attrib_p = newAttribs;
187 if (needToAddPbufAttr) {
188 *(attrib_p++) = EGL_SURFACE_TYPE;
189 *(attrib_p++) = EGL_PBUFFER_BIT;
190 }
191 memcpy(attrib_p, attribs, attribCnt*sizeof(EGLint));
192 attrib_p += attribCnt;
193 *attrib_p = EGL_NONE;
194
195 #if 0
196 if (newAttribs) {
197 EGLint * attrib_p = newAttribs;
198 while (attrib_p[0] != EGL_NONE) {
199 DBG("attr: 0x%x %d, ", attrib_p[0], attrib_p[1]);
200 attrib_p += 2;
201 }
202 }
203 #endif
204
205 if (!s_egl.eglChooseConfig(dpy, newAttribs, matchedConfigs, nConfigs, &nConfigs)) {
206 nConfigs = 0;
207 }
208
209 delete[] newAttribs;
210
211 //
212 // From all matchedConfigs we need only config_size FBConfigs, so we intersect both lists compating the CONFIG_ID attribute
213 //
214 uint32_t nVerifiedCfgs = 0;
215 for (int matchedIdx=0; matchedIdx<nConfigs; matchedIdx++) {
216 if ((configs != NULL) && (configs_size > 0) && (nVerifiedCfgs >= configs_size)) break; //We have enouhgt configs
217 int sCfgId;
218 s_egl.eglGetConfigAttrib(dpy, matchedConfigs[matchedIdx], EGL_CONFIG_ID, &sCfgId);
219 for (int fbIdx=0; fbIdx<s_numConfigs; fbIdx++) {
220 int dCfgId = s_fbConfigs[fbIdx]->m_attribValues[4]; //CONFIG_ID
221 if (sCfgId == dCfgId) {
222 //This config matches the requested attributes and filtered into fbConfigs, so we're happy with it
223 if (configs && nVerifiedCfgs < configs_size) {
224 configs[nVerifiedCfgs] = fbIdx;
225 }
226 nVerifiedCfgs++;
227 break;
228 }
229 }
230 }
231
232 delete[] matchedConfigs;
233
234 return nVerifiedCfgs;
235 }
236
FBConfig(EGLDisplay p_eglDpy,EGLConfig p_eglCfg)237 FBConfig::FBConfig(EGLDisplay p_eglDpy, EGLConfig p_eglCfg)
238 {
239 m_eglConfig = p_eglCfg;
240 m_attribValues = new GLint[s_numConfigAttribs];
241 for (int i=0; i<s_numConfigAttribs; i++) {
242 m_attribValues[i] = 0;
243 s_egl.eglGetConfigAttrib(p_eglDpy, p_eglCfg, s_configAttribs[i], &m_attribValues[i]);
244
245 //
246 // All exported configs supports android native window rendering
247 //
248 if (s_configAttribs[i] == EGL_SURFACE_TYPE) {
249 m_attribValues[i] |= EGL_WINDOW_BIT;
250 }
251 }
252 }
253
~FBConfig()254 FBConfig::~FBConfig()
255 {
256 if (m_attribValues) {
257 delete[] m_attribValues;
258 }
259 }
260