emulator opengl: added Bind texture to EGLImage/surface

added functionality to bind an EGLImage to a texture both
in the system and host sides.

Change-Id: I2dc26090b45da080ac4d0e8f5799c95f7cc54634
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp
index 774ad02..f6f15b5 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp
@@ -17,6 +17,10 @@
 #include "FrameBuffer.h"
 #include "EGLDispatch.h"
 #include "GLDispatch.h"
+#include "ThreadInfo.h"
+#ifdef WITH_GLES2
+#include "GL2Dispatch.h"
+#endif
 #include <stdio.h>
 
 ColorBuffer *ColorBuffer::create(int p_width, int p_height,
@@ -134,6 +138,27 @@
     return true;
 }
 
+bool ColorBuffer::bindToTexture()
+{
+    if (m_eglImage) {
+        RenderThreadInfo *tInfo = getRenderThreadInfo();
+        if (tInfo->currContext.Ptr()) {
+#ifdef WITH_GLES2
+            if (tInfo->currContext->isGL2()) {
+                s_gl2.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
+            }
+            else {
+                s_gl.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
+            }
+#else
+            s_gl.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_eglImage);
+#endif
+            return true;
+        }
+    }
+    return false;
+}
+
 bool ColorBuffer::bind_fbo()
 {
     if (m_fbo) {
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h
index 550c6d1..6829581 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h
@@ -35,6 +35,7 @@
     void update(GLenum p_format, GLenum p_type, void *pixels);
     bool blitFromPbuffer(EGLSurface p_pbufSurface);
     bool post();
+    bool bindToTexture();
 
 private:
     ColorBuffer();
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp
index a0f32c8..b0bd7ab 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp
@@ -97,6 +97,7 @@
     //
     if (!init_egl_dispatch()) {
         // Failed to load EGL
+        printf("Failed to init_egl_dispatch\n");
         return false;
     }
 
@@ -105,6 +106,7 @@
     //
     if (!init_gl_dispatch()) {
         // Failed to load GLES
+        printf("Failed to init_gl_dispatch\n");
         return false;
     }
 
@@ -113,6 +115,7 @@
     //
     FrameBuffer *fb = new FrameBuffer(p_x, p_y, p_width, p_height);
     if (!fb) {
+        printf("Fialed to create fb\n");
         return false;
     }
 
@@ -135,6 +138,7 @@
     //
     fb->m_eglDisplay = s_egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
     if (fb->m_eglDisplay == EGL_NO_DISPLAY) {
+        printf("Failed to Initialize backend EGL display\n");
         delete fb;
         return false;
     }
@@ -172,6 +176,7 @@
     int n;
     if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs,
                                &eglConfig, 1, &n)) {
+        printf("Failed on eglChooseConfig\n");
         delete fb;
         return false;
     }
@@ -420,6 +425,19 @@
     return true;
 }
 
+bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer)
+{
+    android::Mutex::Autolock mutex(m_lock);
+
+    ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
+    if (c == m_colorbuffers.end()) {
+        // bad colorbuffer handle
+        return false;
+    }
+
+    return (*c).second->bindToTexture();
+}
+
 bool FrameBuffer::bindContext(HandleType p_context,
                               HandleType p_drawSurface,
                               HandleType p_readSurface)
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h
index e30fba8..99e4999 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h
@@ -67,6 +67,7 @@
 
     bool  bindContext(HandleType p_context, HandleType p_drawSurface, HandleType p_readSurface);
     bool  setWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer);
+    bool  bindColorBufferToTexture(HandleType p_colorbuffer);
 
     bool post(HandleType p_colorbuffer);
 
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp
index 891c89b..f68a153 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp
@@ -229,7 +229,12 @@
 
 static void rcBindTexture(uint32_t colorBuffer)
 {
-   // XXX: TBD - should be implemented
+    FrameBuffer *fb = FrameBuffer::getFB();
+    if (!fb) {
+        return;
+    }
+
+    fb->bindColorBufferToTexture(colorBuffer);
 }
 
 static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer,
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp
index e8d7180..a956e2a 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp
@@ -65,10 +65,15 @@
     //     and either there is no need for depth or stencil buffer
     //     or GL_KHR_gl_renderbuffer_image present.
     //
