/*
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */

#ifndef ANDROID_EGL_OBJECT_H
#define ANDROID_EGL_OBJECT_H

#include <atomic>
#include <stdint.h>
#include <stddef.h>

#include <string>
#include <vector>

#include <EGL/egl.h>
#include <EGL/eglext.h>

#include <system/window.h>

#include <log/log.h>

#include "egl_display.h"

// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------

class egl_display_t;

class egl_object_t {
    egl_display_t *display;
    mutable std::atomic_size_t count;

protected:
    virtual ~egl_object_t();
    virtual void terminate();

public:
    explicit egl_object_t(egl_display_t* display);
    void destroy();

    inline void incRef() { count.fetch_add(1, std::memory_order_relaxed); }
    inline size_t decRef() { return count.fetch_sub(1, std::memory_order_acq_rel); }
    inline egl_display_t* getDisplay() const { return display; }

private:
    static bool get(egl_display_t const* display, egl_object_t* object);

public:
    template <typename N, typename T>
    class LocalRef {
        egl_object_t* ref;
        LocalRef() = delete;
        LocalRef(const LocalRef* rhs) = delete;
    public:
        ~LocalRef();
        explicit LocalRef(egl_object_t* rhs);
        explicit LocalRef(egl_display_t const* display, T o) : ref(0) {
            egl_object_t* native = reinterpret_cast<N*>(o);
            if (o && egl_object_t::get(display, native)) {
                ref = native;
            }
        }
        inline N* get() {
            return static_cast<N*>(ref);
        }
        void acquire() const;
        void release() const;
        void terminate();
    };
    template <typename N, typename T>
    friend class LocalRef;
};

template<typename N, typename T>
egl_object_t::LocalRef<N, T>::LocalRef(egl_object_t* rhs) : ref(rhs) {
    if (ref) {
        ref->incRef();
    }
}

template <typename N, typename T>
egl_object_t::LocalRef<N,T>::~LocalRef() {
    if (ref) {
        ref->destroy();
    }
}

template <typename N, typename T>
void egl_object_t::LocalRef<N,T>::acquire() const {
    if (ref) {
        ref->incRef();
    }
}

template <typename N, typename T>
void egl_object_t::LocalRef<N,T>::release() const {
    if (ref) {
        if (ref->decRef() == 1) {
            // shouldn't happen because this is called from LocalRef
            ALOGE("LocalRef::release() removed the last reference!");
        }
    }
}

template <typename N, typename T>
void egl_object_t::LocalRef<N,T>::terminate() {
    if (ref) {
        ref->terminate();
    }
}

// ----------------------------------------------------------------------------

class egl_surface_t : public egl_object_t {
protected:
    ~egl_surface_t();
    void terminate() override;
public:
    typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;

    egl_surface_t(egl_display_t* dpy, EGLConfig config, EGLNativeWindowType win, EGLSurface surface,
                  EGLint colorSpace, egl_connection_t const* cnx);

    ANativeWindow* getNativeWindow() { return win; }
    ANativeWindow* getNativeWindow() const { return win; }
    EGLint getColorSpace() const { return colorSpace; }

    // Try to keep the order of these fields and size unchanged. It's not public API, but
    // it's not hard to imagine native games accessing them.
    EGLSurface surface;
    EGLConfig config;
private:
    ANativeWindow* win;
public:
    egl_connection_t const* cnx;
private:
    bool connected;
    void disconnect();
    EGLint colorSpace;
};

class egl_context_t: public egl_object_t {
protected:
    ~egl_context_t() {}
public:
    typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref;

    egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
            egl_connection_t const* cnx, int version);

    void onLooseCurrent();
    void onMakeCurrent(EGLSurface draw, EGLSurface read);

    EGLDisplay dpy;
    EGLContext context;
    EGLConfig config;
    EGLSurface read;
    EGLSurface draw;
    egl_connection_t const* cnx;
    int version;
    std::string gl_extensions;
    std::vector<std::string> tokenized_gl_extensions;
};

// ----------------------------------------------------------------------------

typedef egl_surface_t::Ref  SurfaceRef;
typedef egl_context_t::Ref  ContextRef;

// ----------------------------------------------------------------------------

template<typename NATIVE, typename EGL>
static inline NATIVE* egl_to_native_cast(EGL arg) {
    return reinterpret_cast<NATIVE*>(arg);
}

static inline
egl_surface_t* get_surface(EGLSurface surface) {
    return egl_to_native_cast<egl_surface_t>(surface);
}

static inline
egl_context_t* get_context(EGLContext context) {
    return egl_to_native_cast<egl_context_t>(context);
}

// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------

#endif // ANDROID_EGL_OBJECT_H
