using System; using System.Runtime.InteropServices; namespace Avalonia.DmaBufInteropTests; /// /// P/Invoke bindings for GBM, DRM, and Linux kernel interfaces used for test buffer allocation. /// internal static unsafe partial class NativeInterop { // GBM private const string LibGbm = "libgbm.so.1"; [LibraryImport(LibGbm, EntryPoint = "gbm_create_device")] public static partial IntPtr GbmCreateDevice(int fd); [LibraryImport(LibGbm, EntryPoint = "gbm_device_destroy")] public static partial void GbmDeviceDestroy(IntPtr gbm); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_create")] public static partial IntPtr GbmBoCreate(IntPtr gbm, uint width, uint height, uint format, uint flags); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_create_with_modifiers")] public static partial IntPtr GbmBoCreateWithModifiers(IntPtr gbm, uint width, uint height, uint format, ulong* modifiers, uint count); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_destroy")] public static partial void GbmBoDestroy(IntPtr bo); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_get_fd")] public static partial int GbmBoGetFd(IntPtr bo); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_get_stride")] public static partial uint GbmBoGetStride(IntPtr bo); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_get_modifier")] public static partial ulong GbmBoGetModifier(IntPtr bo); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_get_width")] public static partial uint GbmBoGetWidth(IntPtr bo); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_get_height")] public static partial uint GbmBoGetHeight(IntPtr bo); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_get_format")] public static partial uint GbmBoGetFormat(IntPtr bo); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_map")] public static partial IntPtr GbmBoMap(IntPtr bo, uint x, uint y, uint width, uint height, uint flags, uint* stride, IntPtr* mapData); [LibraryImport(LibGbm, EntryPoint = "gbm_bo_unmap")] public static partial void GbmBoUnmap(IntPtr bo, IntPtr mapData); // GBM flags public const uint GBM_BO_USE_RENDERING = 1 << 2; public const uint GBM_BO_USE_LINEAR = 1 << 4; // GBM_BO_TRANSFER flags for gbm_bo_map public const uint GBM_BO_TRANSFER_WRITE = 2; public const uint GBM_BO_TRANSFER_READ_WRITE = 3; // DRM format codes public const uint GBM_FORMAT_ARGB8888 = 0x34325241; // DRM_FORMAT_ARGB8888 public const uint GBM_FORMAT_XRGB8888 = 0x34325258; public const uint GBM_FORMAT_ABGR8888 = 0x34324241; // libc private const string LibC = "libc"; [LibraryImport(LibC, EntryPoint = "open", StringMarshalling = StringMarshalling.Utf8)] public static partial int Open(string path, int flags); [LibraryImport(LibC, EntryPoint = "close")] public static partial int Close(int fd); [LibraryImport(LibC, EntryPoint = "mmap")] public static partial IntPtr Mmap(IntPtr addr, nuint length, int prot, int flags, int fd, long offset); [LibraryImport(LibC, EntryPoint = "munmap")] public static partial int Munmap(IntPtr addr, nuint length); [LibraryImport(LibC, EntryPoint = "memfd_create", StringMarshalling = StringMarshalling.Utf8)] public static partial int MemfdCreate(string name, uint flags); [LibraryImport(LibC, EntryPoint = "ftruncate")] public static partial int Ftruncate(int fd, long length); [LibraryImport(LibC, EntryPoint = "ioctl")] public static partial int Ioctl(int fd, ulong request, void* arg); public const int O_RDWR = 0x02; public const int PROT_READ = 0x1; public const int PROT_WRITE = 0x2; public const int MAP_SHARED = 0x01; public const uint MFD_ALLOW_SEALING = 0x0002; // udmabuf public const ulong UDMABUF_CREATE = 0x40187542; // _IOW('u', 0x42, struct udmabuf_create) [StructLayout(LayoutKind.Sequential)] public struct UdmabufCreate { public int Memfd; public uint Flags; public ulong Offset; public ulong Size; } // EGL private const string LibEgl = "libEGL.so.1"; [LibraryImport(LibEgl, EntryPoint = "eglGetProcAddress", StringMarshalling = StringMarshalling.Utf8)] public static partial IntPtr EglGetProcAddress(string procname); [LibraryImport(LibEgl, EntryPoint = "eglGetDisplay")] public static partial IntPtr EglGetDisplay(IntPtr nativeDisplay); [LibraryImport(LibEgl, EntryPoint = "eglInitialize")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EglInitialize(IntPtr display, out int major, out int minor); [LibraryImport(LibEgl, EntryPoint = "eglTerminate")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EglTerminate(IntPtr display); [LibraryImport(LibEgl, EntryPoint = "eglQueryString")] public static partial IntPtr EglQueryStringNative(IntPtr display, int name); public static string? EglQueryString(IntPtr display, int name) { var ptr = EglQueryStringNative(display, name); return ptr == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(ptr); } [LibraryImport(LibEgl, EntryPoint = "eglBindAPI")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EglBindApi(int api); [LibraryImport(LibEgl, EntryPoint = "eglChooseConfig")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EglChooseConfig(IntPtr display, int[] attribs, IntPtr* configs, int configSize, out int numConfig); [LibraryImport(LibEgl, EntryPoint = "eglCreateContext")] public static partial IntPtr EglCreateContext(IntPtr display, IntPtr config, IntPtr shareContext, int[] attribs); [LibraryImport(LibEgl, EntryPoint = "eglDestroyContext")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EglDestroyContext(IntPtr display, IntPtr context); [LibraryImport(LibEgl, EntryPoint = "eglMakeCurrent")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EglMakeCurrent(IntPtr display, IntPtr draw, IntPtr read, IntPtr context); [LibraryImport(LibEgl, EntryPoint = "eglCreatePbufferSurface")] public static partial IntPtr EglCreatePbufferSurface(IntPtr display, IntPtr config, int[] attribs); [LibraryImport(LibEgl, EntryPoint = "eglDestroySurface")] [return: MarshalAs(UnmanagedType.Bool)] public static partial bool EglDestroySurface(IntPtr display, IntPtr surface); [LibraryImport(LibEgl, EntryPoint = "eglGetError")] public static partial int EglGetError(); // EGL_KHR_platform_gbm [LibraryImport(LibEgl, EntryPoint = "eglGetPlatformDisplayEXT")] public static partial IntPtr EglGetPlatformDisplayExt(int platform, IntPtr nativeDisplay, int[]? attribs); // EGL constants public const int EGL_OPENGL_ES_API = 0x30A0; public const int EGL_OPENGL_ES2_BIT = 0x0004; public const int EGL_OPENGL_ES3_BIT = 0x0040; public const int EGL_RENDERABLE_TYPE = 0x3040; public const int EGL_SURFACE_TYPE = 0x3033; public const int EGL_PBUFFER_BIT = 0x0001; public const int EGL_RED_SIZE = 0x3024; public const int EGL_GREEN_SIZE = 0x3023; public const int EGL_BLUE_SIZE = 0x3022; public const int EGL_ALPHA_SIZE = 0x3021; public const int EGL_NONE = 0x3038; public const int EGL_CONTEXT_MAJOR_VERSION = 0x3098; public const int EGL_CONTEXT_MINOR_VERSION = 0x30FB; public const int EGL_WIDTH = 0x3057; public const int EGL_HEIGHT = 0x3056; public const int EGL_EXTENSIONS = 0x3055; public const int EGL_NO_IMAGE_KHR = 0; public const int EGL_LINUX_DMA_BUF_EXT = 0x3270; public const int EGL_LINUX_DRM_FOURCC_EXT = 0x3271; public const int EGL_DMA_BUF_PLANE0_FD_EXT = 0x3272; public const int EGL_DMA_BUF_PLANE0_OFFSET_EXT = 0x3273; public const int EGL_DMA_BUF_PLANE0_PITCH_EXT = 0x3274; public const int EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT = 0x3443; public const int EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT = 0x3444; public const int EGL_PLATFORM_GBM_KHR = 0x31D7; public const int EGL_SYNC_NATIVE_FENCE_ANDROID = 0x3144; public const int EGL_SYNC_NATIVE_FENCE_FD_ANDROID = 0x3145; public const int EGL_NO_NATIVE_FENCE_FD_ANDROID = -1; public const int EGL_SYNC_FLUSH_COMMANDS_BIT_KHR = 0x0001; public const long EGL_FOREVER_KHR = unchecked((long)0xFFFFFFFFFFFFFFFF); public const int EGL_CONDITION_SATISFIED_KHR = 0x30F6; // GL private const string LibGl = "libGLESv2.so.2"; [LibraryImport(LibGl, EntryPoint = "glGetError")] public static partial int GlGetError(); [LibraryImport(LibGl, EntryPoint = "glGenTextures")] public static partial void GlGenTextures(int n, int* textures); [LibraryImport(LibGl, EntryPoint = "glDeleteTextures")] public static partial void GlDeleteTextures(int n, int* textures); [LibraryImport(LibGl, EntryPoint = "glBindTexture")] public static partial void GlBindTexture(int target, int texture); [LibraryImport(LibGl, EntryPoint = "glGenFramebuffers")] public static partial void GlGenFramebuffers(int n, int* framebuffers); [LibraryImport(LibGl, EntryPoint = "glDeleteFramebuffers")] public static partial void GlDeleteFramebuffers(int n, int* framebuffers); [LibraryImport(LibGl, EntryPoint = "glBindFramebuffer")] public static partial void GlBindFramebuffer(int target, int framebuffer); [LibraryImport(LibGl, EntryPoint = "glFramebufferTexture2D")] public static partial void GlFramebufferTexture2D(int target, int attachment, int texTarget, int texture, int level); [LibraryImport(LibGl, EntryPoint = "glCheckFramebufferStatus")] public static partial int GlCheckFramebufferStatus(int target); [LibraryImport(LibGl, EntryPoint = "glReadPixels")] public static partial void GlReadPixels(int x, int y, int width, int height, int format, int type, void* pixels); [LibraryImport(LibGl, EntryPoint = "glFlush")] public static partial void GlFlush(); [LibraryImport(LibGl, EntryPoint = "glFinish")] public static partial void GlFinish(); public const int GL_TEXTURE_2D = 0x0DE1; public const int GL_FRAMEBUFFER = 0x8D40; public const int GL_COLOR_ATTACHMENT0 = 0x8CE0; public const int GL_FRAMEBUFFER_COMPLETE = 0x8CD5; public const int GL_RGBA = 0x1908; public const int GL_BGRA = 0x80E1; public const int GL_UNSIGNED_BYTE = 0x1401; // Function pointer types for EGL extensions loaded via eglGetProcAddress [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate IntPtr EglCreateImageKHRDelegate(IntPtr dpy, IntPtr ctx, int target, IntPtr buffer, int[] attribs); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.Bool)] public delegate bool EglDestroyImageKHRDelegate(IntPtr dpy, IntPtr image); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.Bool)] public delegate bool EglQueryDmaBufFormatsEXTDelegate(IntPtr dpy, int maxFormats, [Out] int[]? formats, out int numFormats); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.Bool)] public delegate bool EglQueryDmaBufModifiersEXTDelegate(IntPtr dpy, int format, int maxModifiers, [Out] long[]? modifiers, [Out] int[]? externalOnly, out int numModifiers); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GlEGLImageTargetTexture2DOESDelegate(int target, IntPtr image); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate IntPtr EglCreateSyncKHRDelegate(IntPtr dpy, int type, int[] attribs); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.Bool)] public delegate bool EglDestroySyncKHRDelegate(IntPtr dpy, IntPtr sync); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int EglClientWaitSyncKHRDelegate(IntPtr dpy, IntPtr sync, int flags, long timeout); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int EglWaitSyncKHRDelegate(IntPtr dpy, IntPtr sync, int flags); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int EglDupNativeFenceFDANDROIDDelegate(IntPtr dpy, IntPtr sync); public static T? LoadEglExtension(string name) where T : Delegate { var ptr = EglGetProcAddress(name); return ptr == IntPtr.Zero ? null : Marshal.GetDelegateForFunctionPointer(ptr); } }