summaryrefslogtreecommitdiffstats
path: root/src/mesa/vbo/vbo_exec_draw.c
diff options
context:
space:
mode:
authorBrian Paul <brianp@vmware.com>2011-11-10 09:47:37 -0700
committerBrian Paul <brianp@vmware.com>2011-11-11 07:10:56 -0700
commit97dedfda5fbb4078db28519e50adeeeb8e1a1dc1 (patch)
tree2620b2c03120e2e748d3798b1aa5f3ea6c909712 /src/mesa/vbo/vbo_exec_draw.c
parente6c4159372310110ec81273c5d15481c903fefed (diff)
downloadexternal_mesa3d-97dedfda5fbb4078db28519e50adeeeb8e1a1dc1.zip
external_mesa3d-97dedfda5fbb4078db28519e50adeeeb8e1a1dc1.tar.gz
external_mesa3d-97dedfda5fbb4078db28519e50adeeeb8e1a1dc1.tar.bz2
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.c62
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 8ffaaaa..efb6dd1 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)