Commit 2f4ce7b
committed
(GL1) Fix font atlas corruption from GL_UNPACK_ROW_LENGTH state leak
gl1_draw_tex sets glPixelStorei(GL_UNPACK_ROW_LENGTH, pot_width)
before its glTexImage2D and never resets it. GL_UNPACK_ROW_LENGTH
is global pixel-store state that persists until something changes
it, so every subsequent glTexImage2D in the frame inherits it as
the source row stride.
When this leaked stride does not match the source data's actual row
stride, glTexImage2D reads source rows with the wrong pitch and
writes the texture with glyphs landing at offsets that are shifted
relative to where atlas_offset_x/atlas_offset_y say they should be.
In ozone this manifests as the title and sidebar fonts (whichever
fonts are uploaded while a stale ROW_LENGTH is in effect) rendering
as horizontal stripe patterns instead of letters: the texcoords
baked into the vertex block point at slot positions, but those
positions in the actual texture contain the wrong glyph data —
typically the codepoint-0 fallback bitmap from atlas (0,0), which
freetype draws as horizontal bars.
The corruption is invisible to glGetTexImage readback because the
same ROW_LENGTH state that skewed the upload would skew the
readback symmetrically, so a 2D dump comes out looking correct as
an image even though the GPU sampler reading specific (s,t)
coordinates hits different texels than the bake math expects.
A context reset masks the bug because re-running font init under a
GL state where ROW_LENGTH happens to already be 0 produces a clean
upload.
Fix in two places, defense-in-depth:
1. gl1_raster_font_upload_atlas now explicitly sets
GL_UNPACK_ALIGNMENT=1 and GL_UNPACK_ROW_LENGTH=0 immediately
before glTexImage2D, so the upload is robust regardless of what
state it inherits. This matches the existing pattern in
gl3_raster_font_upload_atlas.
2. gl1_draw_tex now resets GL_UNPACK_ROW_LENGTH=0 after its
glTexImage2D, so it stops leaking the value to other uploads in
the first place.
Either fix alone resolves the symptom. Both together also protect
against future code paths that may set ROW_LENGTH and forget to
reset it.
Bug appears to be long-standing — present at least as far back as
April 2026 (commit c10115b), likely much older. Goes unnoticed
because gl1 + ozone is rarely used in practice; gl/glcore/Vulkan
are the common paths.
VITA is excluded from the new glPixelStorei calls, matching the
existing #ifndef VITA guards on the other glPixelStorei sites in
this file.1 parent 3d687a7 commit 2f4ce7b
1 file changed
Lines changed: 26 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
471 | 471 | | |
472 | 472 | | |
473 | 473 | | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
474 | 493 | | |
475 | 494 | | |
476 | 495 | | |
| |||
1446 | 1465 | | |
1447 | 1466 | | |
1448 | 1467 | | |
| 1468 | + | |
| 1469 | + | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + | |
| 1473 | + | |
| 1474 | + | |
1449 | 1475 | | |
1450 | 1476 | | |
1451 | 1477 | | |
| |||
0 commit comments