diff --git a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx index 394e3dd2ab..d920d05495 100644 --- a/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx +++ b/panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx @@ -1272,11 +1272,9 @@ release_texture(TextureContext *tc) { GLTexture *gltex = >c->_gltex; for (int i = 0; i < gltex->num_levels; ++i) { gl_free(gltex->levels[i].pixmap); + gltex->levels[i].pixmap = NULL; } - if (gltex->levels != NULL) { - gl_free(gltex->levels); - gltex->levels = NULL; - } + gltex->num_levels = 0; gtc->dequeue_lru(); @@ -1867,21 +1865,32 @@ setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) { for (int i = 0; i < gltex->num_levels; ++i) { gl_free(gltex->levels[i].pixmap); - } - if (gltex->levels != NULL) { - gl_free(gltex->levels); - gltex->levels = NULL; + gltex->levels[i].pixmap = NULL; } - gltex->levels = (ZTextureLevel *)gl_malloc(sizeof(ZTextureLevel) * MAX_MIPMAP_LEVELS); gltex->num_levels = num_levels; + + // We allocate one big buffer, large enough to include all the + // mipmap levels, and index into that buffer for each level. This + // cuts down on the number of individual alloc calls we have to make + // for each texture. + gltex->total_bytecount = (x_size * y_size * 4); + if (num_levels > 1) { + gltex->total_bytecount = (gltex->total_bytecount * 4 + 3) / 3; + } + + gltex->allocated_buffer = (void *)gl_malloc(gltex->total_bytecount); + char *next_buffer = (char *)gltex->allocated_buffer; + char *end_of_buffer = next_buffer + gltex->total_bytecount; int level = 0; ZTextureLevel *dest = NULL; while (level < num_levels) { dest = &gltex->levels[level]; int bytecount = x_size * y_size * 4; - dest->pixmap = (PIXEL *)gl_malloc(bytecount); + dest->pixmap = (PIXEL *)next_buffer; + next_buffer += bytecount; + nassertr(next_buffer <= end_of_buffer, false); dest->s_mask = (1 << (s_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS); dest->t_mask = (1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS); diff --git a/panda/src/tinydisplay/tinyTextureContext.I b/panda/src/tinydisplay/tinyTextureContext.I index 296ffcb414..ae01c4601e 100644 --- a/panda/src/tinydisplay/tinyTextureContext.I +++ b/panda/src/tinydisplay/tinyTextureContext.I @@ -22,6 +22,7 @@ INLINE TinyTextureContext:: TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) : TextureContext(pgo, tex), SimpleLruPage(0) { + _gltex.num_levels = 0; } //////////////////////////////////////////////////////////////////// @@ -31,7 +32,7 @@ TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) : //////////////////////////////////////////////////////////////////// INLINE TinyTextureContext:: ~TinyTextureContext() { - nassertv(_gltex.levels == NULL); + nassertv(_gltex.num_levels == 0); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/tinydisplay/tinyTextureContext.cxx b/panda/src/tinydisplay/tinyTextureContext.cxx index c2e74d4245..dcef76470d 100644 --- a/panda/src/tinydisplay/tinyTextureContext.cxx +++ b/panda/src/tinydisplay/tinyTextureContext.cxx @@ -38,10 +38,7 @@ evict_lru() { for (int i = 0; i < _gltex.num_levels; ++i) { gl_free(_gltex.levels[i].pixmap); - } - if (_gltex.levels != NULL) { - gl_free(_gltex.levels); - _gltex.levels = NULL; + _gltex.levels[i].pixmap = NULL; } _gltex.num_levels = 0; diff --git a/panda/src/tinydisplay/zgl.h b/panda/src/tinydisplay/zgl.h index db674b662a..2dcc629f4f 100644 --- a/panda/src/tinydisplay/zgl.h +++ b/panda/src/tinydisplay/zgl.h @@ -115,10 +115,13 @@ typedef struct GLVertex { /* The combination of all mipmap levels: one complete texture. */ typedef struct GLTexture { - ZTextureLevel *levels; + ZTextureLevel levels[MAX_MIPMAP_LEVELS]; int num_levels; int xsize, ysize; int s_max, t_max; + + void *allocated_buffer; + int total_bytecount; } GLTexture; struct GLContext;