diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp index adc84d27a..b0a1ba2b3 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -197,6 +197,27 @@ bool ColorBuffer::bindToTexture() return false; } +bool ColorBuffer::bindToRenderbuffer() +{ + if (m_eglImage) { + RenderThreadInfo *tInfo = getRenderThreadInfo(); + if (tInfo->currContext.Ptr()) { +#ifdef WITH_GLES2 + if (tInfo->currContext->isGL2()) { + s_gl2.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, m_eglImage); + } + else { + s_gl.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, m_eglImage); + } +#else + s_gl.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER_OES, 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 25761ce62..4bc495a80 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h +++ b/tools/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h @@ -37,6 +37,7 @@ public: bool blitFromPbuffer(EGLSurface p_pbufSurface); bool post(); bool bindToTexture(); + bool bindToRenderbuffer(); private: ColorBuffer(); diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp index 9f849375d..50ee9cbeb 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -508,6 +508,19 @@ bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) return (*c).second->bindToTexture(); } +bool FrameBuffer::bindColorBufferToRenderbuffer(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->bindToRenderbuffer(); +} + 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 4d80f74d5..d2e77307f 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h +++ b/tools/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.h @@ -65,6 +65,7 @@ public: bool setWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer); bool flushWindowSurfaceColorBuffer(HandleType p_surface); bool bindColorBufferToTexture(HandleType p_colorbuffer); + bool bindColorBufferToRenderbuffer(HandleType p_colorbuffer); bool updateColorBuffer(HandleType p_colorbuffer, int x, int y, int width, int height, GLenum format, GLenum type, void *pixels); diff --git a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp index c5097a4ab..14c342375 100644 --- a/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp +++ b/tools/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp @@ -282,6 +282,16 @@ static void rcBindTexture(uint32_t colorBuffer) fb->bindColorBufferToTexture(colorBuffer); } +static void rcBindRenderbuffer(uint32_t colorBuffer) +{ + FrameBuffer *fb = FrameBuffer::getFB(); + if (!fb) { + return; + } + + fb->bindColorBufferToRenderbuffer(colorBuffer); +} + static EGLint rcColorBufferCacheFlush(uint32_t colorBuffer, EGLint postCount, int forRead) { @@ -333,6 +343,7 @@ void initRenderControlContext(renderControl_decoder_context_t *dec) dec->set_rcFBPost(rcFBPost); dec->set_rcFBSetSwapInterval(rcFBSetSwapInterval); dec->set_rcBindTexture(rcBindTexture); + dec->set_rcBindRenderbuffer(rcBindRenderbuffer); dec->set_rcColorBufferCacheFlush(rcColorBufferCacheFlush); dec->set_rcReadColorBuffer(rcReadColorBuffer); dec->set_rcUpdateColorBuffer(rcUpdateColorBuffer); diff --git a/tools/emulator/opengl/system/GLESv1/gl.cpp b/tools/emulator/opengl/system/GLESv1/gl.cpp index d57624f62..2ab6986ae 100644 --- a/tools/emulator/opengl/system/GLESv1/gl.cpp +++ b/tools/emulator/opengl/system/GLESv1/gl.cpp @@ -34,7 +34,7 @@ static EGLClient_glesInterface * s_gl = NULL; //GL extensions void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES image) { - DBG("glEGLImageTargetTexture2DOES"); + DBG("glEGLImageTargetTexture2DOES v1 image=0x%x", 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; @@ -52,6 +52,26 @@ void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES imag return; } +void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES image) +{ + DBG("glEGLImageTargetRenderbufferStorageOES v1 image=0x%x", 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->rcBindRenderbuffer(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle); + + return; +} + void * getProcAddress(const char * procname) { // search in GL function table @@ -80,6 +100,7 @@ void init() { GET_CONTEXT; ctx->set_glEGLImageTargetTexture2DOES(glEGLImageTargetTexture2DOES); + ctx->set_glEGLImageTargetRenderbufferStorageOES(glEGLImageTargetRenderbufferStorageOES); ctx->set_glGetString(my_glGetString); } diff --git a/tools/emulator/opengl/system/GLESv2/gl2.cpp b/tools/emulator/opengl/system/GLESv2/gl2.cpp index abfa7eadc..f4157d762 100644 --- a/tools/emulator/opengl/system/GLESv2/gl2.cpp +++ b/tools/emulator/opengl/system/GLESv2/gl2.cpp @@ -35,7 +35,7 @@ static EGLClient_glesInterface * s_gl = NULL; //GL extensions void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES image) { - DBG("glEGLImageTargetTexture2DOES"); + DBG("glEGLImageTargetTexture2DOES v2 img=0x%x\n", 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; @@ -53,6 +53,26 @@ void glEGLImageTargetTexture2DOES(void * self, GLenum target, GLeglImageOES imag return; } +void glEGLImageTargetRenderbufferStorageOES(void *self, GLenum target, GLeglImageOES image) +{ + DBG("glEGLImageTargetRenderbufferStorageOES v2 image=0x%x\n", 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->rcBindRenderbuffer(rcEnc, ((cb_handle_t *)(native_buffer->handle))->hostHandle); + + return; +} + void * getProcAddress(const char * procname) { // search in GL function table @@ -81,6 +101,7 @@ void init() { GET_CONTEXT; ctx->set_glEGLImageTargetTexture2DOES(glEGLImageTargetTexture2DOES); + ctx->set_glEGLImageTargetRenderbufferStorageOES(glEGLImageTargetRenderbufferStorageOES); ctx->set_glGetString(my_glGetString); } diff --git a/tools/emulator/opengl/system/egl/Android.mk b/tools/emulator/opengl/system/egl/Android.mk index 312b49d9f..a84c9bc6a 100644 --- a/tools/emulator/opengl/system/egl/Android.mk +++ b/tools/emulator/opengl/system/egl/Android.mk @@ -14,7 +14,8 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \ LOCAL_SRC_FILES := \ eglDisplay.cpp \ - egl.cpp + egl.cpp \ + ClientAPIExts.cpp LOCAL_PRELINK_MODULE := false diff --git a/tools/emulator/opengl/system/egl/ClientAPIExts.cpp b/tools/emulator/opengl/system/egl/ClientAPIExts.cpp new file mode 100644 index 000000000..888c23103 --- /dev/null +++ b/tools/emulator/opengl/system/egl/ClientAPIExts.cpp @@ -0,0 +1,157 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "ClientAPIExts.h" +#include "ThreadInfo.h" +#include +#include +#include "eglContext.h" + +namespace ClientAPIExts +{ + +// +// define function pointer type for each extention function +// typename has the form __egl_{funcname}_t +// +#define FUNC_TYPE(fname) __egl_ ## fname ## _t +#define API_ENTRY(fname,params,args) \ + typedef void (GL_APIENTRY *FUNC_TYPE(fname)) params; + +#define API_ENTRY_RET(rtype,fname,params,args) \ + typedef rtype (GL_APIENTRY *FUNC_TYPE(fname)) params; + +#include "ClientAPIExts.in" +#undef API_ENTRY +#undef API_ENTRY_RET + +///// +// Define static table to store the function value for each +// client API. functions pointers will get initialized through +// ClientAPIExts::initClientFuncs function after each client API has been +// loaded. +///// +#define API_ENTRY(fname,params,args) \ + FUNC_TYPE(fname) fname; + +#define API_ENTRY_RET(rtype,fname,params,args) \ + API_ENTRY(fname,params,args) + +static struct _ext_table +{ +#include "ClientAPIExts.in" +} s_client_extensions[2]; + +#undef API_ENTRY +#undef API_ENTRY_RET + +// +// This function initialized each entry in the s_client_extensions +// struct at the givven index using the givven client interface +// +void initClientFuncs(const EGLClient_glesInterface *iface, int idx) +{ +#define API_ENTRY(fname,params,args) \ + s_client_extensions[idx].fname = \ + (FUNC_TYPE(fname))iface->getProcAddress(#fname); + +#define API_ENTRY_RET(rtype,fname,params,args) \ + API_ENTRY(fname,params,args) + + // + // reset all func pointers to NULL + // + memset(&s_client_extensions[idx], 0, sizeof(struct _ext_table)); + + // + // And now query the GLES library for each proc address + // +#include "ClientAPIExts.in" +#undef API_ENTRY +#undef API_ENTRY_RET +} + +// +// Define implementation for each extension function which checks +// the current context version and calls to the correct client API +// function. +// +#define API_ENTRY(fname,params,args) \ + static void _egl_ ## fname params \ + { \ + EGLThreadInfo* thread = getEGLThreadInfo(); \ + if (!thread->currentContext) { \ + return; \ + } \ + int idx = (int)thread->currentContext->version - 1; \ + if (!s_client_extensions[idx].fname) { \ + return; \ + } \ + (*s_client_extensions[idx].fname) args; \ + } + +#define API_ENTRY_RET(rtype,fname,params,args) \ + static rtype _egl_ ## fname params \ + { \ + EGLThreadInfo* thread = getEGLThreadInfo(); \ + if (!thread->currentContext) { \ + return (rtype)0; \ + } \ + int idx = (int)thread->currentContext->version - 1; \ + if (!s_client_extensions[idx].fname) { \ + return (rtype)0; \ + } \ + return (*s_client_extensions[idx].fname) args; \ + } + +#include "ClientAPIExts.in" +#undef API_ENTRY +#undef API_ENTRY_RET + +// +// Define a table to map function names to the local _egl_ version of +// the extension function, to be used in eglGetProcAddress. +// +#define API_ENTRY(fname,params,args) \ + { #fname, (void*)_egl_ ## fname}, +#define API_ENTRY_RET(rtype,fname,params,args) \ + API_ENTRY(fname,params,args) + +static struct _client_ext_funcs { + const char *fname; + void* proc; +} s_client_ext_funcs[] = { +#include "ClientAPIExts.in" +}; +static const int numExtFuncs = sizeof(s_client_ext_funcs) / + sizeof(s_client_ext_funcs[0]); + +#undef API_ENTRY +#undef API_ENTRY_RET + +// +// returns the __egl_ version of the givven extension function name. +// +void* getProcAddress(const char *fname) +{ + for (int i=0; igetProcAddress( procname ); - if (proc != NULL) { - return (__eglMustCastToProperFunctionPointerType)proc; - } - - // look in gles2 - if (s_display.gles2_iface() != NULL) { - proc = s_display.gles2_iface()->getProcAddress( procname ); - if (proc != NULL) { - return (__eglMustCastToProperFunctionPointerType)proc; - } - } + // look in gles client api's extensions table + return (__eglMustCastToProperFunctionPointerType)ClientAPIExts::getProcAddress(procname); // Fail - function not found. return NULL; @@ -1073,12 +1032,14 @@ EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLC if (!hostCon->gl2Encoder()->isInitialized()) { s_display.gles2_iface()->init(); hostCon->gl2Encoder()->setInitialized(); + ClientAPIExts::initClientFuncs(s_display.gles2_iface(), 1); } } else { if (!hostCon->glEncoder()->isInitialized()) { s_display.gles_iface()->init(); hostCon->glEncoder()->setInitialized(); + ClientAPIExts::initClientFuncs(s_display.gles_iface(), 0); } } } @@ -1217,7 +1178,6 @@ EGLBoolean eglUnlockSurfaceKHR(EGLDisplay display, EGLSurface surface) EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) { VALIDATE_DISPLAY_INIT(dpy, EGL_NO_IMAGE_KHR); - if (ctx != EGL_NO_CONTEXT) { setErrorReturn(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); } @@ -1253,7 +1213,6 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EG EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) { VALIDATE_DISPLAY_INIT(dpy, EGL_FALSE); - android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) diff --git a/tools/emulator/opengl/system/egl/eglContext.h b/tools/emulator/opengl/system/egl/eglContext.h new file mode 100644 index 000000000..2ca6d0c21 --- /dev/null +++ b/tools/emulator/opengl/system/egl/eglContext.h @@ -0,0 +1,51 @@ +/* +* Copyright (C) 2011 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#ifndef _EGL_CONTEXT_H +#define _EGL_CONTEXT_H + +#include "GLClientState.h" +#include "GLSharedGroup.h" + +struct EGLContext_t { + + enum { + IS_CURRENT = 0x00010000, + NEVER_CURRENT = 0x00020000 + }; + + EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx); + ~EGLContext_t(); + uint32_t flags; + EGLDisplay dpy; + EGLConfig config; + EGLSurface read; + EGLSurface draw; + EGLContext_t * shareCtx; + EGLint version; + uint32_t rcContext; + const char* versionString; + const char* vendorString; + const char* rendererString; + const char* extensionString; + + GLClientState * getClientState(){ return clientState; } + GLSharedGroupPtr getSharedGroup(){ return sharedGroup; } +private: + GLClientState * clientState; + GLSharedGroupPtr sharedGroup; +}; + +#endif diff --git a/tools/emulator/opengl/system/renderControl_enc/renderControl.in b/tools/emulator/opengl/system/renderControl_enc/renderControl.in index 9ee3d3f1e..18ce8a418 100644 --- a/tools/emulator/opengl/system/renderControl_enc/renderControl.in +++ b/tools/emulator/opengl/system/renderControl_enc/renderControl.in @@ -18,6 +18,7 @@ GL_ENTRY(EGLint, rcMakeCurrent, uint32_t context, uint32_t drawSurf, uint32_t re GL_ENTRY(void, rcFBPost, uint32_t colorBuffer) GL_ENTRY(void, rcFBSetSwapInterval, EGLint interval) GL_ENTRY(void, rcBindTexture, uint32_t colorBuffer) +GL_ENTRY(void, rcBindRenderbuffer, uint32_t colorBuffer) GL_ENTRY(EGLint, rcColorBufferCacheFlush, uint32_t colorbuffer, EGLint postCount,int forRead) GL_ENTRY(void, rcReadColorBuffer, uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels) GL_ENTRY(int, rcUpdateColorBuffer, uint32_t colorbuffer, GLint x, GLint y, GLint width, GLint height, GLenum format, GLenum type, void *pixels)