st/osmesa: re-use buffers in OSMesaMakeCurrent()

Rather than creating a new buffer each time.  Fixes problems found
with vtk.

Tested-by: Kevin H. Hobbs <hobbsk@ohio.edu>
This commit is contained in:
Brian Paul 2013-04-09 08:47:00 -06:00
parent 4f1fd920c9
commit acd4fb8b5a
1 changed files with 54 additions and 7 deletions

View File

@ -80,6 +80,8 @@ struct osmesa_buffer
struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
void *map;
struct osmesa_buffer *next; /**< next in linked list */
};
@ -99,6 +101,16 @@ struct osmesa_context
};
/**
* Linked list of all osmesa_buffers.
* We can re-use an osmesa_buffer from one OSMesaMakeCurrent() call to
* the next unless the color/depth/stencil/accum formats change.
* We have to do this to be compatible with the original OSMesa implementation
* because some apps call OSMesaMakeCurrent() several times during rendering
* a frame.
*/
static struct osmesa_buffer *BufferList = NULL;
/**
* Called from the ST manager.
@ -400,6 +412,9 @@ osmesa_create_st_framebuffer(void)
}
/**
* Create new buffer and add to linked list.
*/
static struct osmesa_buffer *
osmesa_create_buffer(enum pipe_format color_format,
enum pipe_format ds_format,
@ -414,11 +429,38 @@ osmesa_create_buffer(enum pipe_format color_format,
osmesa_init_st_visual(&osbuffer->visual, color_format,
ds_format, accum_format);
/* insert into linked list */
osbuffer->next = BufferList;
BufferList = osbuffer;
}
return osbuffer;
}
/**
* Search linked list for a buffer with matching pixel formats.
*/
static struct osmesa_buffer *
osmesa_find_buffer(enum pipe_format color_format,
enum pipe_format ds_format,
enum pipe_format accum_format)
{
struct osmesa_buffer *b;
/* Check if we already have a suitable buffer for the given formats */
for (b = BufferList; b; b = b->next) {
if (b->visual.color_format == color_format &&
b->visual.depth_stencil_format == ds_format &&
b->visual.accum_format == accum_format) {
return b;
}
}
return NULL;
}
static void
osmesa_destroy_buffer(struct osmesa_buffer *osbuffer)
{
@ -581,18 +623,23 @@ OSMesaMakeCurrent(OSMesaContext osmesa, void *buffer, GLenum type,
return GL_FALSE;
}
osbuffer = osmesa_create_buffer(color_format,
osmesa->depth_stencil_format,
osmesa->accum_format);
/* See if we already have a buffer that uses these pixel formats */
osbuffer = osmesa_find_buffer(color_format,
osmesa->depth_stencil_format,
osmesa->accum_format);
if (!osbuffer) {
/* Existing buffer found, create new buffer */
osbuffer = osmesa_create_buffer(color_format,
osmesa->depth_stencil_format,
osmesa->accum_format);
}
osbuffer->width = width;
osbuffer->height = height;
osbuffer->map = buffer;
if (osmesa->current_buffer) {
/* free old buffer */
osmesa_destroy_buffer(osmesa->current_buffer);
}
/* XXX unused for now */
(void) osmesa_destroy_buffer;
osmesa->current_buffer = osbuffer;
osmesa->type = type;