Mon, 21 Apr 2025 17:27:33 +0200
use refcounted objects for textures instead of pass-by-value int structs
50 | 1 | /* |
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | |
3 | * Copyright 2024 Mike Becker. All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are met: | |
7 | * | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | |
14 | * | |
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
25 | * POSSIBILITY OF SUCH DAMAGE. | |
26 | */ | |
27 | ||
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
28 | #include "ascension/context.h" |
50 | 29 | #include "ascension/texture.h" |
30 | #include "ascension/error.h" | |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
31 | #include "ascension/filesystem.h" |
50 | 32 | |
33 | #include <assert.h> | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
34 | #include <cx/utils.h> |
50 | 35 | #include <GL/glew.h> |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
36 | #include <SDL2/SDL_image.h> |
50 | 37 | |
38 | void asc_texture_bind(AscTexture const *tex, int uniform_location, int unit) { | |
39 | glActiveTexture(GL_TEXTURE0 + unit); | |
40 | GLenum error = glGetError(); | |
41 | if (error == GL_INVALID_ENUM) { | |
42 | asc_error("Tried to use more texture units than available."); | |
43 | } | |
44 | glBindTexture(tex->target, tex->tex_id); | |
45 | glUniform1i(uniform_location, unit); | |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
46 | asc_error_catch_all_gl(); |
50 | 47 | } |
48 | ||
49 | void asc_texture_from_surface(AscTexture *tex, SDL_Surface const *surface) { | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
50 | if (tex->tex_id == 0) { |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
51 | asc_error("Tried to use uninitialized texture."); |
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
52 | asc_dprintf("Texture address: %"PRIxPTR, (uintptr_t) tex); |
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
53 | return; |
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
54 | } |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
55 | tex->width = surface->w; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
56 | tex->height = surface->h; |
50 | 57 | glBindTexture(tex->target,tex->tex_id); |
58 | glPixelStorei(GL_UNPACK_ROW_LENGTH, | |
59 | surface->pitch / surface->format->BytesPerPixel); | |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
60 | |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
61 | // Determine the format and internal format based on the SDL surface format |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
62 | GLint internal_format; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
63 | GLenum format; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
64 | switch (surface->format->format) { |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
65 | case SDL_PIXELFORMAT_RGB24: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
66 | internal_format = GL_RGB8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
67 | format = GL_RGB; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
68 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
69 | case SDL_PIXELFORMAT_BGR24: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
70 | internal_format = GL_RGB8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
71 | format = GL_BGR; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
72 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
73 | case SDL_PIXELFORMAT_RGBA32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
74 | case SDL_PIXELFORMAT_ABGR32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
75 | internal_format = GL_RGBA8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
76 | format = GL_RGBA; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
77 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
78 | case SDL_PIXELFORMAT_ARGB32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
79 | case SDL_PIXELFORMAT_BGRA32: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
80 | internal_format = GL_RGBA8; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
81 | format = GL_BGRA; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
82 | break; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
83 | default: |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
84 | // TODO: add more output once asc_error allows format strings |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
85 | asc_error("Unsupported pixel format."); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
86 | return; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
87 | } |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
88 | glTexImage2D(tex->target, 0, internal_format, |
50 | 89 | surface->w, surface->h, |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
90 | 0, format, |
50 | 91 | GL_UNSIGNED_BYTE, surface->pixels); |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
92 | // TODO: replace catch all with proper error handling for this single call |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
93 | asc_error_catch_all_gl(); |
50 | 94 | } |
95 | ||
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
96 | void asc_texture_from_file(AscTexture *tex, const char *name) { |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
97 | cxmutstr filepath = asc_filesystem_combine_paths(cx_strcast(asc_context.texture_path), cx_str(name)); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
98 | asc_dprintf("Load texture from %" CX_PRIstr, CX_SFMT(filepath)); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
99 | SDL_Surface *image = IMG_Load(filepath.ptr); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
100 | cx_strfree(&filepath); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
101 | if (image == NULL) { |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
102 | asc_error("Failed to load texture."); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
103 | asc_error(IMG_GetError()); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
104 | return; |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
105 | } |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
106 | asc_texture_from_surface(tex, image); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
107 | asc_dprintf("Free temporary surface %"PRIxPTR, (uintptr_t) image); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
108 | SDL_FreeSurface(image); |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
109 | } |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
110 | |
50 | 111 | void asc_texture_init( |
112 | AscTexture *tex, | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
113 | unsigned count, |
50 | 114 | enum asc_texture_target target, |
115 | enum asc_texture_min_filter min_filter, | |
116 | enum asc_texture_mag_filter mag_filter | |
117 | ) { | |
118 | static const GLenum texture_targets[] = { | |
88
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
119 | GL_TEXTURE_RECTANGLE, |
6234b7ea48f3
add support for 2d textures in sprite shader - fixes #386
Mike Becker <universe@uap-core.de>
parents:
86
diff
changeset
|
120 | GL_TEXTURE_2D, |
50 | 121 | }; |
122 | static const GLint texture_filters[] = { | |
123 | GL_NEAREST, | |
124 | GL_LINEAR, | |
125 | GL_NEAREST_MIPMAP_NEAREST, | |
126 | GL_LINEAR_MIPMAP_NEAREST, | |
127 | GL_NEAREST_MIPMAP_LINEAR, | |
128 | GL_LINEAR_MIPMAP_LINEAR | |
129 | }; | |
130 | assert(target < sizeof(texture_targets) / sizeof(GLenum)); | |
131 | assert(min_filter < sizeof(texture_filters) / sizeof(GLint)); | |
132 | assert(mag_filter < 2); // mag filter only supports nearest/linear | |
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
133 | |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
134 | GLuint textures[count]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
135 | glGenTextures(count, textures); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
136 | |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
137 | for (unsigned i = 0; i < count; ++i) { |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
138 | memset(&tex[i], 0, sizeof(AscTexture)); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
139 | tex[i].tex_id = textures[i]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
140 | tex[i].target = texture_targets[target]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
141 | glBindTexture(tex[i].target, tex[i].tex_id); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
142 | glTexParameteri(tex[i].target, GL_TEXTURE_MIN_FILTER, |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
143 | texture_filters[min_filter]); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
144 | glTexParameteri(tex[i].target, GL_TEXTURE_MAG_FILTER, |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
145 | texture_filters[mag_filter]); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
146 | asc_dprintf("Initialized texture: %u", tex[i].tex_id); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
147 | } |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
148 | |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
149 | // TODO: proper error handling for each gl call |
86
943bf9d7c6d6
make asset paths configurable
Mike Becker <universe@uap-core.de>
parents:
85
diff
changeset
|
150 | asc_error_catch_all_gl(); |
50 | 151 | } |
152 | ||
89
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
153 | void asc_texture_destroy(AscTexture *tex, unsigned count) { |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
154 | GLuint textures[count]; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
155 | for (unsigned i = 0; i < count; ++i) { |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
156 | if (tex[i].refcount > 0) { |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
157 | // TODO: asc_wprintf() for warnings |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
158 | asc_dprintf("Texture %u still in use by %u objects.", |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
159 | tex[i].tex_id, tex[i].refcount); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
160 | } |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
161 | asc_dprintf("Destroy texture: %u", tex[i].tex_id); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
162 | textures[i] = tex[i].tex_id; |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
163 | memset(&tex[i], 0, sizeof(AscTexture)); |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
164 | } |
e1f682a8a145
use refcounted objects for textures instead of pass-by-value int structs
Mike Becker <universe@uap-core.de>
parents:
88
diff
changeset
|
165 | glDeleteTextures(count, textures); |
50 | 166 | } |