//
// 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.
//

// WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows

#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"

#include "common/debug.h"
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"

namespace rx
{

WindowSurfaceWGL::WindowSurfaceWGL(const egl::SurfaceState &state,
                                   EGLNativeWindowType window,
                                   int pixelFormat,
                                   const FunctionsWGL *functions,
                                   EGLint orientation)
    : SurfaceWGL(state),
      mPixelFormat(pixelFormat),
      mWindow(window),
      mDeviceContext(nullptr),
      mFunctionsWGL(functions),
      mSwapBehavior(0)
{
    // EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces
    ASSERT(orientation == 0);
}

WindowSurfaceWGL::~WindowSurfaceWGL()
{
    ReleaseDC(mWindow, mDeviceContext);
    mDeviceContext = nullptr;
}

egl::Error WindowSurfaceWGL::initialize(const egl::Display *display)
{
    mDeviceContext = GetDC(mWindow);
    if (!mDeviceContext)
    {
        return egl::EglBadNativeWindow()
               << "Failed to get the device context from the native window, "
               << gl::FmtErr(GetLastError());
    }

    // Require that the pixel format for this window has not been set yet or is equal to the
    // Display's pixel format.
    int windowPixelFormat = GetPixelFormat(mDeviceContext);
    if (windowPixelFormat == 0)
    {
        PIXELFORMATDESCRIPTOR pixelFormatDescriptor = {};
        if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor),
                                 &pixelFormatDescriptor))
        {
            return egl::EglBadNativeWindow()
                   << "Failed to DescribePixelFormat, " << gl::FmtErr(GetLastError());
        }

        if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
        {
            return egl::EglNotInitialized()
                   << "Failed to set the pixel format on the device context, "
                   << gl::FmtErr(GetLastError());
        }
    }
    else if (windowPixelFormat != mPixelFormat)
    {
        return egl::EglNotInitialized()
               << "Pixel format of the NativeWindow and NativeDisplayType must match.";
    }

    // Check for the swap behavior of this pixel format
    switch (
        wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL))
    {
        case WGL_SWAP_COPY_ARB:
            mSwapBehavior = EGL_BUFFER_PRESERVED;
            break;

        case WGL_SWAP_EXCHANGE_ARB:
        case WGL_SWAP_UNDEFINED_ARB:
        default:
            mSwapBehavior = EGL_BUFFER_DESTROYED;
            break;
    }

    return egl::NoError();
}

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

egl::Error WindowSurfaceWGL::swap(const gl::Context *context)
{
    if (!mFunctionsWGL->swapBuffers(mDeviceContext))
    {
        // TODO: What error type here?
        return egl::EglContextLost() << "Failed to swap buffers on the child window.";
    }

    return egl::NoError();
}

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

egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
{
    *value = nullptr;
    return egl::NoError();
}

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

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

void WindowSurfaceWGL::setSwapInterval(EGLint interval)
{
    if (mFunctionsWGL->swapIntervalEXT)
    {
        mFunctionsWGL->swapIntervalEXT(interval);
    }
}

EGLint WindowSurfaceWGL::getWidth() const
{
    RECT rect;
    if (!GetClientRect(mWindow, &rect))
    {
        return 0;
    }
    return rect.right - rect.left;
}

EGLint WindowSurfaceWGL::getHeight() const
{
    RECT rect;
    if (!GetClientRect(mWindow, &rect))
    {
        return 0;
    }
    return rect.bottom - rect.top;
}

EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
{
    // PostSubBuffer extension not exposed on WGL.
    UNIMPLEMENTED();
    return EGL_FALSE;
}

EGLint WindowSurfaceWGL::getSwapBehavior() const
{
    return mSwapBehavior;
}

HDC WindowSurfaceWGL::getDC() const
{
    return mDeviceContext;
}
}  // namespace rx
