diff options
author | Brian Paul <[email protected]> | 2011-11-10 09:47:37 -0700 |
---|---|---|
committer | Brian Paul <[email protected]> | 2011-11-11 07:10:56 -0700 |
commit | 97dedfda5fbb4078db28519e50adeeeb8e1a1dc1 (patch) | |
tree | 2620b2c03120e2e748d3798b1aa5f3ea6c909712 /src/mesa/vbo/vbo_exec_draw.c | |
parent | e6c4159372310110ec81273c5d15481c903fefed (diff) |
vbo: better handling of VBO allocation failures
Previously, if we failed to allocate a VBO (either for display list
compilation or immediate mode rendering) we'd eventually segfault
when trying to map the non-existant buffer or in a glVertex/Color/etc
call when we hit a null pointer.
Now we don't try to map non-existant buffers and if we do fail to
allocate a VBO we plug in no-op functions for glVertex/Color/etc
so we don't segfault.
Diffstat (limited to 'src/mesa/vbo/vbo_exec_draw.c')
-rw-r--r-- | src/mesa/vbo/vbo_exec_draw.c | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 8ffaaaa4876..efb6dd10a80 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -28,11 +28,14 @@ #include "main/glheader.h" #include "main/bufferobj.h" #include "main/compiler.h" +#include "main/context.h" #include "main/enums.h" #include "main/mfeatures.h" #include "main/state.h" +#include "main/vtxfmt.h" #include "vbo_context.h" +#include "vbo_noop.h" #if FEATURE_beginend @@ -308,32 +311,55 @@ vbo_exec_vtx_map( struct vbo_exec_context *exec ) if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024) { /* The VBO exists and there's room for more */ - exec->vtx.buffer_map = - (GLfloat *)ctx->Driver.MapBufferRange(ctx, - exec->vtx.buffer_used, - (VBO_VERT_BUFFER_SIZE - - exec->vtx.buffer_used), - accessRange, - exec->vtx.bufferobj); - exec->vtx.buffer_ptr = exec->vtx.buffer_map; + if (exec->vtx.bufferobj->Size > 0) { + exec->vtx.buffer_map = + (GLfloat *)ctx->Driver.MapBufferRange(ctx, + exec->vtx.buffer_used, + (VBO_VERT_BUFFER_SIZE - + exec->vtx.buffer_used), + accessRange, + exec->vtx.bufferobj); + exec->vtx.buffer_ptr = exec->vtx.buffer_map; + } + else { + exec->vtx.buffer_ptr = exec->vtx.buffer_map = NULL; + } } if (!exec->vtx.buffer_map) { /* Need to allocate a new VBO */ exec->vtx.buffer_used = 0; - ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER_ARB, - VBO_VERT_BUFFER_SIZE, - NULL, usage, exec->vtx.bufferobj); + if (ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER_ARB, + VBO_VERT_BUFFER_SIZE, + NULL, usage, exec->vtx.bufferobj)) { + /* buffer allocation worked, now map the buffer */ + exec->vtx.buffer_map = + (GLfloat *)ctx->Driver.MapBufferRange(ctx, + 0, VBO_VERT_BUFFER_SIZE, + accessRange, + exec->vtx.bufferobj); + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "VBO allocation"); + exec->vtx.buffer_map = NULL; + } + } + exec->vtx.buffer_ptr = exec->vtx.buffer_map; - exec->vtx.buffer_map = - (GLfloat *)ctx->Driver.MapBufferRange(ctx, - 0, VBO_VERT_BUFFER_SIZE, - accessRange, - exec->vtx.bufferobj); - assert(exec->vtx.buffer_map); - exec->vtx.buffer_ptr = exec->vtx.buffer_map; + if (!exec->vtx.buffer_map) { + /* out of memory */ + _mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt_noop ); + } + else { + if (_mesa_using_noop_vtxfmt(ctx->Exec)) { + /* The no-op functions are installed so switch back to regular + * functions. We do this test just to avoid frequent and needless + * calls to _mesa_install_exec_vtxfmt(). + */ + _mesa_install_exec_vtxfmt(ctx, &exec->vtxfmt); + } } if (0) |