glplat: Ebitengine backend behind -tags glplat_ebiten (stacked on #392) - #744
Open
mparrett wants to merge 6 commits into
Open
glplat: Ebitengine backend behind -tags glplat_ebiten (stacked on #392)#744mparrett wants to merge 6 commits into
mparrett wants to merge 6 commits into
Conversation
…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.
Second registry.Backend implementation, on Ebitengine instead of GLFW/OpenGL. Ebiten owns the main thread (RunGame), so the root main routes through a boot trampoline: the lg program runs on a goroutine and EndFrame hands each frame's batches to Update over an unbuffered channel — the rendezvous doubles as frame pacing. MVP is applied on the CPU (ebiten is 2D screen-space); no depth buffer, so batches draw in submission order — correct for the top-down frontend, mis-sorts 3D fp geometry. Conformance vs the GL backend on the unmodified xsofy gl-frontend (2026-08-14): XSOFY_GL_DUMP output byte-identical, screenshot pixel diff 0.3% (glyph edges), CPU parity over a 10s run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Layout returned the logical window size, so on Retina the backend drew at half the GL backend's framebuffer resolution and upscaled — visibly rough glyphs. Render device-scaled and derive the NDC->screen mapping from the actual target bounds (screenshots stay logical by design). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
nnunley
approved these changes
Aug 16, 2026
mparrett
marked this pull request as ready for review
August 16, 2026 02:40
mparrett
marked this pull request as draft
August 16, 2026 06:02
Owner
mparrett
marked this pull request as ready for review
September 2, 2026 02:44
Collaborator
|
Architecture dependency update (2026-09-07): #744 remains blocked behind #392, but the intended direction is now explicit: use the merged #572 Please do not treat this as a request for a mechanical rebase yet. #392's unresolved safety/API findings still need fixes after the re-scope, and this Ebitengine backend should be evaluated against the resulting #572-based contract rather than the current |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #392. This branch carries #392's commits rebased onto current main (one
.gitignoreconflict, both sides kept) plus two of ours on top; only the tip two commits are for review here. It will be rebased onto whatever #392 lands as, and closed instead if the commits get folded into #392 directly. Draft until then.A second
registry.Backendimplementation, on Ebitengine instead of GLFW/OpenGL. Two motivations: prove the backend seam with an independent implementation while #392 is still a draft and the interface is cheap to change, and get the two capabilities the GL backend cannot offer — the browser (ebiten's js/wasm target; the GL backend is cgo+GLFW, native only) and modern native APIs (Metal on macOS, where the GL backend rides deprecated OpenGL 4.1).Ebiten owns the main thread, which inverts glplat's caller-owned frame loop. The backend absorbs the inversion so the API and game code see no difference:
mainroutes through a boot trampoline (glplat.EbitenBootMain), the lg program runs on a goroutine, andEndFramehands each frame's batches to ebiten'sUpdateover an unbuffered channel, which doubles as frame pacing. MVP matrices are applied on the CPU since ebiten'sDrawTrianglesis 2D screen-space; rendering is at device scale to match the GL backend's framebuffer resolution.Known limitation: ebiten has no depth buffer, so batches draw in submission order. That is exact for the top-down xsofy frontend (coplanar geometry under an ortho matrix) but mis-sorts first-person-mode geometry; a CPU back-to-front sort for perspective batches is the planned follow-up.
Verified (2026-08-14):
XSOFY_GL_DUMPoutput byte-identical to the GL backend and deterministic across runs; screenshot pixel diff 0.3%.GOOS=js GOARCH=wasmbuilds with the tag and a probe page running an lg draw loop renders correctly in Chromium — the blockingEndFramecontract survives wasm because the Go scheduler parks the blocked lg goroutine while ebiten's requestAnimationFrame loop runs.-tags glplat, and GOOS=linux/plan9/js builds are all unaffected.🤖 Generated with Claude Code