supporting EGL_KHR_image_base & EGL_KHR_gl_texture_2d_image extentions

Change-Id: I69c3e975c892bcd0872c47e349b427f570d7e82d
diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.cpp b/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.cpp
index 0190fdf..27f8017 100644
--- a/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.cpp
@@ -53,3 +53,16 @@
     }
     return true;
 }
+
+bool EglContext::attachImage(unsigned int imageId,ImagePtr img){
+   if(m_attachedImages.find(imageId) == m_attachedImages.end()){
+       m_attachedImages[imageId] = img;
+       return true;
+   }
+   return false;
+}
+
+void EglContext::detachImage(unsigned int imageId){
+    m_attachedImages.erase(imageId);
+}
+
diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.h b/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.h
index f9445a1..0c20723 100644
--- a/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.h
+++ b/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.h
@@ -54,6 +54,8 @@
     GLEScontext* getGlesContext(){return m_glesContext;}
     void setSurfaces(SurfacePtr read,SurfacePtr draw);
     unsigned int getHndl(){return m_hndl;}
+    bool attachImage(unsigned int imageId,ImagePtr img);
+    void detachImage(unsigned int imageId);
 
 private:
     static unsigned int  s_nextContextHndl;
@@ -66,6 +68,7 @@
     bool                 m_destroy;
     GLESVersion          m_version;
     unsigned int         m_hndl;
+    ImagesHndlMap        m_attachedImages;
 };
 
 #endif
diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp b/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp
index 9e17493..31a425f 100644
--- a/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.cpp
@@ -18,7 +18,7 @@
 #include <GLcommon/GLutils.h>
 #include <utils/threads.h>
 
-EglDisplay::EglDisplay(EGLNativeDisplayType dpy,bool isDefault):m_dpy(dpy),m_initialized(false),m_configInitialized(false),m_isDefault(isDefault){};
+EglDisplay::EglDisplay(EGLNativeDisplayType dpy,bool isDefault):m_dpy(dpy),m_initialized(false),m_configInitialized(false),m_isDefault(isDefault),m_nextEglImageId(0){};
 
 EglDisplay::~EglDisplay() {
     android::Mutex::Autolock mutex(m_lock);
@@ -206,3 +206,29 @@
    m_contexts[hndl] = ctx;
    return ret;
 }
+
+
+EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) {
+    android::Mutex::Autolock mutex(m_lock);
+    do { ++m_nextEglImageId; } while(m_nextEglImageId == 0);
+    img->imageId = m_nextEglImageId;
+    m_eglImages[m_nextEglImageId] = img;
+    return reinterpret_cast<EGLImageKHR>(m_nextEglImageId);
+}
+
+ImagePtr EglDisplay::getImage(EGLImageKHR img) {
+    android::Mutex::Autolock mutex(m_lock);
+    ImagesHndlMap::iterator i( m_eglImages.find((unsigned int)img) );
+    return (i != m_eglImages.end()) ? (*i).second :ImagePtr(NULL);
+}
+
+bool EglDisplay:: destroyImageKHR(EGLImageKHR img) {
+    android::Mutex::Autolock mutex(m_lock);
+    ImagesHndlMap::iterator i( m_eglImages.find((unsigned int)img) );
+    if (i != m_eglImages.end())
+    {
+        m_eglImages.erase(i);
+        return true;
+    }
+    return false;
+}
diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h b/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h
index 9c04cf9..81e82e1 100644
--- a/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h
+++ b/tools/emulator/opengl/host/libs/Translator/EGL/EglDisplay.h
@@ -19,6 +19,7 @@
 #include <list>
 #include <map>
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
 #include <utils/threads.h>
 #include <GLcommon/SmartPtr.h>
 
@@ -30,8 +31,8 @@
 
 
 typedef  std::list<EglConfig*>  ConfigsList;
-typedef  std::map< unsigned int,ContextPtr > ContextsHndlMap;
-typedef  std::map< unsigned int,SurfacePtr > SurfacesHndlMap;
+typedef  std::map< unsigned int, ContextPtr>     ContextsHndlMap;
+typedef  std::map< unsigned int, SurfacePtr>     SurfacesHndlMap;
 
 class EglDisplay {
 public:
@@ -60,6 +61,11 @@
     void initialize();
     void terminate();
     bool isInitialize();
+
+    ImagePtr getImage(EGLImageKHR img);
+    EGLImageKHR addImageKHR(ImagePtr);
+    bool destroyImageKHR(EGLImageKHR img);
+
 private:
    void initConfigurations();
 
@@ -71,7 +77,9 @@
    ContextsHndlMap        m_contexts;
    SurfacesHndlMap        m_surfaces;
    ObjectNameManager      m_manager[MAX_GLES_VERSION];
-   android::Mutex m_lock;
+   android::Mutex         m_lock;
+   ImagesHndlMap           m_eglImages;
+   unsigned int           m_nextEglImageId;
 };
 
 #endif
diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp b/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
index 94e3cec..e45000a 100644
--- a/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp
@@ -34,23 +34,41 @@
 #define MINOR          1
 #define MAJOR          4
 
+//declerations
+EglImage *attachEGLImage(unsigned int imageId);
+void detachEGLImage(unsigned int imageId);
+
+
 EglGlobalInfo* g_eglInfo = EglGlobalInfo::getInstance();
 
 __thread EglThreadInfo*    tls_thread  = NULL;
 static EGLiface            s_eglIface = {
-    getThreadInfo: getThreadInfo      // implemented in ThreadInfo.cpp
+    getThreadInfo    : getThreadInfo,      // implemented in ThreadInfo.cpp
+    eglAttachEGLImage:attachEGLImage,
+    eglDetachEGLImage:detachEGLImage
 };
 
+/*****************************************  supported extentions  ***********************************************************************/
+
 //extentions
 typedef struct {
   const char*                              name;
   __eglMustCastToProperFunctionPointerType address;
 } EglExtentionDescriptor;
 
-#define EGL_EXTENTIONS 0
-//supported extentions;
-static EglExtentionDescriptor s_extentions[] = {};
+#define EGL_EXTENTIONS 2
 
+//decleration
+EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLBoolean eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image);
+
+// extentions descriptors
+static EglExtentionDescriptor s_extentions[] = {
+                                                   {"eglCreateImageKHR" ,(__eglMustCastToProperFunctionPointerType)eglCreateImageKHR},
+                                                   {"eglDestroyImageKHR",(__eglMustCastToProperFunctionPointerType)eglDestroyImageKHR}
+                                               };
+
+/****************************************************************************************************************************************/
 //macros for accessing global egl info & tls objects
 
 #define CURRENT_THREAD()                                     \
@@ -92,6 +110,7 @@
             RETURN_ERROR(ret,EGL_BAD_CONTEXT);               \
         }
 
+
 #define VALIDATE_DISPLAY(EGLDisplay) \
         VALIDATE_DISPLAY_RETURN(EGLDisplay,EGL_FALSE)
 
@@ -104,6 +123,7 @@
 #define VALIDATE_CONTEXT(EGLContext) \
         VALIDATE_CONTEXT_RETURN(EGLContext,EGL_FALSE)
 
+
 EGLAPI EGLint EGLAPIENTRY eglGetError(void) {
     CURRENT_THREAD();
     EGLint err = tls_thread->getError();
@@ -168,7 +188,7 @@
     VALIDATE_DISPLAY(display);
     static const char* vendor     = "Google";
     static const char* version    = "1.4";
-    static const char* extensions = "EGL_KHR_image_base EGL_KHR_gl_texture_2d_image";  //XXX: Not implemented yet
+    static const char* extensions = "EGL_KHR_image_base EGL_KHR_gl_texture_2d_image";
     if(!EglValidate::stringName(name)) {
         RETURN_ERROR(NULL,EGL_BAD_PARAMETER);
     }
@@ -593,7 +613,7 @@
     } else {
         iface->deleteGLESContext(glesCtx);
     }
- 
+
 
 return EGL_NO_CONTEXT;
 }
@@ -902,6 +922,7 @@
 /***********************************************************************/
 
 
+
 //do last ( only if needed)
 /*********************************************************************************************************/
 EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
@@ -916,3 +937,74 @@
 /*********************************************************************************************************/
 
 
