//
// Copyright 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// WindowSurfaceGLX.cpp: GLX implementation of egl::Surface for windows

#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"

#include "common/debug.h"

#include "libANGLE/renderer/gl/glx/DisplayGLX.h"
#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"

namespace rx
{

static int IgnoreX11Errors(Display *, XErrorEvent *)
{
    return 0;
}

WindowSurfaceGLX::WindowSurfaceGLX(const egl::SurfaceState &state,
                                   const FunctionsGLX &glx,
                                   DisplayGLX *glxDisplay,
                                   Window window,
                                   Display *display,
                                   glx::FBConfig fbConfig)
    : SurfaceGLX(state),
      mParent(window),
      mWindow(0),
      mDisplay(display),
      mGLX(glx),
      mGLXDisplay(glxDisplay),
      mFBConfig(fbConfig),
      mGLXWindow(0)
{}

WindowSurfaceGLX::~WindowSurfaceGLX()
{
    if (mGLXWindow)
    {
        mGLX.destroyWindow(mGLXWindow);
    }

    if (mWindow)
    {
        // When destroying the window, it may happen that the window has already been
        // destroyed by the application (this happens in Chromium). There is no way to
        // atomically check that a window exists and to destroy it so instead we call
        // XDestroyWindow, ignoring any errors.
        auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
        XDestroyWindow(mDisplay, mWindow);
        XSync(mDisplay, False);
        XSetErrorHandler(oldErrorHandler);
    }

    mGLXDisplay->syncXCommands();
}

egl::Error WindowSurfaceGLX::initialize(const egl::Display *display)
{
    // Check that the window's visual ID is valid, as part of the AMGLE_x11_visual
    // extension.
    {
        XWindowAttributes windowAttributes;
        XGetWindowAttributes(mDisplay, mParent, &windowAttributes);
        unsigned long visualId = windowAttributes.visual->visualid;

        if (!mGLXDisplay->isValidWindowVisualId(visualId))
        {
            return egl::EglBadMatch() << "The visual of native_window doesn't match the visual "
                                         "given with ANGLE_X11_VISUAL_ID";
        }
    }

    // The visual of the X window, GLX window and GLX context must match,
    // however we received a user-created window that can have any visual
    // and wouldn't work with our GLX context. To work in all cases, we
    // create a child window with the right visual that covers all of its
    // parent.
    XVisualInfo *visualInfo = mGLX.getVisualFromFBConfig(mFBConfig);
    if (!visualInfo)
    {
        return egl::EglBadNativeWindow() << "Failed to get the XVisualInfo for the child window.";
    }
    Visual *visual = visualInfo->visual;

    if (!getWindowDimensions(mParent, &mParentWidth, &mParentHeight))
    {
        return egl::EglBadNativeWindow() << "Failed to get the parent window's dimensions.";
    }

    // The depth, colormap and visual must match otherwise we get a X error
    // so we specify the colormap attribute. Also we do not want the window
    // to be taken into account for input so we specify the event and
    // do-not-propagate masks to 0 (the defaults). Finally we specify the
    // border pixel attribute so that we can use a different visual depth
    // than our parent (seems like X uses that as a condition to render
    // the subwindow in a different buffer)
    XSetWindowAttributes attributes;
    unsigned long attributeMask = CWColormap | CWBorderPixel;

    Colormap colormap = XCreateColormap(mDisplay, mParent, visual, AllocNone);
    if (!colormap)
    {
        XFree(visualInfo);
        return egl::EglBadNativeWindow() << "Failed to create the Colormap for the child window.";
    }
    attributes.colormap     = colormap;
    attributes.border_pixel = 0;

    // TODO(cwallez) set up our own error handler to see if the call failed
    mWindow    = XCreateWindow(mDisplay, mParent, 0, 0, mParentWidth, mParentHeight, 0,
                            visualInfo->depth, InputOutput, visual, attributeMask, &attributes);
    mGLXWindow = mGLX.createWindow(mFBConfig, mWindow, nullptr);

    XMapWindow(mDisplay, mWindow);
    XFlush(mDisplay);

    XFree(visualInfo);
    XFreeColormap(mDisplay, colormap);

    mGLXDisplay->syncXCommands();

    return egl::NoError();
}

egl::Error WindowSurfaceGLX::makeCurrent(const gl::Context *context)
{
    return egl::NoError();
}

egl::Error WindowSurfaceGLX::swap(const gl::Context *context)
{
    // We need to swap before resizing as some drivers clobber the back buffer
    // when the window is resized.
    mGLXDisplay->setSwapInterval(mGLXWindow, &mSwapControl);
    mGLX.swapBuffers(mGLXWindow);

    egl::Error error = checkForResize();
    if (error.isError())
    {
        return error;
    }

    return egl::NoError();
}

egl::Error WindowSurfaceGLX::postSubBuffer(const gl::Context *context,
                                           EGLint x,
                                           EGLint y,
                                           EGLint width,
                                           EGLint height)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

egl::Error WindowSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

egl::Error WindowSurfaceGLX::bindTexImage(const gl::Context *context,
                                          gl::Texture *texture,
                                          EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

egl::Error WindowSurfaceGLX::releaseTexImage(const gl::Context *context, EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

void WindowSurfaceGLX::setSwapInterval(EGLint interval)
{
    mSwapControl.targetSwapInterval = interval;
}

EGLint WindowSurfaceGLX::getWidth() const
{
    // The size of the window is always the same as the cached size of its parent.
    return mParentWidth;
}

EGLint WindowSurfaceGLX::getHeight() const
{
    // The size of the window is always the same as the cached size of its parent.
    return mParentHeight;
}

EGLint WindowSurfaceGLX::isPostSubBufferSupported() const
{
    UNIMPLEMENTED();
    return EGL_FALSE;
}

EGLint WindowSurfaceGLX::getSwapBehavior() const
{
    return EGL_BUFFER_DESTROYED;
}

egl::Error WindowSurfaceGLX::checkForResize()
{
    // TODO(cwallez) set up our own error handler to see if the call failed
    unsigned int newParentWidth, newParentHeight;
    if (!getWindowDimensions(mParent, &newParentWidth, &newParentHeight))
    {
        return egl::EglBadCurrentSurface() << "Failed to retrieve the size of the parent window.";
    }

    if (mParentWidth != newParentWidth || mParentHeight != newParentHeight)
    {
        mParentWidth  = newParentWidth;
        mParentHeight = newParentHeight;

        mGLX.waitGL();
        XResizeWindow(mDisplay, mWindow, mParentWidth, mParentHeight);
        mGLX.waitX();
        XSync(mDisplay, False);
    }

    return egl::NoError();
}

glx::Drawable WindowSurfaceGLX::getDrawable() const
{
    return mGLXWindow;
}

bool WindowSurfaceGLX::getWindowDimensions(Window window,
                                           unsigned int *width,
                                           unsigned int *height) const
{
    Window root;
    int x, y;
    unsigned int border, depth;
    return XGetGeometry(mDisplay, window, &root, &x, &y, width, height, &border, &depth) != 0;
}

}  // namespace rx
