From 5b1d5fc0325dc5e20ccb7b1ce445721762256848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20de=20la=20Pe=C3=B1a=20Smirnov?= Date: Wed, 18 Sep 2024 00:02:33 +0300 Subject: opengl: triangle OpenGL hello world triangle on Wayland. --- src/egl.zig | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/egl.zig (limited to 'src/egl.zig') diff --git a/src/egl.zig b/src/egl.zig new file mode 100644 index 0000000..ad5be7c --- /dev/null +++ b/src/egl.zig @@ -0,0 +1,186 @@ +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); + } +}; -- cgit v1.2.3