/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

/*
 * Copyright (C) 2016 Red Hat Inc.
 * Copyright (C) 2019 DisplayLink (UK) Ltd.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 * Written by:
 *     Jonas Ådahl <jadahl@gmail.com>
 */

#pragma once

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglmesaext.h>
#include <glib-object.h>

#define META_EGL_ERROR meta_egl_error_quark ()

#define META_TYPE_EGL (meta_egl_get_type ())
G_DECLARE_FINAL_TYPE (MetaEgl, meta_egl, META, EGL, GObject)

GQuark meta_egl_error_quark (void);

gboolean
meta_extensions_string_has_extensions_valist (const char   *extensions_str,
                                              const char ***missing_extensions,
                                              const char   *first_extension,
                                              va_list       var_args);

gboolean meta_egl_has_extensions (MetaEgl      *egl,
                                  EGLDisplay    display,
                                  const char ***missing_extensions,
                                  const char   *first_extension,
                                  ...);

const char * meta_egl_query_string (MetaEgl    *egl,
                                    EGLDisplay  display,
                                    EGLint      name);

gboolean meta_egl_initialize (MetaEgl   *egl,
                              EGLDisplay display,
                              GError   **error);

gboolean meta_egl_bind_api (MetaEgl  *egl,
                            EGLenum   api,
                            GError  **error);

gpointer meta_egl_get_proc_address (MetaEgl    *egl,
                                    const char *procname,
                                    GError    **error);

gboolean meta_egl_choose_first_config (MetaEgl       *egl,
                                       EGLDisplay     display,
                                       const EGLint  *attrib_list,
                                       EGLConfig     *chosen_config,
                                       GError       **error);

gboolean meta_egl_get_config_attrib (MetaEgl     *egl,
                                     EGLDisplay   display,
                                     EGLConfig    config,
                                     EGLint       attribute,
                                     EGLint      *value,
                                     GError     **error);

EGLConfig * meta_egl_choose_all_configs (MetaEgl       *egl,
                                         EGLDisplay     display,
                                         const EGLint  *attrib_list,
                                         EGLint        *out_num_configs,
                                         GError       **error);

EGLContext meta_egl_create_context (MetaEgl      *egl,
                                    EGLDisplay    display,
                                    EGLConfig     config,
                                    EGLContext    share_context,
                                    const EGLint *attrib_list,
                                    GError      **error);

gboolean meta_egl_destroy_context (MetaEgl   *egl,
                                   EGLDisplay display,
                                   EGLContext context,
                                   GError   **error);

EGLImageKHR meta_egl_create_image (MetaEgl        *egl,
                                   EGLDisplay      display,
                                   EGLContext      context,
                                   EGLenum         target,
                                   EGLClientBuffer buffer,
                                   const EGLint   *attrib_list,
                                   GError        **error);

gboolean meta_egl_destroy_image (MetaEgl    *egl,
                                 EGLDisplay  display,
                                 EGLImageKHR image,
                                 GError    **error);

EGLImageKHR meta_egl_create_dmabuf_image (MetaEgl         *egl,
                                          EGLDisplay       egl_display,
                                          unsigned int     width,
                                          unsigned int     height,
                                          uint32_t         drm_format,
                                          uint32_t         n_planes,
                                          const int       *fds,
                                          const uint32_t  *strides,
                                          const uint32_t  *offsets,
                                          const uint64_t  *modifiers,
                                          GError         **error);

EGLSurface meta_egl_create_window_surface (MetaEgl            *egl,
                                           EGLDisplay          display,
                                           EGLConfig           config,
                                           EGLNativeWindowType native_window_type,
                                           const EGLint       *attrib_list,
                                           GError            **error);

EGLSurface meta_egl_create_pbuffer_surface (MetaEgl      *egl,
                                            EGLDisplay    display,
                                            EGLConfig     config,
                                            const EGLint *attrib_list,
                                            GError      **error);

gboolean meta_egl_destroy_surface (MetaEgl   *egl,
                                   EGLDisplay display,
                                   EGLSurface surface,
                                   GError   **error);

EGLDisplay meta_egl_get_platform_display (MetaEgl      *egl,
                                          EGLenum       platform,
                                          void         *native_display,
                                          const EGLint *attrib_list,
                                          GError      **error);

gboolean meta_egl_terminate (MetaEgl   *egl,
                             EGLDisplay display,
                             GError   **error);

gboolean meta_egl_make_current (MetaEgl   *egl,
                                EGLDisplay display,
                                EGLSurface draw,
                                EGLSurface read,
                                EGLContext context,
                                GError   **error);

gboolean meta_egl_swap_buffers (MetaEgl   *egl,
                                EGLDisplay display,
                                EGLSurface surface,
                                GError   **error);

