From 0ff6e7917b966f10192716527e7f978c8ad460d7 Mon Sep 17 00:00:00 2001 From: Amit Feller Date: Sun, 10 Apr 2011 16:29:55 +0300 Subject: [PATCH] supporting EGL_KHR_image_base & EGL_KHR_gl_texture_2d_image extentions Change-Id: I69c3e975c892bcd0872c47e349b427f570d7e82d --- .../host/libs/Translator/EGL/EglContext.cpp | 13 +++ .../host/libs/Translator/EGL/EglContext.h | 3 + .../host/libs/Translator/EGL/EglDisplay.cpp | 28 ++++- .../host/libs/Translator/EGL/EglDisplay.h | 14 ++- .../host/libs/Translator/EGL/EglImp.cpp | 104 +++++++++++++++++- .../libs/Translator/GLES_CM/GLEScontext.h | 4 + .../host/libs/Translator/GLES_CM/GLESimp.cpp | 53 +++++++++ .../include/GLcommon/TranslatorIfaces.h | 33 ++++++ 8 files changed, 242 insertions(+), 10 deletions(-) diff --git a/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.cpp b/tools/emulator/opengl/host/libs/Translator/EGL/EglContext.cpp index 0190fdf06..27f80174f 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 @@ bool EglContext::getAttrib(EGLint attrib,EGLint* value) { } 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 f9445a1da..0c2072372 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 @@ public: 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 @@ private: 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 9e174933e..31a425f7e 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 #include -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 @@ EGLContext EglDisplay::addContext(ContextPtr ctx ) { 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(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 9c04cf980..81e82e142 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 #include #include +#include #include #include @@ -30,8 +31,8 @@ typedef std::list 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 @@ public: void initialize(); void terminate(); bool isInitialize(); + + ImagePtr getImage(EGLImageKHR img); + EGLImageKHR addImageKHR(ImagePtr); + bool destroyImageKHR(EGLImageKHR img); + private: void initConfigurations(); @@ -71,7 +77,9 @@ private: 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 94e3cec02..e45000ae3 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 @@ static EglExtentionDescriptor s_extentions[] = {}; RETURN_ERROR(ret,EGL_BAD_CONTEXT); \ } + #define VALIDATE_DISPLAY(EGLDisplay) \ VALIDATE_DISPLAY_RETURN(EGLDisplay,EGL_FALSE) @@ -104,6 +123,7 @@ static EglExtentionDescriptor s_extentions[] = {}; #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 @@ EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay display, EGLint name) 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 @@ EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig con } else { iface->deleteGLESContext(glesCtx); } - + return EGL_NO_CONTEXT; } @@ -902,6 +922,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay display, EGLSurface surf /***********************************************************************/ + //do last ( only if needed) /*********************************************************************************************************/ EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { @@ -916,3 +937,74 @@ return 0; /*********************************************************************************************************/ +/************************** KHR IMAGE *************************************************************/ +EglImage *attachEGLImage(unsigned int imageId) +{ + ThreadInfo* thread = getThreadInfo(); + EglDisplay* dpy = static_cast(thread->eglDisplay); + EglContext* ctx = static_cast(thread->eglContext); + if (ctx) { + ImagePtr img = dpy->getImage(reinterpret_cast(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(thread->eglDisplay); + EglContext* ctx = static_cast(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 89add7dcb..5291a523f 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 @@ public: 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 @@ public: static int getMaxTexUnits(){return s_glSupport.maxTexUnits;} static int getMaxTexSize(){return s_glSupport.maxTexSize;} + ~GLEScontext(); private: @@ -100,6 +103,7 @@ private: 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 ba52c17ec..f1d6b75fa 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 #include #include +#include #include @@ -108,6 +109,7 @@ GLESiface* __translator_getIfaces(EGLiface* eglIface){ 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 @@ GL_API void GL_APIENTRY glBindTexture( GLenum target, GLuint texture) { globalTextureName = thrd->shareGroup->getGlobalName(TEXTURE,texture); } } + ctx->setBindedTexture(globalTextureName); ctx->dispatcher().glBindTexture(target,globalTextureName); } @@ -1097,6 +1100,20 @@ GL_API void GL_APIENTRY glTexEnvxv( GLenum target, GLenum pname, const GLfixed 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 @@ GL_API void GL_APIENTRY glTexImage2D( GLenum target, GLint level, GLint interna //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 @@ GL_API void GL_APIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei he 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 a887f9f6a..cf54d9cdd 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 +#include 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 ImagePtr; +typedef std::map< unsigned int, ImagePtr> ImagesHndlMap; + class GLEScontext; typedef struct { @@ -33,6 +64,8 @@ typedef struct { typedef struct { ThreadInfo* (*getThreadInfo)(); + EglImage* (*eglAttachEGLImage)(unsigned int imageId); + void (*eglDetachEGLImage)(unsigned int imageId); }EGLiface; typedef GLESiface* (*__translator_getGLESIfaceFunc)(EGLiface*);