From 6eb079228eeeb18211e16c47204fd275a29f26af Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Wed, 6 Sep 2023 21:01:37 +0100 Subject: [PATCH] Fix infinite loop --- GL/alloc/alloc.c | 25 +++++++++++++++++++-- GL/texture.c | 51 +++++++++++++++++++++++++----------------- tests/test_allocator.h | 20 +++++++++++++++++ 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/GL/alloc/alloc.c b/GL/alloc/alloc.c index cb549e4..1a03cc3 100644 --- a/GL/alloc/alloc.c +++ b/GL/alloc/alloc.c @@ -47,11 +47,20 @@ */ #include +#include #define EIGHT_MEG (8 * 1024 * 1024) #define TWO_KILOBYTES (2 * 1024) #define BLOCK_COUNT (EIGHT_MEG / TWO_KILOBYTES) +#define ALLOC_DEBUG 0 +#if ALLOC_DEBUG +#define DBG_MSG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) +#else +#define DBG_MSG(fmt, ...) do {} while (0) +#endif + + static inline int round_up(int n, int multiple) { assert(multiple); @@ -230,6 +239,8 @@ static inline void block_and_offset_from_subblock(size_t sb, size_t* b, uint8_t* } void* alloc_malloc(void* pool, size_t size) { + DBG_MSG("Allocating: %d\n", size); + size_t start_subblock, required_subblocks; void* ret = alloc_next_available_ex(pool, size, &start_subblock, &required_subblocks); @@ -245,6 +256,8 @@ void* alloc_malloc(void* pool, size_t size) { uint8_t mask = 0; + DBG_MSG("Alloc: size: %d, rs: %d, sb: %d, b: %d, off: %d\n", size, required_subblocks, start_subblock, start_subblock / 8, start_subblock % 8); + /* Toggle any bits for the first block */ int c = (required_subblocks < 8) ? required_subblocks : 8; for(int i = 0; i < c; ++i) { @@ -308,6 +321,8 @@ void* alloc_malloc(void* pool, size_t size) { } } + DBG_MSG("Alloc done\n"); + return ret; } @@ -326,9 +341,12 @@ void alloc_free(void* pool, void* p) { uint8_t mask = 0; + DBG_MSG("Free: size: %d, us: %d, sb: %d, off: %d\n", it->size, used_subblocks, block, offset); + /* Wipe out any leading subblocks */ - for(int i = offset; i > 0; --i) { - mask |= (1 << i); + int c = (used_subblocks < 8) ? used_subblocks : 8; + for(int i = 0; i < c; ++i) { + mask |= (1 << (7 - (offset + i))); used_subblocks--; } @@ -359,6 +377,7 @@ void alloc_free(void* pool, void* p) { pool_header.allocations = it->next; } + DBG_MSG("Freed: size: %d, us: %d, sb: %d, off: %d\n", it->size, used_subblocks, block, offset); free(it); break; } @@ -366,6 +385,8 @@ void alloc_free(void* pool, void* p) { last = it; it = it->next; } + + DBG_MSG("Free done\n"); } void alloc_defrag_start(void* pool) { diff --git a/GL/texture.c b/GL/texture.c index e60200c..5fcf473 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -947,10 +947,7 @@ static GLint _cleanInternalFormat(GLint internalFormat) { case GL_COLOR_INDEX4_TWID_KOS: return internalFormat; case GL_COLOR_INDEX4_EXT: - // FIXME: We can't auto twiddle GL_COLOR_INDEX4 -> GL_COLOR_INDEX4_TWID_KOS - // so until we can, we need to not twiddle 4bpp paletted textures automatically - // return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX4_TWID_KOS : internalFormat; - return internalFormat; + return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX4_TWID_KOS : internalFormat; case GL_COLOR_INDEX8_EXT: return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX8_TWID_KOS : internalFormat; case GL_RGB_TWID_KOS: @@ -1250,9 +1247,8 @@ static int _determineConversion(GLint internalFormat, GLenum format, GLenum type {NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, true}, {NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, true}, - /* FIXME: Implement 4bpp -> 4bpp twiddling {NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, true, false}, - {NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_BYTE, true, false}, */ + {NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_BYTE, true, false}, {NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, false, false}, {NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_BYTE, false, false}, @@ -1457,6 +1453,10 @@ static bool _glTexImage2DValidate(GLenum target, GLint level, GLint internalForm return true; } +static inline GLboolean is4BPPFormat(GLenum format) { + return format == GL_COLOR_INDEX4_EXT || format == GL_COLOR_INDEX4_TWID_KOS; +} + void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data) { @@ -1605,14 +1605,32 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, } } else if(needs_conversion == 2) { // Twiddle - for(uint32_t i = 0; i < (width * height); ++i) { - uint32_t newLocation = twid_location(i, width, height); - dst = conversionBuffer + (destStride * newLocation); + if(is4BPPFormat(internalFormat) && is4BPPFormat(format)) { + // Special case twiddling. We have to unpack each src value + // and repack into the right place + for(uint32_t i = 0; i < (width * height); ++i) { + uint32_t newLocation = twid_location(i, width, height); - for(int j = 0; j < destStride; ++j) - *dst++ = *src++; + // This is the src/dest byte, but we need to figure + // out which half based on the odd/even of i + src = &((uint8_t*) data)[i / 2]; + dst = &conversionBuffer[newLocation / 2]; + if(i % 2 == 0) { + *dst = (*dst & 0xF) | (*src & 0xF0); + } else { + *dst = (*dst & 0xF0) | (*src & 0xF); + } + } + } else { + for(uint32_t i = 0; i < (width * height); ++i) { + uint32_t newLocation = twid_location(i, width, height); + dst = conversionBuffer + (destStride * newLocation); - src += sourceStride; + for(int j = 0; j < destStride; ++j) + *dst++ = *src++; + + src += sourceStride; + } } } else if(needs_conversion == 3) { // Convert + twiddle @@ -1623,14 +1641,11 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, src += sourceStride; } } else if(pack) { - fprintf(stderr, "Just packing\n"); FASTCPY(conversionBuffer, data, srcBytes); } if(pack) { assert(isPaletted); - - fprintf(stderr, "Packing data...\n"); size_t dst_byte = 0; for(size_t src_byte = 0; src_byte < srcBytes; ++src_byte) { uint8_t v = conversionBuffer[src_byte]; @@ -1645,11 +1660,8 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, dst_byte++; } } - - fprintf(stderr, "Packed\n"); } - fprintf(stderr, "Uploading data (%d)...\n", destBytes); FASTCPY(targetData, conversionBuffer, destBytes); free(conversionBuffer); } else { @@ -1659,15 +1671,12 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, gl_assert(destBytes); /* No conversion? Just copy the data, and the pvr_format is correct */ - fprintf(stderr, "Uploading data (%d)...\n", destBytes); FASTCPY(targetData, data, destBytes); gl_assert(active->index == originalId); } gl_assert(active->index == originalId); _glGPUStateMarkDirty(); - - fprintf(stderr, "Done\n"); } void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { diff --git a/tests/test_allocator.h b/tests/test_allocator.h index 1c5d7e9..f31e8aa 100644 --- a/tests/test_allocator.h +++ b/tests/test_allocator.h @@ -55,6 +55,26 @@ public: free(large_pool); } + void test_complex_case2() { + uint8_t* large_pool = (uint8_t*) malloc(8 * 1024 * 1024); + alloc_init(large_pool, 8 * 1024 * 1024); + + void* a1 = alloc_malloc(large_pool, 131072); + alloc_free(large_pool, a1); + + alloc_malloc(large_pool, 174768); + void* a2 = alloc_malloc(large_pool, 131072); + alloc_free(large_pool, a2); + + alloc_malloc(large_pool, 174768); + void* a3 = alloc_malloc(large_pool, 128); + + alloc_free(large_pool, a3); + + alloc_shutdown(large_pool); + free(large_pool); + } + void test_alloc_malloc() { alloc_init(pool, sizeof(pool));