From b8cee0a39eaeda11622d4e2ced44fccfcd702203 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 29 Mar 2022 10:38:10 -0700 Subject: [PATCH] initial glfw stuff working --- build.zig | 26 ++++++++++ nix/devshell.nix | 6 +++ src/glfw/c.zig | 4 ++ src/glfw/errors.zig | 124 ++++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 7 +++ 5 files changed, 167 insertions(+) create mode 100644 build.zig create mode 100644 src/glfw/c.zig create mode 100644 src/glfw/errors.zig create mode 100644 src/main.zig diff --git a/build.zig b/build.zig new file mode 100644 index 000000000..3c2057289 --- /dev/null +++ b/build.zig @@ -0,0 +1,26 @@ +const std = @import("std"); +const Builder = std.build.Builder; +const LibExeObjStep = std.build.LibExeObjStep; + +pub fn build(b: *std.build.Builder) void { + const target = b.standardTargetOptions(.{}); + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("ghostty", "src/main.zig"); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + exe.linkLibC(); + exe.linkSystemLibrary("glfw3"); + // exe.linkSystemLibrary("X11"); + // exe.linkSystemLibrary("xcb"); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/nix/devshell.nix b/nix/devshell.nix index e00f93eb2..78d429dd6 100644 --- a/nix/devshell.nix +++ b/nix/devshell.nix @@ -1,14 +1,18 @@ { mkShell, lib, stdenv +, gdb , pkg-config , scdoc , zig +, glfw , libX11 +, vulkan-headers }: mkShell rec { name = "ghostty"; nativeBuildInputs = [ + gdb pkg-config scdoc zig @@ -16,6 +20,8 @@ buildInputs = [ ] ++ lib.optionals stdenv.isLinux [ + glfw libX11 + vulkan-headers ]; } diff --git a/src/glfw/c.zig b/src/glfw/c.zig new file mode 100644 index 000000000..6a6b352ab --- /dev/null +++ b/src/glfw/c.zig @@ -0,0 +1,4 @@ +pub usingnamespace @cImport({ + @cDefine("GLFW_INCLUDE_VULKAN", "1"); + @cInclude("GLFW/glfw3.h"); +}); diff --git a/src/glfw/errors.zig b/src/glfw/errors.zig new file mode 100644 index 000000000..d9d4103e0 --- /dev/null +++ b/src/glfw/errors.zig @@ -0,0 +1,124 @@ +const c = @import("c.zig"); + +/// Errors that GLFW can produce. +pub const Error = error{ + /// GLFW has not been initialized. + /// + /// This occurs if a GLFW function was called that must not be called unless the library is + /// initialized. + NotInitialized, + + /// No context is current for this thread. + /// + /// This occurs if a GLFW function was called that needs and operates on the current OpenGL or + /// OpenGL ES context but no context is current on the calling thread. One such function is + /// glfw.SwapInterval. + NoCurrentContext, + + /// One of the arguments to the function was an invalid enum value. + /// + /// One of the arguments to the function was an invalid enum value, for example requesting + /// glfw.red_bits with glfw.getWindowAttrib. + InvalidEnum, + + /// One of the arguments to the function was an invalid value. + /// + /// One of the arguments to the function was an invalid value, for example requesting a + /// non-existent OpenGL or OpenGL ES version like 2.7. + /// + /// Requesting a valid but unavailable OpenGL or OpenGL ES version will instead result in a + /// glfw.Error.VersionUnavailable error. + InvalidValue, + + /// A memory allocation failed. + OutOfMemory, + + /// GLFW could not find support for the requested API on the system. + /// + /// The installed graphics driver does not support the requested API, or does not support it + /// via the chosen context creation backend. Below are a few examples. + /// + /// Some pre-installed Windows graphics drivers do not support OpenGL. AMD only supports + /// OpenGL ES via EGL, while Nvidia and Intel only support it via a WGL or GLX extension. macOS + /// does not provide OpenGL ES at all. The Mesa EGL, OpenGL and OpenGL ES libraries do not + /// interface with the Nvidia binary driver. Older graphics drivers do not support Vulkan. + APIUnavailable, + + /// The requested OpenGL or OpenGL ES version (including any requested context or framebuffer + /// hints) is not available on this machine. + /// + /// The machine does not support your requirements. If your application is sufficiently + /// flexible, downgrade your requirements and try again. Otherwise, inform the user that their + /// machine does not match your requirements. + /// + /// Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0 comes out + /// before the 4.x series gets that far, also fail with this error and not glfw.Error.InvalidValue, + /// because GLFW cannot know what future versions will exist. + VersionUnavailable, + + /// A platform-specific error occurred that does not match any of the more specific categories. + /// + /// A bug or configuration error in GLFW, the underlying operating system or its drivers, or a + /// lack of required resources. Report the issue to our [issue tracker](https://github.com/glfw/glfw/issues). + PlatformError, + + /// The requested format is not supported or available. + /// + /// If emitted during window creation, the requested pixel format is not supported. + /// + /// If emitted when querying the clipboard, the contents of the clipboard could not be + /// converted to the requested format. + /// + /// If emitted during window creation, one or more hard constraints did not match any of the + /// available pixel formats. If your application is sufficiently flexible, downgrade your + /// requirements and try again. Otherwise, inform the user that their machine does not match + /// your requirements. + /// + /// If emitted when querying the clipboard, ignore the error or report it to the user, as + /// appropriate. + FormatUnavailable, + + /// The specified window does not have an OpenGL or OpenGL ES context. + /// + /// A window that does not have an OpenGL or OpenGL ES context was passed to a function that + /// requires it to have one. + NoWindowContext, +}; + +fn convertError(e: c_int) Error!void { + return switch (e) { + c.GLFW_NO_ERROR => {}, + c.GLFW_NOT_INITIALIZED => Error.NotInitialized, + c.GLFW_NO_CURRENT_CONTEXT => Error.NoCurrentContext, + c.GLFW_INVALID_ENUM => Error.InvalidEnum, + c.GLFW_INVALID_VALUE => Error.InvalidValue, + c.GLFW_OUT_OF_MEMORY => Error.OutOfMemory, + c.GLFW_API_UNAVAILABLE => Error.APIUnavailable, + c.GLFW_VERSION_UNAVAILABLE => Error.VersionUnavailable, + c.GLFW_PLATFORM_ERROR => Error.PlatformError, + c.GLFW_FORMAT_UNAVAILABLE => Error.FormatUnavailable, + c.GLFW_NO_WINDOW_CONTEXT => Error.NoWindowContext, + else => unreachable, + }; +} + +/// Returns and clears the last error for the calling thread. +/// +/// This function returns and clears the error code of the last error that occurred on the calling +/// thread, and optionally a UTF-8 encoded human-readable description of it. If no error has +/// occurred since the last call, it returns GLFW_NO_ERROR (zero) and the description pointer is +/// set to `NULL`. +/// +/// * @param[in] description Where to store the error description pointer, or `NULL`. +/// @return The last error code for the calling thread, or @ref GLFW_NO_ERROR (zero). +/// +/// @pointer_lifetime The returned string is allocated and freed by GLFW. You should not free it +/// yourself. It is guaranteed to be valid only until the next error occurs or the library is +/// terminated. +/// +/// @remark This function may be called before @ref glfwInit. +/// +/// @thread_safety This function may be called from any thread. +pub inline fn getError() Error!void { + return convertError(c.glfwGetError(null)); +} diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 000000000..f10f3f0e9 --- /dev/null +++ b/src/main.zig @@ -0,0 +1,7 @@ +const std = @import("std"); +const c = @import("glfw/c.zig"); + +pub fn main() !void { + if (c.glfwInit() != c.GLFW_TRUE) return error.GlfwInitFailed; + defer c.glfwTerminate(); +}