/*
 * 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 "GraphicsContextGL.h"
#include "GraphicsTypesGL.h"
#include <optional>
#include <wtf/Noncopyable.h>

namespace WebCore {

class ScopedRestoreTextureBinding {
    WTF_MAKE_NONCOPYABLE(ScopedRestoreTextureBinding);

public:
    ScopedRestoreTextureBinding(GCGLenum bindingPointQuery, GCGLenum bindingPoint, bool condition = true);
    ~ScopedRestoreTextureBinding();

private:
    GCGLenum m_bindingPoint { 0 };
    GCGLuint m_bindingValue { 0u };
};

class ScopedBufferBinding {
    WTF_MAKE_NONCOPYABLE(ScopedBufferBinding);

public:
    ScopedBufferBinding(GCGLenum bindingPoint, GCGLuint bindingValue, bool condition = true);
    ~ScopedBufferBinding();

private:
    static constexpr GCGLenum query(GCGLenum bindingPoint)
    {
        if (bindingPoint == GraphicsContextGL::PIXEL_PACK_BUFFER)
            return GraphicsContextGL::PIXEL_PACK_BUFFER_BINDING;
        ASSERT(bindingPoint == GraphicsContextGL::PIXEL_UNPACK_BUFFER);
        return GraphicsContextGL::PIXEL_UNPACK_BUFFER_BINDING;
    }
    GCGLint m_bindingPoint { 0 };
    GCGLuint m_bindingValue { 0u };
};

class ScopedRestoreReadFramebufferBinding {
    WTF_MAKE_NONCOPYABLE(ScopedRestoreReadFramebufferBinding);

public:
    ScopedRestoreReadFramebufferBinding(bool isForWebGL2, GCGLuint restoreValue)
        : m_framebufferTarget(isForWebGL2 ? GraphicsContextGL::READ_FRAMEBUFFER : GraphicsContextGL::FRAMEBUFFER)
        , m_bindingValue(restoreValue)
    {
    }
    ScopedRestoreReadFramebufferBinding(bool isForWebGL2, GCGLuint restoreValue, GCGLuint value)
        : m_framebufferTarget(isForWebGL2 ? GraphicsContextGL::READ_FRAMEBUFFER : GraphicsContextGL::FRAMEBUFFER)
        , m_bindingValue(restoreValue)
    {
        bindFramebuffer(value);
    }
    ~ScopedRestoreReadFramebufferBinding();
    void markBindingChanged()
    {
        m_bindingChanged = true;
    }
    void bindFramebuffer(GCGLuint bindingValue);
    GCGLuint framebufferTarget() const { return m_framebufferTarget; }

private:
    const GCGLenum m_framebufferTarget;
    GCGLuint m_bindingValue { 0u };
    bool m_bindingChanged { false };
};

class ScopedPixelStorageMode {
    WTF_MAKE_NONCOPYABLE(ScopedPixelStorageMode);

public:
    explicit ScopedPixelStorageMode(GCGLenum name, bool condition = true);
    ScopedPixelStorageMode(GCGLenum name, GCGLint value, bool condition = true);
    ~ScopedPixelStorageMode();
    void pixelStore(GCGLint value);
    operator GCGLint() const
    {
        ASSERT(m_name && !m_valueChanged);
        return m_originalValue;
    }

private:
    const GCGLenum m_name;
    bool m_valueChanged { false };
    GCGLint m_originalValue { 0 };
};

class ScopedTexture {
    WTF_MAKE_NONCOPYABLE(ScopedTexture);

public:
    ScopedTexture();
    ~ScopedTexture();
    operator GCGLuint() const
    {
        return m_object;
    }

private:
    GCGLuint m_object { 0u };
};

class ScopedFramebuffer {
    WTF_MAKE_NONCOPYABLE(ScopedFramebuffer);

public:
    ScopedFramebuffer();
    ~ScopedFramebuffer();
    operator GCGLuint() const
    {
        return m_object;
    }
private:
    GCGLuint 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();
    void abandon() { m_object = { }; }
    void fenceSync();
    GCGLsync get() const { return m_object; }
    operator GCGLsync() const { return m_object; }
    operator bool() const { return m_object; }

private:
    GCGLsync m_object { };
};

class ScopedGLCapability {
    WTF_MAKE_NONCOPYABLE(ScopedGLCapability);
public:
    ScopedGLCapability(GCGLenum capability, bool enable);
    ~ScopedGLCapability();

private:
    const GCGLenum m_capability;
    const std::optional<bool> m_original;
};

bool platformIsANGLEAvailable();

}

#endif
