From 493c078b19edd8bf5ecccdbe7a156dc1478020eb Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Wed, 2 May 2018 09:31:24 +0100 Subject: [PATCH] Replace the texture linked list with a new NamedArray container type --- containers/named_array.h | 93 +++++++++++++++++++++++++++++++++++++++ gl-api.h | 1 - gl-texture.c | 94 ++++++++++------------------------------ 3 files changed, 117 insertions(+), 71 deletions(-) create mode 100644 containers/named_array.h diff --git a/containers/named_array.h b/containers/named_array.h new file mode 100644 index 0000000..88d0774 --- /dev/null +++ b/containers/named_array.h @@ -0,0 +1,93 @@ +#ifndef NAMED_ARRAY_H +#define NAMED_ARRAY_H + +#include +#include +#include + +typedef struct { + unsigned int element_size; + unsigned int max_element_count; + unsigned char* elements; + unsigned char* used_markers; + unsigned char marker_count; +} NamedArray; + + +inline void named_array_init(NamedArray* array, unsigned int element_size, unsigned int max_elements) { + array->element_size = element_size; + array->max_element_count = max_elements; + + float c = (float) max_elements / 8.0f; + array->marker_count = (unsigned char) ceil(c); + +#ifdef _arch_dreamcast + // Use 32-bit aligned memory on the Dreamcast + array->elements = (unsigned char*) memalign(0x20, element_size * max_elements); + array->used_markers = (unsigned char*) memalign(0x20, array->marker_count); +#else + array->elements = (unsigned char*) malloc(element_size * max_elements); + array->used_markers = (unsigned char*) malloc(array->marker_count); +#endif + memset(array->used_markers, 0, sizeof(array->marker_count)); +} + +inline char named_array_used(NamedArray* array, unsigned int id) { + id--; + + unsigned int i = id / 8; + unsigned int j = id % 8; + + unsigned char v = array->used_markers[i] & (unsigned char) (1 << j); + return !!(v); +} + +inline void* named_array_alloc(NamedArray* array, unsigned int* new_id) { + for(unsigned int i = 0; i < array->marker_count; ++i) { + for(unsigned int j = 0; j < 8; ++j) { + unsigned int id = (i * 8) + j + 1; + if(!named_array_used(array, id)) { + array->used_markers[i] |= (unsigned char) 1 << j; + *new_id = id; + unsigned char* ptr = &array->elements[(id - 1) * array->element_size]; + memset(ptr, 0, array->element_size); + return ptr; + } + } + } + + return NULL; +} + +inline void named_array_release(NamedArray* array, unsigned int new_id) { + new_id--; + + unsigned int i = new_id / 8; + unsigned int j = new_id % 8; + + array->used_markers[i] &= (unsigned char) ~(1 << j); +} + +inline void* named_array_get(NamedArray* array, unsigned int id) { + if(id == 0) { + return NULL; + } + + if(!named_array_used(array, id)) { + return NULL; + } + + return &array->elements[(id - 1) * array->element_size]; +} + +inline void named_array_cleanup(NamedArray* array) { + free(array->elements); + free(array->used_markers); + array->elements = NULL; + array->used_markers = NULL; + array->element_size = array->max_element_count = 0; + array->marker_count = 0; +} + + +#endif // NAMED_ARRAY_H diff --git a/gl-api.h b/gl-api.h index d1974b6..421c02b 100644 --- a/gl-api.h +++ b/gl-api.h @@ -35,7 +35,6 @@ typedef struct { GLubyte uv_clamp; GLuint index; GLvoid *data; - GLvoid *link; } GL_TEXTURE_OBJECT; /* KOS Open GL Texture Object */ typedef struct { diff --git a/gl-texture.c b/gl-texture.c index c9ca3bd..29ebe5b 100644 --- a/gl-texture.c +++ b/gl-texture.c @@ -5,16 +5,17 @@ Copyright (C) 2016 Joe Fenton Open GL Texture Submission implementation. - This implementation uses a dynamic linked list to store the texture objects. */ +#include +#include +#include + #include "gl.h" #include "glext.h" #include "gl-api.h" #include "gl-rgb.h" - -#include -#include +#include "containers/named_array.h" //========================================================================================// //== Internal KOS Open GL Texture Unit Structures / Global Variables ==// @@ -23,8 +24,9 @@ #define GL_KOS_CLAMP_U (1<<1) #define GL_KOS_CLAMP_V (1<<0) -static GL_TEXTURE_OBJECT *TEXTURE_OBJ = NULL; + static GL_TEXTURE_OBJECT *GL_KOS_TEXTURE_UNIT[GL_KOS_MAX_TEXTURE_UNITS] = { NULL, NULL }; +static NamedArray TEXTURE_OBJECTS; static GLubyte GL_KOS_ACTIVE_TEXTURE = GL_TEXTURE0_ARB & 0xF; @@ -33,47 +35,12 @@ static GLubyte GL_KOS_ACTIVE_TEXTURE = GL_TEXTURE0_ARB & 0xF; static GLuint _determinePVRFormat(GLint internalFormat, GLenum type); GLubyte _glKosInitTextures() { - TEXTURE_OBJ = malloc(sizeof(GL_TEXTURE_OBJECT)); - - if(TEXTURE_OBJ == NULL) - return 0; - - TEXTURE_OBJ->index = 0; - TEXTURE_OBJ->data = NULL; - TEXTURE_OBJ->link = NULL; - + named_array_init(&TEXTURE_OBJECTS, sizeof(GL_TEXTURE_OBJECT), 256); return 1; } -static GLsizei _glKosGetLastTextureIndex() { - GL_TEXTURE_OBJECT *ptr = TEXTURE_OBJ; - - while(ptr->link != NULL) - ptr = (GL_TEXTURE_OBJECT *)ptr->link; - - return ptr->index; -} - -static void _glKosInsertTextureObj(GL_TEXTURE_OBJECT *obj) { - GL_TEXTURE_OBJECT *ptr = TEXTURE_OBJ; - - while(ptr->link != NULL) - ptr = (GL_TEXTURE_OBJECT *)ptr->link; - - ptr->link = obj; -} - -static GL_TEXTURE_OBJECT *_glKosGetTextureObj(GLuint index) { - GL_TEXTURE_OBJECT *ptr = TEXTURE_OBJ; - - while(ptr->link != NULL && ptr->index != index) - ptr = (GL_TEXTURE_OBJECT *)ptr->link; - - return ptr; -} - static void _glKosBindTexture(GLuint index) { - GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = _glKosGetTextureObj(index); + GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index); } static void _glKosUnbindTexture() { @@ -81,17 +48,17 @@ static void _glKosUnbindTexture() { } GLuint _glKosTextureWidth(GLuint index) { - GL_TEXTURE_OBJECT *tex = _glKosGetTextureObj(index); + GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index); return tex->width; } GLuint _glKosTextureHeight(GLuint index) { - GL_TEXTURE_OBJECT *tex = _glKosGetTextureObj(index); + GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index); return tex->height; } GLvoid *_glKosTextureData(GLuint index) { - GL_TEXTURE_OBJECT *tex = _glKosGetTextureObj(index); + GL_TEXTURE_OBJECT *tex = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, index); return tex->data; } @@ -126,49 +93,36 @@ GLubyte _glKosMaxTextureUnits() { //== Public KOS Open GL API Texture Unit Functionality ==// void APIENTRY glGenTextures(GLsizei n, GLuint *textures) { - GLsizei index = _glKosGetLastTextureIndex(); - while(n--) { - GL_TEXTURE_OBJECT *txr = malloc(sizeof(GL_TEXTURE_OBJECT)); - txr->index = ++index; - txr->data = NULL; - txr->link = NULL; - + GLuint id = 0; + GL_TEXTURE_OBJECT* txr = (GL_TEXTURE_OBJECT*) named_array_alloc(&TEXTURE_OBJECTS, &id); + txr->index = id; txr->width = txr->height = 0; txr->mip_map = 0; txr->uv_clamp = 0; txr->env = PVR_TXRENV_MODULATEALPHA; txr->filter = PVR_FILTER_NONE; + txr->data = NULL; - _glKosInsertTextureObj(txr); + *textures = id; - *textures++ = txr->index; + textures++; } } void APIENTRY glDeleteTextures(GLsizei n, GLuint *textures) { while(n--) { - GL_TEXTURE_OBJECT *txr = TEXTURE_OBJ, *ltxr = NULL; + GL_TEXTURE_OBJECT* txr = (GL_TEXTURE_OBJECT*) named_array_get(&TEXTURE_OBJECTS, *textures); - while(txr->index != *textures && txr->link != NULL) { - ltxr = txr; - txr = txr->link; + if(txr == GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]) { + GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = NULL; } - ltxr->link = txr->link; - - if(txr->index == *textures) { - if(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]) - if(GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE]->index == txr->index) - GL_KOS_TEXTURE_UNIT[GL_KOS_ACTIVE_TEXTURE] = NULL; - - if(txr->data != NULL) - pvr_mem_free(txr->data); - - free(txr); + if(txr->data) { + pvr_mem_free(txr->data); } - ++textures; + named_array_release(&TEXTURE_OBJECTS, *textures++); } }