#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
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)
#include "main/dispatch.h"
#include "vbo_context.h"
+#include "vbo_noop.h"
#if FEATURE_dlist
static struct vbo_save_vertex_store *
alloc_vertex_store(struct gl_context *ctx)
{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
struct vbo_save_vertex_store *vertex_store =
CALLOC_STRUCT(vbo_save_vertex_store);
vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx,
VBO_BUF_ID,
GL_ARRAY_BUFFER_ARB);
+ if (vertex_store->bufferobj) {
+ save->out_of_memory =
+ !ctx->Driver.BufferData(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat),
+ NULL, GL_STATIC_DRAW_ARB,
+ vertex_store->bufferobj);
+ }
+ else {
+ save->out_of_memory = GL_TRUE;
+ }
- ctx->Driver.BufferData(ctx,
- GL_ARRAY_BUFFER_ARB,
- VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat),
- NULL, GL_STATIC_DRAW_ARB, vertex_store->bufferobj);
+ if (save->out_of_memory) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "internal VBO allocation");
+ _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
+ }
vertex_store->buffer = NULL;
vertex_store->used = 0;
{
assert(vertex_store->bufferobj);
assert(!vertex_store->buffer);
- vertex_store->buffer =
- (GLfloat *) ctx->Driver.MapBufferRange(ctx, 0,
- vertex_store->bufferobj->Size,
- GL_MAP_WRITE_BIT, /* not used */
- vertex_store->bufferobj);
-
- assert(vertex_store->buffer);
- return vertex_store->buffer + vertex_store->used;
+ if (vertex_store->bufferobj->Size > 0) {
+ vertex_store->buffer =
+ (GLfloat *) ctx->Driver.MapBufferRange(ctx, 0,
+ vertex_store->bufferobj->Size,
+ GL_MAP_WRITE_BIT, /* not used */
+ vertex_store->bufferobj);
+ assert(vertex_store->buffer);
+ return vertex_store->buffer + vertex_store->used;
+ }
+ else {
+ /* probably ran out of memory for buffers */
+ return NULL;
+ }
}
unmap_vertex_store(struct gl_context *ctx,
struct vbo_save_vertex_store *vertex_store)
{
- ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj);
+ if (vertex_store->bufferobj->Size > 0) {
+ ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj);
+ }
vertex_store->buffer = NULL;
}
*/
save->vertex_store = alloc_vertex_store(ctx);
save->buffer_ptr = map_vertex_store(ctx, save->vertex_store);
+ save->out_of_memory = save->buffer_ptr == NULL;
}
if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
_save_copy_to_current(ctx);
_save_reset_vertex(ctx);
_save_reset_counters(ctx);
- _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
+ if (save->out_of_memory) {
+ _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
+ }
+ else {
+ _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
+ }
ctx->Driver.SaveNeedFlush = 0;
}
save->prim[i].count = 0;
save->prim[i].num_instances = 1;
- _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
+ if (save->out_of_memory) {
+ _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
+ }
+ else {
+ _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
+ }
ctx->Driver.SaveNeedFlush = 1;
return GL_TRUE;
}
* etc. received between here and the next begin will be compiled
* as opcodes.
*/
- _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
+ if (save->out_of_memory) {
+ _mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
+ }
+ else {
+ _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
+ }
}
_save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i;
if (!_mesa_validate_DrawArrays(ctx, mode, start, count))
return;
+ if (save->out_of_memory)
+ return;
+
_ae_map_vbos(ctx);
vbo_save_NotifyBegin(ctx, (mode | VBO_SAVE_PRIM_WEAK
const GLvoid * indices)
{
GET_CURRENT_CONTEXT(ctx);
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i;
if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices, 0))
return;
+ if (save->out_of_memory)
+ return;
+
_ae_map_vbos(ctx);
if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
const GLvoid * indices)
{
GET_CURRENT_CONTEXT(ctx);
- if (_mesa_validate_DrawRangeElements(ctx, mode,
- start, end, count, type, indices, 0)) {
- _save_OBE_DrawElements(mode, count, type, indices);
- }
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (!_mesa_validate_DrawRangeElements(ctx, mode,
+ start, end, count, type, indices, 0))
+ return;
+
+ if (save->out_of_memory)
+ return;
+
+ _save_OBE_DrawElements(mode, count, type, indices);
}
_save_vtxfmt_init(ctx);
_save_current_init(ctx);
+ _mesa_noop_vtxfmt_init(&save->vtxfmt_noop);
/* These will actually get set again when binding/drawing */
for (i = 0; i < VBO_ATTRIB_MAX; i++)