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)