const c = @cImport({ @cInclude("EGL/egl.h"); @cInclude("GL/gl.h"); }); pub const Error = error{ Unknown, NoDisplay, NotInitialized, BadAccess, BadAlloc, BadAttribute, BadContext, BadConfig, BadCurrentSurface, BadDisplay, BadMatch, BadNativePixmap, BadNativeWindow, BadParameter, BadSurface, ContextLost, }; extern fn eglGetError() i32; fn getError() Error!void { return switch (eglGetError()) { c.EGL_NOT_INITIALIZED => Error.NotInitialized, c.EGL_BAD_ACCESS => Error.BadDisplay, c.EGL_BAD_ATTRIBUTE => Error.BadAttribute, c.EGL_BAD_CONFIG => Error.BadConfig, c.EGL_BAD_CONTEXT => Error.BadContext, c.EGL_BAD_CURRENT_SURFACE => Error.BadCurrentSurface, c.EGL_BAD_DISPLAY => Error.BadDisplay, c.EGL_BAD_MATCH => Error.BadMatch, c.EGL_BAD_NATIVE_PIXMAP => Error.BadNativePixmap, c.EGL_BAD_NATIVE_WINDOW => Error.BadNativeWindow, c.EGL_BAD_PARAMETER => Error.BadParameter, c.EGL_BAD_SURFACE => Error.BadSurface, c.EGL_CONTEXT_LOST => Error.ContextLost, else => Error.Unknown, }; } pub const Api = enum(u32) { opengl = c.EGL_OPENGL_API, opengl_es = c.EGL_OPENGL_ES_API, }; extern fn eglBindAPI(api: Api) bool; pub fn bindApi(api: Api) Error!void { if (!eglBindAPI(api)) try getError(); } pub const AttributeType = enum(i32) { none = c.EGL_NONE, alpha_size = c.EGL_ALPHA_SIZE, red_size = c.EGL_RED_SIZE, green_size = c.EGL_GREEN_SIZE, blue_size = c.EGL_BLUE_SIZE, }; pub const Attribute = packed struct { type: AttributeType, value: i32, }; pub const Config = opaque {}; pub const Surface = opaque {}; pub const Context = opaque {}; pub const Display = opaque { extern fn eglGetDisplay(native_display: *anyopaque) ?*Display; pub fn get(native_display: *anyopaque) Error!*Display { return eglGetDisplay( native_display, ) orelse Error.NoDisplay; } extern fn eglInitialize(display: *Display, major: ?*i32, minor: ?*i32) bool; pub fn initialize(display: *Display, major: ?*i32, minor: ?*i32) Error!void { if (!eglInitialize(display, major, minor)) try getError(); } extern fn eglChooseConfig( display: *Display, attributes: [*c]Attribute, configs: [*c]*Config, configs_len: i32, config_cnt: *i32, ) bool; /// Returns the number of configs that were put in @configs. pub fn chooseConfig( display: *Display, attributes: []Attribute, configs: []*Config, ) Error!i32 { var config_cnt: i32 = 0; if (!eglChooseConfig( display, attributes.ptr, configs.ptr, @intCast(configs.len), &config_cnt, )) { try getError(); } return config_cnt; } extern fn eglCreateContext( display: *Display, config: *Config, share_ctx: ?*Context, attributes: [*c]Attribute, ) ?*Context; pub fn createContext( display: *Display, config: *Config, share_ctx: ?*Context, attributes: ?[]Attribute, ) Error!*Context { var attrs: [*c]Attribute = null; if (attributes) |_attrs| attrs = _attrs.ptr; return eglCreateContext(display, config, share_ctx, attrs) orelse { try getError(); unreachable; }; } extern fn eglCreateWindowSurface( display: *Display, config: *Config, native_window: *anyopaque, attributes: [*c]Attribute, ) ?*Surface; pub fn createWindowSurface( display: *Display, config: *Config, native_window: *anyopaque, attributes: ?[]Attribute, ) Error!*Surface { var attrs: [*c]Attribute = null; if (attributes) |_attrs| attrs = _attrs.ptr; return eglCreateWindowSurface(display, config, native_window, attrs) orelse { try getError(); unreachable; }; } extern fn eglMakeCurrent( display: *Display, draw: *Surface, read: *Surface, ctx: *Context, ) bool; pub fn makeCurrent( display: *Display, draw: *Surface, read: *Surface, ctx: *Context, ) Error!void { if (!eglMakeCurrent(display, draw, read, ctx)) try getError(); } extern fn eglQueryString(display: *Display, name: i32) [*:0]const u8; pub const queryString = eglQueryString; extern fn eglSwapBuffers(display: *Display, surface: *Surface) bool; pub fn swapBuffers(display: *Display, surface: *Surface) Error!void { if (!eglSwapBuffers(display, surface)) try getError(); } extern fn eglSwapInterval(display: *Display, interval: i32) bool; pub fn swapInterval(display: *Display, interval: i32) Error!void { if (!eglSwapInterval(display, interval)) try getError(); } extern fn eglTerminate(display: *Display) bool; pub fn terminate(display: *Display) void { // Do I really care if destruction fails? _ = eglTerminate(display); } };