fix(render): gate TextAtlas::sync on the loader, and cover three review findings

Review of the atlas refactor found one Important and three Minor issues:

- Important: TextAtlas::sync called glGetIntegerv before any available() check,
  so a host that synced before plot::gl::load() -- which is legal for a public
  class Tasks 2 and 8 build backends on -- segfaulted on a null entry point
  instead of receiving the Status the interface promises. It now follows the
  handle-constructor convention (available(), then the entry point itself) and
  reports Unsupported.
- empty() no longer means "a GL name exists": releasing one is a
  glDeleteTextures call, so the no-atlas path forgets the atlas and only resets
  the texture when there is a table to release it with.
- end_frame's comment still claimed the frame hands back the unpack alignment
  init() set, contradicting the code below it and renderer.hpp.
- The orientation case's texel probe mapped the atlas' u along the cell's +v
  axis and vice versa, which is a no-op for its two diagonal probes -- so it
  could not fail on a transposed UV mapping, and its own comment misstated the
  rule. Probes now follow the shader's rule and include an off-diagonal pair.
- The null-glyph path of add_text (and its twin in walk_text_clipped) was
  unreached by any case.

Cases: text_atlas_reports_a_status_when_the_entry_points_are_missing,
add_text_skips_a_codepoint_the_backend_cannot_draw.
This commit is contained in:
Martino Ferrari committed 2026-09-28 10:22:38 +02:00
1 parent e1f6b61b7d
commit 3ff7b9c978
5 files changed
+230 -16

No files matched your search

+8 -5
View File
@@ -326,11 +326,14 @@ void Renderer::end_frame() noexcept {
gl_error_ = true;
}
// Leave the host's context as close to neutral as a frame can: nothing bound to
// a pipeline stage, off every state bit the frame turned on, and the two values
// the frame *changed* rather than merely used handed back -- the unpack
// alignment `init()` set for the atlas, and the host's clear colour. What
// remains is the viewport (the caller's to set for its next pass), the pixel-pack
// alignment a PPM dump may have set, and the vertex buffers' own contents.
// a pipeline stage, off every state bit the frame turned on, and the one value
// the frame *changed* rather than merely used handed back -- the host's clear
// colour. What remains is the viewport (the caller's to set for its next pass),
// the pixel-pack alignment a PPM dump may have set, and the vertex buffers' own
// contents. `GL_UNPACK_ALIGNMENT` is not in this list: `render::TextAtlas`
// saves and restores it around every atlas upload, so the frame never leaves it
// moved for the host's own uploads to inherit (see end_frame's contract in
// renderer.hpp).
gl::glBindVertexArray(0);
gl::glUseProgram(0);
gl::glBindBuffer(gl::GL_ARRAY_BUFFER, 0);