--- /dev/null
+/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
+#ifndef VG_TEX_H
+#define VG_TEX_H
+
+#include "vg/vg.h"
+#include "vg/vg_log.h"
+
+#define VG_TEXTURE_NO_MIP 0x1
+#define VG_TEXTURE_REPEAT 0x2
+#define VG_TEXTURE_CLAMP 0x4
+#define VG_TEXTURE_NEAREST 0x8
+#define VG_TEXTURE_ALLOCATED_INTERNAL 0x10
+
+VG_STATIC void *vg_qoi_malloc( size_t size )
+{
+ return vg_linear_alloc( vg_mem.scratch, size );
+}
+
+VG_STATIC void vg_qoi_free( void *ptr )
+{
+
+}
+
+#define QOI_IMPLEMENTATION
+#define QOI_NO_STDIO
+#define QOI_MALLOC(sz) vg_qoi_malloc( sz )
+#define QOI_FREE(p) vg_qoi_free( p )
+
+#include "submodules/qoi/qoi.h"
+
+struct vg_tex2d
+{
+ const char *path;
+ u32 flags;
+ GLuint name;
+};
+
+struct vg_sprite
+{
+ v4f uv_xywh;
+};
+
+VG_STATIC void vg_tex2d_bind( vg_tex2d *tex, u32 id )
+{
+ if( !(tex->flags & VG_TEXTURE_ALLOCATED_INTERNAL) )
+ {
+ vg_error( "Tried to use '%s' while unloaded!\n", tex->path );
+ return;
+ }
+
+ glActiveTexture( GL_TEXTURE0 + id );
+ glBindTexture( GL_TEXTURE_2D, tex->name );
+}
+
+static inline void vg_tex2d_mipmap(void)
+{
+ glGenerateMipmap( GL_TEXTURE_2D );
+}
+
+static inline void vg_tex2d_linear(void)
+{
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+}
+
+static inline void vg_tex2d_nearest(void)
+{
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+}
+
+static inline void vg_tex2d_linear_mipmap(void)
+{
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+}
+
+static inline void vg_tex2d_repeat(void)
+{
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+}
+
+static inline void vg_tex2d_clamp(void)
+{
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+}
+
+VG_STATIC GLuint vg_tex2d_new(void)
+{
+ GLuint texture_name;
+ glGenTextures( 1, &texture_name );
+ glBindTexture( GL_TEXTURE_2D, texture_name );
+
+ return texture_name;
+}
+
+VG_STATIC void vg_tex2d_set_error(void)
+{
+ u32 tex_err[4] =
+ {
+ 0xffff00ff,
+ 0xff000000,
+ 0xff000000,
+ 0xffff00ff
+ };
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_err );
+}
+
+VG_STATIC void vg_tex2d_qoi( void *mem, u32 size, const char *name )
+{
+ qoi_desc info;
+ u8 *tex_buffer = qoi_decode( mem, size, &info, 4 );
+
+ if( tex_buffer )
+ {
+ vg_info( "Texture decoded: [%u %u] %s\n",
+ info.width, info.height, name );
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, info.width, info.height,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_buffer );
+
+ QOI_FREE(tex_buffer);
+ }
+ else
+ {
+ vg_error( "File size: %u\n", size );
+ vg_tex2d_set_error();
+ }
+}
+
+VG_STATIC GLuint vg_tex2d_rgba( const char *path )
+{
+ GLuint texture_name = vg_tex2d_new();
+
+ vg_linear_clear( vg_mem.scratch );
+ u32 size;
+ void *file = vg_file_read( vg_mem.scratch, path, &size );
+
+ if( file )
+ {
+ vg_tex2d_qoi( file, size, path );
+ }
+ else
+ {
+ vg_error( "Loading texture failed (%s)\n", path );
+ vg_tex2d_set_error();
+ }
+
+ return texture_name;
+}
+
+VG_STATIC void vg_tex2d_init( vg_tex2d *textures[], int num )
+{
+ for( int i=0; i<num; i ++ )
+ {
+ vg_tex2d *tex = textures[i];
+ tex->name = vg_tex2d_rgba( tex->path );
+ if( !(tex->flags & VG_TEXTURE_NO_MIP) )
+ vg_tex2d_mipmap();
+
+ if( tex->flags & VG_TEXTURE_NEAREST )
+ {
+ if( tex->flags & VG_TEXTURE_NO_MIP )
+ vg_error( "Invalid texture settings\n" );
+ else
+ vg_tex2d_nearest();
+ }
+ else
+ {
+ if( tex->flags & VG_TEXTURE_NO_MIP )
+ vg_tex2d_linear();
+ else
+ vg_tex2d_linear_mipmap();
+ }
+
+ if( tex->flags & VG_TEXTURE_CLAMP )
+ vg_tex2d_clamp();
+ else
+ vg_tex2d_repeat();
+
+ tex->flags |= VG_TEXTURE_ALLOCATED_INTERNAL;
+ }
+}
+
+VG_STATIC void vg_tex2d_free( vg_tex2d *textures[], int num )
+{
+ for( int i = 0; i < num; i ++ )
+ {
+ glDeleteTextures( 1, &textures[i]->name );
+ }
+}
+
+#endif /* VG_TEX_H */