/*
 * Copyright (C) 2015 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 "../gfx_api.h"
#include "../renderer.h"

#include <gapic/log.h>

#include <cstring>
#include <X11/Xresource.h>

namespace gapir {
namespace {

typedef XID GLXPbuffer;
typedef XID GLXDrawable;
typedef /*struct __GLXcontextRec*/ void *GLXContext;
typedef /*struct __GLXFBConfigRec*/ void *GLXFBConfig;

enum {
    // Used by glXChooseFBConfig.
    GLX_RED_SIZE      = 8,
    GLX_GREEN_SIZE    = 9,
    GLX_BLUE_SIZE     = 10,
    GLX_ALPHA_SIZE    = 11,
    GLX_DEPTH_SIZE    = 12,
    GLX_STENCIL_SIZE  = 13,
    GLX_DRAWABLE_TYPE = 0x8010,
    GLX_RENDER_TYPE   = 0x8011,
    GLX_RGBA_BIT      = 0x00000001,
    GLX_PBUFFER_BIT   = 0x00000004,

    // Used by glXCreateNewContext.
    GLX_RGBA_TYPE = 0x8014,

    // Used by glXCreatePbuffer.
    GLX_PBUFFER_HEIGHT = 0x8040,
    GLX_PBUFFER_WIDTH  = 0x8041
};

extern "C" {

GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attrib_list, int *nelements);
GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type,
                               GLXContext share_list, Bool direct);
GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list);
void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf);
Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
Bool glXQueryVersion(Display *dpy, int *maj, int *min);
void glXDestroyContext(Display *dpy, GLXContext ctx);

} // extern "C"

class RendererImpl : public Renderer {
public:
    RendererImpl();
    virtual ~RendererImpl() override;

    virtual void setBackbuffer(int width, int height, int depthSize, int stencilSize);
    virtual void bind() override;
    virtual void unbind() override;
    virtual const char* name() override;
    virtual const char* extensions() override;
    virtual const char* vendor() override;
    virtual const char* version() override;

private:
    void reset();
    void createPbuffer(int width, int height);

    int mWidth;
    int mHeight;
    int mDepthSize;
    int mStencilSize;
    bool mBound;

    Display *mDisplay;
    GLXContext mContext;
    GLXPbuffer mPbuffer;
    GLXFBConfig mFBConfig;
};

RendererImpl::RendererImpl()
        : mWidth(0)
        , mHeight(0)
        , mDepthSize(0)
        , mStencilSize(0)
        , mBound(false)
        , mDisplay(nullptr)
        , mContext(nullptr)
        , mPbuffer(0) {

    mDisplay = XOpenDisplay(nullptr);
    if (mDisplay == nullptr) {
        GAPID_FATAL("Unable to to open X display\n");
    }

    int major;
    int minor;
    if (!glXQueryVersion(mDisplay, &major, &minor) || (major == 1 && minor < 3)) {
        GAPID_FATAL("GLX 1.3+ unsupported by X server (was %d.%d)\n", major, minor);
    }

    // Initialize with a default target.
    setBackbuffer(8, 8, 24, 8);
}

RendererImpl::~RendererImpl() {
    reset();

    if (mDisplay != nullptr) {
        XCloseDisplay(mDisplay);
    }
}

void RendererImpl::reset() {
    unbind();

    if (mContext != nullptr) {
        glXDestroyContext(mDisplay, mContext);
        mContext = nullptr;
    }

    if (mPbuffer != 0) {
        glXDestroyPbuffer(mDisplay, mPbuffer);
        mPbuffer = 0;
    }

    mWidth = 0;
    mHeight = 0;
    mDepthSize = 0;
    mStencilSize = 0;
}

void RendererImpl::createPbuffer(int width, int height) {
    if (mPbuffer != 0) {
        glXDestroyPbuffer(mDisplay, mPbuffer);
        mPbuffer = 0;
    }
    const int pbufferAttribs[] = {
        GLX_PBUFFER_WIDTH, width,
        GLX_PBUFFER_HEIGHT, height,
        None
    };
    mPbuffer = glXCreatePbuffer(mDisplay, mFBConfig, pbufferAttribs);
}

void RendererImpl::setBackbuffer(int width, int height, int depthSize, int stencilSize) {
    if (mContext != nullptr &&
        mWidth == width &&
        mHeight == height &&
        mDepthSize == depthSize &&
        mStencilSize == stencilSize) {
        // No change
        return;
    }

    if (mContext != nullptr &&
        mDepthSize == depthSize &&
        mStencilSize == stencilSize) {
        // Resize only
        GAPID_INFO("Resizing renderer: %dx%d -> %dx%d\n", mWidth, mHeight, width, height);
        createPbuffer(width, height);
        glXMakeContextCurrent(mDisplay, mPbuffer, mPbuffer, mContext);
        mWidth = width;
        mHeight = height;
        return;
    }

    const bool wasBound = mBound;

    reset();

    const int visualAttribs[] = {
        GLX_RED_SIZE, 8,
        GLX_GREEN_SIZE, 8,
        GLX_BLUE_SIZE, 8,
        GLX_ALPHA_SIZE, 8,
        GLX_DEPTH_SIZE, depthSize,
        GLX_STENCIL_SIZE, stencilSize,
        GLX_RENDER_TYPE, GLX_RGBA_BIT,
        GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
        None
    };
    int fbConfigsCount;
    GLXFBConfig *fbConfigs = glXChooseFBConfig(
            mDisplay, DefaultScreen(mDisplay), visualAttribs, &fbConfigsCount);
    if (fbConfigs == nullptr) {
        GAPID_FATAL("Unable to find a suitable X framebuffer config\n");
    }
    mFBConfig = fbConfigs[0];
    XFree(fbConfigs);

    mContext = glXCreateNewContext(mDisplay, mFBConfig, GLX_RGBA_TYPE, nullptr, True);
    if (mContext == nullptr) {
        GAPID_FATAL("Failed to create glX context\n");
    }
    XSync(mDisplay, False);

    createPbuffer(width, height);

    mWidth = width;
    mHeight = height;
    mDepthSize = depthSize;
    mStencilSize = stencilSize;

    if (wasBound) {
        bind();
    }
}

void RendererImpl::bind() {
    if (!mBound) {
        if (!glXMakeContextCurrent(mDisplay, mPbuffer, mPbuffer, mContext)) {
            GAPID_FATAL("Unable to make GLX context current\n");
        }

        mBound = true;

        // Initialize the graphics API
        // TODO: Inefficient - consider moving the imports into this renderer
        gfxapi::Initialize();
    }
}

void RendererImpl::unbind() {
    if (mBound) {
        // TODO: glXMakeContextCurrent(...)
        mBound = false;
    }
}

const char* RendererImpl::name() {
    return reinterpret_cast<const char*>(
        gfxapi::glGetString(gfxapi::GLenum::GL_RENDERER));
}

const char* RendererImpl::extensions() {
    return reinterpret_cast<const char*>(
        gfxapi::glGetString(gfxapi::GLenum::GL_EXTENSIONS));
}

const char* RendererImpl::vendor() {
    return reinterpret_cast<const char*>(
        gfxapi::glGetString(gfxapi::GLenum::GL_VENDOR));
}

const char* RendererImpl::version() {
    return reinterpret_cast<const char*>(
        gfxapi::glGetString(gfxapi::GLenum::GL_VERSION));
}

} // anonymous namespace

Renderer* Renderer::create() {
    return new RendererImpl();
}

}  // namespace gapir

