bad char
[vg.git] / vg_tex.h
index 3f9cd9850eb8ae45191d0dd5ddb24250e58d2bb9..24a99a0c78c34b8eab5f0e03ecefa3d1818a8036 100644 (file)
--- a/vg_tex.h
+++ b/vg_tex.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2021-2023 Harry Godden (hgn) - All Rights Reserved 
+/* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved 
  *
  * A portion of this file is copied and altered from the QOI projects' source,
  * Originally written by Dominic Szablewski. It is slightly modified.
   SOFTWARE.
 */
 
-#ifndef VG_TEX_H
-#define VG_TEX_H
-
-#define VG_GAME
-#include "vg/vg.h"
-#include "vg/vg_log.h"
-
-#define STB_IMAGE_WRITE_IMPLEMENTATION
-#include "vg/submodules/stb/stb_image_write.h"
-
-/* its a sad day. */
-#if 0
-#define STBI_MALLOC(X) 
-#define STBI_REALLOC(X,Y)
-#define STBI_FREE(X)
-#endif
-
-#define STBI_ONLY_JPEG
-#define STBI_NO_THREAD_LOCALS
-#define STB_IMAGE_IMPLEMENTATION
-#include "vg/submodules/stb/stb_image.h"
+#pragma once
+#include "vg_log.h"
+#include "vg_image.h"
+#include "vg_engine.h"
 
 struct vg_sprite
 {
@@ -63,277 +46,12 @@ struct vg_sprite
 #define VG_TEX2D_CLAMP   0x8
 #define VG_TEX2D_NOMIP   0x10
 
-static u8 const_vg_tex2d_err[] ={
-   0xff,0x00,0xff,0xff, 0x00,0x00,0x00,0xff,
-   0xff,0x00,0xff,0xff, 0x00,0x00,0x00,0xff,
-   0x00,0x00,0x00,0xff, 0xff,0x00,0xff,0xff, 
-   0x00,0x00,0x00,0xff, 0xff,0x00,0xff,0xff, 
-   0xff,0x00,0xff,0xff, 0x00,0x00,0x00,0xff,
-   0xff,0x00,0xff,0xff, 0x00,0x00,0x00,0xff,
-   0x00,0x00,0x00,0xff, 0xff,0x00,0xff,0xff, 
-   0x00,0x00,0x00,0xff, 0xff,0x00,0xff,0xff, 
-};
-
-#define QOI_SRGB   0
-#define QOI_LINEAR 1
-
-typedef struct {
-       unsigned int width;
-       unsigned int height;
-       unsigned char channels;
-       unsigned char colorspace;
-} qoi_desc;
-
-#ifndef QOI_ZEROARR
-       #define QOI_ZEROARR(a) memset((a),0,sizeof(a))
-#endif
-
-#define QOI_OP_INDEX  0x00 /* 00xxxxxx */
-#define QOI_OP_DIFF   0x40 /* 01xxxxxx */
-#define QOI_OP_LUMA   0x80 /* 10xxxxxx */
-#define QOI_OP_RUN    0xc0 /* 11xxxxxx */
-#define QOI_OP_RGB    0xfe /* 11111110 */
-#define QOI_OP_RGBA   0xff /* 11111111 */
-
-#define QOI_MASK_2    0xc0 /* 11000000 */
-
-#define QOI_COLOR_HASH(C) (C.rgba.r*3 + C.rgba.g*5 + C.rgba.b*7 + C.rgba.a*11)
-#define QOI_MAGIC \
-       (((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \
-        ((unsigned int)'i') <<  8 | ((unsigned int)'f'))
-#define QOI_HEADER_SIZE 14
-
-/* 2GB is the max file size that this implementation can safely handle. We guard
-against anything larger than that, assuming the worst case with 5 bytes per
-pixel, rounded down to a nice clean value. 400 million pixels ought to be
-enough for anybody. */
-#define QOI_PIXELS_MAX ((unsigned int)400000000)
-
-typedef union {
-       struct { unsigned char r, g, b, a; } rgba;
-       unsigned int v;
-} qoi_rgba_t;
+/* options to create texutres; call only from loader thread. 
+ * *dest will be replaced synchronously by the main thread when ready. */
 
-static const unsigned char qoi_padding[8] = {0,0,0,0,0,0,0,1};
-static u32 qoi_read_32( const u8 *bytes, int *p ) {
-       u32 a = bytes[(*p)++];
-       u32 b = bytes[(*p)++];
-       u32 c = bytes[(*p)++];
-       u32 d = bytes[(*p)++];
-       return a << 24 | b << 16 | c << 8 | d;
-}
-
-struct texture_load_info{
-   GLuint *dest;
-   u32 width, height, flags;
-   u8 *rgba;
-};
-
-static void async_vg_tex2d_upload( void *payload, u32 size )
-{
-   if( vg_thread_purpose() != k_thread_purpose_main ){
-      vg_fatal_error( "Catastrophic programming error.\n" );
-   }
-
-   struct texture_load_info *info = payload;
-
-       glGenTextures( 1, info->dest );
-       glBindTexture( GL_TEXTURE_2D, *info->dest );
-   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, info->width, info->height,
-                  0, GL_RGBA, GL_UNSIGNED_BYTE, info->rgba );
-
-   if( !(info->flags & VG_TEX2D_NOMIP) ){
-      glGenerateMipmap( GL_TEXTURE_2D );
-   }
-
-   if( info->flags & VG_TEX2D_LINEAR ){
-      if( info->flags & VG_TEX2D_NOMIP ){
-         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-      }
-      else{
-         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
-               GL_LINEAR_MIPMAP_LINEAR );
-      }
-      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-   }
-
-   if( info->flags & VG_TEX2D_NEAREST ){
-      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
-      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
-   }
-
-   if( info->flags & VG_TEX2D_CLAMP ){
-      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
-   }
-
-   if( info->flags & VG_TEX2D_REPEAT ){
-      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
-      glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
-   }
-}
-
-static void vg_tex2d_replace_with_error( GLuint *dest )
-{
-   u32 hdr_size = vg_align8(sizeof(struct texture_load_info));
+void vg_tex2d_replace_with_error_async( GLuint *dest );
 
-   vg_async_item *call = vg_async_alloc( hdr_size );
-   struct texture_load_info *info = call->payload;
-   
-   info->dest = dest;
-   info->flags = VG_TEX2D_NEAREST|VG_TEX2D_REPEAT|VG_TEX2D_NOMIP;
-   info->width = 4;
-   info->height = 4;
-   info->rgba = const_vg_tex2d_err;
-
-   vg_async_dispatch( call, async_vg_tex2d_upload );
-}
-
-static 
 void vg_tex2d_load_qoi_async( const u8 *bytes, u32 size, 
-                              u32 flags, GLuint *dest )
-{
-       u32 header_magic;
-       qoi_rgba_t index[64];
-       qoi_rgba_t px;
-       int px_len, chunks_len, px_pos;
-       int p = 0, run = 0;
-
-   u32 channels = 4; /* TODO */
-
-   qoi_desc desc;
-
-       if (
-               bytes == NULL ||
-               (channels != 0 && channels != 3 && channels != 4) ||
-               size < QOI_HEADER_SIZE + (int)sizeof(qoi_padding)
-       ) {
-      vg_error( "Error while decoding qoi file: illegal parameters\n" );
-      vg_tex2d_replace_with_error( dest );
-               return;
-       }
-
-       header_magic = qoi_read_32(bytes, &p);
-       desc.width = qoi_read_32(bytes, &p);
-       desc.height = qoi_read_32(bytes, &p);
-       desc.channels = bytes[p++];
-       desc.colorspace = bytes[p++];
-
-       if (
-               desc.width == 0 || desc.height == 0 ||
-               desc.channels < 3 || desc.channels > 4 ||
-               desc.colorspace > 1 ||
-               header_magic != QOI_MAGIC ||
-               desc.height >= QOI_PIXELS_MAX / desc.width
-       ) {
-      vg_error( "Error while decoding qoi file: invalid file\n" );
-      vg_tex2d_replace_with_error( dest );
-               return;
-       }
-
-       if (channels == 0) {
-               channels = desc.channels;
-       }
-
-       px_len = desc.width * desc.height * channels;
-
-   /* allocate async call
-    * --------------------------
-    */
-   u32 hdr_size = vg_align8(sizeof(struct texture_load_info)),
-       tex_size = vg_align8(px_len);
-
-   vg_async_item *call = vg_async_alloc( hdr_size + tex_size );
-   struct texture_load_info *info = call->payload;
-   
-   info->dest = dest;
-   info->flags = flags;
-   info->width = desc.width;
-   info->height = desc.height;
-   info->rgba = ((u8*)call->payload) + hdr_size;
-
-   /*
-    * Decode 
-    * ----------------------------
-    */
-
-   u8 *pixels = info->rgba;
-
-       QOI_ZEROARR(index);
-       px.rgba.r = 0;
-       px.rgba.g = 0;
-       px.rgba.b = 0;
-       px.rgba.a = 255;
-
-       chunks_len = size - (int)sizeof(qoi_padding);
-       for (px_pos = 0; px_pos < px_len; px_pos += channels) {
-               if (run > 0) {
-                       run--;
-               }
-               else if (p < chunks_len) {
-                       int b1 = bytes[p++];
-
-                       if (b1 == QOI_OP_RGB) {
-                               px.rgba.r = bytes[p++];
-                               px.rgba.g = bytes[p++];
-                               px.rgba.b = bytes[p++];
-                       }
-                       else if (b1 == QOI_OP_RGBA) {
-                               px.rgba.r = bytes[p++];
-                               px.rgba.g = bytes[p++];
-                               px.rgba.b = bytes[p++];
-                               px.rgba.a = bytes[p++];
-                       }
-                       else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) {
-                               px = index[b1];
-                       }
-                       else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) {
-                               px.rgba.r += ((b1 >> 4) & 0x03) - 2;
-                               px.rgba.g += ((b1 >> 2) & 0x03) - 2;
-                               px.rgba.b += ( b1       & 0x03) - 2;
-                       }
-                       else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) {
-                               int b2 = bytes[p++];
-                               int vg = (b1 & 0x3f) - 32;
-                               px.rgba.r += vg - 8 + ((b2 >> 4) & 0x0f);
-                               px.rgba.g += vg;
-                               px.rgba.b += vg - 8 +  (b2       & 0x0f);
-                       }
-                       else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) {
-                               run = (b1 & 0x3f);
-                       }
-
-                       index[QOI_COLOR_HASH(px) % 64] = px;
-               }
-
-               pixels[px_pos + 0] = px.rgba.r;
-               pixels[px_pos + 1] = px.rgba.g;
-               pixels[px_pos + 2] = px.rgba.b;
-               
-               if (channels == 4) {
-                       pixels[px_pos + 3] = px.rgba.a;
-               }
-       }
-
-   /*
-    * Complete the call
-    * --------------------------
-    */
-
-   vg_async_dispatch( call, async_vg_tex2d_upload );
-}
-
-static 
-void vg_tex2d_load_qoi_async_file( const char *path, u32 flags, GLuint *dest )
-{
-   if( vg_thread_purpose() != k_thread_purpose_loader )
-      vg_fatal_error( "wrong thread\n" );
-
-   vg_linear_clear( vg_mem.scratch );
-
-   u32 size;
-   const void *data = vg_file_read( vg_mem.scratch, path, &size );
-   vg_tex2d_load_qoi_async( data, size, flags, dest );
-}
+                              u32 flags, GLuint *dest );
 
-#endif /* VG_TEX_H */
+void vg_tex2d_load_qoi_async_file( const char *path, u32 flags, GLuint *dest );