Fix infinite loop

This commit is contained in:
Luke Benstead 2023-09-06 21:01:37 +01:00
parent 7ce01ad93f
commit 6eb079228e
3 changed files with 73 additions and 23 deletions

View File

@ -47,11 +47,20 @@
*/ */
#include <assert.h> #include <assert.h>
#include <stdio.h>
#define EIGHT_MEG (8 * 1024 * 1024) #define EIGHT_MEG (8 * 1024 * 1024)
#define TWO_KILOBYTES (2 * 1024) #define TWO_KILOBYTES (2 * 1024)
#define BLOCK_COUNT (EIGHT_MEG / TWO_KILOBYTES) #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) static inline int round_up(int n, int multiple)
{ {
assert(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) { void* alloc_malloc(void* pool, size_t size) {
DBG_MSG("Allocating: %d\n", size);
size_t start_subblock, required_subblocks; size_t start_subblock, required_subblocks;
void* ret = alloc_next_available_ex(pool, size, &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; 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 */ /* Toggle any bits for the first block */
int c = (required_subblocks < 8) ? required_subblocks : 8; int c = (required_subblocks < 8) ? required_subblocks : 8;
for(int i = 0; i < c; ++i) { 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; return ret;
} }
@ -326,9 +341,12 @@ void alloc_free(void* pool, void* p) {
uint8_t mask = 0; 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 */ /* Wipe out any leading subblocks */
for(int i = offset; i > 0; --i) { int c = (used_subblocks < 8) ? used_subblocks : 8;
mask |= (1 << i); for(int i = 0; i < c; ++i) {
mask |= (1 << (7 - (offset + i)));
used_subblocks--; used_subblocks--;
} }
@ -359,6 +377,7 @@ void alloc_free(void* pool, void* p) {
pool_header.allocations = it->next; 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); free(it);
break; break;
} }
@ -366,6 +385,8 @@ void alloc_free(void* pool, void* p) {
last = it; last = it;
it = it->next; it = it->next;
} }
DBG_MSG("Free done\n");
} }
void alloc_defrag_start(void* pool) { void alloc_defrag_start(void* pool) {

View File

@ -947,10 +947,7 @@ static GLint _cleanInternalFormat(GLint internalFormat) {
case GL_COLOR_INDEX4_TWID_KOS: case GL_COLOR_INDEX4_TWID_KOS:
return internalFormat; return internalFormat;
case GL_COLOR_INDEX4_EXT: case GL_COLOR_INDEX4_EXT:
// FIXME: We can't auto twiddle GL_COLOR_INDEX4 -> GL_COLOR_INDEX4_TWID_KOS return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX4_TWID_KOS : internalFormat;
// 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;
case GL_COLOR_INDEX8_EXT: case GL_COLOR_INDEX8_EXT:
return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX8_TWID_KOS : internalFormat; return (TEXTURE_TWIDDLE_ENABLED) ? GL_COLOR_INDEX8_TWID_KOS : internalFormat;
case GL_RGB_TWID_KOS: 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_UNSIGNED_BYTE, true, true},
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_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_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_UNSIGNED_BYTE, false, false},
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_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; 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, void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
GLsizei width, GLsizei height, GLint border, GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *data) { GLenum format, GLenum type, const GLvoid *data) {
@ -1605,6 +1605,23 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
} }
} else if(needs_conversion == 2) { } else if(needs_conversion == 2) {
// Twiddle // Twiddle
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);
// 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) { for(uint32_t i = 0; i < (width * height); ++i) {
uint32_t newLocation = twid_location(i, width, height); uint32_t newLocation = twid_location(i, width, height);
dst = conversionBuffer + (destStride * newLocation); dst = conversionBuffer + (destStride * newLocation);
@ -1614,6 +1631,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
src += sourceStride; src += sourceStride;
} }
}
} else if(needs_conversion == 3) { } else if(needs_conversion == 3) {
// Convert + twiddle // Convert + twiddle
for(uint32_t i = 0; i < (width * height); ++i) { for(uint32_t i = 0; i < (width * height); ++i) {
@ -1623,14 +1641,11 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
src += sourceStride; src += sourceStride;
} }
} else if(pack) { } else if(pack) {
fprintf(stderr, "Just packing\n");
FASTCPY(conversionBuffer, data, srcBytes); FASTCPY(conversionBuffer, data, srcBytes);
} }
if(pack) { if(pack) {
assert(isPaletted); assert(isPaletted);
fprintf(stderr, "Packing data...\n");
size_t dst_byte = 0; size_t dst_byte = 0;
for(size_t src_byte = 0; src_byte < srcBytes; ++src_byte) { for(size_t src_byte = 0; src_byte < srcBytes; ++src_byte) {
uint8_t v = conversionBuffer[src_byte]; uint8_t v = conversionBuffer[src_byte];
@ -1645,11 +1660,8 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
dst_byte++; dst_byte++;
} }
} }
fprintf(stderr, "Packed\n");
} }
fprintf(stderr, "Uploading data (%d)...\n", destBytes);
FASTCPY(targetData, conversionBuffer, destBytes); FASTCPY(targetData, conversionBuffer, destBytes);
free(conversionBuffer); free(conversionBuffer);
} else { } else {
@ -1659,15 +1671,12 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
gl_assert(destBytes); gl_assert(destBytes);
/* No conversion? Just copy the data, and the pvr_format is correct */ /* No conversion? Just copy the data, and the pvr_format is correct */
fprintf(stderr, "Uploading data (%d)...\n", destBytes);
FASTCPY(targetData, data, destBytes); FASTCPY(targetData, data, destBytes);
gl_assert(active->index == originalId); gl_assert(active->index == originalId);
} }
gl_assert(active->index == originalId); gl_assert(active->index == originalId);
_glGPUStateMarkDirty(); _glGPUStateMarkDirty();
fprintf(stderr, "Done\n");
} }
void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {

View File

@ -55,6 +55,26 @@ public:
free(large_pool); 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() { void test_alloc_malloc() {
alloc_init(pool, sizeof(pool)); alloc_init(pool, sizeof(pool));