Skip to content

perf: convert_alpha() cached drawImage surfaces for faster blits - #28

Merged
dmccoystephenson merged 1 commit into
mainfrom
feature/convert-alpha-cached-images
Aug 1, 2026
Merged

perf: convert_alpha() cached drawImage surfaces for faster blits#28
dmccoystephenson merged 1 commit into
mainfrom
feature/convert-alpha-cached-images

Conversation

@dmccoystephenson

@dmccoystephenson dmccoystephenson commented Aug 1, 2026

Copy link
Copy Markdown
Member

Summary

  • drawImage already caches the loaded and scaled surface by filePath to avoid repeating the expensive load/scale work every frame, but the cached surface itself was never converted to the display's pixel format.
  • An unconverted pygame.Surface is reformatted on every single blit() call (pygame's documented perf guidance is to convert()/convert_alpha() once after loading). Doing that conversion when the surface first enters the cache keeps that reformat cost out of the per-frame render path the cache exists to protect.
  • convert_alpha() (rather than convert()) also preserves per-pixel alpha for images that have it, so transparent PNGs continue to render correctly.

No public API surface changed — Graphik.drawImage's signature and observable caching behavior (per-path cache, rescale-on-size-change) are unchanged; this is purely an internal perf improvement.

Test plan

  • python3 -m py_compile src/main/python/preponderous/graphik/graphik.py
  • python3 -m pytest — 25 passed (was 24; added test_draw_image_converts_loaded_surface_for_faster_blits)
  • Regression-verified empirically: stashed the production fix, confirmed the new test fails (SRCALPHA flag absent), restored the fix, confirmed it passes.
  • Existing drawImage correctness/caching tests (pixel-color, load-count, scale-count, rescale-on-size-change) all still pass unchanged.

No tracking issue — gap found during triage; the backlog (issues/PRs) was empty at the start of this cycle.


This PR description was drafted during a Gardener session (Stephenson-Software/gardener).

An unconverted pygame Surface is reformatted to match the display on
every single blit; converting once when the surface enters the
drawImage cache keeps that cost out of the per-frame render path the
cache already exists to protect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dmccoystephenson

dmccoystephenson commented Aug 1, 2026

Copy link
Copy Markdown
Member Author

Self-review rubric:

  • Scope: PASS — only graphik.py (the one-line cache-site change) and its test file are touched; no unrelated formatting/renames.
  • Tests-new: PASS — test_draw_image_converts_loaded_surface_for_faster_blits exercises the new conversion via the surface actually passed to pygame.transform.scale.
  • Tests-fix (empirical): PASS — stashed the production change, confirmed the new test fails (SRCALPHA flag absent on the pre-fix surface), popped the stash, confirmed it passes. Not scored from reasoning alone.
  • Sibling structure: PASS — new test follows the existing drawImage test group's structure/naming and reuses the existing _count_image_scales monkeypatch helper rather than inventing a new pattern.
  • Sibling renames: N/A — no identifier renamed.
  • Docs: PASS — checked README's drawImage bullet against the new code; the documented caching contract (per-path cache, rescale on size change) is unchanged, so no doc update was needed.
  • Issue resolution: N/A — no tracking issue; gap found during triage (backlog was empty at cycle start), noted in the PR body.
  • Manual validation: PASS — py_compile, the import smoke test, and pytest (25 passed, up from 24) all green on the PR head commit (a4113c5).
  • camelCase: N/A — no new/renamed public method; drawImage's name and signature are unchanged.
  • Backward-compat: PASS — drawImage(filePath, xpos, ypos, width, height) signature and observable behavior (per-path caching, rescale-on-size-change, missing-file error) are unchanged; only the internal pixel format of the cached surface changed. Consumer-impact search (gh search code) is blocked pending approval in this headless dispatch (tracked as graphik-dev-loop#14) — not run, but the gate is scoped to changes that rename/remove/alter an existing public member's signature, which this is not, so it does not apply here.
  • Headless: PASS — the new test runs under the suite's existing SDL_VIDEODRIVER=dummy/SDL_AUDIODRIVER=dummy headless setup (conftest.py), no real display/audio required.
  • Version sync: N/A — no version string changed.
  • No new deps: PASS — convert_alpha() is a pygame.Surface method already available via the existing pygame dependency; no new import.

Summary: internal perf-only fix to drawImage's image cache (adds convert_alpha() once per cached path so per-frame blits don't pay the pixel-format conversion cost every call), covered by an empirically-verified regression test. No public API change.


drafted by Claude on behalf of Daniel Stephenson

@dmccoystephenson
dmccoystephenson merged commit f9868d0 into main Aug 1, 2026
5 checks passed
@dmccoystephenson
dmccoystephenson deleted the feature/convert-alpha-cached-images branch August 1, 2026 08:14
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