Skip to content

Imageproc - #222

Merged
techomancer merged 14 commits into
mainfrom
imageproc
Oct 13, 2026
Merged

techomancer merged 14 commits into
mainfrom
imageproc

Conversation

@techomancer

Copy link
Copy Markdown
Owner

image processing series
and some eram fixes for state management

techomancer and others added 14 commits October 12, 2026 20:56
The kernel evicts a context by copying its slot once per GE: reads at S
and S - 1 (GE1's output runs a word late), then both halves back to S.
With one ERAM modelled, GE1's half overwrote GE0's a word off, shifting
the saved GL state by a register: Matador came back from being iconified
drawing into the wrong buffer. A transfer repeating GE0's last one now
goes to GE1's ERAM.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
A negative pixel zoom shows only in GE pixel state 0xDA8, whose rows then
run down from the raster position; draw them that way (Mirai's splash was
upside down). Answer GE readback 0xB9C, glIsEnabled(GL_SCISSOR_TEST):
Mirai disables scissoring for its front-to-back copy only when it is on,
and our 0 clipped the copy to the last widget's box, leaving a stale
menu bar in one bank.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Mirai's RGB16 copies into RGBA16 send narrow strips whose rows do not
fill whole words (93 pixels = 558 bytes in 140 words). The host pixel
size was only recognised when the row bytes divided by the width, so
these were drawn as 8-byte pixels: short, channels mixed, and without
their 0xDA8 offset (the welcome dialog's right edge at its left, menu
labels garbled after a menu closed).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Pixel data commands whose data starts mid-word (libGLcore's rows at
UNPACK_ALIGNMENT 1) carry one more word than their byte count plus a
pad; the HQ took the declared count only, parsed the rest as commands
and the client hung. Realign them.

GE_DATA and the readback answer now belong to the context: another
client clearing the flag wiped a pending answer and its owner waited
forever.

test/gltest/pixtest.c: self-checking tests of every GL 1.1 pixel path
(formats, types, store and transfer modes, zoom, copies, buffers,
textures). tools/mgras-pixdecode.py splits a recording by pixtest case
and names the GE pixel pipeline's modules from the microcode's line
table.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
libGLcore programs the GE11's pixel path as a list of microcode modules
at GE 0x13B (module k's state address in pair k + 1), named from the
microcode's line table: inttofloat, shiftadd, unpack, scalebias,
expand, LUT, clamp, mask, colmatrix, pipecontrol. pixpipe.rs runs them
on a row's component stream with their traced state layouts, so draws
convert every GL format and type, pixel transfer scale/bias and maps
as the board does, and hand the raster engine the transfer type
libGLcore asked for. State blocks too big for a token, and colour
tables (INIT_COLOR_TABLE), come as the next pixel data command: kept.

The raster engine now converts host pixels by XFRMODE format (3-6 one
component, 7 RGB, 8 RGBA) and type (unsigned and signed 8, 16, 32
bits), with RGBorder (bit 22, which the stride-skip field swallowed)
choosing red- or alpha-first RGBA; RGBA16 keeps alpha, in the JIT too.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The draw copied each raster pixel through an 8-byte buffer; RGBA FLOAT
draws now reach the raster engine as four 32-bit components and the HQ
thread panicked.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- GET_PIXELS 0x400A is a PIO read (packed-type rows, one at a time):
  arm a PIO read block, not a DMA one.
- Zoom: the GE repeats rows by 1/zy and, for a fractional x zoom,
  replicates ceil(zx) (xzoom); the raster engine zooms x by XFRFACTOR
  (XFRMODE bit 19) or decimates by it (bit 20). XFRMODE's stride skip
  is bits 18:14.
- shiftadd shifts (left, or right when negative) and adds (index shift
  and offset); expand mode 7 copies an index to all four components for
  the I_TO_* maps; element size from the row when the type word does not
  say (stencil, colour index).
- glBitmap LSB_FIRST: format word bit 17.
- RGBA in wider types honours RGBorder (alpha first without it); host
  components to the framebuffer keep their top bits, 12:12:12 reads all
  twelve.
- pixtest: XFAIL list for libGLcore's own deviations, zoom within a
  source pixel, textures through MODULATE with a white fragment.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…float

- Texture loads (SEND_PIXELS 0x511A) run the GE pipeline too, with its
  compress module (0x399A: the internal format's components out of
  RGBA), so every format and type converts into every internal format.
- Stencil draws: SAVE_RSS has the planes in bits 20:18 for a draw (24:22
  for a read).
- bitmaptofloat (0x24D7) for GL_BITMAP colour indices.
- PIO reads of RGB(A) come last component first.
- The formatter's byte swap with byte components swaps pairs (16-bit
  packed pixels).
- Zoom: the decimation samples at each destination pixel's centre; the
  xzoom replication is its index table's first run.
- pixtest: glTexSubImage2D error check and a resident-texture variant;
  libGLcore's glBitmap sub-byte skip as an expected failure.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ex outputs wrap

PIO reads of RGB(A) come in the reverse of the DMA order unless XFRMODE
bit 18 is set (the X server's XGetImage sets it, libGLcore never does);
stride skip is bits 17:14. Texture loads that compress to fewer
components take four input components. Stencil and colour-index draws
keep the low bits of the pipeline's output.

pixtest: legal glTexSubImage2D geometry (libGLcore wants >= 32 texels
wide or full width), error checks, XFAILs for libGLcore's own
departures. 348 pass, 0 fail, 12 XFAIL on MaxImpact.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Colour-index transfers in every integer type (format 0, types 3/4/5/7)
in the raster engine; the raster JIT leaves them to the interpreter.
Draws take their pixel count from 0xDA8's transfer width rather than the
word-padded row (13 16-bit indices drew 14 wide). The GE's bitmaptoint
module (GL_BITMAP on CI visuals). The LUT's offsets end at the 2^23
word (the 12-bit CI state's cycle word reads 14), and the table memory
moves from the per-context record to the HQ engine, 4096 entries, so a
12-bit visual's full I_TO_I map fits.

pixtest --ci 8|12 runs a colour-index suite: draw and read in every
type, shift/offset, I_TO_I maps, unpack/pack layouts, zoom, GL_BITMAP,
glBitmap, glIndexMask, glCopyPixels. 8-bit: 36 pass, 13 XFAIL; 12-bit:
44 pass, 5 XFAIL; the RGBA run is unchanged (348 pass).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Cases for what PR #221 fixed in the old draw path: 200-pixel-wide RGBA
and RGB images (DMA column chunks of 156 / 144) at zooms 1, 2, 3.2 and
fractional x zooms, and 1x1 / 2x2 / 4x4 GL_RGB textures with unpack
alignment 1 (word-padded DMA rows). All pass on the GE pipeline path:
365 pass, 0 fail, 12 XFAIL.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@techomancer
techomancer merged commit de048a1 into main Oct 13, 2026
4 of 6 checks passed
@techomancer
techomancer deleted the imageproc branch October 13, 2026 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant