diff options
Diffstat (limited to 'emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp')
-rw-r--r-- | emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp | 897 |
1 files changed, 0 insertions, 897 deletions
diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp deleted file mode 100644 index e7a7960..0000000 --- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ /dev/null @@ -1,897 +0,0 @@ -/* -* 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 "FrameBuffer.h" -#include "NativeSubWindow.h" -#include "FBConfig.h" -#include "EGLDispatch.h" -#include "GLDispatch.h" -#include "GL2Dispatch.h" -#include "ThreadInfo.h" -#include "TimeUtils.h" -#include <stdio.h> - -FrameBuffer *FrameBuffer::s_theFrameBuffer = NULL; -HandleType FrameBuffer::s_nextHandle = 0; - -#ifdef WITH_GLES2 -static char* getGLES2ExtensionString(EGLDisplay p_dpy) -{ - EGLConfig config; - EGLSurface surface; - - GLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - - int n; - if (!s_egl.eglChooseConfig(p_dpy, configAttribs, - &config, 1, &n)) { - return NULL; - } - - EGLint pbufAttribs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE - }; - - surface = s_egl.eglCreatePbufferSurface(p_dpy, config, pbufAttribs); - if (surface == EGL_NO_SURFACE) { - return NULL; - } - - GLint gl2ContextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - EGLContext ctx = s_egl.eglCreateContext(p_dpy, config, - EGL_NO_CONTEXT, - gl2ContextAttribs); - if (ctx == EGL_NO_CONTEXT) { - s_egl.eglDestroySurface(p_dpy, surface); - return NULL; - } - - if (!s_egl.eglMakeCurrent(p_dpy, surface, surface, ctx)) { - s_egl.eglDestroySurface(p_dpy, surface); - s_egl.eglDestroyContext(p_dpy, ctx); - return NULL; - } - - // the string pointer may become invalid when the context is destroyed - const char* s = (const char*)s_gl2.glGetString(GL_EXTENSIONS); - char* extString = strdup(s ? s : ""); - - s_egl.eglMakeCurrent(p_dpy, NULL, NULL, NULL); - s_egl.eglDestroyContext(p_dpy, ctx); - s_egl.eglDestroySurface(p_dpy, surface); - - return extString; -} -#endif - -void FrameBuffer::finalize(){ - if(s_theFrameBuffer){ - s_theFrameBuffer->removeSubWindow(); - s_theFrameBuffer->m_colorbuffers.clear(); - s_theFrameBuffer->m_windows.clear(); - s_theFrameBuffer->m_contexts.clear(); - s_egl.eglMakeCurrent(s_theFrameBuffer->m_eglDisplay, NULL, NULL, NULL); - s_egl.eglDestroyContext(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_eglContext); - s_egl.eglDestroyContext(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_pbufContext); - s_egl.eglDestroySurface(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_pbufSurface); - s_theFrameBuffer = NULL; - } -} - -bool FrameBuffer::initialize(int width, int height) -{ - if (s_theFrameBuffer != NULL) { - return true; - } - - // - // allocate space for the FrameBuffer object - // - FrameBuffer *fb = new FrameBuffer(width, height); - if (!fb) { - ERR("Failed to create fb\n"); - return false; - } - -#ifdef WITH_GLES2 - // - // Try to load GLES2 Plugin, not mandatory - // - if (getenv("ANDROID_NO_GLES2")) { - fb->m_caps.hasGL2 = false; - } - else { - fb->m_caps.hasGL2 = s_gl2_enabled; - } -#else - fb->m_caps.hasGL2 = false; -#endif - - // - // Initialize backend EGL display - // - fb->m_eglDisplay = s_egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (fb->m_eglDisplay == EGL_NO_DISPLAY) { - ERR("Failed to Initialize backend EGL display\n"); - delete fb; - return false; - } - - if (!s_egl.eglInitialize(fb->m_eglDisplay, &fb->m_caps.eglMajor, &fb->m_caps.eglMinor)) { - ERR("Failed to eglInitialize\n"); - delete fb; - return false; - } - - DBG("egl: %d %d\n", fb->m_caps.eglMajor, fb->m_caps.eglMinor); - s_egl.eglBindAPI(EGL_OPENGL_ES_API); - - // - // if GLES2 plugin has loaded - try to make GLES2 context and - // get GLES2 extension string - // - char* gl2Extensions = NULL; -#ifdef WITH_GLES2 - if (fb->m_caps.hasGL2) { - gl2Extensions = getGLES2ExtensionString(fb->m_eglDisplay); - if (!gl2Extensions) { - // Could not create GLES2 context - drop GL2 capability - fb->m_caps.hasGL2 = false; - } - } -#endif - - // - // Create EGL context for framebuffer post rendering. - // -#if 0 - GLint configAttribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, - EGL_NONE - }; -#else - GLint configAttribs[] = { - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, - EGL_NONE - }; -#endif - - int n; - if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs, - &fb->m_eglConfig, 1, &n)) { - ERR("Failed on eglChooseConfig\n"); - free(gl2Extensions); - delete fb; - return false; - } - - GLint glContextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 1, - EGL_NONE - }; - - fb->m_eglContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglConfig, - EGL_NO_CONTEXT, - glContextAttribs); - if (fb->m_eglContext == EGL_NO_CONTEXT) { - printf("Failed to create Context 0x%x\n", s_egl.eglGetError()); - free(gl2Extensions); - delete fb; - return false; - } - - // - // Create another context which shares with the eglContext to be used - // when we bind the pbuffer. That prevent switching drawable binding - // back and forth on framebuffer context. - // The main purpose of it is to solve a "blanking" behaviour we see on - // on Mac platform when switching binded drawable for a context however - // it is more efficient on other platforms as well. - // - fb->m_pbufContext = s_egl.eglCreateContext(fb->m_eglDisplay, fb->m_eglConfig, - fb->m_eglContext, - glContextAttribs); - if (fb->m_pbufContext == EGL_NO_CONTEXT) { - printf("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError()); - free(gl2Extensions); - delete fb; - return false; - } - - // - // create a 1x1 pbuffer surface which will be used for binding - // the FB context. - // The FB output will go to a subwindow, if one exist. - // - EGLint pbufAttribs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE - }; - - fb->m_pbufSurface = s_egl.eglCreatePbufferSurface(fb->m_eglDisplay, - fb->m_eglConfig, - pbufAttribs); - if (fb->m_pbufSurface == EGL_NO_SURFACE) { - printf("Failed to create pbuf surface for FB 0x%x\n", s_egl.eglGetError()); - free(gl2Extensions); - delete fb; - return false; - } - - // Make the context current - if (!fb->bind_locked()) { - ERR("Failed to make current\n"); - free(gl2Extensions); - delete fb; - return false; - } - - // - // Initilize framebuffer capabilities - // - const char *glExtensions = (const char *)s_gl.glGetString(GL_EXTENSIONS); - bool has_gl_oes_image = false; - if (glExtensions) { - has_gl_oes_image = strstr(glExtensions, "GL_OES_EGL_image") != NULL; - } - - if (fb->m_caps.hasGL2 && has_gl_oes_image) { - has_gl_oes_image &= strstr(gl2Extensions, "GL_OES_EGL_image") != NULL; - } - free(gl2Extensions); - gl2Extensions = NULL; - - const char *eglExtensions = s_egl.eglQueryString(fb->m_eglDisplay, - EGL_EXTENSIONS); - - if (eglExtensions && has_gl_oes_image) { - fb->m_caps.has_eglimage_texture_2d = - strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image") != NULL; - fb->m_caps.has_eglimage_renderbuffer = - strstr(eglExtensions, "EGL_KHR_gl_renderbuffer_image") != NULL; - } - else { - fb->m_caps.has_eglimage_texture_2d = false; - fb->m_caps.has_eglimage_renderbuffer = false; - } - - // - // Fail initialization if not all of the following extensions - // exist: - // EGL_KHR_gl_texture_2d_image - // GL_OES_EGL_IMAGE (by both GLES implementations [1 and 2]) - // - if (!fb->m_caps.has_eglimage_texture_2d) { - ERR("Failed: Missing egl_image related extension(s)\n"); - delete fb; - return false; - } - - // - // Initialize set of configs - // - InitConfigStatus configStatus = FBConfig::initConfigList(fb); - if (configStatus == INIT_CONFIG_FAILED) { - ERR("Failed: Initialize set of configs\n"); - delete fb; - return false; - } - - // - // Check that we have config for each GLES and GLES2 - // - int nConfigs = FBConfig::getNumConfigs(); - int nGLConfigs = 0; - int nGL2Configs = 0; - for (int i=0; i<nConfigs; i++) { - GLint rtype = FBConfig::get(i)->getRenderableType(); - if (0 != (rtype & EGL_OPENGL_ES_BIT)) { - nGLConfigs++; - } - if (0 != (rtype & EGL_OPENGL_ES2_BIT)) { - nGL2Configs++; - } - } - - // - // Fail initialization if no GLES configs exist - // - if (nGLConfigs == 0) { - delete fb; - return false; - } - - // - // If no GLES2 configs exist - not GLES2 capability - // - if (nGL2Configs == 0) { - fb->m_caps.hasGL2 = false; - } - - // - // Initialize some GL state in the pbuffer context - // - fb->initGLState(); - - // - // Cache the GL strings so we don't have to think about threading or - // current-context when asked for them. - // - fb->m_glVendor = (const char*)s_gl.glGetString(GL_VENDOR); - fb->m_glRenderer = (const char*)s_gl.glGetString(GL_RENDERER); - fb->m_glVersion = (const char*)s_gl.glGetString(GL_VERSION); - - // release the FB context - fb->unbind_locked(); - - // - // Keep the singleton framebuffer pointer - // - s_theFrameBuffer = fb; - return true; -} - -FrameBuffer::FrameBuffer(int p_width, int p_height) : - m_width(p_width), - m_height(p_height), - m_eglDisplay(EGL_NO_DISPLAY), - m_eglSurface(EGL_NO_SURFACE), - m_eglContext(EGL_NO_CONTEXT), - m_pbufContext(EGL_NO_CONTEXT), - m_prevContext(EGL_NO_CONTEXT), - m_prevReadSurf(EGL_NO_SURFACE), - m_prevDrawSurf(EGL_NO_SURFACE), - m_subWin((EGLNativeWindowType)0), - m_subWinDisplay(NULL), - m_lastPostedColorBuffer(0), - m_zRot(0.0f), - m_eglContextInitialized(false), - m_statsNumFrames(0), - m_statsStartTime(0LL), - m_onPost(NULL), - m_onPostContext(NULL), - m_fbImage(NULL), - m_glVendor(NULL), - m_glRenderer(NULL), - m_glVersion(NULL) -{ - m_fpsStats = getenv("SHOW_FPS_STATS") != NULL; -} - -FrameBuffer::~FrameBuffer() -{ - free(m_fbImage); -} - -void FrameBuffer::setPostCallback(OnPostFn onPost, void* onPostContext) -{ - emugl::Mutex::AutoLock mutex(m_lock); - m_onPost = onPost; - m_onPostContext = onPostContext; - if (m_onPost && !m_fbImage) { - m_fbImage = (unsigned char*)malloc(4 * m_width * m_height); - if (!m_fbImage) { - ERR("out of memory, cancelling OnPost callback"); - m_onPost = NULL; - m_onPostContext = NULL; - return; - } - } -} - -bool FrameBuffer::setupSubWindow(FBNativeWindowType p_window, - int p_x, int p_y, - int p_width, int p_height, float zRot) -{ - bool success = false; - - if (s_theFrameBuffer) { - s_theFrameBuffer->m_lock.lock(); - FrameBuffer *fb = s_theFrameBuffer; - if (!fb->m_subWin) { - - // create native subwindow for FB display output - fb->m_subWin = createSubWindow(p_window, - &fb->m_subWinDisplay, - p_x,p_y,p_width,p_height); - if (fb->m_subWin) { - fb->m_nativeWindow = p_window; - - // create EGLSurface from the generated subwindow - fb->m_eglSurface = s_egl.eglCreateWindowSurface(fb->m_eglDisplay, - fb->m_eglConfig, - fb->m_subWin, - NULL); - - if (fb->m_eglSurface == EGL_NO_SURFACE) { - ERR("Failed to create surface\n"); - destroySubWindow(fb->m_subWinDisplay, fb->m_subWin); - fb->m_subWin = (EGLNativeWindowType)0; - } - else if (fb->bindSubwin_locked()) { - // Subwin creation was successfull, - // update viewport and z rotation and draw - // the last posted color buffer. - s_gl.glViewport(0, 0, p_width, p_height); - fb->m_zRot = zRot; - fb->post( fb->m_lastPostedColorBuffer, false ); - fb->unbind_locked(); - success = true; - } - } - } - s_theFrameBuffer->m_lock.unlock(); - } - - return success; -} - -bool FrameBuffer::removeSubWindow() -{ - bool removed = false; - if (s_theFrameBuffer) { - s_theFrameBuffer->m_lock.lock(); - if (s_theFrameBuffer->m_subWin) { - s_egl.eglMakeCurrent(s_theFrameBuffer->m_eglDisplay, NULL, NULL, NULL); - s_egl.eglDestroySurface(s_theFrameBuffer->m_eglDisplay, - s_theFrameBuffer->m_eglSurface); - destroySubWindow(s_theFrameBuffer->m_subWinDisplay, - s_theFrameBuffer->m_subWin); - - s_theFrameBuffer->m_eglSurface = EGL_NO_SURFACE; - s_theFrameBuffer->m_subWin = (EGLNativeWindowType)0; - removed = true; - } - s_theFrameBuffer->m_lock.unlock(); - } - return removed; -} - -HandleType FrameBuffer::genHandle() -{ - HandleType id; - do { - id = ++s_nextHandle; - } while( id == 0 || - m_contexts.find(id) != m_contexts.end() || - m_windows.find(id) != m_windows.end() ); - - return id; -} - -HandleType FrameBuffer::createColorBuffer(int p_width, int p_height, - GLenum p_internalFormat) -{ - emugl::Mutex::AutoLock mutex(m_lock); - HandleType ret = 0; - - ColorBufferPtr cb( ColorBuffer::create(p_width, p_height, p_internalFormat) ); - if (cb.Ptr() != NULL) { - ret = genHandle(); - m_colorbuffers[ret].cb = cb; - m_colorbuffers[ret].refcount = 1; - } - return ret; -} - -HandleType FrameBuffer::createRenderContext(int p_config, HandleType p_share, - bool p_isGL2) -{ - emugl::Mutex::AutoLock mutex(m_lock); - HandleType ret = 0; - - RenderContextPtr share(NULL); - if (p_share != 0) { - RenderContextMap::iterator s( m_contexts.find(p_share) ); - if (s == m_contexts.end()) { - return 0; - } - share = (*s).second; - } - - RenderContextPtr rctx( RenderContext::create(p_config, share, p_isGL2) ); - if (rctx.Ptr() != NULL) { - ret = genHandle(); - m_contexts[ret] = rctx; - } - return ret; -} - -HandleType FrameBuffer::createWindowSurface(int p_config, int p_width, int p_height) -{ - emugl::Mutex::AutoLock mutex(m_lock); - - HandleType ret = 0; - WindowSurfacePtr win( WindowSurface::create(p_config, p_width, p_height) ); - if (win.Ptr() != NULL) { - ret = genHandle(); - m_windows[ret] = win; - } - - return ret; -} - -void FrameBuffer::DestroyRenderContext(HandleType p_context) -{ - emugl::Mutex::AutoLock mutex(m_lock); - m_contexts.erase(p_context); -} - -void FrameBuffer::DestroyWindowSurface(HandleType p_surface) -{ - emugl::Mutex::AutoLock mutex(m_lock); - m_windows.erase(p_surface); -} - -int FrameBuffer::openColorBuffer(HandleType p_colorbuffer) -{ - emugl::Mutex::AutoLock mutex(m_lock); - ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); - if (c == m_colorbuffers.end()) { - // bad colorbuffer handle - ERR("FB: openColorBuffer cb handle %#x not found\n", p_colorbuffer); - return -1; - } - (*c).second.refcount++; - return 0; -} - -void FrameBuffer::closeColorBuffer(HandleType p_colorbuffer) -{ - emugl::Mutex::AutoLock mutex(m_lock); - ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer)); - if (c == m_colorbuffers.end()) { - ERR("FB: closeColorBuffer cb handle %#x not found\n", p_colorbuffer); - // bad colorbuffer handle - return; - } - if (--(*c).second.refcount == 0) { - m_colorbuffers.erase(c); - } -} - -bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface) -{ - emugl::Mutex::AutoLock mutex(m_lock); - - WindowSurfaceMap::iterator w( m_windows.find(p_surface) ); - if (w == m_windows.end()) { - ERR("FB::flushWindowSurfaceColorBuffer: window handle %#x not found\n", p_surface); - // bad surface handle - return false; - } - - return (*w).second->flushColorBuffer(); -} - -bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface, - HandleType p_colorbuffer) -{ - emugl::Mutex::AutoLock mutex(m_lock); - - WindowSurfaceMap::iterator w( m_windows.find(p_surface) ); - if (w == m_windows.end()) { - // bad surface handle - ERR("%s: bad window surface handle %#x\n", __FUNCTION__, p_surface); - return false; - } - - ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); - if (c == m_colorbuffers.end()) { - ERR("%s: bad color buffer handle %#x\n", __FUNCTION__, p_colorbuffer); - // bad colorbuffer handle - return false; - } - - (*w).second->setColorBuffer( (*c).second.cb ); - - return true; -} - -bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer, - int x, int y, int width, int height, - GLenum format, GLenum type, void *pixels) -{ - emugl::Mutex::AutoLock mutex(m_lock); - - ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); - if (c == m_colorbuffers.end()) { - // bad colorbuffer handle - return false; - } - - (*c).second.cb->subUpdate(x, y, width, height, format, type, pixels); - - return true; -} - -bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) -{ - emugl::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.cb->bindToTexture(); -} - -bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) -{ - emugl::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.cb->bindToRenderbuffer(); -} - -bool FrameBuffer::bindContext(HandleType p_context, - HandleType p_drawSurface, - HandleType p_readSurface) -{ - emugl::Mutex::AutoLock mutex(m_lock); - - WindowSurfacePtr draw(NULL), read(NULL); - RenderContextPtr ctx(NULL); - - // - // if this is not an unbind operation - make sure all handles are good - // - if (p_context || p_drawSurface || p_readSurface) { - RenderContextMap::iterator r( m_contexts.find(p_context) ); - if (r == m_contexts.end()) { - // bad context handle - return false; - } - - ctx = (*r).second; - WindowSurfaceMap::iterator w( m_windows.find(p_drawSurface) ); - if (w == m_windows.end()) { - // bad surface handle - return false; - } - draw = (*w).second; - - if (p_readSurface != p_drawSurface) { - WindowSurfaceMap::iterator w( m_windows.find(p_readSurface) ); - if (w == m_windows.end()) { - // bad surface handle - return false; - } - read = (*w).second; - } - else { - read = draw; - } - } - - if (!s_egl.eglMakeCurrent(m_eglDisplay, - draw ? draw->getEGLSurface() : EGL_NO_SURFACE, - read ? read->getEGLSurface() : EGL_NO_SURFACE, - ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT)) { - ERR("eglMakeCurrent failed\n"); - return false; - } - - // - // Bind the surface(s) to the context - // - RenderThreadInfo *tinfo = RenderThreadInfo::get(); - WindowSurfacePtr bindDraw, bindRead; - if (draw.Ptr() == NULL && read.Ptr() == NULL) { - // Unbind the current read and draw surfaces from the context - bindDraw = tinfo->currDrawSurf; - bindRead = tinfo->currReadSurf; - } else { - bindDraw = draw; - bindRead = read; - } - - if (bindDraw.Ptr() != NULL && bindRead.Ptr() != NULL) { - if (bindDraw.Ptr() != bindRead.Ptr()) { - bindDraw->bind(ctx, SURFACE_BIND_DRAW); - bindRead->bind(ctx, SURFACE_BIND_READ); - } - else { - bindDraw->bind(ctx, SURFACE_BIND_READDRAW); - } - } - - // - // update thread info with current bound context - // - tinfo->currContext = ctx; - tinfo->currDrawSurf = draw; - tinfo->currReadSurf = read; - if (ctx) { - if (ctx->isGL2()) tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData()); - else tinfo->m_glDec.setContextData(&ctx->decoderContextData()); - } - else { - tinfo->m_glDec.setContextData(NULL); - tinfo->m_gl2Dec.setContextData(NULL); - } - return true; -} - -// -// The framebuffer lock should be held when calling this function ! -// -bool FrameBuffer::bind_locked() -{ - EGLContext prevContext = s_egl.eglGetCurrentContext(); - EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); - EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); - - if (!s_egl.eglMakeCurrent(m_eglDisplay, m_pbufSurface, - m_pbufSurface, m_pbufContext)) { - ERR("eglMakeCurrent failed\n"); - return false; - } - - m_prevContext = prevContext; - m_prevReadSurf = prevReadSurf; - m_prevDrawSurf = prevDrawSurf; - return true; -} - -bool FrameBuffer::bindSubwin_locked() -{ - EGLContext prevContext = s_egl.eglGetCurrentContext(); - EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); - EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); - - if (!s_egl.eglMakeCurrent(m_eglDisplay, m_eglSurface, - m_eglSurface, m_eglContext)) { - ERR("eglMakeCurrent failed\n"); - return false; - } - - // - // initialize GL state in eglContext if not yet initilaized - // - if (!m_eglContextInitialized) { - initGLState(); - m_eglContextInitialized = true; - } - - m_prevContext = prevContext; - m_prevReadSurf = prevReadSurf; - m_prevDrawSurf = prevDrawSurf; - return true; -} - -bool FrameBuffer::unbind_locked() -{ - if (!s_egl.eglMakeCurrent(m_eglDisplay, m_prevDrawSurf, - m_prevReadSurf, m_prevContext)) { - return false; - } - - m_prevContext = EGL_NO_CONTEXT; - m_prevReadSurf = EGL_NO_SURFACE; - m_prevDrawSurf = EGL_NO_SURFACE; - return true; -} - -bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock) -{ - if (needLock) m_lock.lock(); - bool ret = false; - - ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); - if (c != m_colorbuffers.end()) { - - m_lastPostedColorBuffer = p_colorbuffer; - if (!m_subWin) { - // no subwindow created for the FB output - // cannot post the colorbuffer - if (needLock) m_lock.unlock(); - return ret; - } - - - // bind the subwindow eglSurface - if (!bindSubwin_locked()) { - ERR("FrameBuffer::post eglMakeCurrent failed\n"); - if (needLock) m_lock.unlock(); - return false; - } - - // - // render the color buffer to the window - // - s_gl.glPushMatrix(); - s_gl.glRotatef(m_zRot, 0.0f, 0.0f, 1.0f); - if (m_zRot != 0.0f) { - s_gl.glClear(GL_COLOR_BUFFER_BIT); - } - ret = (*c).second.cb->post(); - s_gl.glPopMatrix(); - - if (ret) { - // - // output FPS statistics - // - if (m_fpsStats) { - long long currTime = GetCurrentTimeMS(); - m_statsNumFrames++; - if (currTime - m_statsStartTime >= 1000) { - float dt = (float)(currTime - m_statsStartTime) / 1000.0f; - printf("FPS: %5.3f\n", (float)m_statsNumFrames / dt); - m_statsStartTime = currTime; - m_statsNumFrames = 0; - } - } - - s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface); - } - - // restore previous binding - unbind_locked(); - - // - // Send framebuffer (without FPS overlay) to callback - // - if (m_onPost) { - (*c).second.cb->readback(m_fbImage); - m_onPost(m_onPostContext, m_width, m_height, -1, - GL_RGBA, GL_UNSIGNED_BYTE, m_fbImage); - } - - } - - if (needLock) m_lock.unlock(); - return ret; -} - -bool FrameBuffer::repost() -{ - if (m_lastPostedColorBuffer) { - return post( m_lastPostedColorBuffer ); - } - return false; -} - -void FrameBuffer::initGLState() -{ - s_gl.glMatrixMode(GL_PROJECTION); - s_gl.glLoadIdentity(); - s_gl.glOrthof(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); - s_gl.glMatrixMode(GL_MODELVIEW); - s_gl.glLoadIdentity(); -} |