gboolean meta_egl_bind_wayland_display (MetaEgl            *egl,
                                        EGLDisplay          display,
                                        struct wl_display  *wayland_display,
                                        GError            **error);

gboolean meta_egl_query_wayland_buffer (MetaEgl            *egl,
                                        EGLDisplay          display,
                                        struct wl_resource *buffer,
                                        EGLint              attribute,
                                        EGLint             *value,
                                        GError            **error);

gboolean meta_egl_query_devices (MetaEgl      *egl,
                                 EGLint        max_devices,
                                 EGLDeviceEXT *devices,
                                 EGLint       *num_devices,
                                 GError      **error);

gboolean meta_egl_query_device_string (MetaEgl       *egl,
                                       EGLDeviceEXT   device,
                                       EGLint         name,
                                       const char   **out_string,
                                       GError       **error);

gboolean meta_egl_egl_device_has_extensions (MetaEgl        *egl,
                                             EGLDeviceEXT    device,
                                             const char   ***missing_extensions,
                                             const char     *first_extension,
                                             ...);

gboolean meta_egl_get_output_layers (MetaEgl           *egl,
                                     EGLDisplay         display,
                                     const EGLAttrib   *attrib_list,
                                     EGLOutputLayerEXT *layers,
                                     EGLint             max_layers,
                                     EGLint            *num_layers,
                                     GError           **error);

gboolean meta_egl_query_output_layer_attrib (MetaEgl          *egl,
                                             EGLDisplay        display,
                                             EGLOutputLayerEXT layer,
                                             EGLint            attribute,
                                             EGLAttrib        *value,
                                             GError          **error);

EGLStreamKHR meta_egl_create_stream (MetaEgl      *egl,
                                     EGLDisplay    display,
                                     const EGLint *attrib_list,
                                     GError      **error);

gboolean meta_egl_destroy_stream (MetaEgl     *egl,
                                  EGLDisplay   display,
                                  EGLStreamKHR stream,
                                  GError      **error);

gboolean meta_egl_query_stream (MetaEgl     *egl,
                                EGLDisplay   display,
                                EGLStreamKHR stream,
                                EGLenum      attribute,
                                EGLint      *value,
                                GError     **error);

EGLStreamKHR meta_egl_create_stream_attrib (MetaEgl         *egl,
                                            EGLDisplay       display,
                                            const EGLAttrib *attrib_list,
                                            GError         **error);

EGLSurface meta_egl_create_stream_producer_surface (MetaEgl     *egl,
                                                    EGLDisplay   display,
                                                    EGLConfig    config,
                                                    EGLStreamKHR stream,
                                                    const EGLint *attrib_list,
                                                    GError      **error);

gboolean meta_egl_stream_consumer_output (MetaEgl          *egl,
                                          EGLDisplay        display,
                                          EGLStreamKHR      stream,
                                          EGLOutputLayerEXT layer,
                                          GError          **error);

gboolean meta_egl_stream_consumer_acquire_attrib (MetaEgl     *egl,
                                                  EGLDisplay   display,
                                                  EGLStreamKHR stream,
                                                  EGLAttrib   *attrib_list,
                                                  GError     **error);

gboolean meta_egl_stream_consumer_acquire (MetaEgl     *egl,
                                           EGLDisplay   display,
                                           EGLStreamKHR stream,
                                           GError     **error);

gboolean meta_egl_stream_consumer_gl_texture_external (MetaEgl     *egl,
                                                       EGLDisplay   display,
                                                       EGLStreamKHR stream,
                                                       GError     **error);

gboolean meta_egl_query_dma_buf_formats (MetaEgl    *egl,
                                         EGLDisplay  display,
                                         EGLint      max_formats,
                                         EGLint     *formats,
                                         EGLint     *num_formats,
                                         GError    **error);

gboolean meta_egl_query_dma_buf_modifiers (MetaEgl      *egl,
                                           EGLDisplay    display,
                                           EGLint        format,
                                           EGLint        max_modifiers,
                                           EGLuint64KHR *modifiers,
                                           EGLBoolean   *external_only,
                                           EGLint       *num_formats,
                                           GError      **error);

gboolean meta_egl_query_display_attrib (MetaEgl     *egl,
                                        EGLDisplay   display,
                                        EGLint       attribute,
                                        EGLAttrib   *value,
                                        GError     **error);

gboolean meta_egl_create_sync (MetaEgl           *egl,
                               EGLDisplay         display,
                               EGLenum            type,
                               const EGLAttrib   *attrib_list,
                               EGLSync           *egl_sync,
                               GError           **error);

gboolean meta_egl_destroy_sync (MetaEgl     *egl,
                                EGLDisplay   display,
                                EGLSync      sync,
                                GError     **error);

gboolean meta_egl_wait_sync (MetaEgl     *egl,
                             EGLDisplay   display,
                             EGLSync      sync,
                             EGLint       flags,
                             GError     **error);
