input joy sleep wake, revisit string cat code
[vg.git] / vg_tex.h
1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
2 #ifndef VG_TEX_H
3 #define VG_TEX_H
4
5 #include "vg/vg.h"
6 #include "vg/vg_log.h"
7
8 #define VG_TEXTURE_NO_MIP 0x1
9 #define VG_TEXTURE_REPEAT 0x2
10 #define VG_TEXTURE_CLAMP 0x4
11 #define VG_TEXTURE_NEAREST 0x8
12 #define VG_TEXTURE_ALLOCATED_INTERNAL 0x10
13
14 VG_STATIC void *vg_qoi_malloc( size_t size )
15 {
16 return vg_linear_alloc( vg_mem.scratch, size );
17 }
18
19 VG_STATIC void vg_qoi_free( void *ptr )
20 {
21
22 }
23
24 #define QOI_IMPLEMENTATION
25 #define QOI_NO_STDIO
26 #define QOI_MALLOC(sz) vg_qoi_malloc( sz )
27 #define QOI_FREE(p) vg_qoi_free( p )
28
29 #include "submodules/qoi/qoi.h"
30
31 struct vg_tex2d
32 {
33 const char *path;
34 u32 flags;
35 GLuint name;
36 };
37
38 struct vg_sprite
39 {
40 v4f uv_xywh;
41 };
42
43 VG_STATIC void vg_tex2d_bind( vg_tex2d *tex, u32 id )
44 {
45 if( !(tex->flags & VG_TEXTURE_ALLOCATED_INTERNAL) )
46 {
47 vg_error( "Tried to use '%s' while unloaded!\n", tex->path );
48 return;
49 }
50
51 glActiveTexture( GL_TEXTURE0 + id );
52 glBindTexture( GL_TEXTURE_2D, tex->name );
53 }
54
55 static inline void vg_tex2d_mipmap(void)
56 {
57 glGenerateMipmap( GL_TEXTURE_2D );
58 }
59
60 static inline void vg_tex2d_linear(void)
61 {
62 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
63 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
64 }
65
66 static inline void vg_tex2d_nearest(void)
67 {
68 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
69 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
70 }
71
72 static inline void vg_tex2d_linear_mipmap(void)
73 {
74 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
75 GL_LINEAR_MIPMAP_LINEAR );
76 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
77 }
78
79 static inline void vg_tex2d_repeat(void)
80 {
81 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
82 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
83 }
84
85 static inline void vg_tex2d_clamp(void)
86 {
87 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
88 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
89 }
90
91 VG_STATIC GLuint vg_tex2d_new(void)
92 {
93 GLuint texture_name;
94 glGenTextures( 1, &texture_name );
95 glBindTexture( GL_TEXTURE_2D, texture_name );
96
97 return texture_name;
98 }
99
100 VG_STATIC void vg_tex2d_set_error(void)
101 {
102 u32 tex_err[4] =
103 {
104 0xffff00ff,
105 0xff000000,
106 0xff000000,
107 0xffff00ff
108 };
109
110 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2,
111 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_err );
112 }
113
114 VG_STATIC void vg_tex2d_qoi( void *mem, u32 size, const char *name )
115 {
116 qoi_desc info;
117 u8 *tex_buffer = qoi_decode( mem, size, &info, 4 );
118
119 if( tex_buffer )
120 {
121 vg_info( "Texture decoded: [%u %u] %s\n",
122 info.width, info.height, name );
123
124 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height,
125 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_buffer );
126
127 QOI_FREE(tex_buffer);
128 }
129 else
130 {
131 vg_error( "File size: %u\n", size );
132 vg_tex2d_set_error();
133 }
134 }
135
136 VG_STATIC GLuint vg_tex2d_rgba( const char *path )
137 {
138 GLuint texture_name = vg_tex2d_new();
139
140 vg_linear_clear( vg_mem.scratch );
141 u32 size;
142 void *file = vg_file_read( vg_mem.scratch, path, &size );
143
144 if( file )
145 {
146 vg_tex2d_qoi( file, size, path );
147 }
148 else
149 {
150 vg_error( "Loading texture failed (%s)\n", path );
151 vg_tex2d_set_error();
152 }
153
154 return texture_name;
155 }
156
157 VG_STATIC void vg_tex2d_init( vg_tex2d *textures[], int num )
158 {
159 for( int i=0; i<num; i ++ )
160 {
161 vg_tex2d *tex = textures[i];
162 tex->name = vg_tex2d_rgba( tex->path );
163 if( !(tex->flags & VG_TEXTURE_NO_MIP) )
164 vg_tex2d_mipmap();
165
166 if( tex->flags & VG_TEXTURE_NEAREST )
167 {
168 if( tex->flags & VG_TEXTURE_NO_MIP )
169 vg_error( "Invalid texture settings\n" );
170 else
171 vg_tex2d_nearest();
172 }
173 else
174 {
175 if( tex->flags & VG_TEXTURE_NO_MIP )
176 vg_tex2d_linear();
177 else
178 vg_tex2d_linear_mipmap();
179 }
180
181 if( tex->flags & VG_TEXTURE_CLAMP )
182 vg_tex2d_clamp();
183 else
184 vg_tex2d_repeat();
185
186 tex->flags |= VG_TEXTURE_ALLOCATED_INTERNAL;
187 }
188 }
189
190 VG_STATIC void vg_tex2d_free( vg_tex2d *textures[], int num )
191 {
192 for( int i = 0; i < num; i ++ )
193 {
194 glDeleteTextures( 1, &textures[i]->name );
195 }
196 }
197
198 #endif /* VG_TEX_H */