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 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 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 133 int FBConfig::getNumConfigs() 134 { 135 return s_numConfigs; 136 } 137 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 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 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 253 FBConfig::~FBConfig() 254 { 255 if (m_attribValues) { 256 delete[] m_attribValues; 257 } 258 } 259