/*
* 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 <stdio.h>
#include "TimeUtils.h"

FrameBuffer *FrameBuffer::s_theFrameBuffer = NULL;
HandleType FrameBuffer::s_nextHandle = 0;

#ifdef WITH_GLES2
static const 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;
    }

    const char *extString = (const char *)s_gl2.glGetString(GL_EXTENSIONS);
    if (!extString) {
        extString = "";
    }

    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.eglDestroyContext(s_theFrameBuffer->m_eglDisplay,s_theFrameBuffer->m_eglContext);
        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;
    }

    //
    // Load EGL Plugin
    //
    if (!init_egl_dispatch()) {
        // Failed to load EGL
        printf("Failed to init_egl_dispatch\n");
        return false;
    }

    //
    // Load GLES Plugin
    //
    if (!init_gl_dispatch()) {
        // Failed to load GLES
        ERR("Failed to init_gl_dispatch\n");
        return false;
    }

    //
    // 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 = init_gl2_dispatch();
    }
#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
    //
    const 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");
        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());
        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());
        delete fb;
        return false;
    }

    // Make the context current
    if (!fb->bind_locked()) {
        ERR("Failed to make current\n");
        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);
    }

    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
    //
    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();

    // 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_prevContext(EGL_NO_CONTEXT),
    m_prevReadSurf(EGL_NO_SURFACE),
    m_prevDrawSurf(EGL_NO_SURFACE),
    m_subWin(NULL),
    m_subWinDisplay(NULL),
    m_lastPostedColorBuffer(0),
    m_zRot(0.0f),
    m_statsNumFrames(0),
    m_statsStartTime(0LL)
{
    m_fpsStats = getenv("SHOW_FPS_STATS") != NULL;
}

FrameBuffer::~FrameBuffer()
{
}

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 = NULL;
                }
                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 = NULL;
            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)
{
    android::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;
    }
    return ret;
}

HandleType FrameBuffer::createRenderContext(int p_config, HandleType p_share,
                                            bool p_isGL2)
{
    android::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)
{
    android::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)
{
    android::Mutex::Autolock mutex(m_lock);
    m_contexts.erase(p_context);
}

void FrameBuffer::DestroyWindowSurface(HandleType p_surface)
{
    android::Mutex::Autolock mutex(m_lock);
    m_windows.erase(p_surface);
}

void FrameBuffer::DestroyColorBuffer(HandleType p_colorbuffer)
{
    android::Mutex::Autolock mutex(m_lock);
    m_colorbuffers.erase(p_colorbuffer);
}

bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface)
{
    android::Mutex::Autolock mutex(m_lock);

    WindowSurfaceMap::iterator w( m_windows.find(p_surface) );
    if (w == m_windows.end()) {
        // bad surface handle
        return false;
    }

    (*w).second->flushColorBuffer();

    return true;
}

bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface,
                                              HandleType p_colorbuffer)
{
    android::Mutex::Autolock mutex(m_lock);

    WindowSurfaceMap::iterator w( m_windows.find(p_surface) );
    if (w == m_windows.end()) {
        // bad surface handle
        return false;
    }

    ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
    if (c == m_colorbuffers.end()) {
        // bad colorbuffer handle
        return false;
    }

    (*w).second->setColorBuffer( (*c).second );

    return true;
}

bool FrameBuffer::updateColorBuffer(HandleType p_colorbuffer,
                                    int x, int y, int width, int height,
                                    GLenum format, GLenum type, void *pixels)
{
    android::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->subUpdate(x, y, width, height, format, type, pixels);

    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::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)
{
    android::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)) {
        // MakeCurrent failed
        return false;
    }

    //
    // Bind the surface(s) to the context
    //
    RenderThreadInfo *tinfo = getRenderThreadInfo();
    if (draw.Ptr() == NULL && read.Ptr() == NULL) {
        // if this is an unbind operation - make sure the current bound
        // surfaces get unbound from the context.
        draw = tinfo->currDrawSurf;
        read = tinfo->currReadSurf;
    }

    if (draw.Ptr() != NULL && read.Ptr() != NULL) {
        if (p_readSurface != p_drawSurface) {
            draw->bind( ctx, SURFACE_BIND_DRAW );
            read->bind( ctx, SURFACE_BIND_READ );
        }
        else {
            draw->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_eglContext)) {
        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;
    }

    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->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();
    }

    if (needLock) m_lock.unlock();
    return ret;
}

bool FrameBuffer::repost()
{
    if (m_lastPostedColorBuffer) {
        return post( m_lastPostedColorBuffer );
    }
    return false;
}
