pub const ext = @import("ext.zig");
const gstglegl = @This();

const std = @import("std");
const compat = @import("compat");
const gstvideo = @import("gstvideo1");
const gstbase = @import("gstbase1");
const gst = @import("gst1");
const gobject = @import("gobject2");
const glib = @import("glib2");
const gmodule = @import("gmodule2");
const gstgl = @import("gstgl1");
/// the contents of a `gstglegl.GLDisplayEGL` are private and should only be accessed
/// through the provided API
pub const GLDisplayEGL = extern struct {
    pub const Parent = gstgl.GLDisplay;
    pub const Implements = [_]type{};
    pub const Class = gstglegl.GLDisplayEGLClass;
    f_parent: gstgl.GLDisplay,
    f_display: ?*anyopaque,
    f_foreign_display: c_int,
    f__padding: [4]*anyopaque,

    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    /// Creates a EGL display connection from a native Display.
    ///
    /// This function will return the same value for multiple calls with the same
    /// `display`.
    ///
    /// The returned `gstglegl.GLDisplayEGL` will *not* be marked as foreign and will free
    /// some display global EGL resources on finalization. If an external API/user
    /// will be also handling the lifetime of the `EGLDisplay`, you should mark the
    /// returned `gstglegl.GLDisplayEGL` as foreign by calling `gstglegl.GLDisplayEGL.setForeign`.
    extern fn gst_gl_display_egl_from_gl_display(p_display: *gstgl.GLDisplay) ?*gstglegl.GLDisplayEGL;
    pub const fromGlDisplay = gst_gl_display_egl_from_gl_display;

    /// Attempts to create a new `EGLDisplay` from `display`.  If `type` is
    /// `GST_GL_DISPLAY_TYPE_ANY` or `GST_GL_DISPLAY_TYPE_EGL_SURFACELESS`, then
    /// `display` must be 0. `type` must not be `GST_GL_DISPLAY_TYPE_NONE`.
    extern fn gst_gl_display_egl_get_from_native(p_type: gstgl.GLDisplayType, p_display: usize) ?*anyopaque;
    pub const getFromNative = gst_gl_display_egl_get_from_native;

    /// Create a new `gstglegl.GLDisplayEGL` using the default EGL_DEFAULT_DISPLAY.
    ///
    /// The returned `gstglegl.GLDisplayEGL` will by default free all EGL resources when
    /// finalized. See `gstglegl.GLDisplayEGL.setForeign` for details on if you need
    /// the EGLDisplay to remain alive.
    extern fn gst_gl_display_egl_new() ?*gstglegl.GLDisplayEGL;
    pub const new = gst_gl_display_egl_new;

    /// Create a new surfaceless `gstglegl.GLDisplayEGL` using the Mesa3D
    /// EGL_PLATFORM_SURFACELESS_MESA extension.
    extern fn gst_gl_display_egl_new_surfaceless() ?*gstglegl.GLDisplayEGL;
    pub const newSurfaceless = gst_gl_display_egl_new_surfaceless;

    extern fn gst_gl_display_egl_new_with_egl_display(p_display: ?*anyopaque) *gstglegl.GLDisplayEGL;
    pub const newWithEglDisplay = gst_gl_display_egl_new_with_egl_display;

    /// Configure whether or not this EGL display is foreign and is managed by an
    /// external application/library.
    ///
    /// A display marked as foreign will not have display global resources freed when
    /// this display is finalized. As such, any external API using the same
    /// `EGLDisplay` must keep the `EGLDisplay` alive while GStreamer is using any
    /// EGL or GL resources associated with that `EGLDisplay`.  The reverse is also
    /// true and a foreign `gstglegl.GLDisplayEGL` must not be used after the associated
    /// `EGLDisplay` has been destroyed externally with ``eglTerminate``.
    ///
    /// A non-foreign `gstglegl.GLDisplayEGL` will destroy the associated `EGLDisplay` on
    /// finalization. This can also be useful when a user would like GStreamer to
    /// assume ownership of the `EGLDisplay` after calling e.g.
    /// `gstglegl.GLDisplayEGL.newWithEglDisplay`.
    extern fn gst_gl_display_egl_set_foreign(p_display_egl: *GLDisplayEGL, p_foreign: c_int) void;
    pub const setForeign = gst_gl_display_egl_set_foreign;

    extern fn gst_gl_display_egl_get_type() usize;
    pub const getGObjectType = gst_gl_display_egl_get_type;

    extern fn g_object_ref(p_self: *gstglegl.GLDisplayEGL) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstglegl.GLDisplayEGL) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *GLDisplayEGL, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// the contents of a `gstglegl.GLDisplayEGLDevice` are private and should only be accessed
