Compare commits
4 Commits
94c08ff3b6
...
ff87d58319
| Author | SHA1 | Date | |
|---|---|---|---|
| ff87d58319 | |||
| 70076f2268 | |||
| 8dbac71007 | |||
| c14fc89c74 |
@@ -114,5 +114,3 @@ typedef uint64_t uintptr_t;
|
||||
|
||||
#define WCHAR_MIN (0)
|
||||
#define WCHAR_MAX (0x10FFFF)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -170,7 +170,7 @@ pub fn isCompatible(comptime ZigType: type, c_type: Type) bool {
|
||||
.unsigned_long => zig_int.signedness == .unsigned and zig_int.bits == 64,
|
||||
.unsigned_long_long => zig_int.signedness == .unsigned and zig_int.bits == 64,
|
||||
|
||||
.char => zig_int.bits = 8,
|
||||
.char => zig_int.bits == 8,
|
||||
|
||||
else => false,
|
||||
},
|
||||
|
||||
@@ -17,8 +17,11 @@ pub fn build(b: *std.Build) void {
|
||||
},
|
||||
});
|
||||
|
||||
mod.addCSourceFile(.{
|
||||
.file = b.path("src/stbi/stb_image.c"),
|
||||
mod.addCSourceFiles(.{
|
||||
.files = &.{
|
||||
"src/stbi/stb_image.c",
|
||||
"src/stbtt/stb_truetype.c",
|
||||
},
|
||||
.flags = &.{
|
||||
"-std=c17",
|
||||
"-Wall",
|
||||
|
||||
@@ -451,7 +451,7 @@ pub const ChunkType = enum(u32) {
|
||||
_,
|
||||
|
||||
fn fromName(name: *const [4]u8) u32 {
|
||||
return @bitCast(name.*);
|
||||
return std.mem.bytesToValue(u32, name);
|
||||
}
|
||||
|
||||
pub fn fromBytes(bytes: *const [4]u8) ChunkType {
|
||||
@@ -459,18 +459,18 @@ pub const ChunkType = enum(u32) {
|
||||
}
|
||||
|
||||
pub fn toBytes(self: ChunkType) [4]u8 {
|
||||
return @bitCast(@intFromEnum(self));
|
||||
return std.mem.toBytes(self);
|
||||
}
|
||||
|
||||
pub fn ancillary(self: ChunkType) bool {
|
||||
pub fn isAncillary(self: ChunkType) bool {
|
||||
return self.toBytes()[0] & 0b0010_0000 != 0;
|
||||
}
|
||||
|
||||
pub fn private(self: ChunkType) bool {
|
||||
pub fn isPrivate(self: ChunkType) bool {
|
||||
return self.toBytes()[1] & 0b0010_0000 != 0;
|
||||
}
|
||||
|
||||
pub fn safeToCopy(self: ChunkType) bool {
|
||||
pub fn isSafeToCopy(self: ChunkType) bool {
|
||||
return self.toBytes()[3] & 0b0010_0000 != 0;
|
||||
}
|
||||
|
||||
@@ -493,7 +493,7 @@ pub const StandardKeyword = enum {
|
||||
Description,
|
||||
/// Copyright notice
|
||||
Copyright,
|
||||
/// Time Time of original image creation
|
||||
/// Time of original image creation
|
||||
Creation,
|
||||
/// Software used to create the image
|
||||
Software,
|
||||
|
||||
@@ -9,6 +9,7 @@ pub const png = @import("png.zig");
|
||||
pub const qoa = @import("qoa.zig");
|
||||
pub const qoi = @import("qoi.zig");
|
||||
pub const stbi = @import("stbi.zig");
|
||||
pub const stbtt = @import("stbtt.zig");
|
||||
|
||||
test "refAllDecls" {
|
||||
std.testing.refAllDecls(@This());
|
||||
|
||||
227
packages/media/src/stbtt.zig
Normal file
227
packages/media/src/stbtt.zig
Normal file
@@ -0,0 +1,227 @@
|
||||
const std = @import("std");
|
||||
const Self = @This();
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
|
||||
mutex: std.Io.Mutex = .init,
|
||||
allocations: std.AutoHashMapUnmanaged(*anyopaque, usize) = .empty,
|
||||
allocated_bytes: usize = 0,
|
||||
|
||||
const alignment: std.mem.Alignment = .@"16";
|
||||
const VoidPtr = ?*align(alignment.toByteUnits()) anyopaque;
|
||||
const log = std.log.scoped(.stbi);
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, io: std.Io) Self {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.io = io,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
std.log.scoped(.deinit).debug("Deinitializing {*}", .{self});
|
||||
if (self.allocated_bytes > 0) {
|
||||
log.warn("{d} byte(s) still allocated while deinitializing", .{self.allocated_bytes});
|
||||
}
|
||||
if (self.allocations.size > 0) {
|
||||
log.warn("{d} allocation(s) still tracked while deinitializing", .{self.allocations.size});
|
||||
var it = self.allocations.iterator();
|
||||
var index: usize = 0;
|
||||
while (it.next()) |entry| : (index += 1) {
|
||||
log.warn("Leaked allocation ({d}/{d}) at 0x{x} of {d} byte(s)", .{
|
||||
index + 1,
|
||||
self.allocations.size,
|
||||
@intFromPtr(entry.key_ptr.*),
|
||||
entry.value_ptr.*,
|
||||
});
|
||||
const memory = @as([*]align(alignment.toByteUnits()) u8, @ptrCast(@alignCast(entry.key_ptr.*)))[0..entry.value_ptr.*];
|
||||
self.allocator.free(memory);
|
||||
}
|
||||
}
|
||||
|
||||
self.allocations.deinit(self.allocator);
|
||||
}
|
||||
|
||||
const import = struct {
|
||||
const stbtt__buf = extern struct {
|
||||
data: ?[*]const u8,
|
||||
cursor: c_int,
|
||||
size: c_int,
|
||||
};
|
||||
|
||||
const stbtt_fontinfo = extern struct {
|
||||
userdata: ?*anyopaque,
|
||||
data: [*]const u8,
|
||||
fonstart: c_int,
|
||||
|
||||
numGlyphs: c_int,
|
||||
|
||||
loca: c_int,
|
||||
head: c_int,
|
||||
glyf: c_int,
|
||||
hhea: c_int,
|
||||
hmtx: c_int,
|
||||
kern: c_int,
|
||||
gpos: c_int,
|
||||
svg: c_int,
|
||||
index_map: c_int,
|
||||
indexToLocFormat: c_int,
|
||||
|
||||
cff: stbtt__buf,
|
||||
charstrings: stbtt__buf,
|
||||
gsubrs: stbtt__buf,
|
||||
subrs: stbtt__buf,
|
||||
fontdicts: stbtt__buf,
|
||||
fdselect: stbtt__buf,
|
||||
};
|
||||
|
||||
const stbtt_kerningentry = extern struct {
|
||||
glyph1: c_int,
|
||||
glyph2: c_int,
|
||||
advance: c_int,
|
||||
};
|
||||
|
||||
const STBTT_vmove = enum(u8) {
|
||||
STBTT_vmove = 1,
|
||||
STBTT_vline,
|
||||
STBTT_vcurve,
|
||||
STBTT_vcubic,
|
||||
};
|
||||
|
||||
const stbtt_vertex = extern struct {
|
||||
x: i16,
|
||||
y: i16,
|
||||
cx: i16,
|
||||
cy: i16,
|
||||
cx1: i16,
|
||||
cy1: i16,
|
||||
type: STBTT_vmove,
|
||||
padding: u8,
|
||||
};
|
||||
|
||||
extern fn stbtt_GetNumberOfFonts(data: [*]const u8) c_int;
|
||||
extern fn stbtt_GetFontOffsetForIndex(index: c_int, data: [*]const u8) c_int;
|
||||
extern fn stbtt_InitFont(info: *stbtt_fontinfo, data: [*]const u8, offset: c_int) c_int;
|
||||
extern fn stbtt_FindGlyphIndex(info: *const stbtt_fontinfo, unicode_codepoint: c_int) c_int;
|
||||
extern fn stbtt_GetFontVMetrics(info: *const stbtt_fontinfo, ascent: ?*c_int, descent: ?*c_int, lineGap: ?*c_int) void;
|
||||
extern fn stbtt_GetFontVMetricsOS2(info: *const stbtt_fontinfo, typoAscent: ?*c_int, typoDescent: ?*c_int, typoLineGap: ?*c_int) c_int;
|
||||
extern fn stbtt_GetGlyphHMetrics(info: *const stbtt_fontinfo, glyph_index: c_int, advanceWidth: *c_int, leftSideBearing: *c_int) void;
|
||||
extern fn stbtt_GetGlyphKernAdvance(info: *const stbtt_fontinfo, glyph1: c_int, glyph2: c_int) c_int;
|
||||
extern fn stbtt_GetGlyphBox(info: *const stbtt_fontinfo, glyph_index: c_int, x0: *c_int, y0: *c_int, x1: *c_int, y1: *c_int) c_int;
|
||||
extern fn stbtt_GetKerningTableLength(info: *const stbtt_fontinfo) c_int;
|
||||
extern fn stbtt_GetKerningTable(info: *const stbtt_fontinfo, table: [*]stbtt_kerningentry, table_length: c_int) c_int;
|
||||
extern fn stbtt_IsGlyphEmpty(info: *const stbtt_fontinfo, glyph_index: c_int) c_int;
|
||||
extern fn stbtt_GetGlyphShape(info: *const stbtt_fontinfo, glyph_index: c_int, vertices: *[*]stbtt_vertex) c_int;
|
||||
extern fn stbtt_FreeShape(info: *const stbtt_fontinfo, vertices: [*]stbtt_vertex) void;
|
||||
|
||||
extern fn stbtt_UnitsPerEm(info: *const stbtt_fontinfo) c_int;
|
||||
extern fn stbtt_GetFontCapHeight(info: *const stbtt_fontinfo, capHeight: ?*c_int) c_int;
|
||||
};
|
||||
|
||||
pub fn initFont(self: *Self, data: []const u8) !*Font {
|
||||
const info = try self.allocator.create(import.stbtt_fontinfo);
|
||||
errdefer self.allocator.destroy(info);
|
||||
|
||||
info.userdata = self;
|
||||
const res = import.stbtt_InitFont(info, data.ptr, 0);
|
||||
if (res == 0) return error.StbttError;
|
||||
|
||||
return @ptrCast(info);
|
||||
}
|
||||
|
||||
pub const Font = opaque {
|
||||
pub fn deinit(self: *Font) void {
|
||||
const info = @as(*import.stbtt_fontinfo, @ptrCast(@alignCast(self)));
|
||||
const stbtt = @as(*Self, @ptrCast(@alignCast(info.userdata.?)));
|
||||
stbtt.allocator.destroy(info);
|
||||
}
|
||||
|
||||
pub fn findGlyphIndex(self: *const Font, codepoint: u21) ?u32 {
|
||||
const info = @as(*const import.stbtt_fontinfo, @ptrCast(@alignCast(self)));
|
||||
const res = import.stbtt_FindGlyphIndex(info, codepoint);
|
||||
return if (res != 0) @intCast(res) else null;
|
||||
}
|
||||
|
||||
pub fn getGlyphBox(self: *const Font, glyph: u32) ?GlyphBox {
|
||||
const info = @as(*const import.stbtt_fontinfo, @ptrCast(@alignCast(self)));
|
||||
var x0: c_int = undefined;
|
||||
var y0: c_int = undefined;
|
||||
var x1: c_int = undefined;
|
||||
var y1: c_int = undefined;
|
||||
const res = import.stbtt_GetGlyphBox(info, @intCast(glyph), &x0, &y0, &x1, &y1);
|
||||
return if (res != 0) .{
|
||||
.x_min = @intCast(x0),
|
||||
.y_min = @intCast(y0),
|
||||
.x_max = @intCast(x1),
|
||||
.y_max = @intCast(y1),
|
||||
} else null;
|
||||
}
|
||||
|
||||
pub fn unitsPerEm(self: *const Font) u16 {
|
||||
const info = @as(*const import.stbtt_fontinfo, @ptrCast(@alignCast(self)));
|
||||
const res = import.stbtt_UnitsPerEm(info);
|
||||
return @intCast(res);
|
||||
}
|
||||
|
||||
pub fn getCapHeight(self: *const Font) ?i16 {
|
||||
const info = @as(*const import.stbtt_fontinfo, @ptrCast(@alignCast(self)));
|
||||
|
||||
var cap_height: c_int = undefined;
|
||||
if (import.stbtt_GetFontCapHeight(info, &cap_height) != 0) {
|
||||
return @intCast(cap_height);
|
||||
}
|
||||
|
||||
if (self.findGlyphIndex('H')) |glyph| {
|
||||
if (self.getGlyphBox(glyph)) |box| {
|
||||
return box.y_max;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
test "refAllDecls" {
|
||||
std.testing.refAllDecls(@This());
|
||||
}
|
||||
};
|
||||
|
||||
pub const GlyphBox = struct {
|
||||
x_min: i16,
|
||||
y_min: i16,
|
||||
x_max: i16,
|
||||
y_max: i16,
|
||||
};
|
||||
|
||||
// --- MALLOC INTERFACE --------------------------------------------------------
|
||||
|
||||
export fn castle_media_stbtt_malloc(self: *Self, size: usize) callconv(.c) VoidPtr {
|
||||
self.mutex.lock(self.io) catch return null;
|
||||
defer self.mutex.unlock(self.io);
|
||||
|
||||
self.allocations.ensureUnusedCapacity(self.allocator, 1) catch return null;
|
||||
const memory = self.allocator.alignedAlloc(u8, alignment, size) catch return null;
|
||||
|
||||
self.allocations.putAssumeCapacityNoClobber(memory.ptr, size);
|
||||
self.allocated_bytes += size;
|
||||
//log.debug("Allocated {d} bytes(s) at 0x{x}", .{ size, @intFromPtr(memory.ptr) });
|
||||
|
||||
return memory.ptr;
|
||||
}
|
||||
|
||||
export fn castle_media_stbtt_free(self: *Self, maybe_ptr: VoidPtr) callconv(.c) void {
|
||||
if (maybe_ptr) |ptr| {
|
||||
self.mutex.lockUncancelable(self.io);
|
||||
defer self.mutex.unlock(self.io);
|
||||
|
||||
const size = self.allocations.fetchRemove(ptr).?.value;
|
||||
self.allocated_bytes -= size;
|
||||
const memory = @as([*]align(alignment.toByteUnits()) u8, @ptrCast(ptr))[0..size];
|
||||
|
||||
self.allocator.free(memory);
|
||||
}
|
||||
}
|
||||
|
||||
test "refAllDecls" {
|
||||
std.testing.refAllDecls(@This());
|
||||
}
|
||||
24
packages/media/src/stbtt/stb_truetype.c
Normal file
24
packages/media/src/stbtt/stb_truetype.c
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void *castle_media_stbtt_malloc(void *self, size_t size);
|
||||
void castle_media_stbtt_free(void *self, void *ptr);
|
||||
|
||||
#define STBTT_malloc(size, self) castle_media_stbtt_malloc(self, size)
|
||||
#define STBTT_free(ptr, self) castle_media_stbtt_free(self, ptr)
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "stb_truetype.h"
|
||||
|
||||
STBTT_DEF int stbtt_UnitsPerEm(const stbtt_fontinfo *info)
|
||||
{
|
||||
return ttUSHORT(info->data + info->head + 18);
|
||||
}
|
||||
|
||||
STBTT_DEF int stbtt_GetFontCapHeight(const stbtt_fontinfo *info, int *capHeight)
|
||||
{
|
||||
int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
|
||||
if (!tab || ttUSHORT(info->data+tab) < 2)
|
||||
return 0;
|
||||
if (capHeight) *capHeight = ttSHORT(info->data+tab + 88);
|
||||
return 1;
|
||||
}
|
||||
5079
packages/media/src/stbtt/stb_truetype.h
Normal file
5079
packages/media/src/stbtt/stb_truetype.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,14 @@ pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const vulkan_dep = b.dependency("vulkan_zig", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.registry = b.path("vendor/vk.xml"),
|
||||
});
|
||||
|
||||
const vulkan_mod = vulkan_dep.module("vulkan-zig");
|
||||
|
||||
const mod = b.addModule("xcb", .{
|
||||
.root_source_file = b.path("src/root.zig"),
|
||||
.target = target,
|
||||
@@ -27,6 +35,7 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.imports = &.{
|
||||
.{ .name = "vulkan", .module = vulkan_mod },
|
||||
.{ .name = "xcb", .module = mod },
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
.name = .xcb,
|
||||
.version = "0.0.0",
|
||||
.minimum_zig_version = "0.16.0",
|
||||
.dependencies = .{
|
||||
.vulkan_zig = .{
|
||||
.url = "git+https://github.com/Snektron/vulkan-zig#b496a6a561ffbbeb530b0f9ed4e059f88c0723a5",
|
||||
.hash = "vulkan-0.0.0-r7Ytx7N9AwD7IZt5_XNHtkJ4G9qY0pCH-cpcOsbL8wzD",
|
||||
},
|
||||
},
|
||||
.paths = .{
|
||||
"src",
|
||||
"build.zig",
|
||||
|
||||
176
packages/xcb/sample/Vulkan.zig
Normal file
176
packages/xcb/sample/Vulkan.zig
Normal file
@@ -0,0 +1,176 @@
|
||||
const Vulkan = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const vk = @import("vulkan");
|
||||
const xcb = @import("xcb");
|
||||
|
||||
vulkan_loader: *DynamicLibrary,
|
||||
|
||||
base: vk.BaseWrapper,
|
||||
instance: vk.InstanceProxy,
|
||||
surface: vk.SurfaceKHR,
|
||||
device: vk.DeviceProxy,
|
||||
|
||||
queue_family: u32,
|
||||
queue: vk.Queue,
|
||||
command_pool: vk.CommandPool,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, connection: *xcb.Connection, window: xcb.Window) !Vulkan {
|
||||
const vulkan_loader = try DynamicLibrary.open("libvulkan.so.1");
|
||||
errdefer vulkan_loader.close();
|
||||
|
||||
const vkGetInstanceProcAddr = try vulkan_loader.sym(vk.PfnGetInstanceProcAddr, "vkGetInstanceProcAddr");
|
||||
|
||||
const base = vk.BaseWrapper.load(vkGetInstanceProcAddr);
|
||||
|
||||
const instance_handle = blk: {
|
||||
const enabled_layers: []const [*:0]const u8 = &.{};
|
||||
const enabled_extensions: []const [*:0]const u8 = &.{
|
||||
vk.extensions.khr_surface.name,
|
||||
vk.extensions.khr_xcb_surface.name,
|
||||
};
|
||||
|
||||
break :blk try base.createInstance(&.{
|
||||
.p_application_info = &.{
|
||||
.p_application_name = "xcb_sample",
|
||||
.application_version = vk.makeApiVersion(0, 0, 0, 0).toU32(),
|
||||
.p_engine_name = "xcb_sample",
|
||||
.engine_version = vk.makeApiVersion(0, 0, 0, 0).toU32(),
|
||||
.api_version = vk.API_VERSION_1_0.toU32(),
|
||||
},
|
||||
.enabled_layer_count = @intCast(enabled_layers.len),
|
||||
.pp_enabled_layer_names = enabled_layers.ptr,
|
||||
.enabled_extension_count = @intCast(enabled_extensions.len),
|
||||
.pp_enabled_extension_names = enabled_extensions.ptr,
|
||||
}, null);
|
||||
};
|
||||
|
||||
const instance_wrapper_ptr = try allocator.create(vk.InstanceWrapper);
|
||||
errdefer allocator.destroy(instance_wrapper_ptr);
|
||||
|
||||
instance_wrapper_ptr.* = .load(instance_handle, vkGetInstanceProcAddr);
|
||||
const instance = vk.InstanceProxy.init(instance_handle, instance_wrapper_ptr);
|
||||
errdefer instance.destroyInstance(null);
|
||||
|
||||
const surface = try instance.createXcbSurfaceKHR(&.{
|
||||
.connection = connection,
|
||||
.window = window,
|
||||
}, null);
|
||||
errdefer instance.destroySurfaceKHR(surface, null);
|
||||
|
||||
const physical_device = blk: {
|
||||
const physical_devices = try instance.enumeratePhysicalDevicesAlloc(allocator);
|
||||
defer allocator.free(physical_devices);
|
||||
|
||||
if (physical_devices.len > 0) {
|
||||
break :blk physical_devices[0];
|
||||
}
|
||||
|
||||
return error.NoDevice;
|
||||
};
|
||||
|
||||
const queue_family: u32 = blk: {
|
||||
const queue_families_properties = try instance.getPhysicalDeviceQueueFamilyPropertiesAlloc(physical_device, allocator);
|
||||
defer allocator.free(queue_families_properties);
|
||||
|
||||
// Look for the first family that has the `graphics_bit` set and
|
||||
// supports presentation to a given surface.
|
||||
|
||||
for (queue_families_properties, 0..) |queue_family_properties, i| {
|
||||
const graphics_bit = queue_family_properties.queue_flags.graphics_bit;
|
||||
const supports_presentation = try instance.getPhysicalDeviceSurfaceSupportKHR(physical_device, @intCast(i), surface) != .false;
|
||||
|
||||
if (graphics_bit and supports_presentation) {
|
||||
break :blk @intCast(i);
|
||||
}
|
||||
}
|
||||
|
||||
return error.NoQueue;
|
||||
};
|
||||
|
||||
const device_handle = blk: {
|
||||
const queue_create_infos: []const vk.DeviceQueueCreateInfo = &.{
|
||||
.{
|
||||
.queue_family_index = queue_family,
|
||||
.queue_count = 1,
|
||||
.p_queue_priorities = &.{0},
|
||||
},
|
||||
};
|
||||
const enabled_extensions: []const [*:0]const u8 = &.{
|
||||
vk.extensions.khr_swapchain.name,
|
||||
};
|
||||
|
||||
break :blk try instance.createDevice(physical_device, &.{
|
||||
.queue_create_info_count = @intCast(queue_create_infos.len),
|
||||
.p_queue_create_infos = queue_create_infos.ptr,
|
||||
.enabled_extension_count = @intCast(enabled_extensions.len),
|
||||
.pp_enabled_extension_names = enabled_extensions.ptr,
|
||||
}, null);
|
||||
};
|
||||
|
||||
const device_wrapper_ptr = try allocator.create(vk.DeviceWrapper);
|
||||
errdefer allocator.destroy(device_wrapper_ptr);
|
||||
|
||||
device_wrapper_ptr.* = .load(device_handle, instance.wrapper.dispatch.vkGetDeviceProcAddr.?);
|
||||
const device = vk.DeviceProxy.init(device_handle, device_wrapper_ptr);
|
||||
errdefer device.destroyDevice(null);
|
||||
|
||||
const queue = device.getDeviceQueue(queue_family, 0);
|
||||
|
||||
const command_pool = try device.createCommandPool(&.{
|
||||
.flags = .{ .transient_bit = true },
|
||||
.queue_family_index = queue_family,
|
||||
}, null);
|
||||
errdefer device.destroyCommandPool(command_pool, null);
|
||||
|
||||
return .{
|
||||
.vulkan_loader = vulkan_loader,
|
||||
|
||||
.base = base,
|
||||
.instance = instance,
|
||||
.surface = surface,
|
||||
.device = device,
|
||||
|
||||
.queue_family = queue_family,
|
||||
.queue = queue,
|
||||
.command_pool = command_pool,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Vulkan, allocator: std.mem.Allocator) void {
|
||||
self.device.destroyCommandPool(self.command_pool, null);
|
||||
|
||||
self.device.destroyDevice(null);
|
||||
allocator.destroy(self.device.wrapper);
|
||||
self.instance.destroySurfaceKHR(self.surface, null);
|
||||
self.instance.destroyInstance(null);
|
||||
allocator.destroy(self.instance.wrapper);
|
||||
|
||||
self.vulkan_loader.close();
|
||||
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
const DynamicLibrary = opaque {
|
||||
fn open(path: [*:0]const u8) !*DynamicLibrary {
|
||||
const ptr = std.c.dlopen(path, .{ .NOW = true }) orelse {
|
||||
std.debug.print("{s}\n", .{std.c.dlerror().?});
|
||||
return error.DlOpen;
|
||||
};
|
||||
|
||||
return @ptrCast(ptr);
|
||||
}
|
||||
|
||||
fn close(self: *DynamicLibrary) void {
|
||||
_ = std.c.dlclose(self);
|
||||
}
|
||||
|
||||
fn sym(self: *DynamicLibrary, comptime Ptr: type, symbol: [*:0]const u8) !Ptr {
|
||||
const ptr = std.c.dlsym(self, symbol) orelse {
|
||||
std.debug.print("{s}\n", .{std.c.dlerror().?});
|
||||
return error.DlSym;
|
||||
};
|
||||
|
||||
return @ptrCast(@alignCast(ptr));
|
||||
}
|
||||
};
|
||||
@@ -1,9 +1,15 @@
|
||||
const std = @import("std");
|
||||
const xcb = @import("xcb");
|
||||
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
_ = init;
|
||||
const Vulkan = @import("Vulkan.zig");
|
||||
|
||||
// Declarations picked up by "vulkan" module
|
||||
|
||||
pub const xcb_connection_t = xcb.Connection;
|
||||
pub const xcb_visualid_t = xcb.Visualid;
|
||||
pub const xcb_window_t = xcb.Window;
|
||||
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
const connection = xcb.Connection.connect(null, null);
|
||||
defer connection.disconnect();
|
||||
|
||||
@@ -64,6 +70,9 @@ pub fn main(init: std.process.Init) !void {
|
||||
_ = connection.mapWindow(window);
|
||||
_ = connection.flush();
|
||||
|
||||
var vulkan = try Vulkan.init(init.gpa, connection, window);
|
||||
defer vulkan.deinit(init.gpa);
|
||||
|
||||
var running = true;
|
||||
while (running) {
|
||||
if (connection.waitForEvent()) |event| {
|
||||
|
||||
35719
packages/xcb/vendor/vk.xml
vendored
Normal file
35719
packages/xcb/vendor/vk.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user