+/************************** KHR IMAGE *************************************************************/
+EglImage *attachEGLImage(unsigned int imageId)
+{
+    ThreadInfo* thread  = getThreadInfo();
+    EglDisplay* dpy     = static_cast<EglDisplay*>(thread->eglDisplay);
+    EglContext* ctx     = static_cast<EglContext*>(thread->eglContext);
+    if (ctx) {
+        ImagePtr img = dpy->getImage(reinterpret_cast<EGLImageKHR>(imageId));
+        if(img.Ptr()) {
+             ctx->attachImage(imageId,img);
+             return img.Ptr();
+        }
+    }
+    return NULL;
+}
+
+void detachEGLImage(unsigned int imageId)
+{
+    ThreadInfo* thread  = getThreadInfo();
+    EglDisplay* dpy     = static_cast<EglDisplay*>(thread->eglDisplay);
+    EglContext* ctx     = static_cast<EglContext*>(thread->eglContext);
+    if (ctx) {
+        ctx->detachImage(imageId);
+    }
+}
+
+
+EGLImageKHR eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
+{
+    VALIDATE_DISPLAY(display);
+    VALIDATE_CONTEXT(context);
+
+    // We only support EGL_GL_TEXTURE_2D images
+    if (target != EGL_GL_TEXTURE_2D_KHR) {
+        RETURN_ERROR(EGL_NO_IMAGE_KHR,EGL_BAD_PARAMETER);
+    }
+
+    ThreadInfo* thread  = getThreadInfo();
+    ShareGroupPtr sg = thread->shareGroup;
+    if (sg.Ptr() != NULL) {
+        unsigned int globalTexName = sg->getGlobalName(TEXTURE, (unsigned int)buffer);
+        if (!globalTexName) return EGL_NO_IMAGE_KHR;
+
+        ImagePtr img( new EglImage() );
+        if (img.Ptr() != NULL) {
+
+            ObjectDataPtr objData = sg->getObjectData(TEXTURE, (unsigned int)buffer);
+            if (!objData.Ptr()) return EGL_NO_IMAGE_KHR;
+
+            TextureData *texData = (TextureData *)objData.Ptr();
+            if(!texData->width || !texData->height) return EGL_NO_IMAGE_KHR;
+            img->width = texData->width;
+            img->height = texData->height;
+            img->border = texData->border;
+            img->internalFormat = texData->internalFormat;
+            img->globalTexName = globalTexName;
+            return dpy->addImageKHR(img);
+        }
+    }
+
+    return EGL_NO_IMAGE_KHR;
+}
+
+
+EGLBoolean eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image)
+{
+    VALIDATE_DISPLAY(display);
+    return dpy->destroyImageKHR(image) ? EGL_TRUE:EGL_FALSE;
+}
+
+/*********************************************************************************/
diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScontext.h b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScontext.h
index 89add7d..5291a52 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScontext.h
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLEScontext.h
@@ -56,6 +56,8 @@
     void  setGLerror(GLenum err);
     void  setActiveTexture(GLenum tex);
     const GLvoid* setPointer(GLenum arrType,GLint size,GLenum type,GLsizei stride,const GLvoid* data);
+    unsigned int getBindedTexture(){return m_tex2DBind[m_activeTexture];};
+    void setBindedTexture(unsigned int tex){ m_tex2DBind[m_activeTexture] = tex;};
     const GLESpointer* getPointer(GLenum arrType);
 
     void convertArrs(GLESFloatArrays& fArrs,GLint first,GLsizei count,GLenum type,const GLvoid* indices,bool direct);
@@ -78,6 +80,7 @@
     static int getMaxTexUnits(){return s_glSupport.maxTexUnits;}
     static int getMaxTexSize(){return s_glSupport.maxTexSize;}
 
+
     ~GLEScontext();
 private:
 
@@ -100,6 +103,7 @@
     GLESpointer*          m_texCoords;
     GLenum                m_glError;
     unsigned int          m_activeTexture;
+    unsigned int          m_tex2DBind[MAX_TEX_UNITS];
     unsigned int          m_arrayBuffer;
     unsigned int          m_elementBuffer;
     int                   m_pointsIndex;
diff --git a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLESimp.cpp b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLESimp.cpp
index ba52c17..f1d6b75 100644
--- a/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLESimp.cpp
+++ b/tools/emulator/opengl/host/libs/Translator/GLES_CM/GLESimp.cpp
@@ -24,6 +24,7 @@
 #include <GLcommon/TranslatorIfaces.h>
 #include <GLcommon/ThreadInfo.h>
 #include <GLES/gl.h>
+#include <GLES/glext.h>
 #include <cmath>
 
 
@@ -108,6 +109,7 @@
 
 GL_API GLboolean GL_APIENTRY glIsBuffer(GLuint buffer) {
     GET_CTX_RET(GL_FALSE)
+
     if(buffer && thrd->shareGroup.Ptr()) {
        ObjectDataPtr objData = thrd->shareGroup->getObjectData(VERTEXBUFFER,buffer);
        return objData.Ptr() ? ((GLESbuffer*)objData.Ptr())->wasBinded():GL_FALSE;
@@ -212,6 +214,7 @@
             globalTextureName = thrd->shareGroup->getGlobalName(TEXTURE,texture);
         }
     }
+    ctx->setBindedTexture(globalTextureName);
     ctx->dispatcher().glBindTexture(target,globalTextureName);
 }
 
@@ -1097,6 +1100,20 @@
     ctx->dispatcher().glTexEnvfv(target,pname,tmpParams);
 }
 
+static TextureData* getTextureData(){
+    GET_CTX_RET(NULL);
+    unsigned int tex = ctx->getBindedTexture();
+    TextureData *texData = NULL;
+    ObjectDataPtr objData = thrd->shareGroup->getObjectData(TEXTURE,tex);
+    if(!objData.Ptr()){
+        TextureData *texData = new TextureData();
+        thrd->shareGroup->setObjectData(TEXTURE, tex, ObjectDataPtr(texData));
+    } else {
+        texData = (TextureData*)objData.Ptr();
+    }
+    return texData;
+}
+
 GL_API void GL_APIENTRY  glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
     GET_CTX()
 
@@ -1108,6 +1125,16 @@
     //SET_ERROR_IF(level < 0 || border !=0 || level > log2(ctx->getMaxTexSize()) || !GLESvalidate::texImgDim(width,height,ctx->getMaxTexSize()),GL_INVALID_VALUE);
     SET_ERROR_IF(!(GLESvalidate::pixelOp(format,type) && internalformat == ((GLint)format)),GL_INVALID_OPERATION);
 
+    if (thrd->shareGroup.Ptr()){
+        unsigned int tex = ctx->getBindedTexture();
+        TextureData *texData = getTextureData();
+        if(texData) {
+            texData->width = width;
+            texData->height = height;
+            texData->border = border;
+            texData->internalFormat = internalformat;
+        }
+    }
     ctx->dispatcher().glTexImage2D(target,level,internalformat,width,height,border,format,type,pixels);
 }
 
@@ -1180,3 +1207,29 @@
     GET_CTX()
     ctx->dispatcher().glViewport(x,y,width,height);
 }
+
+void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
+{
+    GET_CTX();
+    SET_ERROR_IF(!GLESvalidate::textureTarget(target),GL_INVALID_ENUM);
+    EglImage *img = s_eglIface->eglAttachEGLImage((unsigned int)image);
+    if (img) {
+        // Create the texture object in the underlying EGL implementation,
+        // flag to the OpenGL layer to skip the image creation and map the
+        // current binded texture object to the existing global object.
+        if (thrd->shareGroup) {
+            unsigned int tex = ctx->getBindedTexture();
+            unsigned int oldGlobal = thrd->shareGroup->getGlobalName(TEXTURE, tex);
+            // Delete old texture object
+            if (oldGlobal) {
+                ctx->dispatcher().glDeleteTextures(1, &oldGlobal);
+            }
+            // replace mapping and bind the new global object
+            thrd->shareGroup->replaceGlobalName(TEXTURE, tex,img->globalTexName);
+            ctx->dispatcher().glBindTexture(GL_TEXTURE_2D, img->globalTexName);
+            TextureData *texData = getTextureData();
+            texData->sourceEGLImage = (unsigned int)image;
+            texData->eglImageDetach = s_eglIface->eglDetachEGLImage;
+        }
+    }
+}
diff --git a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h
index a887f9f..cf54d9c 100644
--- a/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h
+++ b/tools/emulator/opengl/host/libs/Translator/include/GLcommon/TranslatorIfaces.h
@@ -16,9 +16,40 @@
 #ifndef TRANSLATOR_IFACES_H
 #define TRANSLATOR_IFACES_H
 #include <GLcommon/ThreadInfo.h>
+#include <GLES/gl.h>
 
 extern "C" {
 
+class TextureData : public ObjectData
+{
+public:
+    ~TextureData() {
+        if (sourceEGLImage && eglImageDetach) (*eglImageDetach)(sourceEGLImage);
+    }
+    TextureData():width(0),height(0),border(0),internalFormat(GL_RGBA),sourceEGLImage(0){};
+
+    unsigned int width;
+    unsigned int height;
+    unsigned int border;
+    unsigned int internalFormat;
+    unsigned int sourceEGLImage;
+    void (*eglImageDetach)(unsigned int imageId);
+};
+
+struct EglImage
+{
+    ~EglImage(){};
+    unsigned int imageId;
+    unsigned int globalTexName;
+    unsigned int width;
+    unsigned int height;
+    unsigned int internalFormat;
+    unsigned int border;
+};
+
+typedef SmartPtr<EglImage> ImagePtr;
+typedef  std::map< unsigned int, ImagePtr>       ImagesHndlMap;
+
 class GLEScontext;
 
 typedef struct {
@@ -33,6 +64,8 @@
 
 typedef struct {
     ThreadInfo* (*getThreadInfo)();
+    EglImage* (*eglAttachEGLImage)(unsigned int imageId);
+    void        (*eglDetachEGLImage)(unsigned int imageId);
 }EGLiface;
 
 typedef GLESiface* (*__translator_getGLESIfaceFunc)(EGLiface*);