glplat: minimal GL platform layer (experiment) — GLFW/OpenGL backend, font primitives, screenshot - #392
glplat: minimal GL platform layer (experiment) — GLFW/OpenGL backend, font primitives, screenshot#392nnunley wants to merge 4 commits into
Conversation
nooga
left a comment
There was a problem hiding this comment.
This is a solid spike and the seams (registry/interface, pure-Go API vs internal/native) look right. Before this lands non-draft, the cgo/GLFW dependency needs to be behind a build tag (e.g. //go:build glplat on internal/native and a stub/no-op registration otherwise) so go build ./... and the wasm target don't require GLFW/OpenGL/cgo on every machine and CI runner. Right now pkg/rt unconditionally pulls in the native backend, which would break headless CI and the existing GOOS=js wasm build.
|
Rebased onto current main ( |
|
Build-tag gate implemented in 2382162: Verified all three configurations locally:
Staying draft for now — it's still a spike — but the unconditional-cgo blocker is gone. |
…wport from framebuffer size each frame (Retina)
FontLoad (ttf/otf/ttc), FontHasGlyph, FontRasterizeCell (fit-to-cell alpha grid), SaveGlyphAtlasPNG — minimal Go surface; layout/policy moved to xsofy's tools/bake_atlas.lg. cmd/lgatlas deleted (replaced).
glReadPixels of the back buffer (call after rendering, before EndFrame swaps), rows flipped, alpha forced opaque. Registry interface + native backend + public API + rt binding.
Without the tag no backend registers: the pure-Go API returns 'no backend registered' errors, and plain go build ./..., headless CI, and the GOOS=js wasm target no longer require GLFW/OpenGL/cgo. Build with -tags glplat to get the native GLFW/OpenGL backend.
|
Rebased onto current main ( |
There was a problem hiding this comment.
Looked at the tip (489d5c62) with the build-tag gate in. The seams (registry, pure-Go API, -tags glplat) look right, and the unconditional-cgo blocker is gone. A few concrete issues to fix before this leaves draft:
P1: LoadTextureRGBA buffer length
LoadTextureRGBA passes w, h, and gl.Ptr(pixels) to gl.TexImage2D with no len(pixels) >= w*h*4 check (pkg/glplat/internal/native/native.go). A short slice (easy from the lg seq→byte unbox) is a C-side over-read. Reject up front in the public API and/or the native backend.
P2: texture Y orientation
LoadTextureFile / LoadTextureRGBA upload the first row first. OpenGL treats that as the texture bottom, while the spike UVs put v=0 at the top of the quad. Atlases from SaveGlyphAtlasPNG / FontRasterizeCell are top-down, so glyphs render upside-down unless something else compensates. Flip on upload (or invert V in the contract) and say which convention the API owns.
P2: WindowSize frozen at Init
BeginFrame refreshes the viewport from the framebuffer each frame (good for Retina), but WindowSize() returns the dimensions cached in Init. After a resize, ortho/UI math that trusts WindowSize drifts from the viewport. Read GetWindowSize() (and/or a size callback).
P2: Terminate leaves a live window pointer
window.Destroy() runs but b.window is not nil'd, and the texture map still holds deleted GL IDs. Later ShouldClose / BeginFrame / SubmitTriangles is use-after-destroy. Nil the window, clear maps/IDs, and decide whether re-Init is supported.
P2: font registry locking vs sfnt.Buffer
FontHasGlyph / FontRasterizeCell unlock, then call GlyphIndex on the shared entry.buf. Concurrent has-glyph/rasterize (or overlap with getFace mutating faces) races. Hold the mutex across buffer use, or give each call its own sfnt.Buffer.
P2: getFace swallows NewFace errors
Failed face creation stores nil; later DrawString panics. Easy to hit when width-fit scales int(newSize) to 0. Propagate the error and reject non-positive sizes.
Smaller / residual
- No Go or lg tests for the contracts that matter (vertex stride, MVP column-major layout, screenshot-before-swap, font cell fit).
- Spike examples don't say that
lgneeds-tags glplat. - Depth-test + alpha blending will bite overlapping translucent glyphs.
- Unknown texture IDs fall through to GL texture
0instead of the white fallback. - Hand-written
pkg/rt/interop_glplat.gois labeled "Code generated bylginterop/ DO NOT EDIT"; fine that it's hand-rolled (cgo), but the header will mislead the next editor.
Fonts usable without GLFW is the right cut of the surface. If this starts competing with a surface-style seam, spell out how it relates to #255's host-owned graphics model.
|
We rebased this branch onto current The rebase is nearly freeThe branch was 42 commits behind Two notes from driving the input queueBoth only really show up from the client side, so they are easy to miss from inside the package. One physical keypress arrives as two events.
A WebGL backend looks closer than expected
The hard part is the loop. A frame loop that never returns starves the browser's event loop, and this one is built to block, with We have not built this, so treat the shape as an assessment rather than a result. One question before the seam setsShould a browser backend live behind this package's own registry, or behind the surface capability from #255 as reshaped in #572? Those are two different extension points for the same kind of thing, and picking one is cheaper now than after both have implementations. That reads like a maintainer call rather than ours. The two input findings stand on their own and are worth folding in whenever this branch next moves. The WebGL sketch can wait on that question — happy to work it up in detail, or to drop it if the answer makes it moot. |
Experimental platform layer backing xsofy's GL frontend spike (see the companion xsofy
gl-frontendbranch). Draft — for visibility and review of the seams, not necessarily for merging as-is.What's here
pkg/glplat: pure-Go public API delegating through an interface/registry tointernal/native(cgo: GLFW 3.3 + OpenGL 4.1 core). Contract: 9-float vertices (x y z u v r g b a),SubmitTrianglesdraws immediately with the current column-major MVP, texture 0 = untextured white.FontLoadttf/otf/ttc,FontHasGlyph,FontRasterizeCell,SaveGlyphAtlasPNG) — minimal rasterization surface so atlas-baking policy lives in lg code (xsofytools/bake_atlas.lg), per 'as minimal as possible in Go'. Replaces the earliercmd/lgatlasCLI (deleted).Screenshot(path): glReadPixels of the back buffer → PNG, for headless frame verification.pkg/rt/interop_glplat.go(lginterop style; the source importer can't typecheck cgo packages).Notes
Part of #259 (Epic: Host integration & interop) — realizes the graphics host-capability seam scoped in #255.