+#if 0
+    //XXX: This path should be implemented
     win->m_useEGLImage =
          (caps.has_eglimage_texture_2d &&
           (caps.has_eglimage_renderbuffer ||
            (fbconf->getDepthSize() + fbconf->getStencilSize() == 0)) );
+#else
+    win->m_useEGLImage = false;
+#endif
 
     if (win->m_useEGLImage) {
     }
diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp
index 2551f6f..da9682b 100644
--- a/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp
+++ b/tools/emulator/opengl/host/libs/libOpenglRender/render_api.cpp
@@ -121,14 +121,14 @@
         // flag the thread it should exit
         s_renderThread->flagNeedExit();
 
-        // open a dummy connection to the renderer to make it 
+        // open a dummy connection to the renderer to make it
         // realize the exit request
         IOStream *dummy = createRenderThread(8);
         if (dummy) {
             // wait for the thread to exit
             int status;
             ret = s_renderThread->wait(&status);
-    
+
             delete dummy;
         }
 
@@ -143,10 +143,12 @@
 {
     TcpStream *stream = new TcpStream(p_stream_buffer_size);
     if (!stream) {
+        ERR("createRenderThread failed to create stream\n");
         return NULL;
     }
 
     if (stream->connect("localhost", s_renderPort) < 0) {
+        ERR("createRenderThread failed to connect\n");
         delete stream;
         return NULL;
     }
diff --git a/tools/emulator/opengl/system/GLESv1/Android.mk b/tools/emulator/opengl/system/GLESv1/Android.mk
index fc7bc2d..aa5725c 100644
--- a/tools/emulator/opengl/system/GLESv1/Android.mk
+++ b/tools/emulator/opengl/system/GLESv1/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH := $(call my-dir)
 emulatorOpengl := $(LOCAL_PATH)/../..
 
-### EGL implementation ###########################################
+### GLESv1 implementation ###########################################
 include $(CLEAR_VARS)
 
 # add additional depencies to ensure that the generated code that we depend on
diff --git a/tools/emulator/opengl/system/GLESv1_enc/Android.mk b/tools/emulator/opengl/system/GLESv1_enc/Android.mk
index 1d28673..16f29b1 100644
--- a/tools/emulator/opengl/system/GLESv1_enc/Android.mk
+++ b/tools/emulator/opengl/system/GLESv1_enc/Android.mk
@@ -21,11 +21,18 @@
     $(emulatorOpengl)/shared/OpenglCodecCommon \
     $(emulatorOpengl)/system/OpenglSystemCommon \
     $(emulatorOpengl)/host/include/libOpenglRender \
+    $(emulatorOpengl)/system/renderControl_enc \
+	$(call intermediates-dir-for, SHARED_LIBRARIES, lib_renderControl_enc) \
     $(glesv1_intermediates)
 
 LOCAL_STATIC_LIBRARIES := \
-        libOpenglCodecCommon
-LOCAL_SHARED_LIBRARIES := libcutils
+    libOpenglSystemCommon \
+    libOpenglCodecCommon  \
+	libqemu
+
+LOCAL_SHARED_LIBRARIES := 	\
+    lib_renderControl_enc	\
+	libcutils
 
 EMUGEN := $(HOST_OUT_EXECUTABLES)/emugen
 
diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp
index 63fa1b3..6633d13 100644
--- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp
+++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.cpp
@@ -16,6 +16,9 @@
 #include "GLEncoder.h"
 #include "glUtils.h"
 #include "FixedBuffer.h"
+#include "HostConnection.h"
+#include <private/ui/android_natives_priv.h>
+#include "gralloc_cb.h"
 
 #include <cutils/log.h>
 #include <assert.h>
@@ -25,6 +28,18 @@
 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES-CM 1.0";
 static GLubyte *gExtensionsString= (GLubyte *) ""; // no extensions at this point;
 
+#define DEFINE_AND_VALIDATE_HOST_CONNECTION(ret) \
+    HostConnection *hostCon = HostConnection::get(); \
+    if (!hostCon) { \
+        LOGE("egl: Failed to get host connection\n"); \
+        return ret; \
+    } \
+    renderControl_encoder_context_t *rcEnc = hostCon->rcEncoder(); \
+    if (!rcEnc) { \
+        LOGE("egl: Failed to get renderControl encoder context\n"); \
+        return ret; \
+    }
+
 
 GLint * GLEncoder::getCompressedTextureFormats()
 {
@@ -468,6 +483,7 @@
     m_glDrawElements_enc = set_glDrawElements(s_glDrawElements);
     set_glGetString(s_glGetString);
     set_glFinish(s_glFinish);
+    set_glEGLImageTargetTexture2DOES(s_glEGLImageTargetTexture2DOES);
 
 }
 
@@ -487,3 +503,22 @@
     GLEncoder *ctx = (GLEncoder *)self;
     ctx->glFinishRoundTrip(self);
 }
