mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-22 19:56:08 +03:00
renderer/opengl: convert to SharedGrid, new windows/tabs are frozen
This commit is contained in:
@ -72,8 +72,12 @@ gl_cells_written: usize = 0,
|
|||||||
gl_state: ?GLState = null,
|
gl_state: ?GLState = null,
|
||||||
|
|
||||||
/// The font structures.
|
/// The font structures.
|
||||||
font_group: *font.GroupCache,
|
font_grid: *font.SharedGrid,
|
||||||
font_shaper: font.Shaper,
|
font_shaper: font.Shaper,
|
||||||
|
texture_greyscale_modified: usize = 0,
|
||||||
|
texture_greyscale_resized: usize = 0,
|
||||||
|
texture_color_modified: usize = 0,
|
||||||
|
texture_color_resized: usize = 0,
|
||||||
|
|
||||||
/// True if the window is focused
|
/// True if the window is focused
|
||||||
focused: bool,
|
focused: bool,
|
||||||
@ -333,14 +337,13 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
});
|
});
|
||||||
errdefer shaper.deinit();
|
errdefer shaper.deinit();
|
||||||
|
|
||||||
// Setup our font metrics uniform
|
// For the remainder of the setup we lock our font grid data because
|
||||||
const metrics = try resetFontMetrics(
|
// we're reading it.
|
||||||
alloc,
|
const grid = options.font_grid;
|
||||||
options.font_group,
|
grid.lock.lockShared();
|
||||||
options.config.font_thicken,
|
defer grid.lock.unlockShared();
|
||||||
);
|
|
||||||
|
|
||||||
var gl_state = try GLState.init(alloc, options.config, options.font_group);
|
var gl_state = try GLState.init(alloc, options.config, grid);
|
||||||
errdefer gl_state.deinit();
|
errdefer gl_state.deinit();
|
||||||
|
|
||||||
return OpenGL{
|
return OpenGL{
|
||||||
@ -348,10 +351,10 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
.config = options.config,
|
.config = options.config,
|
||||||
.cells_bg = .{},
|
.cells_bg = .{},
|
||||||
.cells = .{},
|
.cells = .{},
|
||||||
.grid_metrics = metrics,
|
.grid_metrics = grid.metrics,
|
||||||
.screen_size = null,
|
.screen_size = null,
|
||||||
.gl_state = gl_state,
|
.gl_state = gl_state,
|
||||||
.font_group = options.font_group,
|
.font_grid = grid,
|
||||||
.font_shaper = shaper,
|
.font_shaper = shaper,
|
||||||
.draw_background = options.config.background,
|
.draw_background = options.config.background,
|
||||||
.focused = true,
|
.focused = true,
|
||||||
@ -360,7 +363,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
.cursor_color = options.config.cursor_color,
|
.cursor_color = options.config.cursor_color,
|
||||||
.padding = options.padding,
|
.padding = options.padding,
|
||||||
.surface_mailbox = options.surface_mailbox,
|
.surface_mailbox = options.surface_mailbox,
|
||||||
.deferred_font_size = .{ .metrics = metrics },
|
.deferred_font_size = .{ .metrics = grid.metrics },
|
||||||
.deferred_config = .{},
|
.deferred_config = .{},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -470,15 +473,16 @@ pub fn displayRealize(self: *OpenGL) !void {
|
|||||||
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();
|
||||||
|
|
||||||
// Reset our GPU uniforms
|
|
||||||
const metrics = try resetFontMetrics(
|
|
||||||
self.alloc,
|
|
||||||
self.font_group,
|
|
||||||
self.config.font_thicken,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Make our new state
|
// Make our new state
|
||||||
var gl_state = try GLState.init(self.alloc, self.config, self.font_group);
|
var gl_state = gl_state: {
|
||||||
|
self.font_grid.lock.lockShared();
|
||||||
|
defer self.font_grid.lock.unlockShared();
|
||||||
|
break :gl_state try GLState.init(
|
||||||
|
self.alloc,
|
||||||
|
self.config,
|
||||||
|
self.font_grid,
|
||||||
|
);
|
||||||
|
};
|
||||||
errdefer gl_state.deinit();
|
errdefer gl_state.deinit();
|
||||||
|
|
||||||
// Unrealize if we have to
|
// Unrealize if we have to
|
||||||
@ -491,14 +495,16 @@ pub fn displayRealize(self: *OpenGL) !void {
|
|||||||
// reflush everything
|
// reflush everything
|
||||||
self.gl_cells_size = 0;
|
self.gl_cells_size = 0;
|
||||||
self.gl_cells_written = 0;
|
self.gl_cells_written = 0;
|
||||||
self.font_group.atlas_greyscale.modified = true;
|
self.texture_greyscale_modified = 0;
|
||||||
self.font_group.atlas_color.modified = true;
|
self.texture_color_modified = 0;
|
||||||
|
self.texture_greyscale_resized = 0;
|
||||||
|
self.texture_color_resized = 0;
|
||||||
|
|
||||||
// We need to reset our uniforms
|
// We need to reset our uniforms
|
||||||
if (self.screen_size) |size| {
|
if (self.screen_size) |size| {
|
||||||
self.deferred_screen_size = .{ .size = size };
|
self.deferred_screen_size = .{ .size = size };
|
||||||
}
|
}
|
||||||
self.deferred_font_size = .{ .metrics = metrics };
|
self.deferred_font_size = .{ .metrics = self.grid_metrics };
|
||||||
self.deferred_config = .{};
|
self.deferred_config = .{};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,64 +591,40 @@ pub fn setFocus(self: *OpenGL, focus: bool) !void {
|
|||||||
///
|
///
|
||||||
/// Must be called on the render thread.
|
/// Must be called on the render thread.
|
||||||
pub fn setFontSize(self: *OpenGL, size: font.face.DesiredSize) !void {
|
pub fn setFontSize(self: *OpenGL, size: font.face.DesiredSize) !void {
|
||||||
if (single_threaded_draw) self.draw_mutex.lock();
|
_ = self;
|
||||||
defer if (single_threaded_draw) self.draw_mutex.unlock();
|
_ = size;
|
||||||
|
if (true) @panic("TODO"); // TODO(fontmem)
|
||||||
log.info("set font size={}", .{size});
|
//
|
||||||
|
// if (single_threaded_draw) self.draw_mutex.lock();
|
||||||
// Set our new size, this will also reset our font atlas.
|
// defer if (single_threaded_draw) self.draw_mutex.unlock();
|
||||||
try self.font_group.setSize(size);
|
//
|
||||||
|
// log.info("set font size={}", .{size});
|
||||||
// Reset our GPU uniforms
|
//
|
||||||
const metrics = try resetFontMetrics(
|
// // Set our new size, this will also reset our font atlas.
|
||||||
self.alloc,
|
// try self.font_group.setSize(size);
|
||||||
self.font_group,
|
//
|
||||||
self.config.font_thicken,
|
// // Reset our GPU uniforms
|
||||||
);
|
// const metrics = try resetFontMetrics(
|
||||||
|
// self.alloc,
|
||||||
// Defer our GPU updates
|
// self.font_group,
|
||||||
self.deferred_font_size = .{ .metrics = metrics };
|
// self.config.font_thicken,
|
||||||
|
// );
|
||||||
// Recalculate our cell size. If it is the same as before, then we do
|
//
|
||||||
// nothing since the grid size couldn't have possibly changed.
|
// // Defer our GPU updates
|
||||||
if (std.meta.eql(self.grid_metrics, metrics)) return;
|
// self.deferred_font_size = .{ .metrics = metrics };
|
||||||
self.grid_metrics = metrics;
|
//
|
||||||
|
// // Recalculate our cell size. If it is the same as before, then we do
|
||||||
// Notify the window that the cell size changed.
|
// // nothing since the grid size couldn't have possibly changed.
|
||||||
_ = self.surface_mailbox.push(.{
|
// if (std.meta.eql(self.grid_metrics, metrics)) return;
|
||||||
.cell_size = .{
|
// self.grid_metrics = metrics;
|
||||||
.width = metrics.cell_width,
|
//
|
||||||
.height = metrics.cell_height,
|
// // Notify the window that the cell size changed.
|
||||||
},
|
// _ = self.surface_mailbox.push(.{
|
||||||
}, .{ .forever = {} });
|
// .cell_size = .{
|
||||||
}
|
// .width = metrics.cell_width,
|
||||||
|
// .height = metrics.cell_height,
|
||||||
/// Reload the font metrics, recalculate cell size, and send that all
|
// },
|
||||||
/// down to the GPU.
|
// }, .{ .forever = {} });
|
||||||
fn resetFontMetrics(
|
|
||||||
alloc: Allocator,
|
|
||||||
font_group: *font.GroupCache,
|
|
||||||
font_thicken: bool,
|
|
||||||
) !font.face.Metrics {
|
|
||||||
// Get our cell metrics based on a regular font ascii 'M'. Why 'M'?
|
|
||||||
// Doesn't matter, any normal ASCII will do we're just trying to make
|
|
||||||
// sure we use the regular font.
|
|
||||||
const metrics = metrics: {
|
|
||||||
const index = (try font_group.indexForCodepoint(alloc, 'M', .regular, .text)).?;
|
|
||||||
const face = try font_group.group.faceFromIndex(index);
|
|
||||||
break :metrics face.metrics;
|
|
||||||
};
|
|
||||||
log.debug("cell dimensions={}", .{metrics});
|
|
||||||
|
|
||||||
// Set details for our sprite font
|
|
||||||
font_group.group.sprite = font.sprite.Face{
|
|
||||||
.width = metrics.cell_width,
|
|
||||||
.height = metrics.cell_height,
|
|
||||||
.thickness = metrics.underline_thickness * @as(u32, if (font_thicken) 2 else 1),
|
|
||||||
.underline_position = metrics.underline_position,
|
|
||||||
};
|
|
||||||
|
|
||||||
return metrics;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The primary render callback that is completely thread-safe.
|
/// The primary render callback that is completely thread-safe.
|
||||||
@ -1056,7 +1038,7 @@ pub fn rebuildCells(
|
|||||||
|
|
||||||
// Split our row into runs and shape each one.
|
// Split our row into runs and shape each one.
|
||||||
var iter = self.font_shaper.runIterator(
|
var iter = self.font_shaper.runIterator(
|
||||||
self.font_group,
|
self.font_grid,
|
||||||
screen,
|
screen,
|
||||||
row,
|
row,
|
||||||
selection,
|
selection,
|
||||||
@ -1170,33 +1152,21 @@ fn addPreeditCell(
|
|||||||
const bg = self.foreground_color;
|
const bg = self.foreground_color;
|
||||||
const fg = self.background_color;
|
const fg = self.background_color;
|
||||||
|
|
||||||
// Get the font for this codepoint.
|
// Render the glyph for our preedit text
|
||||||
const font_index = if (self.font_group.indexForCodepoint(
|
const render_ = self.font_grid.renderCodepoint(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
@intCast(cp.codepoint),
|
@intCast(cp.codepoint),
|
||||||
.regular,
|
.regular,
|
||||||
.text,
|
.text,
|
||||||
)) |index| index orelse return else |_| return;
|
|
||||||
|
|
||||||
// Get the font face so we can get the glyph
|
|
||||||
const face = self.font_group.group.faceFromIndex(font_index) catch |err| {
|
|
||||||
log.warn("error getting face for font_index={} err={}", .{ font_index, err });
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Use the face to now get the glyph index
|
|
||||||
const glyph_index = face.glyphIndex(@intCast(cp.codepoint)) orelse return;
|
|
||||||
|
|
||||||
// Render the glyph for our preedit text
|
|
||||||
const glyph = self.font_group.renderGlyph(
|
|
||||||
self.alloc,
|
|
||||||
font_index,
|
|
||||||
glyph_index,
|
|
||||||
.{ .grid_metrics = self.grid_metrics },
|
.{ .grid_metrics = self.grid_metrics },
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
log.warn("error rendering preedit glyph err={}", .{err});
|
log.warn("error rendering preedit glyph err={}", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
const render = render_ orelse {
|
||||||
|
log.warn("failed to find font for preedit codepoint={X}", .{cp.codepoint});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
// Add our opaque background cell
|
// Add our opaque background cell
|
||||||
self.cells_bg.appendAssumeCapacity(.{
|
self.cells_bg.appendAssumeCapacity(.{
|
||||||
@ -1226,12 +1196,12 @@ fn addPreeditCell(
|
|||||||
.grid_col = @intCast(x),
|
.grid_col = @intCast(x),
|
||||||
.grid_row = @intCast(y),
|
.grid_row = @intCast(y),
|
||||||
.grid_width = if (cp.wide) 2 else 1,
|
.grid_width = if (cp.wide) 2 else 1,
|
||||||
.glyph_x = glyph.atlas_x,
|
.glyph_x = render.glyph.atlas_x,
|
||||||
.glyph_y = glyph.atlas_y,
|
.glyph_y = render.glyph.atlas_y,
|
||||||
.glyph_width = glyph.width,
|
.glyph_width = render.glyph.width,
|
||||||
.glyph_height = glyph.height,
|
.glyph_height = render.glyph.height,
|
||||||
.glyph_offset_x = glyph.offset_x,
|
.glyph_offset_x = render.glyph.offset_x,
|
||||||
.glyph_offset_y = glyph.offset_y,
|
.glyph_offset_y = render.glyph.offset_y,
|
||||||
.r = fg.r,
|
.r = fg.r,
|
||||||
.g = fg.g,
|
.g = fg.g,
|
||||||
.b = fg.b,
|
.b = fg.b,
|
||||||
@ -1275,13 +1245,13 @@ fn addCursor(
|
|||||||
.underline => .underline,
|
.underline => .underline,
|
||||||
};
|
};
|
||||||
|
|
||||||
const glyph = self.font_group.renderGlyph(
|
const render = self.font_grid.renderGlyph(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
font.sprite_index,
|
font.sprite_index,
|
||||||
@intFromEnum(sprite),
|
@intFromEnum(sprite),
|
||||||
.{
|
.{
|
||||||
.grid_metrics = self.grid_metrics,
|
|
||||||
.cell_width = if (wide) 2 else 1,
|
.cell_width = if (wide) 2 else 1,
|
||||||
|
.grid_metrics = self.grid_metrics,
|
||||||
},
|
},
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
log.warn("error rendering cursor glyph err={}", .{err});
|
log.warn("error rendering cursor glyph err={}", .{err});
|
||||||
@ -1301,12 +1271,12 @@ fn addCursor(
|
|||||||
.bg_g = 0,
|
.bg_g = 0,
|
||||||
.bg_b = 0,
|
.bg_b = 0,
|
||||||
.bg_a = 0,
|
.bg_a = 0,
|
||||||
.glyph_x = glyph.atlas_x,
|
.glyph_x = render.glyph.atlas_x,
|
||||||
.glyph_y = glyph.atlas_y,
|
.glyph_y = render.glyph.atlas_y,
|
||||||
.glyph_width = glyph.width,
|
.glyph_width = render.glyph.width,
|
||||||
.glyph_height = glyph.height,
|
.glyph_height = render.glyph.height,
|
||||||
.glyph_offset_x = glyph.offset_x,
|
.glyph_offset_x = render.glyph.offset_x,
|
||||||
.glyph_offset_y = glyph.offset_y,
|
.glyph_offset_y = render.glyph.offset_y,
|
||||||
});
|
});
|
||||||
|
|
||||||
return &self.cells.items[self.cells.items.len - 1];
|
return &self.cells.items[self.cells.items.len - 1];
|
||||||
@ -1455,7 +1425,7 @@ fn updateCell(
|
|||||||
// If the cell has a character, draw it
|
// If the cell has a character, draw it
|
||||||
if (cell.hasText()) fg: {
|
if (cell.hasText()) fg: {
|
||||||
// Render
|
// Render
|
||||||
const glyph = try self.font_group.renderGlyph(
|
const render = try self.font_grid.renderGlyph(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
shaper_run.font_index,
|
shaper_run.font_index,
|
||||||
shaper_cell.glyph_index orelse break :fg,
|
shaper_cell.glyph_index orelse break :fg,
|
||||||
@ -1467,9 +1437,8 @@ fn updateCell(
|
|||||||
|
|
||||||
// If we're rendering a color font, we use the color atlas
|
// If we're rendering a color font, we use the color atlas
|
||||||
const mode: CellProgram.CellMode = switch (try fgMode(
|
const mode: CellProgram.CellMode = switch (try fgMode(
|
||||||
&self.font_group.group,
|
render.presentation,
|
||||||
cell_pin,
|
cell_pin,
|
||||||
shaper_run,
|
|
||||||
)) {
|
)) {
|
||||||
.normal => .fg,
|
.normal => .fg,
|
||||||
.color => .fg_color,
|
.color => .fg_color,
|
||||||
@ -1481,12 +1450,12 @@ fn updateCell(
|
|||||||
.grid_col = @intCast(x),
|
.grid_col = @intCast(x),
|
||||||
.grid_row = @intCast(y),
|
.grid_row = @intCast(y),
|
||||||
.grid_width = cell.gridWidth(),
|
.grid_width = cell.gridWidth(),
|
||||||
.glyph_x = glyph.atlas_x,
|
.glyph_x = render.glyph.atlas_x,
|
||||||
.glyph_y = glyph.atlas_y,
|
.glyph_y = render.glyph.atlas_y,
|
||||||
.glyph_width = glyph.width,
|
.glyph_width = render.glyph.width,
|
||||||
.glyph_height = glyph.height,
|
.glyph_height = render.glyph.height,
|
||||||
.glyph_offset_x = glyph.offset_x + shaper_cell.x_offset,
|
.glyph_offset_x = render.glyph.offset_x + shaper_cell.x_offset,
|
||||||
.glyph_offset_y = glyph.offset_y + shaper_cell.y_offset,
|
.glyph_offset_y = render.glyph.offset_y + shaper_cell.y_offset,
|
||||||
.r = colors.fg.r,
|
.r = colors.fg.r,
|
||||||
.g = colors.fg.g,
|
.g = colors.fg.g,
|
||||||
.b = colors.fg.b,
|
.b = colors.fg.b,
|
||||||
@ -1508,13 +1477,13 @@ fn updateCell(
|
|||||||
.curly => .underline_curly,
|
.curly => .underline_curly,
|
||||||
};
|
};
|
||||||
|
|
||||||
const underline_glyph = try self.font_group.renderGlyph(
|
const render = try self.font_grid.renderGlyph(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
font.sprite_index,
|
font.sprite_index,
|
||||||
@intFromEnum(sprite),
|
@intFromEnum(sprite),
|
||||||
.{
|
.{
|
||||||
.grid_metrics = self.grid_metrics,
|
|
||||||
.cell_width = if (cell.wide == .wide) 2 else 1,
|
.cell_width = if (cell.wide == .wide) 2 else 1,
|
||||||
|
.grid_metrics = self.grid_metrics,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1525,12 +1494,12 @@ fn updateCell(
|
|||||||
.grid_col = @intCast(x),
|
.grid_col = @intCast(x),
|
||||||
.grid_row = @intCast(y),
|
.grid_row = @intCast(y),
|
||||||
.grid_width = cell.gridWidth(),
|
.grid_width = cell.gridWidth(),
|
||||||
.glyph_x = underline_glyph.atlas_x,
|
.glyph_x = render.glyph.atlas_x,
|
||||||
.glyph_y = underline_glyph.atlas_y,
|
.glyph_y = render.glyph.atlas_y,
|
||||||
.glyph_width = underline_glyph.width,
|
.glyph_width = render.glyph.width,
|
||||||
.glyph_height = underline_glyph.height,
|
.glyph_height = render.glyph.height,
|
||||||
.glyph_offset_x = underline_glyph.offset_x,
|
.glyph_offset_x = render.glyph.offset_x,
|
||||||
.glyph_offset_y = underline_glyph.offset_y,
|
.glyph_offset_y = render.glyph.offset_y,
|
||||||
.r = color.r,
|
.r = color.r,
|
||||||
.g = color.g,
|
.g = color.g,
|
||||||
.b = color.b,
|
.b = color.b,
|
||||||
@ -1587,10 +1556,12 @@ pub fn changeConfig(self: *OpenGL, config: *DerivedConfig) !void {
|
|||||||
// so to be safe we just always reset it. This has a performance hit
|
// so to be safe we just always reset it. This has a performance hit
|
||||||
// when its not necessary but config reloading shouldn't be so
|
// when its not necessary but config reloading shouldn't be so
|
||||||
// common to cause a problem.
|
// common to cause a problem.
|
||||||
self.font_group.reset();
|
//
|
||||||
self.font_group.group.styles = config.font_styles;
|
// TODO(fontmem): see Metal
|
||||||
self.font_group.atlas_greyscale.clear();
|
// self.font_group.reset();
|
||||||
self.font_group.atlas_color.clear();
|
// self.font_group.group.styles = config.font_styles;
|
||||||
|
// self.font_group.atlas_greyscale.clear();
|
||||||
|
// self.font_group.atlas_color.clear();
|
||||||
|
|
||||||
// We always redo the font shaper in case font features changed. We
|
// We always redo the font shaper in case font features changed. We
|
||||||
// could check to see if there was an actual config change but this is
|
// could check to see if there was an actual config change but this is
|
||||||
@ -1657,71 +1628,85 @@ pub fn setScreenSize(
|
|||||||
fn flushAtlas(self: *OpenGL) !void {
|
fn flushAtlas(self: *OpenGL) !void {
|
||||||
const gl_state = self.gl_state orelse return;
|
const gl_state = self.gl_state orelse return;
|
||||||
|
|
||||||
{
|
texture: {
|
||||||
const atlas = &self.font_group.atlas_greyscale;
|
// If the texture isn't modified we do nothing
|
||||||
if (atlas.modified) {
|
const atlas = &self.font_grid.atlas_greyscale;
|
||||||
atlas.modified = false;
|
const modified = atlas.modified.load(.monotonic);
|
||||||
var texbind = try gl_state.texture.bind(.@"2D");
|
if (modified <= self.texture_greyscale_modified) break :texture;
|
||||||
defer texbind.unbind();
|
self.texture_greyscale_modified = modified;
|
||||||
|
|
||||||
if (atlas.resized) {
|
// If it is modified we need to grab a read-lock
|
||||||
atlas.resized = false;
|
self.font_grid.lock.lockShared();
|
||||||
try texbind.image2D(
|
defer self.font_grid.lock.unlockShared();
|
||||||
0,
|
|
||||||
.red,
|
var texbind = try gl_state.texture.bind(.@"2D");
|
||||||
@intCast(atlas.size),
|
defer texbind.unbind();
|
||||||
@intCast(atlas.size),
|
|
||||||
0,
|
const resized = atlas.resized.load(.monotonic);
|
||||||
.red,
|
if (resized > self.texture_greyscale_resized) {
|
||||||
.UnsignedByte,
|
self.texture_greyscale_resized = resized;
|
||||||
atlas.data.ptr,
|
try texbind.image2D(
|
||||||
);
|
0,
|
||||||
} else {
|
.red,
|
||||||
try texbind.subImage2D(
|
@intCast(atlas.size),
|
||||||
0,
|
@intCast(atlas.size),
|
||||||
0,
|
0,
|
||||||
0,
|
.red,
|
||||||
@intCast(atlas.size),
|
.UnsignedByte,
|
||||||
@intCast(atlas.size),
|
atlas.data.ptr,
|
||||||
.red,
|
);
|
||||||
.UnsignedByte,
|
} else {
|
||||||
atlas.data.ptr,
|
try texbind.subImage2D(
|
||||||
);
|
0,
|
||||||
}
|
0,
|
||||||
|
0,
|
||||||
|
@intCast(atlas.size),
|
||||||
|
@intCast(atlas.size),
|
||||||
|
.red,
|
||||||
|
.UnsignedByte,
|
||||||
|
atlas.data.ptr,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
texture: {
|
||||||
const atlas = &self.font_group.atlas_color;
|
// If the texture isn't modified we do nothing
|
||||||
if (atlas.modified) {
|
const atlas = &self.font_grid.atlas_color;
|
||||||
atlas.modified = false;
|
const modified = atlas.modified.load(.monotonic);
|
||||||
var texbind = try gl_state.texture_color.bind(.@"2D");
|
if (modified <= self.texture_color_modified) break :texture;
|
||||||
defer texbind.unbind();
|
self.texture_color_modified = modified;
|
||||||
|
|
||||||
if (atlas.resized) {
|
// If it is modified we need to grab a read-lock
|
||||||
atlas.resized = false;
|
self.font_grid.lock.lockShared();
|
||||||
try texbind.image2D(
|
defer self.font_grid.lock.unlockShared();
|
||||||
0,
|
|
||||||
.rgba,
|
var texbind = try gl_state.texture_color.bind(.@"2D");
|
||||||
@intCast(atlas.size),
|
defer texbind.unbind();
|
||||||
@intCast(atlas.size),
|
|
||||||
0,
|
const resized = atlas.resized.load(.monotonic);
|
||||||
.bgra,
|
if (resized > self.texture_color_resized) {
|
||||||
.UnsignedByte,
|
self.texture_color_resized = resized;
|
||||||
atlas.data.ptr,
|
try texbind.image2D(
|
||||||
);
|
0,
|
||||||
} else {
|
.rgba,
|
||||||
try texbind.subImage2D(
|
@intCast(atlas.size),
|
||||||
0,
|
@intCast(atlas.size),
|
||||||
0,
|
0,
|
||||||
0,
|
.bgra,
|
||||||
@intCast(atlas.size),
|
.UnsignedByte,
|
||||||
@intCast(atlas.size),
|
atlas.data.ptr,
|
||||||
.bgra,
|
);
|
||||||
.UnsignedByte,
|
} else {
|
||||||
atlas.data.ptr,
|
try texbind.subImage2D(
|
||||||
);
|
0,
|
||||||
}
|
0,
|
||||||
|
0,
|
||||||
|
@intCast(atlas.size),
|
||||||
|
@intCast(atlas.size),
|
||||||
|
.bgra,
|
||||||
|
.UnsignedByte,
|
||||||
|
atlas.data.ptr,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1999,7 +1984,7 @@ const GLState = struct {
|
|||||||
pub fn init(
|
pub fn init(
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
config: DerivedConfig,
|
config: DerivedConfig,
|
||||||
font_group: *font.GroupCache,
|
font_grid: *font.SharedGrid,
|
||||||
) !GLState {
|
) !GLState {
|
||||||
var arena = ArenaAllocator.init(alloc);
|
var arena = ArenaAllocator.init(alloc);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
@ -2045,12 +2030,12 @@ const GLState = struct {
|
|||||||
try texbind.image2D(
|
try texbind.image2D(
|
||||||
0,
|
0,
|
||||||
.red,
|
.red,
|
||||||
@intCast(font_group.atlas_greyscale.size),
|
@intCast(font_grid.atlas_greyscale.size),
|
||||||
@intCast(font_group.atlas_greyscale.size),
|
@intCast(font_grid.atlas_greyscale.size),
|
||||||
0,
|
0,
|
||||||
.red,
|
.red,
|
||||||
.UnsignedByte,
|
.UnsignedByte,
|
||||||
font_group.atlas_greyscale.data.ptr,
|
font_grid.atlas_greyscale.data.ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2066,12 +2051,12 @@ const GLState = struct {
|
|||||||
try texbind.image2D(
|
try texbind.image2D(
|
||||||
0,
|
0,
|
||||||
.rgba,
|
.rgba,
|
||||||
@intCast(font_group.atlas_color.size),
|
@intCast(font_grid.atlas_color.size),
|
||||||
@intCast(font_group.atlas_color.size),
|
@intCast(font_grid.atlas_color.size),
|
||||||
0,
|
0,
|
||||||
.bgra,
|
.bgra,
|
||||||
.UnsignedByte,
|
.UnsignedByte,
|
||||||
font_group.atlas_color.data.ptr,
|
font_grid.atlas_color.data.ptr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user