address review: port win32 apprt to zigwin32
Per @marler8997 and @jcollie, use the marlersoft/zigwin32 bindings
instead of hand-rolled extern decls for the Win32 API. Drops the
inline type / constant / function declarations in App.zig and
Surface.zig in favor of `@import("win32").everything`. The binding
is declared lazy in build.zig.zon so it's only fetched when building
the win32 apprt.
Net effect: -240 / +101 lines. Type-safe style flags (packed structs
for `WNDCLASS_STYLES`, `WINDOW_STYLE`, pixel format flags) replace
raw OR'd u32 constants. Also clears a known Zig 0.16 risk since
std.os.windows is shedding symbols the earlier code was relying on
(pointed out in jcollie's review note).
Co-authored-by: Claude <noreply@anthropic.com>
pull/12403/head
parent
289c6a578f
commit
2ad00dc628
|
|
@ -61,6 +61,12 @@
|
|||
.hash = "gobject-0.3.0-Skun7ANLnwDvEfIpVmohcppXgOvg_I6YOJFmPIsKfXk-",
|
||||
.lazy = true,
|
||||
},
|
||||
.win32 = .{
|
||||
// marlersoft/zigwin32 -- Win32 API bindings for the win32 apprt.
|
||||
.url = "git+https://github.com/marlersoft/zigwin32#ec98bb4d9eea532320a8551720a9e3ec6de64994",
|
||||
.hash = "win32-25.0.28-preview-mX5pFWMt5QPTVIGh3r2-OpPunpcCCjApyRbA6Zn6WALH",
|
||||
.lazy = true,
|
||||
},
|
||||
|
||||
// C libs
|
||||
.dcimgui = .{ .path = "./pkg/dcimgui", .lazy = true },
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const App = @This();
|
|||
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const win32 = @import("win32").everything;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const apprt = @import("../../apprt.zig");
|
||||
const configpkg = @import("../../config.zig");
|
||||
|
|
@ -15,109 +16,9 @@ const renderer = @import("../../renderer.zig");
|
|||
|
||||
const log = std.log.scoped(.win32);
|
||||
|
||||
// Win32 type definitions
|
||||
const BOOL = i32;
|
||||
const UINT = u32;
|
||||
const DWORD = u32;
|
||||
const WPARAM = usize;
|
||||
const LPARAM = isize;
|
||||
const LRESULT = isize;
|
||||
const HWND = std.os.windows.HWND;
|
||||
const HINSTANCE = std.os.windows.HINSTANCE;
|
||||
const HICON = ?*anyopaque;
|
||||
const HCURSOR = ?*anyopaque;
|
||||
const HBRUSH = ?*anyopaque;
|
||||
const HDC = ?*anyopaque;
|
||||
const HMENU = ?*anyopaque;
|
||||
const ATOM = u16;
|
||||
const LONG_PTR = isize;
|
||||
|
||||
const POINT = extern struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
const MSG = extern struct {
|
||||
hwnd: ?HWND,
|
||||
message: UINT,
|
||||
wParam: WPARAM,
|
||||
lParam: LPARAM,
|
||||
time: DWORD,
|
||||
pt: POINT,
|
||||
};
|
||||
|
||||
const RECT = extern struct {
|
||||
left: i32,
|
||||
top: i32,
|
||||
right: i32,
|
||||
bottom: i32,
|
||||
};
|
||||
|
||||
const PAINTSTRUCT = extern struct {
|
||||
hdc: HDC,
|
||||
fErase: BOOL,
|
||||
rcPaint: RECT,
|
||||
fRestore: BOOL,
|
||||
fIncUpdate: BOOL,
|
||||
rgbReserved: [32]u8,
|
||||
};
|
||||
|
||||
const WNDPROC = *const fn (HWND, UINT, WPARAM, LPARAM) callconv(.winapi) LRESULT;
|
||||
|
||||
const WNDCLASSEXW = extern struct {
|
||||
cbSize: UINT,
|
||||
style: UINT,
|
||||
lpfnWndProc: WNDPROC,
|
||||
cbClsExtra: c_int,
|
||||
cbWndExtra: c_int,
|
||||
hInstance: ?HINSTANCE,
|
||||
hIcon: HICON,
|
||||
hCursor: HCURSOR,
|
||||
hbrBackground: HBRUSH,
|
||||
lpszMenuName: ?[*:0]const u16,
|
||||
lpszClassName: [*:0]const u16,
|
||||
hIconSm: HICON,
|
||||
};
|
||||
|
||||
// Win32 constants
|
||||
const WM_CLOSE = 0x0010;
|
||||
const WM_DESTROY = 0x0002;
|
||||
const WM_PAINT = 0x000F;
|
||||
const WM_SIZE = 0x0005;
|
||||
const WM_KEYDOWN = 0x0100;
|
||||
const WM_CHAR = 0x0102;
|
||||
const WM_USER = 0x0400;
|
||||
const WM_WAKEUP = WM_USER + 1;
|
||||
const CS_HREDRAW = 0x0002;
|
||||
const CS_VREDRAW = 0x0001;
|
||||
const CS_OWNDC = 0x0020;
|
||||
const WS_OVERLAPPEDWINDOW = 0x00CF0000;
|
||||
const CW_USEDEFAULT: i32 = @bitCast(@as(u32, 0x80000000));
|
||||
const SW_SHOWNORMAL = 1;
|
||||
const IDC_ARROW: ?[*:0]align(1) const u16 = @ptrFromInt(32512);
|
||||
const GWLP_USERDATA: c_int = -21;
|
||||
|
||||
// Win32 API extern declarations
|
||||
extern "user32" fn RegisterClassExW(lpWndClass: *const WNDCLASSEXW) callconv(.winapi) ATOM;
|
||||
extern "user32" fn CreateWindowExW(dwExStyle: DWORD, lpClassName: ?[*:0]const u16, lpWindowName: ?[*:0]const u16, dwStyle: DWORD, x: i32, y: i32, nWidth: i32, nHeight: i32, hWndParent: ?HWND, hMenu: HMENU, hInstance: ?HINSTANCE, lpParam: ?*anyopaque) callconv(.winapi) ?HWND;
|
||||
extern "user32" fn ShowWindow(hWnd: HWND, nCmdShow: c_int) callconv(.winapi) BOOL;
|
||||
extern "user32" fn UpdateWindow(hWnd: HWND) callconv(.winapi) BOOL;
|
||||
extern "user32" fn DestroyWindow(hWnd: HWND) callconv(.winapi) BOOL;
|
||||
extern "user32" fn DefWindowProcW(hWnd: HWND, msg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(.winapi) LRESULT;
|
||||
extern "user32" fn GetMessageW(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) callconv(.winapi) BOOL;
|
||||
extern "user32" fn TranslateMessage(lpMsg: *const MSG) callconv(.winapi) BOOL;
|
||||
extern "user32" fn DispatchMessageW(lpMsg: *const MSG) callconv(.winapi) LRESULT;
|
||||
extern "user32" fn PostMessageW(hWnd: HWND, msg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(.winapi) BOOL;
|
||||
extern "user32" fn PostQuitMessage(nExitCode: c_int) callconv(.winapi) void;
|
||||
extern "user32" fn BeginPaint(hWnd: HWND, lpPaint: *PAINTSTRUCT) callconv(.winapi) HDC;
|
||||
extern "user32" fn EndPaint(hWnd: HWND, lpPaint: *const PAINTSTRUCT) callconv(.winapi) BOOL;
|
||||
extern "user32" fn LoadCursorW(hInstance: ?HINSTANCE, lpCursorName: ?[*:0]align(1) const u16) callconv(.winapi) HCURSOR;
|
||||
extern "user32" fn SetWindowLongPtrW(hWnd: HWND, nIndex: c_int, dwNewLong: LONG_PTR) callconv(.winapi) LONG_PTR;
|
||||
extern "user32" fn GetWindowLongPtrW(hWnd: HWND, nIndex: c_int) callconv(.winapi) LONG_PTR;
|
||||
extern "user32" fn GetClientRect(hWnd: HWND, lpRect: *RECT) callconv(.winapi) BOOL;
|
||||
extern "user32" fn InvalidateRect(hWnd: ?HWND, lpRect: ?*const RECT, bErase: BOOL) callconv(.winapi) BOOL;
|
||||
extern "kernel32" fn GetModuleHandleW(lpModuleName: ?[*:0]const u16) callconv(.winapi) ?HINSTANCE;
|
||||
extern "kernel32" fn GetLastError() callconv(.winapi) DWORD;
|
||||
/// User-defined wakeup message sent via PostMessage to break out of
|
||||
/// GetMessage and run the core app's tick.
|
||||
const WM_WAKEUP = win32.WM_USER + 1;
|
||||
|
||||
/// The core app instance.
|
||||
core_app: *CoreApp,
|
||||
|
|
@ -132,7 +33,7 @@ alloc: Allocator,
|
|||
running: bool = true,
|
||||
|
||||
/// The main window handle.
|
||||
hwnd: ?HWND = null,
|
||||
hwnd: ?win32.HWND = null,
|
||||
|
||||
/// The surface for the main window.
|
||||
surface: Surface = undefined,
|
||||
|
|
@ -165,8 +66,14 @@ pub fn init(
|
|||
// Initialize the surface with OpenGL
|
||||
try self.surface.init(self.hwnd.?);
|
||||
|
||||
// Store self pointer in window for use in wndProc
|
||||
_ = SetWindowLongPtrW(self.hwnd.?, GWLP_USERDATA, @bitCast(@intFromPtr(self)));
|
||||
// Store self pointer in window for use in wndProc. SetWindowLongPtrW
|
||||
// returns the previous value, which for a freshly created window is 0;
|
||||
// we don't care about it here.
|
||||
_ = win32.SetWindowLongPtrW(
|
||||
self.hwnd.?,
|
||||
win32.GWLP_USERDATA,
|
||||
@bitCast(@intFromPtr(self)),
|
||||
);
|
||||
|
||||
// Initialize the core surface (terminal emulation + rendering)
|
||||
try self.initCoreSurface();
|
||||
|
|
@ -176,27 +83,27 @@ pub fn run(self: *App) !void {
|
|||
log.info("starting Win32 event loop", .{});
|
||||
|
||||
while (self.running) {
|
||||
var msg: MSG = std.mem.zeroes(MSG);
|
||||
const ret = GetMessageW(&msg, null, 0, 0);
|
||||
var msg: win32.MSG = std.mem.zeroes(win32.MSG);
|
||||
const ret = win32.GetMessageW(&msg, null, 0, 0);
|
||||
if (ret == 0) {
|
||||
// WM_QUIT
|
||||
self.running = false;
|
||||
break;
|
||||
}
|
||||
if (ret == -1) {
|
||||
log.err("GetMessage failed", .{});
|
||||
log.err("GetMessage failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
_ = TranslateMessage(&msg);
|
||||
_ = DispatchMessageW(&msg);
|
||||
_ = win32.TranslateMessage(&msg);
|
||||
_ = win32.DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terminate(self: *App) void {
|
||||
self.surface.deinit();
|
||||
if (self.hwnd) |hwnd| {
|
||||
if (DestroyWindow(hwnd) == 0) {
|
||||
log.warn("DestroyWindow failed: err={d}", .{GetLastError()});
|
||||
if (win32.DestroyWindow(hwnd) == 0) {
|
||||
log.warn("DestroyWindow failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
}
|
||||
self.hwnd = null;
|
||||
}
|
||||
|
|
@ -206,8 +113,8 @@ pub fn terminate(self: *App) void {
|
|||
|
||||
pub fn wakeup(self: *App) void {
|
||||
if (self.hwnd) |hwnd| {
|
||||
if (PostMessageW(hwnd, WM_WAKEUP, 0, 0) == 0) {
|
||||
log.warn("PostMessage(WM_WAKEUP) failed: err={d}", .{GetLastError()});
|
||||
if (win32.PostMessageW(hwnd, WM_WAKEUP, 0, 0) == 0) {
|
||||
log.warn("PostMessage(WM_WAKEUP) failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -224,7 +131,7 @@ pub fn performAction(
|
|||
|
||||
switch (action) {
|
||||
.quit => {
|
||||
PostQuitMessage(0);
|
||||
win32.PostQuitMessage(0);
|
||||
return true;
|
||||
},
|
||||
.new_window => {
|
||||
|
|
@ -287,68 +194,66 @@ fn initCoreSurface(self: *App) !void {
|
|||
}
|
||||
|
||||
fn createWindow(self: *App) !void {
|
||||
const class_name = std.unicode.utf8ToUtf16LeStringLiteral("GhosttyWindow");
|
||||
const hinstance = GetModuleHandleW(null);
|
||||
const class_name = win32.L("GhosttyWindow");
|
||||
const hinstance = win32.GetModuleHandleW(null);
|
||||
|
||||
const wc: WNDCLASSEXW = .{
|
||||
.cbSize = @sizeOf(WNDCLASSEXW),
|
||||
.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
|
||||
const wc: win32.WNDCLASSEXW = .{
|
||||
.cbSize = @sizeOf(win32.WNDCLASSEXW),
|
||||
.style = .{ .HREDRAW = 1, .VREDRAW = 1, .OWNDC = 1 },
|
||||
.lpfnWndProc = wndProc,
|
||||
.cbClsExtra = 0,
|
||||
.cbWndExtra = 0,
|
||||
.hInstance = hinstance,
|
||||
.hIcon = null,
|
||||
.hCursor = LoadCursorW(null, IDC_ARROW),
|
||||
.hCursor = win32.LoadCursorW(null, win32.IDC_ARROW),
|
||||
.hbrBackground = null,
|
||||
.lpszMenuName = null,
|
||||
.lpszClassName = class_name,
|
||||
.hIconSm = null,
|
||||
};
|
||||
|
||||
if (RegisterClassExW(&wc) == 0) {
|
||||
log.err("RegisterClassEx failed", .{});
|
||||
if (win32.RegisterClassExW(&wc) == 0) {
|
||||
log.err("RegisterClassExW failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
|
||||
const title = std.unicode.utf8ToUtf16LeStringLiteral("Ghostty");
|
||||
const title = win32.L("Ghostty");
|
||||
|
||||
self.hwnd = CreateWindowExW(
|
||||
0,
|
||||
self.hwnd = win32.CreateWindowExW(
|
||||
.{},
|
||||
class_name,
|
||||
title,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
win32.WS_OVERLAPPEDWINDOW,
|
||||
win32.CW_USEDEFAULT,
|
||||
win32.CW_USEDEFAULT,
|
||||
800,
|
||||
600,
|
||||
null,
|
||||
null,
|
||||
hinstance,
|
||||
null,
|
||||
);
|
||||
|
||||
if (self.hwnd == null) {
|
||||
log.err("CreateWindowEx failed", .{});
|
||||
) orelse {
|
||||
log.err("CreateWindowExW failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
};
|
||||
|
||||
_ = ShowWindow(self.hwnd.?, SW_SHOWNORMAL);
|
||||
_ = UpdateWindow(self.hwnd.?);
|
||||
_ = win32.ShowWindow(self.hwnd.?, win32.SW_SHOWNORMAL);
|
||||
_ = win32.UpdateWindow(self.hwnd.?);
|
||||
}
|
||||
|
||||
fn getApp(hwnd: HWND) ?*App {
|
||||
const ptr = GetWindowLongPtrW(hwnd, GWLP_USERDATA);
|
||||
fn getApp(hwnd: win32.HWND) ?*App {
|
||||
const ptr = win32.GetWindowLongPtrW(hwnd, win32.GWLP_USERDATA);
|
||||
if (ptr == 0) return null;
|
||||
return @ptrFromInt(@as(usize, @bitCast(ptr)));
|
||||
}
|
||||
|
||||
fn wndProc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) callconv(.winapi) LRESULT {
|
||||
fn wndProc(hwnd: win32.HWND, msg: u32, wparam: win32.WPARAM, lparam: win32.LPARAM) callconv(.winapi) win32.LRESULT {
|
||||
switch (msg) {
|
||||
WM_CLOSE => {
|
||||
PostQuitMessage(0);
|
||||
win32.WM_CLOSE => {
|
||||
win32.PostQuitMessage(0);
|
||||
return 0;
|
||||
},
|
||||
WM_SIZE => {
|
||||
win32.WM_SIZE => {
|
||||
if (getApp(hwnd)) |app| {
|
||||
const width: u32 = @intCast(lparam & 0xFFFF);
|
||||
const height: u32 = @intCast((lparam >> 16) & 0xFFFF);
|
||||
|
|
@ -367,13 +272,13 @@ fn wndProc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) callconv(.wina
|
|||
}
|
||||
return 0;
|
||||
},
|
||||
WM_PAINT => {
|
||||
var ps: PAINTSTRUCT = std.mem.zeroes(PAINTSTRUCT);
|
||||
_ = BeginPaint(hwnd, &ps);
|
||||
win32.WM_PAINT => {
|
||||
var ps: win32.PAINTSTRUCT = std.mem.zeroes(win32.PAINTSTRUCT);
|
||||
_ = win32.BeginPaint(hwnd, &ps);
|
||||
if (getApp(hwnd)) |app| {
|
||||
app.surface.swapBuffers();
|
||||
}
|
||||
_ = EndPaint(hwnd, &ps);
|
||||
_ = win32.EndPaint(hwnd, &ps);
|
||||
return 0;
|
||||
},
|
||||
WM_WAKEUP => {
|
||||
|
|
@ -384,6 +289,6 @@ fn wndProc(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) callconv(.wina
|
|||
}
|
||||
return 0;
|
||||
},
|
||||
else => return DefWindowProcW(hwnd, msg, wparam, lparam),
|
||||
else => return win32.DefWindowProcW(hwnd, msg, wparam, lparam),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
const Self = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const win32 = @import("win32").everything;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const apprt = @import("../../apprt.zig");
|
||||
const configpkg = @import("../../config.zig");
|
||||
|
|
@ -12,71 +13,17 @@ const CoreApp = @import("../../App.zig");
|
|||
|
||||
const log = std.log.scoped(.win32_surface);
|
||||
|
||||
// Win32 types
|
||||
const HWND = std.os.windows.HWND;
|
||||
const HINSTANCE = std.os.windows.HINSTANCE;
|
||||
const BOOL = i32;
|
||||
const HDC = ?*anyopaque;
|
||||
const HGLRC = ?*anyopaque;
|
||||
|
||||
const PIXELFORMATDESCRIPTOR = extern struct {
|
||||
nSize: u16,
|
||||
nVersion: u16,
|
||||
dwFlags: u32,
|
||||
iPixelType: u8,
|
||||
cColorBits: u8,
|
||||
cRedBits: u8,
|
||||
cRedShift: u8,
|
||||
cGreenBits: u8,
|
||||
cGreenShift: u8,
|
||||
cBlueBits: u8,
|
||||
cBlueShift: u8,
|
||||
cAlphaBits: u8,
|
||||
cAlphaShift: u8,
|
||||
cAccumBits: u8,
|
||||
cAccumRedBits: u8,
|
||||
cAccumGreenBits: u8,
|
||||
cAccumBlueBits: u8,
|
||||
cAccumAlphaBits: u8,
|
||||
cDepthBits: u8,
|
||||
cStencilBits: u8,
|
||||
cAuxBuffers: u8,
|
||||
iLayerType: u8,
|
||||
bReserved: u8,
|
||||
dwLayerMask: u32,
|
||||
dwVisibleMask: u32,
|
||||
dwDamageMask: u32,
|
||||
};
|
||||
|
||||
// WGL / GDI constants
|
||||
const PFD_DRAW_TO_WINDOW = 0x00000004;
|
||||
const PFD_SUPPORT_OPENGL = 0x00000020;
|
||||
const PFD_DOUBLEBUFFER = 0x00000001;
|
||||
const PFD_TYPE_RGBA = 0;
|
||||
const PFD_MAIN_PLANE = 0;
|
||||
|
||||
// WGL / GDI extern declarations
|
||||
extern "user32" fn GetDC(hWnd: ?HWND) callconv(.winapi) HDC;
|
||||
extern "user32" fn ReleaseDC(hWnd: ?HWND, hDC: HDC) callconv(.winapi) c_int;
|
||||
extern "gdi32" fn ChoosePixelFormat(hdc: HDC, ppfd: *const PIXELFORMATDESCRIPTOR) callconv(.winapi) c_int;
|
||||
extern "gdi32" fn SetPixelFormat(hdc: HDC, format: c_int, ppfd: *const PIXELFORMATDESCRIPTOR) callconv(.winapi) BOOL;
|
||||
extern "gdi32" fn SwapBuffers(hdc: HDC) callconv(.winapi) BOOL;
|
||||
extern "opengl32" fn wglCreateContext(hdc: HDC) callconv(.winapi) HGLRC;
|
||||
extern "opengl32" fn wglDeleteContext(hglrc: HGLRC) callconv(.winapi) BOOL;
|
||||
extern "opengl32" fn wglMakeCurrent(hdc: HDC, hglrc: HGLRC) callconv(.winapi) BOOL;
|
||||
extern "kernel32" fn GetLastError() callconv(.winapi) u32;
|
||||
|
||||
/// The window this surface belongs to.
|
||||
hwnd: HWND,
|
||||
hwnd: win32.HWND,
|
||||
|
||||
/// Pointer back to the App.
|
||||
app: ?*App = null,
|
||||
|
||||
/// GDI device context.
|
||||
hdc: HDC = null,
|
||||
hdc: ?win32.HDC = null,
|
||||
|
||||
/// OpenGL rendering context.
|
||||
hglrc: HGLRC = null,
|
||||
hglrc: ?win32.HGLRC = null,
|
||||
|
||||
/// The core surface, if initialized.
|
||||
core_surface: ?*CoreSurface = null,
|
||||
|
|
@ -95,7 +42,7 @@ pub fn rtApp(self: *Self) *App {
|
|||
return self.app.?;
|
||||
}
|
||||
|
||||
pub fn init(self: *Self, hwnd: HWND) !void {
|
||||
pub fn init(self: *Self, hwnd: win32.HWND) !void {
|
||||
self.* = .{ .hwnd = hwnd };
|
||||
try self.initOpenGL();
|
||||
}
|
||||
|
|
@ -105,51 +52,49 @@ pub fn deinit(self: *Self) void {
|
|||
surface.deinit();
|
||||
// core_surface is allocated by CoreApp, freed there
|
||||
}
|
||||
if (self.hglrc != null) {
|
||||
_ = wglMakeCurrent(null, null);
|
||||
_ = wglDeleteContext(self.hglrc);
|
||||
if (self.hglrc) |hglrc| {
|
||||
_ = win32.wglMakeCurrent(null, null);
|
||||
_ = win32.wglDeleteContext(hglrc);
|
||||
}
|
||||
if (self.hdc != null) {
|
||||
_ = ReleaseDC(self.hwnd, self.hdc);
|
||||
if (self.hdc) |hdc| {
|
||||
_ = win32.ReleaseDC(self.hwnd, hdc);
|
||||
}
|
||||
}
|
||||
|
||||
fn initOpenGL(self: *Self) !void {
|
||||
self.hdc = GetDC(self.hwnd);
|
||||
if (self.hdc == null) {
|
||||
log.err("GetDC failed", .{});
|
||||
self.hdc = win32.GetDC(self.hwnd) orelse {
|
||||
log.err("GetDC failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
};
|
||||
|
||||
var pfd: PIXELFORMATDESCRIPTOR = std.mem.zeroes(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nSize = @sizeOf(PIXELFORMATDESCRIPTOR);
|
||||
var pfd: win32.PIXELFORMATDESCRIPTOR = std.mem.zeroes(win32.PIXELFORMATDESCRIPTOR);
|
||||
pfd.nSize = @sizeOf(win32.PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.dwFlags = .{ .DRAW_TO_WINDOW = 1, .SUPPORT_OPENGL = 1, .DOUBLEBUFFER = 1 };
|
||||
pfd.iPixelType = .RGBA;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cDepthBits = 24;
|
||||
pfd.cStencilBits = 8;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
pfd.iLayerType = .MAIN_PLANE;
|
||||
|
||||
const pixel_format = ChoosePixelFormat(self.hdc, &pfd);
|
||||
const pixel_format = win32.ChoosePixelFormat(self.hdc, &pfd);
|
||||
if (pixel_format == 0) {
|
||||
log.err("ChoosePixelFormat failed", .{});
|
||||
log.err("ChoosePixelFormat failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
|
||||
if (SetPixelFormat(self.hdc, pixel_format, &pfd) == 0) {
|
||||
log.err("SetPixelFormat failed", .{});
|
||||
if (win32.SetPixelFormat(self.hdc, pixel_format, &pfd) == 0) {
|
||||
log.err("SetPixelFormat failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
|
||||
self.hglrc = wglCreateContext(self.hdc);
|
||||
if (self.hglrc == null) {
|
||||
log.err("wglCreateContext failed", .{});
|
||||
self.hglrc = win32.wglCreateContext(self.hdc) orelse {
|
||||
log.err("wglCreateContext failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
};
|
||||
|
||||
if (wglMakeCurrent(self.hdc, self.hglrc) == 0) {
|
||||
log.err("wglMakeCurrent failed", .{});
|
||||
if (win32.wglMakeCurrent(self.hdc, self.hglrc) == 0) {
|
||||
log.err("wglMakeCurrent failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
return error.Win32Error;
|
||||
}
|
||||
|
||||
|
|
@ -157,34 +102,36 @@ fn initOpenGL(self: *Self) !void {
|
|||
}
|
||||
|
||||
pub fn swapBuffers(self: *Self) void {
|
||||
if (self.hdc != null) {
|
||||
if (SwapBuffers(self.hdc) == 0) {
|
||||
log.warn("SwapBuffers failed: err={d}", .{GetLastError()});
|
||||
if (self.hdc) |hdc| {
|
||||
if (win32.SwapBuffers(hdc) == 0) {
|
||||
log.warn("SwapBuffers failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Make the WGL context current on the calling thread.
|
||||
pub fn makeContextCurrent(self: *Self) void {
|
||||
if (self.hdc != null and self.hglrc != null) {
|
||||
if (wglMakeCurrent(self.hdc, self.hglrc) == 0) {
|
||||
log.warn("wglMakeCurrent failed: err={d}", .{GetLastError()});
|
||||
if (self.hdc) |hdc| {
|
||||
if (self.hglrc) |hglrc| {
|
||||
if (win32.wglMakeCurrent(hdc, hglrc) == 0) {
|
||||
log.warn("wglMakeCurrent failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Release the WGL context from the calling thread.
|
||||
pub fn releaseContext() void {
|
||||
if (wglMakeCurrent(null, null) == 0) {
|
||||
log.warn("wglMakeCurrent(null) failed: err={d}", .{GetLastError()});
|
||||
if (win32.wglMakeCurrent(null, null) == 0) {
|
||||
log.warn("wglMakeCurrent(null) failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
}
|
||||
}
|
||||
|
||||
/// Release context from the main thread before handing off to renderer thread.
|
||||
pub fn releaseMainThreadContext(self: *Self) void {
|
||||
_ = self;
|
||||
if (wglMakeCurrent(null, null) == 0) {
|
||||
log.warn("wglMakeCurrent(null) failed: err={d}", .{GetLastError()});
|
||||
if (win32.wglMakeCurrent(null, null) == 0) {
|
||||
log.warn("wglMakeCurrent(null) failed: err={d}", .{@intFromEnum(win32.GetLastError())});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -609,6 +609,9 @@ pub fn add(
|
|||
step.linkSystemLibrary2("user32", .{});
|
||||
step.linkSystemLibrary2("gdi32", .{});
|
||||
step.linkSystemLibrary2("opengl32", .{});
|
||||
if (b.lazyDependency("win32", .{})) |dep| {
|
||||
step.root_module.addImport("win32", dep.module("win32"));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue