emulator opengl: implement eglChooseConfig functionality.

Added new RenderControl command to request the host to execute
the ChooseConfig functionality.

Change-Id: Ib92be313a6df740de69d671c6994ec6cae17ea13
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp
index 14e84b9..81ba067 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp
@@ -24,15 +24,15 @@
 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_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_CONFIG_ID,
     EGL_LEVEL,
     EGL_MAX_PBUFFER_HEIGHT,
     EGL_MAX_PBUFFER_PIXELS,
@@ -201,6 +201,52 @@
     }
 }
 
+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];
+    s_egl.eglChooseConfig(dpy, attribs, matchedConfigs, nConfigs, &nConfigs);
+
+    //
+    // 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 (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
+                configs[nVerifiedCfgs++] = fbIdx;
+                break;
+            }
+        }
+    }
+
+    delete matchedConfigs;
+
+    return nVerifiedCfgs;
+}
+
 FBConfig::FBConfig(EGLDisplay p_eglDpy, EGLConfig p_eglCfg)
 {
     m_eglConfig = p_eglCfg;
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.h b/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.h
index b898b37..8e0356a 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.h
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/FBConfig.h
@@ -35,6 +35,7 @@
     static int getNumConfigs();
     static int getNumAttribs() { return s_numConfigAttribs; }
     static void packConfigsInfo(GLuint *buffer);
+    static int chooseConfig(FrameBuffer *fb, EGLint * attribs, uint32_t * configs, uint32_t configs_size);
     ~FBConfig();
 
     EGLConfig getEGLConfig() const { return m_eglConfig; }
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp
index 504d792..891c89b 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp
@@ -78,6 +78,16 @@
     return nConfigs;
 }
 