/// through the provided API
pub const GLDisplayEGLDevice = extern struct {
    pub const Parent = gstgl.GLDisplay;
    pub const Implements = [_]type{};
    pub const Class = gstglegl.GLDisplayEGLDeviceClass;
    f_parent: gstgl.GLDisplay,
    f_device: ?*anyopaque,
    f__padding: [4]*anyopaque,

    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    /// Create a new `gstglegl.GLDisplayEGLDevice` with an EGLDevice supported device
    extern fn gst_gl_display_egl_device_new(p_device_index: c_uint) ?*gstglegl.GLDisplayEGLDevice;
    pub const new = gst_gl_display_egl_device_new;

    /// Creates a new `gstglegl.GLDisplayEGLDevice` with EGLDeviceEXT .
    /// The `device` must be created using EGLDevice enumeration.
    extern fn gst_gl_display_egl_device_new_with_egl_device(p_device: ?*anyopaque) *gstglegl.GLDisplayEGLDevice;
    pub const newWithEglDevice = gst_gl_display_egl_device_new_with_egl_device;

    extern fn gst_gl_display_egl_device_get_type() usize;
    pub const getGObjectType = gst_gl_display_egl_device_get_type;

    extern fn g_object_ref(p_self: *gstglegl.GLDisplayEGLDevice) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstglegl.GLDisplayEGLDevice) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *GLDisplayEGLDevice, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Opaque `gstglegl.GLMemoryEGLAllocator` struct
