/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "FBConfig.h" #include "FrameBuffer.h" #include "EGLDispatch.h" #include <stdio.h> FBConfig **FBConfig::s_fbConfigs = NULL; int FBConfig::s_numConfigs = 0; const GLuint FBConfig::s_configAttribs[] = { EGL_DEPTH_SIZE, // must be first - see getDepthSize() EGL_STENCIL_SIZE, // must be second - see getStencilSize() EGL_RENDERABLE_TYPE,// must be third - see getRenderableType() EGL_SURFACE_TYPE, // must be fourth - see getSurfaceType() EGL_CONFIG_ID, // must be fifth - see chooseConfig() EGL_BUFFER_SIZE, EGL_ALPHA_SIZE, EGL_BLUE_SIZE, EGL_GREEN_SIZE, EGL_RED_SIZE, EGL_CONFIG_CAVEAT, EGL_LEVEL, EGL_MAX_PBUFFER_HEIGHT, EGL_MAX_PBUFFER_PIXELS, EGL_MAX_PBUFFER_WIDTH, EGL_NATIVE_RENDERABLE, EGL_NATIVE_VISUAL_ID, EGL_NATIVE_VISUAL_TYPE, EGL_SAMPLES, EGL_SAMPLE_BUFFERS, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_BLUE_VALUE, EGL_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_RED_VALUE, EGL_BIND_TO_TEXTURE_RGB, EGL_BIND_TO_TEXTURE_RGBA, EGL_MIN_SWAP_INTERVAL, EGL_MAX_SWAP_INTERVAL, EGL_LUMINANCE_SIZE, EGL_ALPHA_MASK_SIZE, EGL_COLOR_BUFFER_TYPE, //EGL_MATCH_NATIVE_PIXMAP, EGL_CONFORMANT }; const int FBConfig::s_numConfigAttribs = sizeof(FBConfig::s_configAttribs) / sizeof(GLuint); InitConfigStatus FBConfig::initConfigList(FrameBuffer *fb) { InitConfigStatus ret = INIT_CONFIG_FAILED; if (!fb) { return ret; } EGLDisplay dpy = fb->getDisplay(); if (dpy == EGL_NO_DISPLAY) { fprintf(stderr,"Could not get EGL Display\n"); return ret; } // // Query the set of configs in the EGL backend // EGLint nConfigs; if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) { fprintf(stderr, "Could not get number of available configs\n"); return ret; } EGLConfig *configs = new EGLConfig[nConfigs]; s_egl.eglGetConfigs(dpy, configs, nConfigs, &nConfigs); // // copy the config attributes, filter out // configs we do not want to support. // int j = 0; s_fbConfigs = new FBConfig*[nConfigs]; for (int i=0; i<nConfigs; i++) { // // filter out configs which does not support pbuffers. // we only support pbuffer configs since we use a pbuffer // handle to bind a guest created window object. // EGLint surfaceType; s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_SURFACE_TYPE, &surfaceType); if (!(surfaceType & EGL_PBUFFER_BIT)) continue; // // Filter out not RGB configs // EGLint redSize, greenSize, blueSize; s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_RED_SIZE, &redSize); s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_BLUE_SIZE, &blueSize); s_egl.eglGetConfigAttrib(dpy, configs[i], EGL_GREEN_SIZE, &greenSize); if (redSize==0 || greenSize==0 || blueSize==0) continue; s_fbConfigs[j++] = new FBConfig(dpy, configs[i]); } s_numConfigs = j; delete[] configs; return s_numConfigs > 0 ? INIT_CONFIG_PASSED : INIT_CONFIG_FAILED; } const FBConfig *FBConfig::get(int p_config) { if (p_config >= 0 && p_config < s_numConfigs) { return s_fbConfigs[p_config]; } return NULL; } int FBConfig::getNumConfigs() { return s_numConfigs; } void FBConfig::packConfigsInfo(GLuint *buffer) { memcpy(buffer, s_configAttribs, s_numConfigAttribs * sizeof(GLuint)); for (int i=0; i<s_numConfigs; i++) { memcpy(buffer+(i+1)*s_numConfigAttribs, s_fbConfigs[i]->m_attribValues, s_numConfigAttribs * sizeof(GLuint)); } } int FBConfig::chooseConfig(FrameBuffer *fb, EGLint * attribs, uint32_t * configs, uint32_t configs_size) { EGLDisplay dpy = fb->getDisplay(); int ret = 0; if (dpy == EGL_NO_DISPLAY) { fprintf(stderr,"Could not get EGL Display\n"); return ret; } // // Query the num of configs in the EGL backend // EGLint nConfigs; if (!s_egl.eglGetConfigs(dpy, NULL, 0, &nConfigs)) { fprintf(stderr, "Could not get number of available configs\n"); return ret; } // // Query the max matching configs in the backend // EGLConfig *matchedConfigs = new EGLConfig[nConfigs]; // //Until we have EGLImage implementation, we force pbuf configs // bool needToAddPbufAttr = true; int attribCnt = 0; EGLint * attrib_p = attribs; if (attribs) { while (attrib_p[0] != EGL_NONE) { if (attrib_p[0] == EGL_SURFACE_TYPE) { attrib_p[1] = EGL_PBUFFER_BIT; //replace whatever was there before needToAddPbufAttr = false; } attrib_p += 2; attribCnt += 2; } } EGLint * newAttribs = new EGLint[attribCnt + 1 + ((needToAddPbufAttr) ? 2 : 0)]; attrib_p = newAttribs; if (needToAddPbufAttr) { *(attrib_p++) = EGL_SURFACE_TYPE; *(attrib_p++) = EGL_PBUFFER_BIT; } memcpy(attrib_p, attribs, attribCnt*sizeof(EGLint)); attrib_p += attribCnt; *attrib_p = EGL_NONE; #if 0 if (newAttribs) { EGLint * attrib_p = newAttribs; while (attrib_p[0] != EGL_NONE) { DBG("attr: 0x%x %d, ", attrib_p[0], attrib_p[1]); attrib_p += 2; } } #endif if (!s_egl.eglChooseConfig(dpy, newAttribs, matchedConfigs, nConfigs, &nConfigs)) { nConfigs = 0; } delete[] newAttribs; // // From all matchedConfigs we need only config_size FBConfigs, so we intersect both lists compating the CONFIG_ID attribute // uint32_t nVerifiedCfgs = 0; for (int matchedIdx=0; matchedIdx<nConfigs; matchedIdx++) { if ((configs != NULL) && (configs_size > 0) && (nVerifiedCfgs >= configs_size)) break; //We have enouhgt configs int sCfgId; s_egl.eglGetConfigAttrib(dpy, matchedConfigs[matchedIdx], EGL_CONFIG_ID, &sCfgId); for (int fbIdx=0; fbIdx<s_numConfigs; fbIdx++) { int dCfgId = s_fbConfigs[fbIdx]->m_attribValues[4]; //CONFIG_ID if (sCfgId == dCfgId) { //This config matches the requested attributes and filtered into fbConfigs, so we're happy with it if (configs && nVerifiedCfgs < configs_size) { configs[nVerifiedCfgs] = fbIdx; } nVerifiedCfgs++; break; } } } delete[] matchedConfigs; return nVerifiedCfgs; } FBConfig::FBConfig(EGLDisplay p_eglDpy, EGLConfig p_eglCfg) { m_eglConfig = p_eglCfg; m_attribValues = new GLint[s_numConfigAttribs]; for (int i=0; i<s_numConfigAttribs; i++) { m_attribValues[i] = 0; s_egl.eglGetConfigAttrib(p_eglDpy, p_eglCfg, s_configAttribs[i], &m_attribValues[i]); // // All exported configs supports android native window rendering // if (s_configAttribs[i] == EGL_SURFACE_TYPE) { m_attribValues[i] |= EGL_WINDOW_BIT; } } } FBConfig::~FBConfig() { if (m_attribValues) { delete[] m_attribValues; } }