|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Fixed-budget image-tile cache – implementation (Layer 3b, #147). More...
#include "ra8_tile_cache.h"#include <stddef.h>#include <stdint.h>#include <string.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_keycache.h"Go to the source code of this file.
Data Structures | |
| struct | priv_pan_line_t |
| The lead-edge tile run a pan prefetch walks (one row or one column). More... | |
Functions | |
| static ra8_err_t | internal_tile_decode (void *ctx, const void *key, uint8_t *cell, uint32_t cell_bytes, void *user) |
| Decode trampoline: adapt ra8_tile_decode_fn to the keycache seam. | |
| static uint16_t | internal_clamp_tile (uint32_t index, uint16_t count) |
| Clamp a tile index to the last valid index of a grid dimension. | |
| ra8_err_t | ra8_tile_rect_of_pixels (uint32_t px, uint32_t py, uint32_t pw, uint32_t ph, uint16_t tile_w, uint16_t tile_h, uint16_t tile_cols, uint16_t tile_rows, ra8_tile_rect_t *out) |
| Convert a pixel rectangle into the inclusive tile rectangle covering it. | |
| ra8_err_t | ra8_tile_cache_init (ra8_tile_cache_t *tc, const ra8_tile_cache_cfg_t *cfg) |
| Initialise a tile cache over caller-supplied storage. | |
| ra8_err_t | ra8_tile_cache_get (ra8_tile_cache_t *tc, const ra8_tile_key_t *key, ra8_tile_t *out_tile) |
Get (and pin) the decoded tile for key. | |
| ra8_err_t | ra8_tile_cache_put (ra8_tile_cache_t *tc, const uint8_t *pixels) |
| Release one pin on a tile previously returned by ra8_tile_cache_get. | |
| uint32_t | ra8_tile_cache_capacity (const ra8_tile_cache_t *tc) |
| Report the number of cells the cache can hold. | |
| ra8_err_t | ra8_tile_cache_prefetch (ra8_tile_cache_t *tc, const ra8_tile_key_t *key) |
| Warm one tile into the cache without holding a pin (read-ahead). | |
| static ra8_err_t | internal_validate_req (const ra8_tile_prefetch_req_t *req) |
| Reject a structurally invalid prefetch request. | |
| static bool | internal_pan_line (const ra8_tile_prefetch_req_t *req, priv_pan_line_t *out) |
| Compute the lead-edge tile run for a pan direction, or none at an edge. | |
| ra8_err_t | ra8_tile_cache_prefetch_pan (ra8_tile_cache_t *tc, const ra8_tile_prefetch_req_t *req, uint16_t *out_warmed) |
| Predictively warm the tiles one step ahead of a panning viewport. | |
| ra8_err_t | ra8_tile_cache_stats (const ra8_tile_cache_t *tc, uint32_t *out_hits, uint32_t *out_misses, uint32_t *out_evictions) |
| Report the cache hit / miss / eviction counters. | |
Variables | |
| static const char *const | s_tag = "ra8_tile_cache" |
| Module log tag. | |
Fixed-budget image-tile cache – implementation (Layer 3b, #147).
A thin typed facade over ::ra8_keycache, the image counterpart of ::ra8_glyph_atlas: the tile key is the cache key, the decoded tile is the cell payload, and the decoded width/height ride in the per-cell ra8_tile_dims_t user descriptor. A small decode trampoline adapts the public ra8_tile_decode_fn (out_w/out_h) to the keycache's render-on-miss seam (user descriptor) so the production stb_image-backed decoder and the test stubs are unchanged. All cache mechanics – the single LRU list, pinned-cell skip, hash chaining, eviction – live in ::ra8_keycache.
Definition in file ra8_tile_cache.c.
|
static |
Clamp a tile index to the last valid index of a grid dimension.
A rectangle that runs past the image edge names the last tile rather than an out-of-grid index the prefetch would have to re-clamp, so the clamp lives here, once, at the point the index is formed.
| [in] | index | Candidate tile index. |
| [in] | count | Tile count on that axis (> 0). |
| index | The index was already inside the grid. |
| count - 1 | The index addressed past the last tile. |
count is non-zero (validated by the caller). index is a tile index, not a pixel coordinate. count. Definition at line 97 of file ra8_tile_cache.c.
References RA8_INTERNAL.
Referenced by ra8_tile_rect_of_pixels().
|
static |
Compute the lead-edge tile run for a pan direction, or none at an edge.
Selects the row/column one step beyond req->view in req->dir and clamps it to the tile grid: a pan already against the image edge (or k_ra8_tile_pan_none) yields no run. Each direction's edge test is an independent single-condition guard.
| [in] | req | The validated prefetch request. |
| [out] | out | Receives the lead-edge run when the return is true. |
| true | *out holds the run to walk. |
| false | Nothing to warm (*out is untouched). |
Definition at line 277 of file ra8_tile_cache.c.
References ra8_tile_prefetch_req_t::dir, k_ra8_tile_pan_down, k_ra8_tile_pan_left, k_ra8_tile_pan_none, k_ra8_tile_pan_right, k_ra8_tile_pan_up, RA8_INTERNAL, ra8_tile_prefetch_req_t::tile_cols, ra8_tile_prefetch_req_t::tile_rows, ra8_tile_rect_t::tx0, ra8_tile_rect_t::tx1, ra8_tile_rect_t::ty0, ra8_tile_rect_t::ty1, and ra8_tile_prefetch_req_t::view.
Referenced by ra8_tile_cache_prefetch_pan().
|
static |
Decode trampoline: adapt ra8_tile_decode_fn to the keycache seam.
Casts the keycache render context back to the owning cache, calls the caller's tile decoder for the cell, and on success records the decoded width/height into the cell's ra8_tile_dims_t descriptor.
| [in] | ctx | The owning ra8_tile_cache_t (keycache render_ctx). |
| [in] | key | The ra8_tile_key_t to decode. |
| [out] | cell | Destination pixel buffer (cell_bytes writable). |
| [in] | cell_bytes | Cell capacity in bytes. |
| [out] | user | The cell's ra8_tile_dims_t descriptor. |
| k_ra8_ok | The tile was decoded and the descriptor recorded. |
| k_ra8_err_* | The caller's decoder error (descriptor left untouched). |
Definition at line 63 of file ra8_tile_cache.c.
References ra8_tile_cache_t::decode, ra8_tile_cache_t::decode_ctx, ra8_tile_dims_t::h, k_ra8_ok, and ra8_tile_dims_t::w.
Referenced by ra8_tile_cache_init().
|
static |
Reject a structurally invalid prefetch request.
Each guard is an independent single-condition check kept intact here: the visible rectangle must be ordered (tx0<=tx1, ty0<=ty1) and lie inside the tile grid (tx1<tile_cols, ty1<tile_rows).
| [in] | req | The prefetch request to validate (non-NULL). |
| k_ra8_ok | The request is well-formed. |
| k_ra8_err_invalid_arg | A rectangle bound is unordered or off-grid. |
Definition at line 235 of file ra8_tile_cache.c.
References k_ra8_err_invalid_arg, k_ra8_ok, RA8_INTERNAL, ra8_tile_prefetch_req_t::tile_cols, ra8_tile_prefetch_req_t::tile_rows, ra8_tile_rect_t::tx0, ra8_tile_rect_t::tx1, ra8_tile_rect_t::ty0, ra8_tile_rect_t::ty1, and ra8_tile_prefetch_req_t::view.
Referenced by ra8_tile_cache_prefetch_pan().
|
nodiscard |
Report the number of cells the cache can hold.
The cache capacity in tiles, used by a pan-prefetch caller to size its residency budget (spare = capacity - currently-visible tiles) so a prefetch cannot evict an on-screen tile.
| [in] | tc | Initialised cache. |
tc is NULL / uninitialised. | 0 | tc was NULL or was never ra8_tile_cache_init'd. |
| >0 | The configured cell count. |
Definition at line 177 of file ra8_tile_cache.c.
References ra8_keycache_cfg_t::cell_count, ra8_keycache_cfg_t::cell_mem, ra8_keycache_t::cfg, and ra8_tile_cache_t::kc.
Referenced by mg_reader_prefetch().
|
nodiscard |
Get (and pin) the decoded tile for key.
On a hit the cell is moved to the MRU and pinned. On a miss an unpinned LRU victim is evicted, the tile is decoded into the cell, inserted, and pinned. The returned pixels stay valid until ra8_tile_cache_put.
| [in] | tc | Initialised cache. |
| [in] | key | Tile to fetch. |
| [out] | out_tile | Receives the pinned tile view. |
| k_ra8_ok | Tile resident and pinned; *out_tile set. |
| k_ra8_err_null_ptr | tc, key, or out_tile was NULL. |
| k_ra8_err_no_mem | Every cell is pinned (cannot evict for the miss). |
| k_ra8_err_* | The decoder failed (returned verbatim). |
Definition at line 155 of file ra8_tile_cache.c.
References ra8_keycache_view_t::data, ra8_tile_dims_t::h, k_ra8_ok, ra8_tile_cache_t::kc, RA8_CHECK_NULL_PTR, ra8_keycache_get(), s_tag, ra8_keycache_view_t::user, and ra8_tile_dims_t::w.
Referenced by internal_draw_band(), internal_warm_band(), mem_tile_touch(), and mg_render_page().
|
nodiscard |
Initialise a tile cache over caller-supplied storage.
| [out] | tc | Cache state to populate (zero-initialised by the caller). |
| [in] | cfg | Storage + decoder configuration. |
| k_ra8_ok | Cache ready; all cells cold. |
| k_ra8_err_null_ptr | tc, cfg, or a required cfg pointer NULL. |
| k_ra8_err_invalid_size | cell_count, cell_bytes, or bucket_count 0. |
Definition at line 131 of file ra8_tile_cache.c.
References ra8_keycache_cfg_t::bucket_count, ra8_tile_cache_cfg_t::bucket_count, ra8_keycache_cfg_t::buckets, ra8_tile_cache_cfg_t::buckets, ra8_keycache_cfg_t::cell_bytes, ra8_tile_cache_cfg_t::cell_bytes, ra8_keycache_cfg_t::cell_count, ra8_tile_cache_cfg_t::cell_count, ra8_keycache_cfg_t::cell_mem, ra8_tile_cache_cfg_t::cell_mem, ra8_tile_cache_cfg_t::decode, ra8_tile_cache_t::decode, ra8_tile_cache_cfg_t::decode_ctx, ra8_tile_cache_t::decode_ctx, ra8_tile_cache_cfg_t::dims, internal_tile_decode(), ra8_tile_cache_t::kc, ra8_keycache_cfg_t::key_bytes, ra8_keycache_cfg_t::key_mem, ra8_tile_cache_cfg_t::keys, memset(), ra8_keycache_cfg_t::meta, ra8_tile_cache_cfg_t::meta, RA8_CHECK_NULL_PTR, ra8_keycache_init(), ra8_keycache_cfg_t::render, ra8_keycache_cfg_t::render_ctx, s_tag, ra8_keycache_cfg_t::user_bytes, and ra8_keycache_cfg_t::user_mem.
Referenced by ez_bind_page(), internal_wire(), ls_open_strip(), mem_run_tiles(), and mg_setup_cache().
|
nodiscard |
Warm one tile into the cache without holding a pin (read-ahead).
Decode-on-miss + immediate unpin, so on return the tile is resident but evictable. A thin typed facade over ra8_keycache_prefetch: warming changes only residency, never the pixels a later ra8_tile_cache_get returns, so rendered output is unchanged and goldens hold.
| [in,out] | tc | Initialised cache. |
| [in] | key | Tile to warm (fully initialised; zero-fill before setting). |
| k_ra8_ok | The tile is resident and unpinned (warmed or hit). |
| k_ra8_err_null_ptr | tc or key was NULL. |
| k_ra8_err_no_mem | Every cell is pinned (cannot evict to warm). |
| k_ra8_err_* | The decoder failed (returned verbatim). |
Definition at line 188 of file ra8_tile_cache.c.
References ra8_tile_cache_t::kc, RA8_CHECK_NULL_PTR, ra8_keycache_prefetch(), and s_tag.
Referenced by ra8_tile_cache_prefetch_pan().
|
nodiscard |
Predictively warm the tiles one step ahead of a panning viewport.
On a pan, warms the tile row or column immediately beyond req->view in req->dir, so the next tiles the viewport exposes are resident before they are needed – the image counterpart of ::ra8_book_src_prefetch_chapter's text read-ahead. The lead edge is clamped to the tile grid (req->tile_cols / req->tile_rows): a pan already at the image edge warms nothing. The number of tiles warmed is bounded by req->max_tiles (the caller's spare-capacity budget) and by the edge length, so the prefetch cannot exceed the cache budget or evict an on-screen tile. Best-effort: each tile is warmed with ra8_tile_cache_prefetch and a per-tile failure stops the sweep without failing the call, so a pan never errors because read-ahead could not complete.
| [in,out] | tc | Initialised cache. |
| [in] | req | The visible rectangle + direction + budget. |
| [out] | out_warmed | Tiles warmed by this call (may be NULL). |
| k_ra8_ok | The sweep ran (0 or more tiles warmed). |
| k_ra8_err_null_ptr | tc or req was NULL. |
| k_ra8_err_invalid_arg | req->view is not tx0<=tx1 / ty0<=ty1, or a bound lies outside the tile grid. |
Definition at line 329 of file ra8_tile_cache.c.
References priv_pan_line_t::count, ra8_tile_prefetch_req_t::image_id, internal_pan_line(), internal_validate_req(), k_ra8_ok, ra8_tile_prefetch_req_t::max_tiles, RA8_CHECK_NULL_PTR, ra8_tile_cache_prefetch(), s_tag, priv_pan_line_t::step_x, priv_pan_line_t::step_y, priv_pan_line_t::x, priv_pan_line_t::y, and ra8_tile_prefetch_req_t::zoom.
Referenced by mg_reader_prefetch().
|
nodiscard |
Release one pin on a tile previously returned by ra8_tile_cache_get.
| [in] | tc | Initialised cache. |
| [in] | pixels | The pixels pointer from a returned ra8_tile_t. |
| k_ra8_ok | Pin released. |
| k_ra8_err_null_ptr | tc or pixels was NULL. |
| k_ra8_err_invalid_arg | pixels is not a cell of this cache, or the cell was not pinned. |
Definition at line 170 of file ra8_tile_cache.c.
References ra8_tile_cache_t::kc, RA8_CHECK_NULL_PTR, ra8_keycache_put(), and s_tag.
Referenced by internal_draw_band(), internal_warm_band(), mem_tile_touch(), and mg_render_page().
|
nodiscard |
Report the cache hit / miss / eviction counters.
| [in] | tc | Initialised cache. |
| [out] | out_hits | Hits so far (may be NULL). |
| [out] | out_misses | Misses so far (may be NULL). |
| [out] | out_evictions | Evictions so far (may be NULL). |
| k_ra8_ok | Counters reported. |
| k_ra8_err_null_ptr | tc was NULL. |
| k_ra8_err_invalid_state | The cache was not initialised. |
Definition at line 364 of file ra8_tile_cache.c.
References ra8_keycache_cfg_t::cell_mem, ra8_keycache_t::cfg, k_ra8_err_invalid_state, ra8_tile_cache_t::kc, RA8_CHECK_NULL_PTR, ra8_keycache_stats(), and s_tag.
Referenced by ez_scene_selftest(), and mem_run_tiles().
|
nodiscard |
Convert a pixel rectangle into the inclusive tile rectangle covering it.
The producer ra8_tile_rect_t never had. Every consumer that needed "which tiles does this viewport touch?" open-coded the same four divisions in its own app, so the residency question was answered in a slightly different place from the prefetch that acts on it. Answering it once, here, is what lets a zoom viewer state its resident set and warm its lead edge from the same number.
The result is clamped to the tile grid, so a rectangle that runs past the image edge yields the last tile rather than an out-of-grid index the prefetch would then have to re-clamp. An empty rectangle (pw == 0 or ph == 0) is rejected rather than collapsed: a viewport showing no pixels is a caller defect, and silently returning tile (0,0) would understate residency.
| [in] | px | Rectangle left edge, source pixels. |
| [in] | py | Rectangle top edge, source pixels. |
| [in] | pw | Rectangle width, source pixels (> 0). |
| [in] | ph | Rectangle height, source pixels (> 0). |
| [in] | tile_w | Tile width, pixels (> 0). |
| [in] | tile_h | Tile height, pixels (> 0). |
| [in] | tile_cols | Tile columns in the image (> 0; the clamp bound). |
| [in] | tile_rows | Tile rows in the image (> 0; the clamp bound). |
| [out] | out | Receives the inclusive tile rectangle. |
| k_ra8_ok | out spans exactly the covering tiles. |
| k_ra8_err_null_ptr | out is NULL. |
| k_ra8_err_invalid_arg | An extent or a grid dimension is zero. |
out addresses writable storage for one ra8_tile_rect_t. out.Definition at line 103 of file ra8_tile_cache.c.
References internal_clamp_tile(), k_ra8_err_invalid_arg, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_error, s_tag, ra8_tile_rect_t::tx0, ra8_tile_rect_t::tx1, ra8_tile_rect_t::ty0, and ra8_tile_rect_t::ty1.
|
static |
Module log tag.
Definition at line 34 of file ra8_tile_cache.c.