pub const GLMemoryEGLAllocator = extern struct {
    pub const Parent = gstgl.GLMemoryAllocator;
    pub const Implements = [_]type{};
    pub const Class = gstglegl.GLMemoryEGLAllocatorClass;
    f_parent: gstgl.GLMemoryAllocator,
    f__padding: [4]*anyopaque,

    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_gl_memory_egl_allocator_get_type() usize;
    pub const getGObjectType = gst_gl_memory_egl_allocator_get_type;

    extern fn g_object_ref(p_self: *gstglegl.GLMemoryEGLAllocator) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstglegl.GLMemoryEGLAllocator) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *GLMemoryEGLAllocator, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstglegl.EGLImage` represents and holds an `EGLImage` handle.
///
/// A `gstglegl.EGLImage` can be created from a dmabuf with `gstglegl.eglImageFromDmabuf`,
/// or `gstglegl.eglImageFromDmabufDirect`, or `gstglegl.GLMemoryEGL` provides a
/// `gst.Allocator` to allocate `EGLImage`'s bound to and OpenGL texture.
pub const EGLImage = extern struct {
    f_parent: gst.MiniObject,
    f_context: ?*gstgl.GLContext,
    f_image: ?*anyopaque,
    f_format: gstgl.GLFormat,
    f_destroy_data: ?*anyopaque,
    f_destroy_notify: ?gstglegl.EGLImageDestroyNotify,
    f__padding: [4]*anyopaque,

    /// Checks if the given `context` can emulate `format` using a limited subset of
    /// RGB texture formats. Such `format` is then suitable for importing using
    /// `gstglegl.eglImageFromDmabuf` even when GL supports the video format as
    /// external-only or not at all.
    extern fn gst_egl_image_can_emulate(p_context: *gstgl.GLContext, p_format: gstvideo.VideoFormat) c_int;
    pub const canEmulate = gst_egl_image_can_emulate;

    /// Creates an EGL image that imports the dmabuf FD. The dmabuf data
    /// is passed as RGBA data. Shaders later take this "RGBA" data and
    /// convert it from its true format (described by in_info) to actual
    /// RGBA output. For example, with I420, three EGL images are created,
    /// one for each `plane`, each EGL image with a single-channel R format.
    /// With NV12, two EGL images are created, one with R format, one
    /// with RG format etc.
    extern fn gst_egl_image_from_dmabuf(p_context: *gstgl.GLContext, p_dmabuf: c_int, p_in_info: *const gstvideo.VideoInfo, p_plane: c_int, p_offset: usize) ?*gstglegl.EGLImage;
    pub const fromDmabuf = gst_egl_image_from_dmabuf;

    /// Creates an EGL image that imports the dmabuf FD. The dmabuf data
    /// is passed directly as the format described in in_info. This is
    /// useful if the hardware is capable of performing color space conversions
    /// internally. The appropriate DRM format is picked, and the EGL image
    /// is created with this DRM format.
    ///
    /// Another notable difference to `gstglegl.eglImageFromDmabuf`
    /// is that this function creates one EGL image for all planes, not one for
    /// a single plane.
    extern fn gst_egl_image_from_dmabuf_direct(p_context: *gstgl.GLContext, p_fd: *c_int, p_offset: *const usize, p_in_info: *const gstvideo.VideoInfo) ?*gstglegl.EGLImage;
    pub const fromDmabufDirect = gst_egl_image_from_dmabuf_direct;

    /// Creates an EGL image that imports the dmabuf FD. The dmabuf data
    /// is passed directly as the format described in `in_info`. This is
    /// useful if the hardware is capable of performing color space conversions
    /// internally. The appropriate DRM format is picked, and the EGL image
    /// is created with this DRM format.
    ///
    /// Another notable difference to `gstglegl.eglImageFromDmabuf`
    /// is that this function creates one EGL image for all planes, not one for
    /// a single plane.
    extern fn gst_egl_image_from_dmabuf_direct_target(p_context: *gstgl.GLContext, p_fd: *c_int, p_offset: *const usize, p_in_info: *const gstvideo.VideoInfo, p_target: gstgl.GLTextureTarget) ?*gstglegl.EGLImage;
    pub const fromDmabufDirectTarget = gst_egl_image_from_dmabuf_direct_target;

    /// Creates an EGL image that imports the dmabuf FD. The dmabuf data is passed
    /// directly as the format described in `in_info`. This is useful if the hardware
    /// is capable of performing color space conversions internally.
    ///
    /// Another notable difference to `gstglegl.eglImageFromDmabuf` is that this
    /// function creates one EGL image for all planes, not one for a single plane.
    extern fn gst_egl_image_from_dmabuf_direct_target_with_dma_drm(p_context: *gstgl.GLContext, p_n_planes: c_uint, p_fd: *c_int, p_offset: *const usize, p_in_info_dma: *const gstvideo.VideoInfoDmaDrm, p_target: gstgl.GLTextureTarget) ?*gstglegl.EGLImage;
    pub const fromDmabufDirectTargetWithDmaDrm = gst_egl_image_from_dmabuf_direct_target_with_dma_drm;

    extern fn gst_egl_image_from_texture(p_context: *gstgl.GLContext, p_gl_mem: *gstgl.GLMemory, p_attribs: *usize) ?*gstglegl.EGLImage;
    pub const fromTexture = gst_egl_image_from_texture;

    extern fn gst_egl_image_new_wrapped(p_context: *gstgl.GLContext, p_image: ?*anyopaque, p_format: gstgl.GLFormat, p_user_data: ?*anyopaque, p_user_data_destroy: gstglegl.EGLImageDestroyNotify) *gstglegl.EGLImage;
    pub const newWrapped = gst_egl_image_new_wrapped;

    extern fn gst_egl_image_export_dmabuf(p_image: *EGLImage, p_fd: *c_int, p_stride: *c_int, p_offset: *usize) c_int;
    pub const exportDmabuf = gst_egl_image_export_dmabuf;

    extern fn gst_egl_image_get_image(p_image: *EGLImage) ?*anyopaque;
    pub const getImage = gst_egl_image_get_image;

    extern fn gst_egl_image_get_type() usize;
    pub const getGObjectType = gst_egl_image_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const GLDisplayEGLClass = extern struct {
    pub const Instance = gstglegl.GLDisplayEGL;

    f_object_class: gstgl.GLDisplayClass,
    f__padding: [4]*anyopaque,

    pub fn as(p_instance: *GLDisplayEGLClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Opaque `gstglegl.GLDisplayEGLDeviceClass` struct
pub const GLDisplayEGLDeviceClass = extern struct {
    pub const Instance = gstglegl.GLDisplayEGLDevice;

    f_object_class: gstgl.GLDisplayClass,
    f__padding: [4]*anyopaque,

    pub fn as(p_instance: *GLDisplayEGLDeviceClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `gstglegl.GLMemoryEGL` is created or wrapped through `gstgl.glBaseMemoryAlloc`
/// with `gstgl.GLVideoAllocationParams`.
pub const GLMemoryEGL = extern struct {
    f_mem: gstgl.GLMemory,
    f_image: ?*gstglegl.EGLImage,
    f__padding: [4]*anyopaque,

    /// Initializes the GL Memory allocator. It is safe to call this function
    /// multiple times.  This must be called before any other GstGLMemoryEGL operation.
    extern fn gst_gl_memory_egl_init_once() void;
    pub const initOnce = gst_gl_memory_egl_init_once;

    extern fn gst_gl_memory_egl_get_display(p_mem: *GLMemoryEGL) ?*anyopaque;
    pub const getDisplay = gst_gl_memory_egl_get_display;

    extern fn gst_gl_memory_egl_get_image(p_mem: *GLMemoryEGL) ?*anyopaque;
    pub const getImage = gst_gl_memory_egl_get_image;

    extern fn gst_gl_memory_egl_get_type() usize;
    pub const getGObjectType = gst_gl_memory_egl_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// The `gstglegl.GLMemoryEGLAllocatorClass` only contains private data
pub const GLMemoryEGLAllocatorClass = extern struct {
    pub const Instance = gstglegl.GLMemoryEGLAllocator;

    f_parent_class: gstgl.GLMemoryAllocatorClass,
    f__padding: [4]*anyopaque,

    pub fn as(p_instance: *GLMemoryEGLAllocatorClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

extern fn gst_egl_get_error_string(p_err: i32) [*:0]const u8;
pub const eglGetErrorString = gst_egl_get_error_string;

extern fn gst_is_gl_memory_egl(p_mem: *gst.Memory) c_int;
pub const isGlMemoryEgl = gst_is_gl_memory_egl;

/// Function to be called when the GstEGLImage is destroyed. It should free
/// the associated `EGLImage` if necessary
pub const EGLImageDestroyNotify = *const fn (p_image: *anyopaque, p_data: ?*anyopaque) callconv(.c) void;

pub const GL_DISPLAY_EGL_NAME = "gst.gl.display.egl";
/// The name of the GL Memory EGL allocator
pub const GL_MEMORY_EGL_ALLOCATOR_NAME = "GLMemoryEGL";

test {
    @setEvalBranchQuota(100_000);
    std.testing.refAllDecls(@This());
    std.testing.refAllDecls(ext);
}
