commit 62f0f04
shrub
·
2026-07-30 21:20:38 +0000 UTC
parent 0970030
add renderer texture creation from memory
5 files changed,
+78,
-25
+9,
-0
1@@ -11,6 +11,12 @@ typedef u32 MGMesh;
2 typedef u32 MGTexture;
3 #define MGTEXTURE_INVALID ((MGTexture)0)
4
5+typedef struct {
6+ const u8* pixels;
7+ i32 width;
8+ i32 height;
9+} MGTextureDesc;
10+
11 typedef struct {
12 float x;
13 float y;
14@@ -54,6 +60,9 @@ void renderer_mesh_destroy(MGMesh id);
15 /* load texture from file */
16 MGTexture renderer_texture_load(const char* path);
17
18+/* create an RGBA8 texture from pixels */
19+MGTexture renderer_texture_create(const MGTextureDesc* desc);
20+
21 /* destroy texture */
22 void renderer_texture_destroy(MGTexture id);
23
+5,
-0
1@@ -41,6 +41,11 @@ MGTexture renderer_texture_load(const char* path)
2 return renderer_backend_texture_load(path);
3 }
4
5+MGTexture renderer_texture_create(const MGTextureDesc* desc)
6+{
7+ return renderer_backend_texture_create(desc);
8+}
9+
10 void renderer_texture_destroy(MGTexture texture)
11 {
12 renderer_backend_texture_destroy(texture);
+1,
-0
1@@ -13,6 +13,7 @@ void renderer_backend_mesh_draw(MGMesh mesh, MGTexture texture, const MGMat4* mv
2 void renderer_backend_mesh_destroy(MGMesh mesh);
3
4 MGTexture renderer_backend_texture_load(const char* path);
5+MGTexture renderer_backend_texture_create(const MGTextureDesc* desc);
6 void renderer_backend_texture_destroy(MGTexture texture);
7
8 #endif /* RENDERER_BACKEND_H */
+30,
-7
1@@ -450,14 +450,33 @@ void renderer_backend_mesh_destroy(MGMesh id)
2
3 MGTexture renderer_backend_texture_load(const char* path)
4 {
5- RendererTexture* texture;
6+ stbi_uc* pixels;
7 int width;
8 int height;
9 int channels;
10- u32 id;
11+ MGTextureDesc desc;
12+ MGTexture texture;
13
14 if (!path)
15 return MGTEXTURE_INVALID;
16+ pixels = stbi_load(path, &width, &height, &channels, 4);
17+ if (!pixels) {
18+ mg_log(LOG_ERR, "Failed to load texture: %s", path);
19+ return MGTEXTURE_INVALID;
20+ }
21+ desc.pixels = pixels;
22+ desc.width = width;
23+ desc.height = height;
24+ texture = renderer_backend_texture_create(&desc);
25+ stbi_image_free(pixels);
26+ return texture;
27+}
28+
29+MGTexture renderer_backend_texture_create(const MGTextureDesc* desc)
30+{
31+ RendererTexture* texture;
32+ size_t size;
33+ u32 id;
34
35 /* find free texture slot */
36 for (id = 1; id < MAX_TEXTURES; id++) {
37@@ -471,14 +490,18 @@ MGTexture renderer_backend_texture_load(const char* path)
38 }
39
40 texture = &ren.textures[id];
41- texture->pixels = stbi_load(path, &width, &height, &channels, 4);
42+ if (!desc || !desc->pixels || desc->width <= 0 || desc->height <= 0)
43+ return MGTEXTURE_INVALID;
44+ size = (size_t)desc->width * (size_t)desc->height * 4;
45+ texture->pixels = (u8*)malloc(size);
46 if (!texture->pixels) {
47- mg_log(LOG_ERR, "Failed to load texture: %s", path);
48+ mg_log(LOG_ERR, "Failed to create texture");
49 return MGTEXTURE_INVALID;
50 }
51
52- texture->width = width;
53- texture->height = height;
54+ memcpy(texture->pixels, desc->pixels, size);
55+ texture->width = desc->width;
56+ texture->height = desc->height;
57 texture->used = 1;
58
59 return id;
60@@ -495,6 +518,6 @@ void renderer_backend_texture_destroy(MGTexture id)
61 if (!texture->used)
62 return;
63
64- stbi_image_free(texture->pixels);
65+ free(texture->pixels);
66 *texture = (RendererTexture){ 0 };
67 }
+33,
-18
1@@ -356,19 +356,40 @@ void renderer_backend_mesh_destroy(MGMesh id)
2
3 MGTexture renderer_backend_texture_load(const char* path)
4 {
5- sg_image_desc image_desc = { 0 };
6- sg_view_desc view_desc = { 0 };
7- RendererTexture* texture;
8 stbi_uc* pixels;
9 int width;
10 int height;
11 int channels;
12- u32 id;
13+ MGTextureDesc desc;
14+ MGTexture texture;
15
16 if (!path)
17 return MGTEXTURE_INVALID;
18
19- /* find free texture slot */
20+ pixels = stbi_load(path, &width, &height, &channels, 4);
21+ if (!pixels) {
22+ mg_log(LOG_ERR, "Failed to load texture: %s", path);
23+ return MGTEXTURE_INVALID;
24+ }
25+
26+ desc.pixels = pixels;
27+ desc.width = width;
28+ desc.height = height;
29+ texture = renderer_backend_texture_create(&desc);
30+ stbi_image_free(pixels);
31+ return texture;
32+}
33+
34+MGTexture renderer_backend_texture_create(const MGTextureDesc* desc)
35+{
36+ sg_image_desc image_desc = { 0 };
37+ sg_view_desc view_desc = { 0 };
38+ RendererTexture* texture;
39+ u32 id;
40+
41+ if (!desc || !desc->pixels || desc->width <= 0 || desc->height <= 0)
42+ return MGTEXTURE_INVALID;
43+
44 for (id = 1; id < MAX_TEXTURES; id++) {
45 if (!ren.textures[id].used)
46 break;
47@@ -380,23 +401,17 @@ MGTexture renderer_backend_texture_load(const char* path)
48 }
49
50 texture = &ren.textures[id];
51- pixels = stbi_load(path, &width, &height, &channels, 4);
52- if (!pixels) {
53- mg_log(LOG_ERR, "Failed to load texture: %s", path);
54- return MGTEXTURE_INVALID;
55- }
56-
57- image_desc.width = width;
58- image_desc.height = height;
59+ image_desc.width = desc->width;
60+ image_desc.height = desc->height;
61 image_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
62- image_desc.data.mip_levels[0].ptr = pixels;
63- image_desc.data.mip_levels[0].size = width * height * 4;
64+ image_desc.data.mip_levels[0].ptr = desc->pixels;
65+ image_desc.data.mip_levels[0].size =
66+ (size_t)desc->width * (size_t)desc->height * 4;
67
68 texture->image = sg_make_image(&image_desc);
69- stbi_image_free(pixels);
70 if (sg_query_image_state(texture->image) != SG_RESOURCESTATE_VALID) {
71 *texture = (RendererTexture){ 0 };
72- mg_log(LOG_ERR, "Failed to create texture: %s", path);
73+ mg_log(LOG_ERR, "Failed to create texture");
74 return MGTEXTURE_INVALID;
75 }
76
77@@ -406,7 +421,7 @@ MGTexture renderer_backend_texture_load(const char* path)
78 if (sg_query_view_state(texture->view) != SG_RESOURCESTATE_VALID) {
79 sg_destroy_image(texture->image);
80 *texture = (RendererTexture){ 0 };
81- mg_log(LOG_ERR, "Failed to create texture view: %s", path);
82+ mg_log(LOG_ERR, "Failed to create texture view");
83 return MGTEXTURE_INVALID;
84 }
85