+
+void GLEncoder::s_glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES image)
+{
+    //TODO: check error - we don't have a way to set gl error
+    android_native_buffer_t* native_buffer = (android_native_buffer_t*)image;
+
+    if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) {
+        return;
+    }
+
+    if (native_buffer->common.version != sizeof(android_native_buffer_t)) {
+        return;
+    }
+
+    DEFINE_AND_VALIDATE_HOST_CONNECTION();
+    rcEnc->rcBindTexture(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle);
+
+    return;
+}
diff --git a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h
index cdf3657..2d727f5 100644
--- a/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h
+++ b/tools/emulator/opengl/system/GLESv1_enc/GLEncoder.h
@@ -89,6 +89,8 @@
     static void s_glPixelStorei(void *self, GLenum param, GLint value);
 
     static void s_glFinish(void *self);
+    static void s_glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES image);
     void sendVertexData(unsigned first, unsigned count);
+
 };
 #endif
diff --git a/tools/emulator/opengl/system/GLESv1_enc/gl.attrib b/tools/emulator/opengl/system/GLESv1_enc/gl.attrib
index 5b54ef1..d3d97fc 100644
--- a/tools/emulator/opengl/system/GLESv1_enc/gl.attrib
+++ b/tools/emulator/opengl/system/GLESv1_enc/gl.attrib
@@ -674,4 +674,3 @@
 #void glExtGetProgramBinarySourceQCOM(GLuint program, GLenum shadertype, GLchar *source, GLint *length)
 glExtGetProgramBinarySourceQCOM
 	flag unsupported
-
diff --git a/tools/emulator/opengl/system/egl/egl.cpp b/tools/emulator/opengl/system/egl/egl.cpp
index 7ad1760..84a7664 100644
--- a/tools/emulator/opengl/system/egl/egl.cpp
+++ b/tools/emulator/opengl/system/egl/egl.cpp
@@ -118,7 +118,7 @@
     EGLConfig           config;
 
 
-    egl_surface_t(EGLDisplay dpy, EGLConfig config);
+    egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType);
     virtual     ~egl_surface_t();
 
     virtual     EGLBoolean         rcCreate() = 0;
@@ -132,6 +132,7 @@
     uint32_t     getRcSurface(){ return rcSurface; }
 
     virtual     EGLBoolean    isValid(){ return valid; }
+    EGLint        getSurfaceType(){ return surfaceType; }
 
     void        setWidth(EGLint w){ width = w; }
     EGLint      getWidth(){ return width; }
@@ -152,14 +153,15 @@
     EGLint    texTarget;
 
 protected:
+    EGLint        surfaceType;
     EGLBoolean    valid;
     uint32_t     rcSurface; //handle to surface created via remote control
 
 
 };
 
-egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config)
-    : dpy(dpy), config(config), valid(EGL_FALSE), rcSurface(0)
+egl_surface_t::egl_surface_t(EGLDisplay dpy, EGLConfig config, EGLint surfaceType)
+    : dpy(dpy), config(config), surfaceType(surfaceType), valid(EGL_FALSE), rcSurface(0)
 {
     width = 0;
     height = 0;
@@ -177,7 +179,7 @@
 struct egl_window_surface_t : public egl_surface_t {
 
     egl_window_surface_t(
-            EGLDisplay dpy, EGLConfig config,
+            EGLDisplay dpy, EGLConfig config, EGLint surfType,
             ANativeWindow* window);
 
     ~egl_window_surface_t();
@@ -197,9 +199,9 @@
 
 
 egl_window_surface_t::egl_window_surface_t (
-            EGLDisplay dpy, EGLConfig config,
+            EGLDisplay dpy, EGLConfig config, EGLint surfType,
             ANativeWindow* window)
-    : egl_surface_t(dpy, config),
+    : egl_surface_t(dpy, config, surfType),
     nativeWindow(window),
     buffer(NULL)
 {
@@ -294,7 +296,7 @@
     GLenum    format;
 
     egl_pbuffer_surface_t(
-            EGLDisplay dpy, EGLConfig config,
+            EGLDisplay dpy, EGLConfig config, EGLint surfType,
             int32_t w, int32_t h, GLenum format);
 
     virtual ~egl_pbuffer_surface_t();
@@ -310,9 +312,9 @@
 };
 
 egl_pbuffer_surface_t::egl_pbuffer_surface_t(
-        EGLDisplay dpy, EGLConfig config,
+        EGLDisplay dpy, EGLConfig config, EGLint surfType,
         int32_t w, int32_t h, GLenum pixelFormat)
-    : egl_surface_t(dpy, config), format(pixelFormat)
+    : egl_surface_t(dpy, config, surfType), format(pixelFormat)
 {
     setWidth(w);
     setHeight(h);
@@ -530,7 +532,7 @@
     }
 
     egl_surface_t* surface;
-    surface = new egl_window_surface_t(&s_display, config, static_cast<ANativeWindow*>(win));
+    surface = new egl_window_surface_t(&s_display, config, surfaceType, static_cast<ANativeWindow*>(win));
     if (!surface)
         return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
     if (!surface->rcCreate()) {
@@ -586,7 +588,7 @@
     if (s_display.getConfigPixelFormat(config, &pixelFormat) == EGL_FALSE)
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
 
-    egl_surface_t* surface = new egl_pbuffer_surface_t(dpy, config, w, h, pixelFormat);
+    egl_surface_t* surface = new egl_pbuffer_surface_t(dpy, config, surfaceType, w, h, pixelFormat);
     if (!surface)
         return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
     if (!surface->rcCreate()) {
@@ -697,11 +699,35 @@
     return 0;
 }
 
-EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface eglSurface, EGLint buffer)
 {
-    //TODO
-    LOGW("%s not implemented", __FUNCTION__);
-    return 0;
+    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+    VALIDATE_SURFACE_RETURN(eglSurface, EGL_FALSE);
+    if (eglSurface == EGL_NO_SURFACE) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    if (buffer != EGL_BACK_BUFFER) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
+
+    if (surface->getTextureFormat() == EGL_NO_TEXTURE) {
+        return setError(EGL_BAD_MATCH, EGL_FALSE);
+    }
+
+    if (!(surface->getSurfaceType() & EGL_PBUFFER_BIT)) {
+        return setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
+    //It's now safe to cast to pbuffer surface
+    egl_pbuffer_surface_t* pbSurface = (egl_pbuffer_surface_t*)surface;
+
+    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+    rcEnc->rcBindTexture(rcEnc, pbSurface->getRcColorBuffer());
+
+    return GL_TRUE;
 }
 
 EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
@@ -713,9 +739,11 @@
 
 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
 {
-    //TODO
-    LOGW("%s not implemented", __FUNCTION__);
-    return 0;
+    VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE);
+
+    DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+    rcEnc->rcFBSetSwapInterval(rcEnc, interval); //TODO: implement on the host
+    return EGL_TRUE;
 }
 
 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)