• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     const FrameBufferCaps &caps = fb->getCaps();
71     EGLDisplay dpy = fb->getDisplay();
72 
73     if (dpy == EGL_NO_DISPLAY) {
74         fprintf(stderr,"Could not get EGL Display\n");
75         return ret;
76     }
77 
78     //
79     // Query the set of configs in the EGL backend
80     //
81     EGLint nConfigs;
82     if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
83         fprintf(stderr, "Could not get number of available configs\n");
84         return ret;
85     }
86     EGLConfig *configs = new EGLConfig[nConfigs];
87     s_egl.eglGetConfigs(dpy, configs, nConfigs, &nConfigs);
88 
89     //
90     // copy the config attributes, filter out
91     // configs we do not want to support.
92     //
93     int j = 0;
94     s_fbConfigs = new FBConfig*[nConfigs];
95     for (int i=0; i<nConfigs; i++) {
96 
97         //
98         // filter out configs which does not support pbuffers.
99         // we only support pbuffer configs since we use a pbuffer
100         // handle to bind a guest created window object.
101         //
102         EGLint surfaceType;
103         s_egl.eglGetConfigAttrib(dpy, configs[i],
104                                  EGL_SURFACE_TYPE, &surfaceType);
105         if (!(surfaceType & EGL_PBUFFER_BIT)) continue;
106 
107         //
108         // Filter out not RGB configs
109         //
110         EGLint redSize, greenSize, blueSize;
111         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE, &redSize);
112         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE, &blueSize);
113         s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &greenSize);
114         if (redSize==0 || greenSize==0 || blueSize==0) continue;
115 
116         s_fbConfigs[j++] = new FBConfig(dpy, configs[i]);
117     }
118     s_numConfigs = j;
119 
120     delete[] configs;
121 
122     return s_numConfigs > 0 ? INIT_CONFIG_PASSED : INIT_CONFIG_FAILED;
123 }
124 
get(int p_config)125 const FBConfig *FBConfig::get(int p_config)
126 {
127     if (p_config >= 0 && p_config < s_numConfigs) {
128         return s_fbConfigs[p_config];
129     }
130     return NULL;
131 }
132 
getNumConfigs()133 int FBConfig::getNumConfigs()
134 {
135     return s_numConfigs;
136 }
137 
packConfigsInfo(GLuint * buffer)138 void FBConfig::packConfigsInfo(GLuint *buffer)
139 {
140     memcpy(buffer, s_configAttribs, s_numConfigAttribs * sizeof(GLuint));
141     for (int i=0; i<s_numConfigs; i++) {
142         memcpy(buffer+(i+1)*s_numConfigAttribs,
143                s_fbConfigs[i]->m_attribValues,
144                s_numConfigAttribs * sizeof(GLuint));
145     }
146 }
147 
chooseConfig(FrameBuffer * fb,EGLint * attribs,uint32_t * configs,uint32_t configs_size)148 int FBConfig::chooseConfig(FrameBuffer *fb, EGLint * attribs, uint32_t * configs, uint32_t configs_size)
149 {
150     EGLDisplay dpy = fb->getDisplay();
151     int ret = 0;
152 
153     if (dpy == EGL_NO_DISPLAY) {
154         fprintf(stderr,"Could not get EGL Display\n");
155         return ret;
156     }
157     //
158     // Query the num of configs in the EGL backend
159     //
160     EGLint nConfigs;
161     if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) {
162         fprintf(stderr, "Could not get number of available configs\n");
163         return ret;
164     }
165     //
166     // Query the max matching configs in the backend
167     //
168     EGLConfig *matchedConfigs = new EGLConfig[nConfigs];
169 
170     //
171     //Until we have EGLImage implementation, we force pbuf configs
172     //
173     bool needToAddPbufAttr = true;
174     int attribCnt = 0;
175     EGLint * attrib_p = attribs;
176     if (attribs) {
177         while (attrib_p[0] != EGL_NONE) {
178             if (attrib_p[0] == EGL_SURFACE_TYPE) {
179                 attrib_p[1] = EGL_PBUFFER_BIT; //replace whatever was there before
180                 needToAddPbufAttr = false;
181             }
182             attrib_p += 2;
183             attribCnt += 2;
184         }
185     }
186     EGLint * newAttribs = new EGLint[attribCnt + 1 + ((needToAddPbufAttr) ? 2 : 0)];
187     attrib_p = newAttribs;
188     if (needToAddPbufAttr) {
189         *(attrib_p++) = EGL_SURFACE_TYPE;
190         *(attrib_p++) = EGL_PBUFFER_BIT;
191     }
192     memcpy(attrib_p, attribs, attribCnt*sizeof(EGLint));
193     attrib_p += attribCnt;
194     *attrib_p = EGL_NONE;
195 
196 #if 0
197     if (newAttribs) {
198         EGLint * attrib_p = newAttribs;
199         while (attrib_p[0] != EGL_NONE) {
200             DBG("attr: 0x%x %d, ", attrib_p[0], attrib_p[1]);
201             attrib_p += 2;
202         }
203     }
204 #endif
205 
206     s_egl.eglChooseConfig(dpy, newAttribs, matchedConfigs, nConfigs, &nConfigs);
207 
208     delete[] newAttribs;
209 
210     //
211     // From all matchedConfigs we need only config_size FBConfigs, so we intersect both lists compating the CONFIG_ID attribute
212     //
213     uint32_t nVerifiedCfgs = 0;
214     for (int matchedIdx=0; matchedIdx<nConfigs; matchedIdx++) {
215         if ((configs != NULL) && (configs_size > 0) && (nVerifiedCfgs >= configs_size)) break; //We have enouhgt configs
216         int sCfgId;
217         s_egl.eglGetConfigAttrib(dpy, matchedConfigs[matchedIdx], EGL_CONFIG_ID, &sCfgId);
218         for (int fbIdx=0; fbIdx<s_numConfigs; fbIdx++) {
219             int dCfgId = s_fbConfigs[fbIdx]->m_attribValues[4]; //CONFIG_ID
220             if (sCfgId == dCfgId) {
221                 //This config matches the requested attributes and filtered into fbConfigs, so we're happy with it
222                 if (configs && nVerifiedCfgs < configs_size) {
223                     configs[nVerifiedCfgs] = fbIdx;
224                 }
225                 nVerifiedCfgs++;
226                 break;
227             }
228         }
229     }
230 
231     delete[] matchedConfigs;
232 
233     return nVerifiedCfgs;
234 }
235 
FBConfig(EGLDisplay p_eglDpy,EGLConfig p_eglCfg)236 FBConfig::FBConfig(EGLDisplay p_eglDpy, EGLConfig p_eglCfg)
237 {
238     m_eglConfig = p_eglCfg;
239     m_attribValues = new GLint[s_numConfigAttribs];
240     for (int i=0; i<s_numConfigAttribs; i++) {
241         m_attribValues[i] = 0;
242         s_egl.eglGetConfigAttrib(p_eglDpy, p_eglCfg, s_configAttribs[i], &m_attribValues[i]);
243 
244         //
245         // All exported configs supports android native window rendering
246         //
247         if (s_configAttribs[i] == EGL_SURFACE_TYPE) {
248             m_attribValues[i] |= EGL_WINDOW_BIT;
249         }
250     }
251 }
252 
~FBConfig()253 FBConfig::~FBConfig()
254 {
255     if (m_attribValues) {
256         delete[] m_attribValues;
257     }
258 }
259