/*
 * Copyright (C) 2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#if ENABLE(WEBGL) && USE(ANGLE)

#include "ANGLEHeaders.h"
#include "GraphicsTypesGL.h"
#include <wtf/Noncopyable.h>

namespace WebCore {

class ScopedRestoreTextureBinding {
    WTF_MAKE_NONCOPYABLE(ScopedRestoreTextureBinding);
public:
    ScopedRestoreTextureBinding(GLenum bindingPointQuery, GLenum bindingPoint, bool condition = true)
    {
        ASSERT(bindingPoint != static_cast<GLenum>(0u));
        if (condition) {
            m_bindingPoint = bindingPoint;
            gl::GetIntegerv(bindingPointQuery, reinterpret_cast<GLint*>(&m_bindingValue));
        }
    }

    ~ScopedRestoreTextureBinding()
    {
        if (m_bindingPoint)
            gl::BindTexture(m_bindingPoint, m_bindingValue);
    }

private:
    GLenum m_bindingPoint { 0 };
    GLuint m_bindingValue { 0u };
};


class ScopedBufferBinding {
    WTF_MAKE_NONCOPYABLE(ScopedBufferBinding);
public:
    ScopedBufferBinding(GLenum bindingPoint, GLuint bindingValue, bool condition = true)
    {
        if (!condition)
            return;
        gl::GetIntegerv(query(bindingPoint), reinterpret_cast<GLint*>(&m_bindingValue));
        if (bindingValue == m_bindingValue)
            return;
        m_bindingPoint = bindingPoint;
        gl::BindBuffer(m_bindingPoint, bindingValue);
    }

    ~ScopedBufferBinding()
    {
        if (m_bindingPoint)
            gl::BindBuffer(m_bindingPoint, m_bindingValue);
    }

private:
    static constexpr GLenum query(GLenum bindingPoint)
    {
        if (bindingPoint == GL_PIXEL_PACK_BUFFER)
            return GL_PIXEL_PACK_BUFFER_BINDING;
        ASSERT(bindingPoint == GL_PIXEL_UNPACK_BUFFER);
        return GL_PIXEL_UNPACK_BUFFER_BINDING;
    }
    GLint m_bindingPoint { 0 };
    GLuint m_bindingValue { 0u };
};
class ScopedRestoreReadFramebufferBinding {
    WTF_MAKE_NONCOPYABLE(ScopedRestoreReadFramebufferBinding);
public:
    ScopedRestoreReadFramebufferBinding(bool isForWebGL2, GLuint restoreValue)
        : m_framebufferTarget(isForWebGL2 ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER)
        , m_bindingValue(restoreValue)
    {
    }
    ScopedRestoreReadFramebufferBinding(bool isForWebGL2, GLuint restoreValue, GLuint value)
        : m_framebufferTarget(isForWebGL2 ? GL_READ_FRAMEBUFFER : GL_FRAMEBUFFER)
        , m_bindingValue(restoreValue)
    {
        bindFramebuffer(value);
    }
    void markBindingChanged()
    {
        m_bindingChanged = true;
    }
    void bindFramebuffer(GLuint bindingValue)
    {
        if (!m_bindingChanged && m_bindingValue == bindingValue)
            return;
        gl::BindFramebuffer(m_framebufferTarget, bindingValue);
        m_bindingChanged = m_bindingValue != bindingValue;
    }
    GLuint framebufferTarget() const { return m_framebufferTarget; }
    ~ScopedRestoreReadFramebufferBinding()
    {
        if (m_bindingChanged)
            gl::BindFramebuffer(m_framebufferTarget, m_bindingValue);
    }
private:
    const GLenum m_framebufferTarget;
    GLuint m_bindingValue { 0u };
    bool m_bindingChanged { false };
};

class ScopedPixelStorageMode {
    WTF_MAKE_NONCOPYABLE(ScopedPixelStorageMode);
public:
    explicit ScopedPixelStorageMode(GLenum name, bool condition = true)
        : m_name(condition ? name : 0)
    {
        if (m_name)
            gl::GetIntegerv(m_name, &m_originalValue);
    }
    ScopedPixelStorageMode(GLenum name, GLint value, bool condition = true)
        : m_name(condition ? name : 0)
    {
        if (m_name) {
            gl::GetIntegerv(m_name, &m_originalValue);
            pixelStore(value);
        }
    }
    ~ScopedPixelStorageMode()
    {
        if (m_name && m_valueChanged)
            gl::PixelStorei(m_name, m_originalValue);
    }
    void pixelStore(GLint value)
    {
        ASSERT(m_name);
        if (!m_valueChanged && m_originalValue == value)
            return;
        gl::PixelStorei(m_name, value);
        m_valueChanged = m_originalValue != value;
    }
    operator GLint() const
    {
        ASSERT(m_name && !m_valueChanged);
        return m_originalValue;
    }
private:
    const GLenum m_name;
    bool m_valueChanged { false };
    GLint m_originalValue { 0 };
};

class ScopedTexture {
    WTF_MAKE_NONCOPYABLE(ScopedTexture);
public:
    ScopedTexture()
    {
        gl::GenTextures(1, &m_object);
    }
    ~ScopedTexture()
    {
        gl::DeleteTextures(1, &m_object);
    }
    operator GLuint() const
    {
        return m_object;
    }
private:
    GLuint m_object { 0u };
};

class ScopedFramebuffer {
    WTF_MAKE_NONCOPYABLE(ScopedFramebuffer);
public:
    ScopedFramebuffer()
    {
        gl::GenFramebuffers(1, &m_object);
    }
    ~ScopedFramebuffer()
    {
        gl::DeleteFramebuffers(1, &m_object);
    }
    operator GLuint() const
    {
        return m_object;
    }
private:
    GLuint m_object { 0 };
};

class ScopedGLFence {
    WTF_MAKE_NONCOPYABLE(ScopedGLFence);
public:
    ScopedGLFence() = default;
    ScopedGLFence(ScopedGLFence&& other)
        : m_object(std::exchange(other.m_object, { }))
    {
    }
    ~ScopedGLFence() { reset(); }
    ScopedGLFence& operator=(ScopedGLFence&& other)
    {
        if (this != &other) {
            reset();
            m_object = std::exchange(other.m_object, { });
        }
        return *this;
    }
    void reset()
    {
        if (m_object) {
            gl::DeleteSync(m_object);
            m_object = { };
        }
    }
    void abandon() { m_object = { }; }
    void fenceSync()
    {
        reset();
        m_object = gl::FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
    }
    operator GLsync() const { return m_object; }
    operator bool() const { return m_object; }
private:
    GLsync m_object { };
};

bool platformIsANGLEAvailable();

}

#endif
