Textures, which cannot be tested without a GPU

LoadTexture, UnloadTexture, the four DrawTexture variants and IsTextureValid.
Nothing about them pushes against the aggregate rule: every raylib signature
here takes its structs by value, and every one has an obvious pointer form the
shim dereferences, so the declarations are scalars and pointers as before.

The predicate is IsTextureValid and not IsTextureReady, which this version of
raylib does not export at all — 5.5 renamed it, and calling the old name would
be a link error rather than a silent miss. It is bound because the failure it
reports is otherwise invisible: LoadTexture on a missing file returns a texture
with an id of 0 and says so only on the trace log, and then every draw with it
is a no-op that looks like a drawing bug.

cstr's one caller used to be the window title, and its comment said so. A path
is the second caller and wants far more than 256 bytes, so each caller now
passes a buffer sized for what it holds. Truncating still beats reading past
the end: a truncated path simply fails to open, and texture-valid? is how the
program notices.

None of this is in the acceptance table, and deliberately. Loading a texture
needs a GL context, so anything headless would be asserting on the failure
path while appearing to test the working one. It is exercised by sand.flan.
This commit is contained in:
Joseph Ferano 2026-09-11 17:52:51 +07:00
parent 07d068d297
commit a178135143
2 changed files with 119 additions and 2 deletions

View File

@ -163,3 +163,76 @@
out (Rectangle {})]
(get-collision-rec-raw (addr x) (addr y) (addr out))
out))
;; ── Textures ────────────────────────────────────────────────────────
;;
;; Everything here needs a GL context, so a window has to be open first —
;; load-texture before init-window returns an id of 0 and raylib says so on
;; the log. texture-valid? is how that is noticed in the program rather than
;; only in the log; raylib 5.5 spells it IsTextureValid, and IsTextureReady,
;; which older code calls, does not exist in this version.
(declare load-texture-raw [path string out (Ptr Texture2D)] "flan_rl_load_texture")
(defn load-texture [path string] Texture2D
(let [t (Texture2D {})]
(load-texture-raw path (addr t))
t))
(declare texture-valid?-raw [texture (Ptr Texture2D)] bool "flan_rl_is_texture_valid")
(defn texture-valid? [texture Texture2D] bool
(let [t texture]
(texture-valid?-raw (addr t))))
(declare unload-texture-raw [texture (Ptr Texture2D)] "flan_rl_unload_texture")
(defn unload-texture [texture Texture2D]
(let [t texture]
(unload-texture-raw (addr t))))
(declare draw-texture-raw
[texture (Ptr Texture2D) x i32 y i32 tint (Ptr Color)]
"flan_rl_draw_texture")
(defn draw-texture [texture Texture2D x i32 y i32 tint Color]
(let [t texture
c tint]
(draw-texture-raw (addr t) x y (addr c))))
(declare draw-texture-v-raw
[texture (Ptr Texture2D) position (Ptr Vector2) tint (Ptr Color)]
"flan_rl_draw_texture_v")
(defn draw-texture-v [texture Texture2D position Vector2 tint Color]
(let [t texture
p position
c tint]
(draw-texture-v-raw (addr t) (addr p) (addr c))))
(declare draw-texture-ex-raw
[texture (Ptr Texture2D) position (Ptr Vector2) rotation f32 scale f32
tint (Ptr Color)]
"flan_rl_draw_texture_ex")
(defn draw-texture-ex [texture Texture2D position Vector2 rotation f32
scale f32 tint Color]
(let [t texture
p position
c tint]
(draw-texture-ex-raw (addr t) (addr p) rotation scale (addr c))))
;; A negative source width or height flips the sprite, which is how a sheet is
;; drawn facing the other way without a second image.
(declare draw-texture-rec-raw
[texture (Ptr Texture2D) source (Ptr Rectangle) position (Ptr Vector2)
tint (Ptr Color)]
"flan_rl_draw_texture_rec")
(defn draw-texture-rec [texture Texture2D source Rectangle position Vector2
tint Color]
(let [t texture
s source
p position
c tint]
(draw-texture-rec-raw (addr t) (addr s) (addr p) (addr c))))

48
vendor/raylib/shim.c vendored
View File

@ -15,6 +15,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
typedef struct { float x, y; } Vector2;
@ -44,10 +45,22 @@ extern void SetShapesTexture(Texture2D texture, Rectangle source);
extern Texture2D GetShapesTexture(void);
extern Rectangle GetShapesTextureRectangle(void);
extern Rectangle GetCollisionRec(Rectangle a, Rectangle b);
extern Texture2D LoadTexture(const char *fileName);
extern bool IsTextureValid(Texture2D texture);
extern void UnloadTexture(Texture2D texture);
extern void DrawTexture(Texture2D texture, int posX, int posY, Color tint);
extern void DrawTextureV(Texture2D texture, Vector2 position, Color tint);
extern void DrawTextureEx(Texture2D texture, Vector2 position, float rotation,
float scale, Color tint);
extern void DrawTextureRec(Texture2D texture, Rectangle source,
Vector2 position, Color tint);
/* A Flan string arrives as ptr+len and is not NUL-terminated, so a C API that
* wants a C string needs a copy. The window title is the only one, it is short
* by nature, and truncating is better than reading past the end. */
* wants a C string needs a copy. Two callers want one: the window title and a
* texture's file path. Each passes a buffer big enough for what it is 256
* for a title, PATH_MAX for a path and truncating is better than reading
* past the end. A truncated path fails to open and LoadTexture returns an id
* of 0, which is what texture-valid? is for. */
static const char *cstr(const char *p, long long n, char *buf, size_t cap) {
size_t k = (size_t)n < cap - 1 ? (size_t)n : cap - 1;
memcpy(buf, p, k);
@ -102,3 +115,34 @@ void flan_rl_get_collision_rec(const Rectangle *a, const Rectangle *b,
Rectangle *out) {
*out = GetCollisionRec(*a, *b);
}
void flan_rl_load_texture(const char *path, long long n, Texture2D *out) {
char buf[PATH_MAX];
*out = LoadTexture(cstr(path, n, buf, sizeof buf));
}
bool flan_rl_is_texture_valid(const Texture2D *texture) {
return IsTextureValid(*texture);
}
void flan_rl_unload_texture(const Texture2D *texture) { UnloadTexture(*texture); }
void flan_rl_draw_texture(const Texture2D *texture, int x, int y,
const Color *tint) {
DrawTexture(*texture, x, y, *tint);
}
void flan_rl_draw_texture_v(const Texture2D *texture, const Vector2 *position,
const Color *tint) {
DrawTextureV(*texture, *position, *tint);
}
void flan_rl_draw_texture_ex(const Texture2D *texture, const Vector2 *position,
float rotation, float scale, const Color *tint) {
DrawTextureEx(*texture, *position, rotation, scale, *tint);
}
void flan_rl_draw_texture_rec(const Texture2D *texture, const Rectangle *source,
const Vector2 *position, const Color *tint) {
DrawTextureRec(*texture, *source, *position, *tint);
}