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

// 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,
                                     EGLint width,
                                     EGLint height,
                                     EGLenum textureFormat,
                                     EGLenum textureTarget,
                                     bool largest,
                                     int pixelFormat,
                                     HDC deviceContext,
                                     const FunctionsWGL *functions)
    : SurfaceWGL(state),
      mWidth(width),
      mHeight(height),
      mLargest(largest),
      mTextureFormat(textureFormat),
      mTextureTarget(textureTarget),
      mPixelFormat(pixelFormat),
      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 egl::Display *display)
{
    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::EglBadAlloc() << "Failed to create a native WGL pbuffer, "
                                  << gl::FmtErr(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::EglBadAlloc() << "Failed to query the WGL pbuffer's dimensions, "
                                  << gl::FmtErr(HRESULT_CODE(error));
    }

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

        DWORD error = GetLastError();
        return egl::EglBadAlloc() << "Failed to get the WGL pbuffer handle, "
                                  << gl::FmtErr(HRESULT_CODE(error));
    }

    return egl::NoError();
}

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

egl::Error PbufferSurfaceWGL::swap(const gl::Context *context)
{
    return egl::NoError();
}

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

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

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

egl::Error PbufferSurfaceWGL::bindTexImage(const gl::Context *context,
                                           gl::Texture *texture,
                                           EGLint buffer)
{
    if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
    {
        DWORD error = GetLastError();
        return egl::EglBadSurface()
               << "Failed to bind native wgl pbuffer, " << gl::FmtErr(HRESULT_CODE(error));
    }

    return egl::NoError();
}

egl::Error PbufferSurfaceWGL::releaseTexImage(const gl::Context *context, EGLint buffer)
{
    if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
    {
        DWORD error = GetLastError();
        return egl::EglBadSurface()
               << "Failed to unbind native wgl pbuffer, " << gl::FmtErr(HRESULT_CODE(error));
    }

    return egl::NoError();
}

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;
}

HDC PbufferSurfaceWGL::getDC() const
{
    return mPbufferDeviceContext;
}
}  // namespace rx
