From 8df3e7b54c52273b8698f2352b53ce1f79fe4b87 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 9 Dec 2009 15:20:47 +0000 Subject: Sculpt Branch: * Fallback code in case VBO allocation fails. --- source/blender/gpu/intern/gpu_buffers.c | 338 ++++++++++++++++++++++---------- 1 file changed, 231 insertions(+), 107 deletions(-) (limited to 'source/blender/gpu') diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 4c55f759e47..ec9392c3694 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -386,8 +386,22 @@ typedef struct { } VertexBufferFormat; typedef struct { + /* opengl buffer handles */ GLuint vert_buf, index_buf; GLenum index_type; + + /* mesh pointers in case buffer allocation fails */ + MFace *mface; + MVert *mvert; + int *face_indices; + int totface; + + /* grid pointers */ + DMGridData **grids; + int *grid_indices; + int totgrid; + int gridsize; + unsigned int tot_tri, tot_quad; } GPU_Buffers; @@ -398,21 +412,34 @@ void GPU_update_mesh_buffers(void *buffers_v, MVert *mvert, VertexBufferFormat *vert_data; int i; - /* Build VBO */ - glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); - glBufferDataARB(GL_ARRAY_BUFFER_ARB, - sizeof(VertexBufferFormat) * totvert, - NULL, GL_STATIC_DRAW_ARB); - vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + if(buffers->vert_buf) { + /* Build VBO */ + glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, + sizeof(VertexBufferFormat) * totvert, + NULL, GL_STATIC_DRAW_ARB); + vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + + if(vert_data) { + for(i = 0; i < totvert; ++i) { + MVert *v = mvert + vert_indices[i]; + VertexBufferFormat *out = vert_data + i; + + copy_v3_v3(out->co, v->co); + memcpy(out->no, v->no, sizeof(short) * 3); + } - for(i = 0; i < totvert; ++i) { - MVert *v = mvert + vert_indices[i]; - VertexBufferFormat *out = vert_data + i; + glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); + } + else { + glDeleteBuffersARB(1, &buffers->vert_buf); + buffers->vert_buf = 0; + } - copy_v3_v3(out->co, v->co); - memcpy(out->no, v->no, sizeof(short) * 3); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); } - glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); + + buffers->mvert = mvert; } void *GPU_build_mesh_buffers(GHash *map, MVert *mvert, MFace *mface, @@ -431,47 +458,61 @@ void *GPU_build_mesh_buffers(GHash *map, MVert *mvert, MFace *mface, for(i = 0, tottri = 0; i < totface; ++i) tottri += mface[face_indices[i]].v4 ? 2 : 1; - /* Generate index buffer object */ - glGenBuffersARB(1, &buffers->index_buf); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, - sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB); - - /* Fill the triangle buffer */ - tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - for(i = 0; i < totface; ++i) { - MFace *f = mface + face_indices[i]; - int v[3] = {f->v1, f->v2, f->v3}; - - for(j = 0; j < (f->v4 ? 2 : 1); ++j) { - for(k = 0; k < 3; ++k) { - void *value, *key = SET_INT_IN_POINTER(v[k]); - int vbo_index; - - value = BLI_ghash_lookup(map, key); - vbo_index = GET_INT_FROM_POINTER(value); - - if(vbo_index < 0) { - vbo_index = -vbo_index + - tot_uniq_verts - 1; + if(buffers->index_buf) { + /* Generate index buffer object */ + glGenBuffersARB(1, &buffers->index_buf); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, + sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB); + + /* Fill the triangle buffer */ + tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + if(tri_data) { + for(i = 0; i < totface; ++i) { + MFace *f = mface + face_indices[i]; + int v[3] = {f->v1, f->v2, f->v3}; + + for(j = 0; j < (f->v4 ? 2 : 1); ++j) { + for(k = 0; k < 3; ++k) { + void *value, *key = SET_INT_IN_POINTER(v[k]); + int vbo_index; + + value = BLI_ghash_lookup(map, key); + vbo_index = GET_INT_FROM_POINTER(value); + + if(vbo_index < 0) { + vbo_index = -vbo_index + + tot_uniq_verts - 1; + } + + *tri_data = vbo_index; + ++tri_data; + } + v[0] = f->v4; + v[1] = f->v1; + v[2] = f->v3; } - - *tri_data = vbo_index; - ++tri_data; } - v[0] = f->v4; - v[1] = f->v1; - v[2] = f->v3; + glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); + } + else { + glDeleteBuffersARB(1, &buffers->index_buf); + buffers->index_buf = 0; } + + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } - glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); - /* Build VBO */ - glGenBuffersARB(1, &buffers->vert_buf); + if(buffers->vert_buf) + glGenBuffersARB(1, &buffers->vert_buf); GPU_update_mesh_buffers(buffers, mvert, vert_indices, totvert); buffers->tot_tri = tottri; + buffers->mface = mface; + buffers->face_indices = face_indices; + buffers->totface = totface; + return buffers; } @@ -485,18 +526,31 @@ void GPU_update_grid_buffers(void *buffers_v, DMGridData **grids, totvert= gridsize*gridsize*totgrid; /* Build VBO */ - glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); - glBufferDataARB(GL_ARRAY_BUFFER_ARB, - sizeof(DMGridData) * totvert, - NULL, GL_STATIC_DRAW_ARB); - vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - - for(i = 0; i < totgrid; ++i) { - DMGridData *grid= grids[grid_indices[i]]; - memcpy(vert_data, grid, sizeof(DMGridData)*gridsize*gridsize); - vert_data += gridsize*gridsize; + if(buffers->vert_buf) { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, + sizeof(DMGridData) * totvert, + NULL, GL_STATIC_DRAW_ARB); + vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + if(vert_data) { + for(i = 0; i < totgrid; ++i) { + DMGridData *grid= grids[grid_indices[i]]; + memcpy(vert_data, grid, sizeof(DMGridData)*gridsize*gridsize); + vert_data += gridsize*gridsize; + } + glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); + } + else { + glDeleteBuffersARB(1, &buffers->vert_buf); + buffers->vert_buf = 0; + } + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); } - glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); + + buffers->grids = grids; + buffers->grid_indices = grid_indices; + buffers->totgrid = totgrid; + buffers->gridsize = gridsize; //printf("node updated %p\n", buffers_v); } @@ -514,57 +568,75 @@ void *GPU_build_grid_buffers(DMGridData **grids, /* Generate index buffer object */ glGenBuffersARB(1, &buffers->index_buf); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); - - if(totquad < USHRT_MAX) { - unsigned short *quad_data; + if(buffers->index_buf) { + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); + + if(totquad < USHRT_MAX) { + unsigned short *quad_data; + + buffers->index_type = GL_UNSIGNED_SHORT; + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, + sizeof(unsigned short) * totquad * 4, NULL, GL_STATIC_DRAW_ARB); + + /* Fill the quad buffer */ + quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + if(quad_data) { + for(i = 0; i < totgrid; ++i) { + for(j = 0; j < gridsize-1; ++j) { + for(k = 0; k < gridsize-1; ++k) { + *(quad_data++)= offset + j*gridsize + k; + *(quad_data++)= offset + (j+1)*gridsize + k; + *(quad_data++)= offset + (j+1)*gridsize + k+1; + *(quad_data++)= offset + j*gridsize + k+1; + } + } - buffers->index_type = GL_UNSIGNED_SHORT; - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, - sizeof(unsigned short) * totquad * 4, NULL, GL_STATIC_DRAW_ARB); - - /* Fill the quad buffer */ - quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - for(i = 0; i < totgrid; ++i) { - for(j = 0; j < gridsize-1; ++j) { - for(k = 0; k < gridsize-1; ++k) { - *(quad_data++)= offset + j*gridsize + k; - *(quad_data++)= offset + (j+1)*gridsize + k; - *(quad_data++)= offset + (j+1)*gridsize + k+1; - *(quad_data++)= offset + j*gridsize + k+1; + offset += gridsize*gridsize; } + glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); + } + else { + glDeleteBuffersARB(1, &buffers->index_buf); + buffers->index_buf = 0; } - - offset += gridsize*gridsize; } - glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); - } - else { - unsigned int *quad_data; + else { + unsigned int *quad_data; + + buffers->index_type = GL_UNSIGNED_INT; + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, + sizeof(unsigned int) * totquad * 4, NULL, GL_STATIC_DRAW_ARB); + + /* Fill the quad buffer */ + quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + + if(quad_data) { + for(i = 0; i < totgrid; ++i) { + for(j = 0; j < gridsize-1; ++j) { + for(k = 0; k < gridsize-1; ++k) { + *(quad_data++)= offset + j*gridsize + k; + *(quad_data++)= offset + (j+1)*gridsize + k; + *(quad_data++)= offset + (j+1)*gridsize + k+1; + *(quad_data++)= offset + j*gridsize + k+1; + } + } - buffers->index_type = GL_UNSIGNED_INT; - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, - sizeof(unsigned int) * totquad * 4, NULL, GL_STATIC_DRAW_ARB); - - /* Fill the quad buffer */ - quad_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - for(i = 0; i < totgrid; ++i) { - for(j = 0; j < gridsize-1; ++j) { - for(k = 0; k < gridsize-1; ++k) { - *(quad_data++)= offset + j*gridsize + k; - *(quad_data++)= offset + (j+1)*gridsize + k; - *(quad_data++)= offset + (j+1)*gridsize + k+1; - *(quad_data++)= offset + j*gridsize + k+1; + offset += gridsize*gridsize; } + glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); + } + else { + glDeleteBuffersARB(1, &buffers->index_buf); + buffers->index_buf = 0; } - - offset += gridsize*gridsize; } - glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); + + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } /* Build VBO */ - glGenBuffersARB(1, &buffers->vert_buf); + if(buffers->index_buf) + glGenBuffersARB(1, &buffers->vert_buf); GPU_update_grid_buffers(buffers, grids, grid_indices, totgrid, gridsize); buffers->tot_quad = totquad; @@ -576,20 +648,70 @@ void GPU_draw_buffers(void *buffers_v) { GPU_Buffers *buffers = buffers_v; - glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); + if(buffers->vert_buf && buffers->index_buf) { + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); - if(buffers->tot_quad) { - glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), 0); - glNormalPointer(GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, no)); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); - glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0); + if(buffers->tot_quad) { + glVertexPointer(3, GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, co)); + glNormalPointer(GL_FLOAT, sizeof(DMGridData), (void*)offsetof(DMGridData, no)); + + glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0); + } + else { + glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, co)); + glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, no)); + + glDrawElements(GL_TRIANGLES, buffers->tot_tri * 3, buffers->index_type, 0); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + } + else if(buffers->totface) { + /* fallback if we are out of memory */ + int i; + + for(i = 0; i < buffers->totface; ++i) { + MFace *f = buffers->mface + buffers->face_indices[i]; + + glBegin((f->v4)? GL_QUADS: GL_TRIANGLES); + glNormal3sv(buffers->mvert[f->v1].no); + glVertex3fv(buffers->mvert[f->v1].co); + glNormal3sv(buffers->mvert[f->v2].no); + glVertex3fv(buffers->mvert[f->v2].co); + glNormal3sv(buffers->mvert[f->v3].no); + glVertex3fv(buffers->mvert[f->v3].co); + if(f->v4) { + glNormal3sv(buffers->mvert[f->v4].no); + glVertex3fv(buffers->mvert[f->v4].co); + } + glEnd(); + } } - else { - glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), 0); - glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), (void*)offsetof(VertexBufferFormat, no)); + else if(buffers->totgrid) { + int i, x, y, gridsize = buffers->gridsize; + + for(i = 0; i < buffers->totgrid; ++i) { + DMGridData *grid = buffers->grids[buffers->grid_indices[i]]; + + for(y = 0; y < gridsize-1; y++) { + glBegin(GL_QUAD_STRIP); + for(x = 0; x < gridsize; x++) { + DMGridData *a = &grid[y*gridsize + x]; + DMGridData *b = &grid[(y+1)*gridsize + x]; - glDrawElements(GL_TRIANGLES, buffers->tot_tri * 3, buffers->index_type, 0); + glNormal3fv(a->no); + glVertex3fv(a->co); + glNormal3fv(b->no); + glVertex3fv(b->co); + } + glEnd(); + } + } } } @@ -598,8 +720,10 @@ void GPU_free_buffers(void *buffers_v) if(buffers_v) { GPU_Buffers *buffers = buffers_v; - glDeleteBuffersARB(1, &buffers->vert_buf); - glDeleteBuffersARB(1, &buffers->index_buf); + if(buffers->vert_buf) + glDeleteBuffersARB(1, &buffers->vert_buf); + if(buffers->index_buf) + glDeleteBuffersARB(1, &buffers->index_buf); MEM_freeN(buffers); } -- cgit v1.2.3