//
// Copyright (c) 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.
//

// SurfaceWGL.cpp: WGL implementation of egl::Surface

#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.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
{

PbufferSurfaceWGL::PbufferSurfaceWGL(const egl::SurfaceState &state,
                                     RendererGL *renderer,
                                     EGLint width,
                                     EGLint height,
                                     EGLenum textureFormat,
                                     EGLenum textureTarget,
                                     bool largest,
                                     int pixelFormat,
                                     HDC deviceContext,
                                     HGLRC wglContext,
                                     const FunctionsWGL *functions)
    : SurfaceGL(state, renderer),
      mWidth(width),
      mHeight(height),
      mLargest(largest),
      mTextureFormat(textureFormat),
      mTextureTarget(textureTarget),
      mPixelFormat(pixelFormat),
      mShareWGLContext(wglContext),
      mParentDeviceContext(deviceContext),
      mPbuffer(nullptr),
      mPbufferDeviceContext(nullptr),
      mFunctionsWGL(functions)
{
}

PbufferSurfaceWGL::~PbufferSurfaceWGL()
{
    mFunctionsWGL->releasePbufferDCARB(mPbuffer, mPbufferDeviceContext);
    mPbufferDeviceContext = nullptr;

    mFunctionsWGL->destroyPbufferARB(mPbuffer);
    mPbuffer = nullptr;
}

static int GetWGLTextureType(EGLenum eglTextureType)
{
    switch (eglTextureType)
    {
      case EGL_NO_TEXTURE:    return WGL_NO_TEXTURE_ARB;
      case EGL_TEXTURE_RGB:   return WGL_TEXTURE_RGB_ARB;
      case EGL_TEXTURE_RGBA:  return WGL_TEXTURE_RGBA_ARB;
      default: UNREACHABLE(); return 0;
    }
}

static int GetWGLTextureTarget(EGLenum eglTextureTarget)
{
    switch (eglTextureTarget)
    {
      case EGL_NO_TEXTURE:    return WGL_NO_TEXTURE_ARB;
      case EGL_TEXTURE_2D:    return WGL_TEXTURE_2D_ARB;
      default: UNREACHABLE(); return 0;
    }
}

egl::Error PbufferSurfaceWGL::initialize(const DisplayImpl *displayImpl)
{
    const int pbufferCreationAttributes[] =
    {
        WGL_PBUFFER_LARGEST_ARB, mLargest ? 1 : 0,
        WGL_TEXTURE_FORMAT_ARB, GetWGLTextureType(mTextureFormat),
        WGL_TEXTURE_TARGET_ARB, GetWGLTextureTarget(mTextureTarget),
        0, 0,
    };

    mPbuffer = mFunctionsWGL->createPbufferARB(mParentDeviceContext, mPixelFormat, mWidth, mHeight,
                                               pbufferCreationAttributes);
    if (mPbuffer == nullptr)
    {
        DWORD error = GetLastError();
        return egl::Error(EGL_BAD_ALLOC, "Failed to create a native WGL pbuffer, error: 0x%08x.", HRESULT_CODE(error));
    }

    // The returned pbuffer may not be as large as requested, update the size members.
    if (mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_WIDTH_ARB, &mWidth) != TRUE ||
        mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_HEIGHT_ARB, &mHeight) != TRUE)
    {
        DWORD error = GetLastError();
        return egl::Error(EGL_BAD_ALLOC, "Failed to query the WGL pbuffer's dimensions, error: 0x%08x.", HRESULT_CODE(error));
    }

    mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer);
    if (mPbufferDeviceContext == nullptr)
    {
        mFunctionsWGL->destroyPbufferARB(mPbuffer);
        mPbuffer = nullptr;

        DWORD error = GetLastError();
        return egl::Error(EGL_BAD_ALLOC, "Failed to get the WGL pbuffer handle, error: 0x%08x.", HRESULT_CODE(error));
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error PbufferSurfaceWGL::makeCurrent()
{
    if (!mFunctionsWGL->makeCurrent(mPbufferDeviceContext, mShareWGLContext))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error PbufferSurfaceWGL::swap(const DisplayImpl *displayImpl)
{
    return egl::Error(EGL_SUCCESS);
}

egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
    return egl::Error(EGL_SUCCESS);
}

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

static int GetWGLBufferBindTarget(EGLint buffer)
{
    switch (buffer)
    {
      case EGL_BACK_BUFFER:   return WGL_BACK_LEFT_ARB;
      default: UNREACHABLE(); return 0;
    }
}

egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
{
    if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
    {
        DWORD error = GetLastError();
        return egl::Error(EGL_BAD_SURFACE, "Failed to bind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error PbufferSurfaceWGL::releaseTexImage(EGLint buffer)
{
    if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
    {
        DWORD error = GetLastError();
        return egl::Error(EGL_BAD_SURFACE, "Failed to unbind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
    }

    return egl::Error(EGL_SUCCESS);
}

void PbufferSurfaceWGL::setSwapInterval(EGLint interval)
{
}

EGLint PbufferSurfaceWGL::getWidth() const
{
    return mWidth;
}

EGLint PbufferSurfaceWGL::getHeight() const
{
    return mHeight;
}

EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const
{
    return EGL_FALSE;
}

EGLint PbufferSurfaceWGL::getSwapBehavior() const
{
    return EGL_BUFFER_PRESERVED;
}

}