+static EGLint rcChooseConfig(EGLint *attribs, uint32_t attribs_size, uint32_t *configs, uint32_t configs_size)
+{
+    FrameBuffer *fb = FrameBuffer::getFB();
+    if (!fb) {
+        return 0;
+    }
+
+    return FBConfig::chooseConfig(fb, attribs, configs, configs_size);
+}
+
 static EGLint rcGetFBParam(EGLint param)
 {
     FrameBuffer *fb = FrameBuffer::getFB();
@@ -252,6 +262,7 @@
     dec->set_rcQueryEGLString(rcQueryEGLString);
     dec->set_rcGetNumConfigs(rcGetNumConfigs);
     dec->set_rcGetConfigs(rcGetConfigs);
+    dec->set_rcChooseConfig(rcChooseConfig);
     dec->set_rcGetFBParam(rcGetFBParam);
     dec->set_rcCreateContext(rcCreateContext);
     dec->set_rcDestroyContext(rcDestroyContext);
diff --git a/tools/emulator/opengl/system/egl/egl.cpp b/tools/emulator/opengl/system/egl/egl.cpp
index 8f1cca0..5427363 100644
--- a/tools/emulator/opengl/system/egl/egl.cpp
+++ b/tools/emulator/opengl/system/egl/egl.cpp
@@ -461,43 +461,21 @@
 
 EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
 {
-#if 0
-    VALIDATE_DISPLAY_INIT(dpy, NULL);
+    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
 
-    //First construct a vector of all configs
-    Vector<EGLint> possibleConfigs;
-    for (int i=0; i<s_display.getNumConfigs(); i++)
-        possibleConfigs.push(i);
-
-    //Now go over the attrib_list and drop unmatching configs
-    while (attrib_list[0])
-    {
-        EGLInt paramAttrName = attrib_list[0];
-        EGLInt paramAttrVal = attrib_list[1];
-        attrib_list+=2;
-
-        int cIdx = 0;
-        while (cIdx < possibleConfigs.size()) {
-            EGLInt conf = possibleConfigs[cIdx];
-            EGLInt value;
-            if (s_display.getConfigAttrib((EGLConfig)conf, paramAttrName, &value) == EGL_FALSE) {
-                return setError(EGL_BAD_ATTRIBUTE, EGL_FALSE)
-            }
-            //if the attrib value doesn't match, the current config doesn't match
-            if (paramAttrValue != value)
-                possibleConfigs.removeAt(cIdx); //don't advance cIdx
-            else
-                cIdx++;
+    int attribs_size = 0;
+    if (attrib_list) {
+        const EGLint * attrib_p = attrib_list;
+        while (attrib_p[0] != EGL_NONE) {
+            attribs_size += 2;
+            attrib_p += 2;
         }
+        attribs_size++; //for the terminating EGL_NONE
     }
 
-    //at this point possibleConfigs holds (if any) the matching configs
-    cIdx=0;
-    for (cIdx=0 ; cIdx<possibleConfigs.size() && cIdx<config_size ; cIdx++) {
-        *configs++ = possibleConfigs[cIdx]
-    }
-    *num_config = cIdx;
-#endif
+    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+    *num_config = rcEnc->rcChooseConfig(rcEnc, (EGLint*)attrib_list, attribs_size, (uint32_t*)configs, config_size);
+
     return EGL_TRUE;
 }
 
diff --git a/tools/emulator/opengl/system/renderControl_enc/README b/tools/emulator/opengl/system/renderControl_enc/README
index 41bb669..b8ffc49 100644
--- a/tools/emulator/opengl/system/renderControl_enc/README
+++ b/tools/emulator/opengl/system/renderControl_enc/README
@@ -39,6 +39,15 @@
        holding the attribute values for that config, the values are specified
        in the same order as the attribute vector.
 
+EGLint rcChooseConfig(EGLint *attribs, uint32_t attribs_size, uint32_t *configs, uint32_t configs_size)
+       This function triggers an eglChooseConfig on the host, to get a list of 
+       configs matching the given attribs values.
+ 	attribs - a list of attribute names followed by the desired values, terminated by EGL_NONE
+	attribs_size - the size of the list
+	configs - the returned matching configuration names (same names as familiar to the client in rcGetConfigs)
+	configs_size - the size of the configs buffers
+	returns - the actual number of matching configurations (<= configs_size) 
+
 EGLint rcGetFBParam(EGLint param);
        queries the host for framebuffer parameter, see renderControl_types.h
        for possible values of 'param'.
diff --git a/tools/emulator/opengl/system/renderControl_enc/renderControl.attrib b/tools/emulator/opengl/system/renderControl_enc/renderControl.attrib
index 310d3d0..a77d21f 100644
--- a/tools/emulator/opengl/system/renderControl_enc/renderControl.attrib
+++ b/tools/emulator/opengl/system/renderControl_enc/renderControl.attrib
@@ -20,6 +20,12 @@
     dir buffer out
     len buffer bufSize
 
+rcChooseConfig
+    dir attribs in
+	len attribs attribs_size
+	dir configs out
+	len configs configs_size
+
 rcReadColorBuffer
     dir pixels out
     len pixels (((glUtilsPixelBitSize(format, type) * width) >> 3) * height)
diff --git a/tools/emulator/opengl/system/renderControl_enc/renderControl.in b/tools/emulator/opengl/system/renderControl_enc/renderControl.in
index db23c5b..c91a662 100644
--- a/tools/emulator/opengl/system/renderControl_enc/renderControl.in
+++ b/tools/emulator/opengl/system/renderControl_enc/renderControl.in
@@ -3,6 +3,7 @@
 GL_ENTRY(EGLint, rcQueryEGLString, EGLenum name, void *buffer, EGLint bufferSize)
 GL_ENTRY(EGLint, rcGetNumConfigs, uint32_t *numAttribs)
 GL_ENTRY(EGLint, rcGetConfigs, uint32_t bufSize, GLuint *buffer)
+GL_ENTRY(EGLint, rcChooseConfig, EGLint *attribs, uint32_t attribs_size, uint32_t *configs, uint32_t configs_size)
 GL_ENTRY(EGLint, rcGetFBParam, EGLint param)
 GL_ENTRY(uint32_t, rcCreateContext, uint32_t config, uint32_t share, uint32_t glVersion)
 GL_ENTRY(void, rcDestroyContext, uint32_t context)