mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-20 02:36:22 +03:00
renderer/opengl: OpenGL state may be nil to disable rendering
This commit is contained in:
@ -72,12 +72,7 @@ gl_cells_size: usize = 0,
|
|||||||
gl_cells_written: usize = 0,
|
gl_cells_written: usize = 0,
|
||||||
|
|
||||||
/// Shader program for cell rendering.
|
/// Shader program for cell rendering.
|
||||||
program: gl.Program,
|
gl_state: ?GLState = null,
|
||||||
vao: gl.VertexArray,
|
|
||||||
ebo: gl.Buffer,
|
|
||||||
vbo: gl.Buffer,
|
|
||||||
texture: gl.Texture,
|
|
||||||
texture_color: gl.Texture,
|
|
||||||
|
|
||||||
/// The font structures.
|
/// The font structures.
|
||||||
font_group: *font.GroupCache,
|
font_group: *font.GroupCache,
|
||||||
@ -110,6 +105,8 @@ const SetScreenSize = struct {
|
|||||||
size: renderer.ScreenSize,
|
size: renderer.ScreenSize,
|
||||||
|
|
||||||
fn apply(self: SetScreenSize, r: *const OpenGL) !void {
|
fn apply(self: SetScreenSize, r: *const OpenGL) !void {
|
||||||
|
const gl_state = r.gl_state orelse return error.OpenGLUninitialized;
|
||||||
|
|
||||||
// Apply our padding
|
// Apply our padding
|
||||||
const padding = r.padding.explicit.add(if (r.padding.balance)
|
const padding = r.padding.explicit.add(if (r.padding.balance)
|
||||||
renderer.Padding.balanced(self.size, r.gridSize(self.size), r.cell_size)
|
renderer.Padding.balanced(self.size, r.gridSize(self.size), r.cell_size)
|
||||||
@ -135,7 +132,7 @@ const SetScreenSize = struct {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Update the projection uniform within our shader
|
// Update the projection uniform within our shader
|
||||||
try r.program.setUniform(
|
try gl_state.program.setUniform(
|
||||||
"projection",
|
"projection",
|
||||||
|
|
||||||
// 2D orthographic projection with the full w/h
|
// 2D orthographic projection with the full w/h
|
||||||
@ -153,18 +150,20 @@ const SetFontSize = struct {
|
|||||||
metrics: font.face.Metrics,
|
metrics: font.face.Metrics,
|
||||||
|
|
||||||
fn apply(self: SetFontSize, r: *const OpenGL) !void {
|
fn apply(self: SetFontSize, r: *const OpenGL) !void {
|
||||||
try r.program.setUniform(
|
const gl_state = r.gl_state orelse return error.OpenGLUninitialized;
|
||||||
|
|
||||||
|
try gl_state.program.setUniform(
|
||||||
"cell_size",
|
"cell_size",
|
||||||
@Vector(2, f32){
|
@Vector(2, f32){
|
||||||
@floatFromInt(self.metrics.cell_width),
|
@floatFromInt(self.metrics.cell_width),
|
||||||
@floatFromInt(self.metrics.cell_height),
|
@floatFromInt(self.metrics.cell_height),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
try r.program.setUniform(
|
try gl_state.program.setUniform(
|
||||||
"strikethrough_position",
|
"strikethrough_position",
|
||||||
@as(f32, @floatFromInt(self.metrics.strikethrough_position)),
|
@as(f32, @floatFromInt(self.metrics.strikethrough_position)),
|
||||||
);
|
);
|
||||||
try r.program.setUniform(
|
try gl_state.program.setUniform(
|
||||||
"strikethrough_thickness",
|
"strikethrough_thickness",
|
||||||
@as(f32, @floatFromInt(self.metrics.strikethrough_thickness)),
|
@as(f32, @floatFromInt(self.metrics.strikethrough_thickness)),
|
||||||
);
|
);
|
||||||
@ -295,12 +294,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
});
|
});
|
||||||
errdefer shaper.deinit();
|
errdefer shaper.deinit();
|
||||||
|
|
||||||
// Create our shader
|
|
||||||
const program = try gl.Program.createVF(
|
|
||||||
@embedFile("shaders/cell.v.glsl"),
|
|
||||||
@embedFile("shaders/cell.f.glsl"),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Setup our font metrics uniform
|
// Setup our font metrics uniform
|
||||||
const metrics = try resetFontMetrics(
|
const metrics = try resetFontMetrics(
|
||||||
alloc,
|
alloc,
|
||||||
@ -308,109 +301,8 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
options.config.font_thicken,
|
options.config.font_thicken,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set our cell dimensions
|
var gl_state = try GLState.init(options.font_group);
|
||||||
const pbind = try program.use();
|
errdefer gl_state.deinit();
|
||||||
defer pbind.unbind();
|
|
||||||
|
|
||||||
// Set all of our texture indexes
|
|
||||||
try program.setUniform("text", 0);
|
|
||||||
try program.setUniform("text_color", 1);
|
|
||||||
|
|
||||||
// Setup our VAO
|
|
||||||
const vao = try gl.VertexArray.create();
|
|
||||||
errdefer vao.destroy();
|
|
||||||
try vao.bind();
|
|
||||||
defer gl.VertexArray.unbind() catch null;
|
|
||||||
|
|
||||||
// Element buffer (EBO)
|
|
||||||
const ebo = try gl.Buffer.create();
|
|
||||||
errdefer ebo.destroy();
|
|
||||||
var ebobind = try ebo.bind(.ElementArrayBuffer);
|
|
||||||
defer ebobind.unbind();
|
|
||||||
try ebobind.setData([6]u8{
|
|
||||||
0, 1, 3, // Top-left triangle
|
|
||||||
1, 2, 3, // Bottom-right triangle
|
|
||||||
}, .StaticDraw);
|
|
||||||
|
|
||||||
// Vertex buffer (VBO)
|
|
||||||
const vbo = try gl.Buffer.create();
|
|
||||||
errdefer vbo.destroy();
|
|
||||||
var vbobind = try vbo.bind(.ArrayBuffer);
|
|
||||||
defer vbobind.unbind();
|
|
||||||
var offset: usize = 0;
|
|
||||||
try vbobind.attributeAdvanced(0, 2, gl.c.GL_UNSIGNED_SHORT, false, @sizeOf(GPUCell), offset);
|
|
||||||
offset += 2 * @sizeOf(u16);
|
|
||||||
try vbobind.attributeAdvanced(1, 2, gl.c.GL_UNSIGNED_INT, false, @sizeOf(GPUCell), offset);
|
|
||||||
offset += 2 * @sizeOf(u32);
|
|
||||||
try vbobind.attributeAdvanced(2, 2, gl.c.GL_UNSIGNED_INT, false, @sizeOf(GPUCell), offset);
|
|
||||||
offset += 2 * @sizeOf(u32);
|
|
||||||
try vbobind.attributeAdvanced(3, 2, gl.c.GL_INT, false, @sizeOf(GPUCell), offset);
|
|
||||||
offset += 2 * @sizeOf(i32);
|
|
||||||
try vbobind.attributeAdvanced(4, 4, gl.c.GL_UNSIGNED_BYTE, false, @sizeOf(GPUCell), offset);
|
|
||||||
offset += 4 * @sizeOf(u8);
|
|
||||||
try vbobind.attributeAdvanced(5, 4, gl.c.GL_UNSIGNED_BYTE, false, @sizeOf(GPUCell), offset);
|
|
||||||
offset += 4 * @sizeOf(u8);
|
|
||||||
try vbobind.attributeIAdvanced(6, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(GPUCell), offset);
|
|
||||||
offset += 1 * @sizeOf(u8);
|
|
||||||
try vbobind.attributeIAdvanced(7, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(GPUCell), offset);
|
|
||||||
try vbobind.enableAttribArray(0);
|
|
||||||
try vbobind.enableAttribArray(1);
|
|
||||||
try vbobind.enableAttribArray(2);
|
|
||||||
try vbobind.enableAttribArray(3);
|
|
||||||
try vbobind.enableAttribArray(4);
|
|
||||||
try vbobind.enableAttribArray(5);
|
|
||||||
try vbobind.enableAttribArray(6);
|
|
||||||
try vbobind.enableAttribArray(7);
|
|
||||||
try vbobind.attributeDivisor(0, 1);
|
|
||||||
try vbobind.attributeDivisor(1, 1);
|
|
||||||
try vbobind.attributeDivisor(2, 1);
|
|
||||||
try vbobind.attributeDivisor(3, 1);
|
|
||||||
try vbobind.attributeDivisor(4, 1);
|
|
||||||
try vbobind.attributeDivisor(5, 1);
|
|
||||||
try vbobind.attributeDivisor(6, 1);
|
|
||||||
try vbobind.attributeDivisor(7, 1);
|
|
||||||
|
|
||||||
// Build our texture
|
|
||||||
const tex = try gl.Texture.create();
|
|
||||||
errdefer tex.destroy();
|
|
||||||
{
|
|
||||||
const texbind = try tex.bind(.@"2D");
|
|
||||||
try texbind.parameter(.WrapS, gl.c.GL_CLAMP_TO_EDGE);
|
|
||||||
try texbind.parameter(.WrapT, gl.c.GL_CLAMP_TO_EDGE);
|
|
||||||
try texbind.parameter(.MinFilter, gl.c.GL_LINEAR);
|
|
||||||
try texbind.parameter(.MagFilter, gl.c.GL_LINEAR);
|
|
||||||
try texbind.image2D(
|
|
||||||
0,
|
|
||||||
.Red,
|
|
||||||
@intCast(options.font_group.atlas_greyscale.size),
|
|
||||||
@intCast(options.font_group.atlas_greyscale.size),
|
|
||||||
0,
|
|
||||||
.Red,
|
|
||||||
.UnsignedByte,
|
|
||||||
options.font_group.atlas_greyscale.data.ptr,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build our color texture
|
|
||||||
const tex_color = try gl.Texture.create();
|
|
||||||
errdefer tex_color.destroy();
|
|
||||||
{
|
|
||||||
const texbind = try tex_color.bind(.@"2D");
|
|
||||||
try texbind.parameter(.WrapS, gl.c.GL_CLAMP_TO_EDGE);
|
|
||||||
try texbind.parameter(.WrapT, gl.c.GL_CLAMP_TO_EDGE);
|
|
||||||
try texbind.parameter(.MinFilter, gl.c.GL_LINEAR);
|
|
||||||
try texbind.parameter(.MagFilter, gl.c.GL_LINEAR);
|
|
||||||
try texbind.image2D(
|
|
||||||
0,
|
|
||||||
.RGBA,
|
|
||||||
@intCast(options.font_group.atlas_color.size),
|
|
||||||
@intCast(options.font_group.atlas_color.size),
|
|
||||||
0,
|
|
||||||
.BGRA,
|
|
||||||
.UnsignedByte,
|
|
||||||
options.font_group.atlas_color.data.ptr,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return OpenGL{
|
return OpenGL{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
@ -420,12 +312,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
.cells_lru = CellsLRU.init(0),
|
.cells_lru = CellsLRU.init(0),
|
||||||
.cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height },
|
.cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height },
|
||||||
.screen_size = null,
|
.screen_size = null,
|
||||||
.program = program,
|
.gl_state = gl_state,
|
||||||
.vao = vao,
|
|
||||||
.ebo = ebo,
|
|
||||||
.vbo = vbo,
|
|
||||||
.texture = tex,
|
|
||||||
.texture_color = tex_color,
|
|
||||||
.font_group = options.font_group,
|
.font_group = options.font_group,
|
||||||
.font_shaper = shaper,
|
.font_shaper = shaper,
|
||||||
.draw_background = options.config.background,
|
.draw_background = options.config.background,
|
||||||
@ -440,12 +327,7 @@ pub fn deinit(self: *OpenGL) void {
|
|||||||
self.font_shaper.deinit();
|
self.font_shaper.deinit();
|
||||||
self.alloc.free(self.font_shaper.cell_buf);
|
self.alloc.free(self.font_shaper.cell_buf);
|
||||||
|
|
||||||
self.texture.destroy();
|
if (self.gl_state) |*v| v.deinit();
|
||||||
self.texture_color.destroy();
|
|
||||||
self.vbo.destroy();
|
|
||||||
self.ebo.destroy();
|
|
||||||
self.vao.destroy();
|
|
||||||
self.program.destroy();
|
|
||||||
|
|
||||||
self.resetCellsLRU();
|
self.resetCellsLRU();
|
||||||
self.cells_lru.deinit(self.alloc);
|
self.cells_lru.deinit(self.alloc);
|
||||||
@ -1429,11 +1311,13 @@ pub fn setScreenSize(
|
|||||||
|
|
||||||
/// Updates the font texture atlas if it is dirty.
|
/// Updates the font texture atlas if it is dirty.
|
||||||
fn flushAtlas(self: *OpenGL) !void {
|
fn flushAtlas(self: *OpenGL) !void {
|
||||||
|
const gl_state = self.gl_state orelse return;
|
||||||
|
|
||||||
{
|
{
|
||||||
const atlas = &self.font_group.atlas_greyscale;
|
const atlas = &self.font_group.atlas_greyscale;
|
||||||
if (atlas.modified) {
|
if (atlas.modified) {
|
||||||
atlas.modified = false;
|
atlas.modified = false;
|
||||||
var texbind = try self.texture.bind(.@"2D");
|
var texbind = try gl_state.texture.bind(.@"2D");
|
||||||
defer texbind.unbind();
|
defer texbind.unbind();
|
||||||
|
|
||||||
if (atlas.resized) {
|
if (atlas.resized) {
|
||||||
@ -1467,7 +1351,7 @@ fn flushAtlas(self: *OpenGL) !void {
|
|||||||
const atlas = &self.font_group.atlas_color;
|
const atlas = &self.font_group.atlas_color;
|
||||||
if (atlas.modified) {
|
if (atlas.modified) {
|
||||||
atlas.modified = false;
|
atlas.modified = false;
|
||||||
var texbind = try self.texture_color.bind(.@"2D");
|
var texbind = try gl_state.texture_color.bind(.@"2D");
|
||||||
defer texbind.unbind();
|
defer texbind.unbind();
|
||||||
|
|
||||||
if (atlas.resized) {
|
if (atlas.resized) {
|
||||||
@ -1507,6 +1391,7 @@ pub fn draw(self: *OpenGL) !void {
|
|||||||
// If we're in single-threaded more we grab a lock since we use shared data.
|
// If we're in single-threaded more we grab a lock since we use shared data.
|
||||||
if (single_threaded_draw) self.draw_mutex.lock();
|
if (single_threaded_draw) self.draw_mutex.lock();
|
||||||
defer if (single_threaded_draw) self.draw_mutex.unlock();
|
defer if (single_threaded_draw) self.draw_mutex.unlock();
|
||||||
|
const gl_state = self.gl_state orelse return;
|
||||||
|
|
||||||
// If we have no cells to render, then we render nothing.
|
// If we have no cells to render, then we render nothing.
|
||||||
if (self.cells.items.len == 0) return;
|
if (self.cells.items.len == 0) return;
|
||||||
@ -1525,28 +1410,28 @@ pub fn draw(self: *OpenGL) !void {
|
|||||||
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
|
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// Setup our VAO
|
// Setup our VAO
|
||||||
try self.vao.bind();
|
try gl_state.vao.bind();
|
||||||
defer gl.VertexArray.unbind() catch null;
|
defer gl.VertexArray.unbind() catch null;
|
||||||
|
|
||||||
// Bind EBO
|
// Bind EBO
|
||||||
var ebobind = try self.ebo.bind(.ElementArrayBuffer);
|
var ebobind = try gl_state.ebo.bind(.ElementArrayBuffer);
|
||||||
defer ebobind.unbind();
|
defer ebobind.unbind();
|
||||||
|
|
||||||
// Bind VBO and set data
|
// Bind VBO and set data
|
||||||
var binding = try self.vbo.bind(.ArrayBuffer);
|
var binding = try gl_state.vbo.bind(.ArrayBuffer);
|
||||||
defer binding.unbind();
|
defer binding.unbind();
|
||||||
|
|
||||||
// Bind our textures
|
// Bind our textures
|
||||||
try gl.Texture.active(gl.c.GL_TEXTURE0);
|
try gl.Texture.active(gl.c.GL_TEXTURE0);
|
||||||
var texbind = try self.texture.bind(.@"2D");
|
var texbind = try gl_state.texture.bind(.@"2D");
|
||||||
defer texbind.unbind();
|
defer texbind.unbind();
|
||||||
|
|
||||||
try gl.Texture.active(gl.c.GL_TEXTURE1);
|
try gl.Texture.active(gl.c.GL_TEXTURE1);
|
||||||
var texbind1 = try self.texture_color.bind(.@"2D");
|
var texbind1 = try gl_state.texture_color.bind(.@"2D");
|
||||||
defer texbind1.unbind();
|
defer texbind1.unbind();
|
||||||
|
|
||||||
// Pick our shader to use
|
// Pick our shader to use
|
||||||
const pbind = try self.program.use();
|
const pbind = try gl_state.program.use();
|
||||||
defer pbind.unbind();
|
defer pbind.unbind();
|
||||||
|
|
||||||
// If we have deferred operations, run them.
|
// If we have deferred operations, run them.
|
||||||
@ -1611,3 +1496,145 @@ fn drawCells(
|
|||||||
cells.items.len,
|
cells.items.len,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The OpenGL objects that are associated with a renderer. This makes it
|
||||||
|
/// easy to create/destroy these as a set in situations i.e. where the
|
||||||
|
/// OpenGL context is replaced.
|
||||||
|
const GLState = struct {
|
||||||
|
program: gl.Program,
|
||||||
|
vao: gl.VertexArray,
|
||||||
|
ebo: gl.Buffer,
|
||||||
|
vbo: gl.Buffer,
|
||||||
|
texture: gl.Texture,
|
||||||
|
texture_color: gl.Texture,
|
||||||
|
|
||||||
|
pub fn init(font_group: *font.GroupCache) !GLState {
|
||||||
|
// Shader
|
||||||
|
const program = try gl.Program.createVF(
|
||||||
|
@embedFile("shaders/cell.v.glsl"),
|
||||||
|
@embedFile("shaders/cell.f.glsl"),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set our cell dimensions
|
||||||
|
const pbind = try program.use();
|
||||||
|
defer pbind.unbind();
|
||||||
|
|
||||||
|
// Set all of our texture indexes
|
||||||
|
try program.setUniform("text", 0);
|
||||||
|
try program.setUniform("text_color", 1);
|
||||||
|
|
||||||
|
// Setup our VAO
|
||||||
|
const vao = try gl.VertexArray.create();
|
||||||
|
errdefer vao.destroy();
|
||||||
|
try vao.bind();
|
||||||
|
defer gl.VertexArray.unbind() catch null;
|
||||||
|
|
||||||
|
// Element buffer (EBO)
|
||||||
|
const ebo = try gl.Buffer.create();
|
||||||
|
errdefer ebo.destroy();
|
||||||
|
var ebobind = try ebo.bind(.ElementArrayBuffer);
|
||||||
|
defer ebobind.unbind();
|
||||||
|
try ebobind.setData([6]u8{
|
||||||
|
0, 1, 3, // Top-left triangle
|
||||||
|
1, 2, 3, // Bottom-right triangle
|
||||||
|
}, .StaticDraw);
|
||||||
|
|
||||||
|
// Vertex buffer (VBO)
|
||||||
|
const vbo = try gl.Buffer.create();
|
||||||
|
errdefer vbo.destroy();
|
||||||
|
var vbobind = try vbo.bind(.ArrayBuffer);
|
||||||
|
defer vbobind.unbind();
|
||||||
|
var offset: usize = 0;
|
||||||
|
try vbobind.attributeAdvanced(0, 2, gl.c.GL_UNSIGNED_SHORT, false, @sizeOf(GPUCell), offset);
|
||||||
|
offset += 2 * @sizeOf(u16);
|
||||||
|
try vbobind.attributeAdvanced(1, 2, gl.c.GL_UNSIGNED_INT, false, @sizeOf(GPUCell), offset);
|
||||||
|
offset += 2 * @sizeOf(u32);
|
||||||
|
try vbobind.attributeAdvanced(2, 2, gl.c.GL_UNSIGNED_INT, false, @sizeOf(GPUCell), offset);
|
||||||
|
offset += 2 * @sizeOf(u32);
|
||||||
|
try vbobind.attributeAdvanced(3, 2, gl.c.GL_INT, false, @sizeOf(GPUCell), offset);
|
||||||
|
offset += 2 * @sizeOf(i32);
|
||||||
|
try vbobind.attributeAdvanced(4, 4, gl.c.GL_UNSIGNED_BYTE, false, @sizeOf(GPUCell), offset);
|
||||||
|
offset += 4 * @sizeOf(u8);
|
||||||
|
try vbobind.attributeAdvanced(5, 4, gl.c.GL_UNSIGNED_BYTE, false, @sizeOf(GPUCell), offset);
|
||||||
|
offset += 4 * @sizeOf(u8);
|
||||||
|
try vbobind.attributeIAdvanced(6, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(GPUCell), offset);
|
||||||
|
offset += 1 * @sizeOf(u8);
|
||||||
|
try vbobind.attributeIAdvanced(7, 1, gl.c.GL_UNSIGNED_BYTE, @sizeOf(GPUCell), offset);
|
||||||
|
try vbobind.enableAttribArray(0);
|
||||||
|
try vbobind.enableAttribArray(1);
|
||||||
|
try vbobind.enableAttribArray(2);
|
||||||
|
try vbobind.enableAttribArray(3);
|
||||||
|
try vbobind.enableAttribArray(4);
|
||||||
|
try vbobind.enableAttribArray(5);
|
||||||
|
try vbobind.enableAttribArray(6);
|
||||||
|
try vbobind.enableAttribArray(7);
|
||||||
|
try vbobind.attributeDivisor(0, 1);
|
||||||
|
try vbobind.attributeDivisor(1, 1);
|
||||||
|
try vbobind.attributeDivisor(2, 1);
|
||||||
|
try vbobind.attributeDivisor(3, 1);
|
||||||
|
try vbobind.attributeDivisor(4, 1);
|
||||||
|
try vbobind.attributeDivisor(5, 1);
|
||||||
|
try vbobind.attributeDivisor(6, 1);
|
||||||
|
try vbobind.attributeDivisor(7, 1);
|
||||||
|
|
||||||
|
// Build our texture
|
||||||
|
const tex = try gl.Texture.create();
|
||||||
|
errdefer tex.destroy();
|
||||||
|
{
|
||||||
|
const texbind = try tex.bind(.@"2D");
|
||||||
|
try texbind.parameter(.WrapS, gl.c.GL_CLAMP_TO_EDGE);
|
||||||
|
try texbind.parameter(.WrapT, gl.c.GL_CLAMP_TO_EDGE);
|
||||||
|
try texbind.parameter(.MinFilter, gl.c.GL_LINEAR);
|
||||||
|
try texbind.parameter(.MagFilter, gl.c.GL_LINEAR);
|
||||||
|
try texbind.image2D(
|
||||||
|
0,
|
||||||
|
.Red,
|
||||||
|
@intCast(font_group.atlas_greyscale.size),
|
||||||
|
@intCast(font_group.atlas_greyscale.size),
|
||||||
|
0,
|
||||||
|
.Red,
|
||||||
|
.UnsignedByte,
|
||||||
|
font_group.atlas_greyscale.data.ptr,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build our color texture
|
||||||
|
const tex_color = try gl.Texture.create();
|
||||||
|
errdefer tex_color.destroy();
|
||||||
|
{
|
||||||
|
const texbind = try tex_color.bind(.@"2D");
|
||||||
|
try texbind.parameter(.WrapS, gl.c.GL_CLAMP_TO_EDGE);
|
||||||
|
try texbind.parameter(.WrapT, gl.c.GL_CLAMP_TO_EDGE);
|
||||||
|
try texbind.parameter(.MinFilter, gl.c.GL_LINEAR);
|
||||||
|
try texbind.parameter(.MagFilter, gl.c.GL_LINEAR);
|
||||||
|
try texbind.image2D(
|
||||||
|
0,
|
||||||
|
.RGBA,
|
||||||
|
@intCast(font_group.atlas_color.size),
|
||||||
|
@intCast(font_group.atlas_color.size),
|
||||||
|
0,
|
||||||
|
.BGRA,
|
||||||
|
.UnsignedByte,
|
||||||
|
font_group.atlas_color.data.ptr,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.program = program,
|
||||||
|
.vao = vao,
|
||||||
|
.ebo = ebo,
|
||||||
|
.vbo = vbo,
|
||||||
|
.texture = tex,
|
||||||
|
.texture_color = tex_color,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *GLState) void {
|
||||||
|
self.texture.destroy();
|
||||||
|
self.texture_color.destroy();
|
||||||
|
self.vbo.destroy();
|
||||||
|
self.ebo.destroy();
|
||||||
|
self.vao.destroy();
|
||||||
|
self.program.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Reference in New Issue
Block a user