/*
* 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 "EglOsApi.h"

#include "emugl/common/lazy_instance.h"
#include "emugl/common/mutex.h"
#include "emugl/common/shared_library.h"
#include "GLcommon/GLLibrary.h"

#include "OpenglCodecCommon/ErrorLog.h"

#include <string.h>
#include <X11/Xlib.h>
#include <GL/glx.h>

namespace {

typedef Display X11Display;

class ErrorHandler{
public:
    ErrorHandler(EGLNativeDisplayType dpy);
    ~ErrorHandler();
    int getLastError() const { return s_lastErrorCode; }

private:
    static int s_lastErrorCode;
    int (*m_oldErrorHandler)(Display *, XErrorEvent *) = nullptr;
    static emugl::Mutex s_lock;
    static int errorHandlerProc(EGLNativeDisplayType dpy,XErrorEvent* event);
};

// static
int ErrorHandler::s_lastErrorCode = 0;

// static
emugl::Mutex ErrorHandler::s_lock;

ErrorHandler::ErrorHandler(EGLNativeDisplayType dpy) {
   emugl::Mutex::AutoLock mutex(s_lock);
   XSync(dpy,False);
   s_lastErrorCode = 0;
   m_oldErrorHandler = XSetErrorHandler(errorHandlerProc);
}

ErrorHandler::~ErrorHandler() {
   emugl::Mutex::AutoLock mutex(s_lock);
   XSetErrorHandler(m_oldErrorHandler);
   s_lastErrorCode = 0;
}

int ErrorHandler::errorHandlerProc(EGLNativeDisplayType dpy,
                                   XErrorEvent* event) {
    s_lastErrorCode = event->error_code;
    return 0;
}

#define IS_SUCCESS(a) \
        do { if (a != Success) return 0; } while (0)

#define EXIT_IF_FALSE(a) \
        do { if (a != Success) return; } while (0)

// Implementation of EglOS::PixelFormat based on GLX.
class GlxPixelFormat : public EglOS::PixelFormat {
public:
    explicit GlxPixelFormat(GLXFBConfig fbconfig) : mFbConfig(fbconfig) {}

    virtual EglOS::PixelFormat* clone() {
        return new GlxPixelFormat(mFbConfig);
    }

    GLXFBConfig fbConfig() const { return mFbConfig; }

    static GLXFBConfig from(const EglOS::PixelFormat* f) {
        return static_cast<const GlxPixelFormat*>(f)->fbConfig();
    }

private:
    GLXFBConfig mFbConfig = nullptr;
};

void pixelFormatToConfig(EGLNativeDisplayType dpy,
                         int renderableType,
                         GLXFBConfig frmt,
                         EglOS::AddConfigCallback* addConfigFunc,
                         void* addConfigOpaque) {
    EglOS::ConfigInfo info;
    int  tmp;

    memset(&info, 0, sizeof(info));

    EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_TRANSPARENT_TYPE, &tmp));
    if (tmp == GLX_TRANSPARENT_INDEX) {
        return; // not supporting transparent index
    } else if (tmp == GLX_NONE) {
        info.transparent_type = EGL_NONE;
        info.trans_red_val = 0;
        info.trans_green_val = 0;
        info.trans_blue_val = 0;
    } else {
        info.transparent_type = EGL_TRANSPARENT_RGB;

        EXIT_IF_FALSE(glXGetFBConfigAttrib(
                dpy, frmt, GLX_TRANSPARENT_RED_VALUE, &info.trans_red_val));
        EXIT_IF_FALSE(glXGetFBConfigAttrib(
                dpy, frmt, GLX_TRANSPARENT_GREEN_VALUE, &info.trans_green_val));
        EXIT_IF_FALSE(glXGetFBConfigAttrib(
                dpy, frmt, GLX_TRANSPARENT_BLUE_VALUE, &info.trans_blue_val));
    }

    //
    // filter out single buffer configurations
    //
    int doubleBuffer = 0;
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_DOUBLEBUFFER, &doubleBuffer));
    if (!doubleBuffer) {
        return;
    }

    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy ,frmt, GLX_RED_SIZE, &info.red_size));
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy ,frmt, GLX_GREEN_SIZE, &info.green_size));
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy ,frmt, GLX_BLUE_SIZE, &info.blue_size));
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy ,frmt, GLX_ALPHA_SIZE, &info.alpha_size));
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy ,frmt, GLX_DEPTH_SIZE, &info.depth_size));
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy ,frmt, GLX_STENCIL_SIZE, &info.stencil_size));

    info.renderable_type = renderableType;
    int nativeRenderable = 0;
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_X_RENDERABLE, &nativeRenderable));
    info.native_renderable = !!nativeRenderable;

    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_X_VISUAL_TYPE, &info.native_visual_type));

    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_VISUAL_ID, &info.native_visual_id));

    //supported surfaces types
    info.surface_type = 0;
    EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_DRAWABLE_TYPE, &tmp));
    if (tmp & GLX_WINDOW_BIT && info.native_visual_id != 0) {
        info.surface_type |= EGL_WINDOW_BIT;
    } else {
        info.native_visual_id = 0;
        info.native_visual_type = EGL_NONE;
    }
    if (tmp & GLX_PBUFFER_BIT) {
        info.surface_type |= EGL_PBUFFER_BIT;
    }

    info.caveat = 0;
    EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_CONFIG_CAVEAT, &tmp));
    if (tmp == GLX_NONE) {
        info.caveat = EGL_NONE;
    } else if (tmp == GLX_SLOW_CONFIG) {
        info.caveat = EGL_SLOW_CONFIG;
    } else if (tmp == GLX_NON_CONFORMANT_CONFIG) {
        info.caveat = EGL_NON_CONFORMANT_CONFIG;
    }
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_MAX_PBUFFER_WIDTH, &info.max_pbuffer_width));
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_height));
    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_MAX_PBUFFER_HEIGHT, &info.max_pbuffer_size));

    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_LEVEL, &info.frame_buffer_level));

    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_FBCONFIG_ID, &info.config_id));

    EXIT_IF_FALSE(glXGetFBConfigAttrib(
            dpy, frmt, GLX_SAMPLES, &info.samples_per_pixel));

    // Filter out configs that do not support RGBA
    EXIT_IF_FALSE(glXGetFBConfigAttrib(dpy, frmt, GLX_RENDER_TYPE, &tmp));
    if (!(tmp & GLX_RGBA_BIT)) {
        return;
    }
    // Filter out configs that do not support depthstencil buffers
    // For dEQP-GLES2.functional.depth_stencil_clear
    // and dEQP-GLES2.usecases.*
    if (info.depth_size == 0 || info.stencil_size == 0) {
        return;
    }

    info.frmt = new GlxPixelFormat(frmt);

    (*addConfigFunc)(addConfigOpaque, &info);
}

// Implementation of EglOS::Surface based on GLX.
class GlxSurface : public EglOS::Surface {
public:
    GlxSurface(GLXDrawable drawable, SurfaceType type) :
            Surface(type), mDrawable(drawable) {}

    GLXDrawable drawable() const { return mDrawable; }

    // Helper routine to down-cast an EglOS::Surface and extract
    // its drawable.
    static GLXDrawable drawableFor(EglOS::Surface* surface) {
        return static_cast<GlxSurface*>(surface)->drawable();
    }

private:
    GLXDrawable mDrawable = 0;
};

// Implementation of EglOS::Context based on GLX.
class GlxContext : public EglOS::Context {
public:
    explicit GlxContext(GLXContext context) : mContext(context) {}

    GLXContext context() const { return mContext; }

    static GLXContext contextFor(EglOS::Context* context) {
        return static_cast<GlxContext*>(context)->context();
    }
private:
    GLXContext mContext = nullptr;
};

// Implementation of EglOS::Display based on GLX.
class GlxDisplay : public EglOS::Display {
public:
    explicit GlxDisplay(X11Display* disp) : mDisplay(disp) {}

    virtual ~GlxDisplay() { XCloseDisplay(mDisplay); }

    virtual void queryConfigs(int renderableType,
                              EglOS::AddConfigCallback* addConfigFunc,
                              void* addConfigOpaque) {
        int n;
        GLXFBConfig* frmtList = glXGetFBConfigs(mDisplay, 0, &n);
        if (frmtList) {
            for(int i = 0; i < n; i++) {
                pixelFormatToConfig(
                        mDisplay,
                        renderableType,
                        frmtList[i],
                        addConfigFunc,
                        addConfigOpaque);
            }
            XFree(frmtList);
        }
    }

    virtual bool isValidNativeWin(EglOS::Surface* win) {
        if (!win) {
            return false;
        } else {
            return isValidNativeWin(GlxSurface::drawableFor(win));
        }
    }

    virtual bool isValidNativeWin(EGLNativeWindowType win) {
        Window root;
        int t;
        unsigned int u;
        ErrorHandler handler(mDisplay);
        if (!XGetGeometry(mDisplay, win, &root, &t, &t, &u, &u, &u, &u)) {
            return false;
        }
        return handler.getLastError() == 0;
    }

    virtual bool checkWindowPixelFormatMatch(
            EGLNativeWindowType win,
            const EglOS::PixelFormat* pixelFormat,
            unsigned int* width,
            unsigned int* height) {
        //TODO: to check what does ATI & NVIDIA enforce on win pixelformat
        unsigned int depth, configDepth, border;
        int r, g, b, x, y;
        GLXFBConfig fbconfig = GlxPixelFormat::from(pixelFormat);

        IS_SUCCESS(glXGetFBConfigAttrib(
                mDisplay, fbconfig, GLX_RED_SIZE, &r));
        IS_SUCCESS(glXGetFBConfigAttrib(
                mDisplay, fbconfig, GLX_GREEN_SIZE, &g));
        IS_SUCCESS(glXGetFBConfigAttrib(
                mDisplay, fbconfig, GLX_BLUE_SIZE, &b));
        configDepth = r + g + b;
        Window root;
        if (!XGetGeometry(
                mDisplay, win, &root, &x, &y, width, height, &border, &depth)) {
            return false;
        }
        return depth >= configDepth;
    }

    virtual EglOS::Context* createContext(
            const EglOS::PixelFormat* pixelFormat,
            EglOS::Context* sharedContext) {
        ErrorHandler handler(mDisplay);
        GLXContext ctx = glXCreateNewContext(
                mDisplay,
                GlxPixelFormat::from(pixelFormat),
                GLX_RGBA_TYPE,
                sharedContext ? GlxContext::contextFor(sharedContext) : NULL,
                true);

        if (handler.getLastError()) {
            return NULL;
        }

        return new GlxContext(ctx);
    }

    virtual bool destroyContext(EglOS::Context* context) {
        glXDestroyContext(mDisplay, GlxContext::contextFor(context));
        return true;
    }

    virtual EglOS::Surface* createPbufferSurface(
            const EglOS::PixelFormat* pixelFormat,
            const EglOS::PbufferInfo* info) {
        const int attribs[] = {
            GLX_PBUFFER_WIDTH, info->width,
            GLX_PBUFFER_HEIGHT, info->height,
            GLX_LARGEST_PBUFFER, info->largest,
            None
        };
        GLXPbuffer pb = glXCreatePbuffer(
                mDisplay,
                GlxPixelFormat::from(pixelFormat),
                attribs);
        return pb ? new GlxSurface(pb, GlxSurface::PBUFFER) : NULL;
    }

    virtual bool releasePbuffer(EglOS::Surface* pb) {
        if (!pb) {
            return false;
        } else {
            glXDestroyPbuffer(mDisplay, GlxSurface::drawableFor(pb));
            return true;
        }
    }

    virtual bool makeCurrent(EglOS::Surface* read,
                             EglOS::Surface* draw,
                             EglOS::Context* context) {
        ErrorHandler handler(mDisplay);
        bool retval = false;
        if (!context && !read && !draw) {
            // unbind
            retval = glXMakeContextCurrent(mDisplay, 0, 0, NULL);
        }
        else if (context && read && draw) {
            retval = glXMakeContextCurrent(
                    mDisplay,
                    GlxSurface::drawableFor(draw),
                    GlxSurface::drawableFor(read),
                    GlxContext::contextFor(context));
        }
        return (handler.getLastError() == 0) && retval;
    }

    virtual void swapBuffers(EglOS::Surface* srfc) {
        if (srfc) {
            glXSwapBuffers(mDisplay, GlxSurface::drawableFor(srfc));
        }
    }

private:
    X11Display* mDisplay = nullptr;
};

class GlxLibrary : public GlLibrary {
public:
    typedef GlFunctionPointer (ResolverFunc)(const char* name);

    // Important: Use libGL.so.1 explicitly, because it will always link to
    // the vendor-specific version of the library. libGL.so might in some
    // cases, depending on bad ldconfig configurations, link to the wrapper
    // lib that doesn't behave the same.
    GlxLibrary() {
        static const char kLibName[] = "libGL.so.1";
        char error[256];
        mLib = emugl::SharedLibrary::open(kLibName, error, sizeof(error));
        if (!mLib) {
            ERR("%s: Could not open GL library %s [%s]\n",
                __FUNCTION__, kLibName, error);
            return;
        }
        // NOTE: Don't use glXGetProcAddress here, only glXGetProcAddressARB
        // is guaranteed to be supported by vendor-specific libraries.
        static const char kResolverName[] = "glXGetProcAddressARB";
        mResolver = reinterpret_cast<ResolverFunc*>(
                mLib->findSymbol(kResolverName));
        if (!mResolver) {
            ERR("%s: Could not find resolver %s in %s\n",
                __FUNCTION__, kResolverName, kLibName);
            delete mLib;
            mLib = NULL;
        }
    }

    ~GlxLibrary() {
        delete mLib;
    }

    // override
    virtual GlFunctionPointer findSymbol(const char* name) {
        if (!mLib) {
            return NULL;
        }
        GlFunctionPointer ret = (*mResolver)(name);
        if (!ret) {
            ret = reinterpret_cast<GlFunctionPointer>(mLib->findSymbol(name));
        }
        return ret;
    }

private:
    emugl::SharedLibrary* mLib = nullptr;
    ResolverFunc* mResolver = nullptr;
};

class GlxEngine : public EglOS::Engine {
public:
    virtual EglOS::Display* getDefaultDisplay() {
        return new GlxDisplay(XOpenDisplay(0));
    }

    virtual GlLibrary* getGlLibrary() {
        return &mGlLib;
    }

    virtual EglOS::Surface* createWindowSurface(EGLNativeWindowType wnd) {
        return new GlxSurface(wnd, GlxSurface::WINDOW);
    }
private:
    GlxLibrary mGlLib;
};

emugl::LazyInstance<GlxEngine> sHostEngine = LAZY_INSTANCE_INIT;

}  // namespace

// static
EglOS::Engine* EglOS::Engine::getHostInstance() {
    return sHostEngine.ptr();
}
