diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 533 |
1 files changed, 188 insertions, 345 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index b4617b9790e..072ff5235bf 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -28,8 +28,7 @@ /** \file blender/gpu/intern/gpu_buffers.c * \ingroup gpu * - * Mesh drawing using OpenGL VBO (Vertex Buffer Objects), - * with fall-back to vertex arrays. + * Mesh drawing using OpenGL VBO (Vertex Buffer Objects) */ #include <limits.h> @@ -58,6 +57,7 @@ #include "GPU_buffers.h" #include "GPU_draw.h" +#include "GPU_basic_shader.h" #include "bmesh.h" @@ -80,28 +80,27 @@ static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type); const GPUBufferTypeSettings gpu_buffer_type_settings[] = { /* vertex */ - {GL_ARRAY_BUFFER_ARB, 3}, + {GL_ARRAY_BUFFER, 3}, /* normal */ - {GL_ARRAY_BUFFER_ARB, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */ + {GL_ARRAY_BUFFER, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */ /* mcol */ - {GL_ARRAY_BUFFER_ARB, 3}, + {GL_ARRAY_BUFFER, 3}, /* uv */ - {GL_ARRAY_BUFFER_ARB, 2}, + {GL_ARRAY_BUFFER, 2}, /* uv for texpaint */ - {GL_ARRAY_BUFFER_ARB, 4}, + {GL_ARRAY_BUFFER, 4}, /* edge */ - {GL_ELEMENT_ARRAY_BUFFER_ARB, 2}, + {GL_ELEMENT_ARRAY_BUFFER, 2}, /* uv edge */ - {GL_ELEMENT_ARRAY_BUFFER_ARB, 4}, + {GL_ELEMENT_ARRAY_BUFFER, 4}, /* triangles, 1 point since we are allocating from tottriangle points, which account for all points */ - {GL_ELEMENT_ARRAY_BUFFER_ARB, 1}, + {GL_ELEMENT_ARRAY_BUFFER, 1}, }; #define MAX_GPU_ATTRIB_DATA 32 #define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n)) -/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */ static GPUBufferState GLStates = 0; static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } }; @@ -209,10 +208,7 @@ static void gpu_buffer_pool_delete_last(GPUBufferPool *pool) return; /* delete the buffer's data */ - if (last->use_vbo) - glDeleteBuffersARB(1, &last->id); - else - MEM_freeN(last->pointer); + glDeleteBuffers(1, &last->id); /* delete the buffer and remove from pool */ MEM_freeN(last); @@ -273,7 +269,7 @@ void GPU_global_buffer_pool_free_unused(void) * * Thread-unsafe version for internal usage only. */ -static GPUBuffer *gpu_buffer_alloc_intern(size_t size, bool use_VBO) +static GPUBuffer *gpu_buffer_alloc_intern(size_t size) { GPUBufferPool *pool; GPUBuffer *buf; @@ -298,11 +294,6 @@ static GPUBuffer *gpu_buffer_alloc_intern(size_t size, bool use_VBO) * twice as big */ for (i = 0; i < pool->totbuf; i++) { bufsize = pool->buffers[i]->size; - - /* only return a buffer that matches the VBO preference */ - if (pool->buffers[i]->use_vbo != use_VBO) { - continue; - } /* check for an exact size match */ if (bufsize == size) { @@ -332,44 +323,19 @@ static GPUBuffer *gpu_buffer_alloc_intern(size_t size, bool use_VBO) /* no acceptable buffer found in the pool, create a new one */ buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer"); buf->size = size; - buf->use_vbo = use_VBO; - - if (use_VBO) { - /* create a new VBO and initialize it to the requested - * size */ - glGenBuffersARB(1, &buf->id); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, buf->id); - glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - } - else { - static int time = 0; - buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer"); - - time++; - /* purpose of this seems to be dealing with - * out-of-memory errors? looks a bit iffy to me - * though, at least on Linux I expect malloc() would - * just overcommit. --nicholas */ - while (!buf->pointer && pool->totbuf > 0) { - gpu_buffer_pool_delete_last(pool); - buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer"); - } - if (!buf->pointer) { - MEM_freeN(buf); - return NULL; - } - } + glGenBuffers(1, &buf->id); + glBindBuffer(GL_ARRAY_BUFFER, buf->id); + glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); return buf; } /* Same as above, but safe for threading. */ -GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays) +GPUBuffer *GPU_buffer_alloc(size_t size) { GPUBuffer *buffer; - bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO) && !force_vertex_arrays; if (size == 0) { /* Early out, no lock needed in this case. */ @@ -377,7 +343,7 @@ GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays) } BLI_mutex_lock(&buffer_mutex); - buffer = gpu_buffer_alloc_intern(size, use_VBOs); + buffer = gpu_buffer_alloc_intern(size); BLI_mutex_unlock(&buffer_mutex); return buffer; @@ -451,9 +417,7 @@ void GPU_buffer_multires_free(bool force) if (force && BLI_thread_is_main()) { if (mres_glob_buffer) { if (mres_glob_buffer->id) - glDeleteBuffersARB(1, &mres_glob_buffer->id); - else if (mres_glob_buffer->pointer) - MEM_freeN(mres_glob_buffer->pointer); + glDeleteBuffers(1, &mres_glob_buffer->id); MEM_freeN(mres_glob_buffer); } } @@ -502,7 +466,7 @@ void GPU_drawobject_free(DerivedMesh *dm) dm->drawObject = NULL; } -static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, size_t size, bool use_VBOs) +static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, size_t size) { /* try freeing an entry from the pool * and reallocating the buffer */ @@ -512,24 +476,22 @@ static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, size_t while (pool->totbuf && !buffer) { gpu_buffer_pool_delete_last(pool); - buffer = gpu_buffer_alloc_intern(size, use_VBOs); + buffer = gpu_buffer_alloc_intern(size); } return buffer; } static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, - int type, void *user) + int type, void *user, GPUBuffer *buffer) { GPUBufferPool *pool; - GPUBuffer *buffer; float *varray; int *mat_orig_to_new; int i; const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type]; GLenum target = ts->gl_buffer_type; size_t size = gpu_buffer_size_from_type(dm, type); - bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO); GLboolean uploaded; pool = gpu_get_global_buffer_pool(); @@ -537,9 +499,11 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, BLI_mutex_lock(&buffer_mutex); /* alloc a GPUBuffer; fall back to legacy mode on failure */ - if (!(buffer = gpu_buffer_alloc_intern(size, use_VBOs))) { - BLI_mutex_unlock(&buffer_mutex); - return NULL; + if (!buffer) { + if (!(buffer = gpu_buffer_alloc_intern(size))) { + BLI_mutex_unlock(&buffer_mutex); + return NULL; + } } mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat, @@ -550,56 +514,35 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, mat_orig_to_new[object->materials[i].mat_nr] = i; } - if (use_VBOs) { - bool success = false; - - while (!success) { - /* bind the buffer and discard previous data, - * avoids stalling gpu */ - glBindBufferARB(target, buffer->id); - glBufferDataARB(target, buffer->size, NULL, GL_STATIC_DRAW_ARB); - - /* attempt to map the buffer */ - if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) { - buffer = gpu_try_realloc(pool, buffer, size, true); + /* bind the buffer and discard previous data, + * avoids stalling gpu */ + glBindBuffer(target, buffer->id); + glBufferData(target, buffer->size, NULL, GL_STATIC_DRAW); - /* allocation still failed; fall back - * to legacy mode */ - if (!(buffer && (varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB)))) { - use_VBOs = false; - success = true; - } - } - else { - success = true; - } - } + /* attempt to map the buffer */ + if (!(varray = glMapBuffer(target, GL_WRITE_ONLY))) { + buffer = gpu_try_realloc(pool, buffer, size); - /* check legacy fallback didn't happen */ - if (use_VBOs) { - uploaded = GL_FALSE; - /* attempt to upload the data to the VBO */ - while (uploaded == GL_FALSE) { - dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user); - /* glUnmapBuffer returns GL_FALSE if - * the data store is corrupted; retry - * in that case */ - uploaded = glUnmapBufferARB(target); - } + /* allocation still failed; unfortunately we need to exit */ + if (!(buffer && (varray = glMapBuffer(target, GL_WRITE_ONLY)))) { + if (buffer) + gpu_buffer_free_intern(buffer); + BLI_mutex_unlock(&buffer_mutex); + return NULL; } - glBindBufferARB(target, 0); } - if (!use_VBOs) { - /* VBO not supported, use vertex array fallback */ - if (!buffer || !buffer->pointer) { - buffer = gpu_try_realloc(pool, buffer, size, false); - } - - if (buffer) { - varray = buffer->pointer; - dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user); - } + + uploaded = GL_FALSE; + + /* attempt to upload the data to the VBO */ + while (uploaded == GL_FALSE) { + dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user); + /* glUnmapBuffer returns GL_FALSE if + * the data store is corrupted; retry + * in that case */ + uploaded = glUnmapBuffer(target); } + glBindBuffer(target, 0); MEM_freeN(mat_orig_to_new); @@ -636,33 +579,33 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer /* get the amount of space to allocate for a buffer of a particular type */ static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type) { + const int components = gpu_buffer_type_settings[type].num_components; switch (type) { case GPU_BUFFER_VERTEX: - return sizeof(float) * gpu_buffer_type_settings[type].num_components * (dm->drawObject->tot_loop_verts + dm->drawObject->tot_loose_point); + return sizeof(float) * components * (dm->drawObject->tot_loop_verts + dm->drawObject->tot_loose_point); case GPU_BUFFER_NORMAL: - return sizeof(short) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts; + return sizeof(short) * components * dm->drawObject->tot_loop_verts; case GPU_BUFFER_COLOR: - return sizeof(char) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts; + return sizeof(char) * components * dm->drawObject->tot_loop_verts; case GPU_BUFFER_UV: - return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts; + return sizeof(float) * components * dm->drawObject->tot_loop_verts; case GPU_BUFFER_UV_TEXPAINT: - return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts; + return sizeof(float) * components * dm->drawObject->tot_loop_verts; case GPU_BUFFER_EDGE: - return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->totedge; + return sizeof(int) * components * dm->drawObject->totedge; case GPU_BUFFER_UVEDGE: - return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts; + return sizeof(int) * components * dm->drawObject->tot_loop_verts; case GPU_BUFFER_TRIANGLES: - return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point; + return sizeof(int) * components * dm->drawObject->tot_triangle_point; default: return -1; } } /* call gpu_buffer_setup with settings for a particular type of buffer */ -static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) +static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type, GPUBuffer *buf) { void *user_data = NULL; - GPUBuffer *buf; /* special handling for MCol and UV buffers */ if (type == GPU_BUFFER_COLOR) { @@ -674,14 +617,14 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) return NULL; } - buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data); + buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data, buf); return buf; } /* get the buffer of `type', initializing the GPUDrawObject and * buffer if needed */ -static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type) +static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type, bool update) { GPUBuffer **buf; @@ -690,83 +633,61 @@ static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type) buf = gpu_drawobject_buffer_from_type(dm->drawObject, type); if (!(*buf)) - *buf = gpu_buffer_setup_type(dm, type); + *buf = gpu_buffer_setup_type(dm, type, NULL); + else if (update) + *buf = gpu_buffer_setup_type(dm, type, *buf); return *buf; } void GPU_vertex_setup(DerivedMesh *dm) { - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX, false)) return; glEnableClientState(GL_VERTEX_ARRAY); - if (dm->drawObject->points->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id); - glVertexPointer(3, GL_FLOAT, 0, 0); - } - else { - glVertexPointer(3, GL_FLOAT, 0, dm->drawObject->points->pointer); - } + glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->points->id); + glVertexPointer(3, GL_FLOAT, 0, 0); GLStates |= GPU_BUFFER_VERTEX_STATE; } void GPU_normal_setup(DerivedMesh *dm) { - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_NORMAL)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_NORMAL, false)) return; glEnableClientState(GL_NORMAL_ARRAY); - if (dm->drawObject->normals->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id); - glNormalPointer(GL_SHORT, 4 * sizeof(short), 0); - } - else { - glNormalPointer(GL_SHORT, 4 * sizeof(short), dm->drawObject->normals->pointer); - } + glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->normals->id); + glNormalPointer(GL_SHORT, 4 * sizeof(short), 0); GLStates |= GPU_BUFFER_NORMAL_STATE; } void GPU_uv_setup(DerivedMesh *dm) { - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV, false)) return; glEnableClientState(GL_TEXTURE_COORD_ARRAY); - if (dm->drawObject->uv->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id); - glTexCoordPointer(2, GL_FLOAT, 0, 0); - } - else { - glTexCoordPointer(2, GL_FLOAT, 0, dm->drawObject->uv->pointer); - } + glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->uv->id); + glTexCoordPointer(2, GL_FLOAT, 0, 0); GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE; } void GPU_texpaint_uv_setup(DerivedMesh *dm) { - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV_TEXPAINT)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV_TEXPAINT, false)) return; glEnableClientState(GL_TEXTURE_COORD_ARRAY); - if (dm->drawObject->uv_tex->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv_tex->id); - glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0); - glClientActiveTexture(GL_TEXTURE2); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), BUFFER_OFFSET(2 * sizeof(float))); - glClientActiveTexture(GL_TEXTURE0); - } - else { - glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv_tex->pointer); - glClientActiveTexture(GL_TEXTURE2); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv_tex->pointer + 2 * sizeof(float)); - glClientActiveTexture(GL_TEXTURE0); - } + glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->uv_tex->id); + glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0); + glClientActiveTexture(GL_TEXTURE2); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), BUFFER_OFFSET(2 * sizeof(float))); + glClientActiveTexture(GL_TEXTURE0); GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE; } @@ -774,6 +695,8 @@ void GPU_texpaint_uv_setup(DerivedMesh *dm) void GPU_color_setup(DerivedMesh *dm, int colType) { + bool update = false; + if (!dm->drawObject) { /* XXX Not really nice, but we need a valid gpu draw object to set the colType... * Else we would have to add a new param to gpu_buffer_setup_common. */ @@ -784,27 +707,17 @@ void GPU_color_setup(DerivedMesh *dm, int colType) /* In paint mode, dm may stay the same during stroke, however we still want to update colors! * Also check in case we changed color type (i.e. which MCol cdlayer we use). */ else if ((dm->dirty & DM_DIRTY_MCOL_UPDATE_DRAW) || (colType != dm->drawObject->colType)) { - GPUBuffer **buf = gpu_drawobject_buffer_from_type(dm->drawObject, GPU_BUFFER_COLOR); - /* XXX Freeing this buffer is a bit stupid, as geometry has not changed, size should remain the same. - * Not sure though it would be worth defining a sort of gpu_buffer_update func - nor whether - * it is even possible ! */ - GPU_buffer_free(*buf); - *buf = NULL; + update = true; dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW; dm->drawObject->colType = colType; } - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR, update)) return; glEnableClientState(GL_COLOR_ARRAY); - if (dm->drawObject->colors->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id); - glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); - } - else { - glColorPointer(3, GL_UNSIGNED_BYTE, 0, dm->drawObject->colors->pointer); - } + glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->colors->id); + glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); GLStates |= GPU_BUFFER_COLOR_STATE; } @@ -812,13 +725,8 @@ void GPU_color_setup(DerivedMesh *dm, int colType) void GPU_buffer_bind_as_color(GPUBuffer *buffer) { glEnableClientState(GL_COLOR_ARRAY); - if (buffer->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0); - } - else { - glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer->pointer); - } + glBindBuffer(GL_ARRAY_BUFFER, buffer->id); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0); GLStates |= GPU_BUFFER_COLOR_STATE; } @@ -826,55 +734,39 @@ void GPU_buffer_bind_as_color(GPUBuffer *buffer) void GPU_edge_setup(DerivedMesh *dm) { - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE, false)) return; - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX, false)) return; glEnableClientState(GL_VERTEX_ARRAY); - if (dm->drawObject->points->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id); - glVertexPointer(3, GL_FLOAT, 0, 0); - } - else { - glVertexPointer(3, GL_FLOAT, 0, dm->drawObject->points->pointer); - } + glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->points->id); + glVertexPointer(3, GL_FLOAT, 0, 0); - GLStates |= GPU_BUFFER_VERTEX_STATE; + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dm->drawObject->edges->id); - if (dm->drawObject->edges->use_vbo) - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id); - - GLStates |= GPU_BUFFER_ELEMENT_STATE; + GLStates |= (GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_ELEMENT_STATE); } void GPU_uvedge_setup(DerivedMesh *dm) { - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UVEDGE)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UVEDGE, false)) return; glEnableClientState(GL_VERTEX_ARRAY); - if (dm->drawObject->uvedges->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id); - glVertexPointer(2, GL_FLOAT, 0, 0); - } - else { - glVertexPointer(2, GL_FLOAT, 0, dm->drawObject->uvedges->pointer); - } + glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->uvedges->id); + glVertexPointer(2, GL_FLOAT, 0, 0); GLStates |= GPU_BUFFER_VERTEX_STATE; } void GPU_triangle_setup(struct DerivedMesh *dm) { - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_TRIANGLES)) + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_TRIANGLES, false)) return; - if (dm->drawObject->triangles->use_vbo) { - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->triangles->id); - } - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dm->drawObject->triangles->id); GLStates |= GPU_BUFFER_ELEMENT_STATE; } @@ -912,12 +804,11 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda { int i; int elementsize; - intptr_t offset = 0; - char *basep; + size_t offset = 0; for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) { if (attribData[i].index != -1) { - glDisableVertexAttribArrayARB(attribData[i].index); + glDisableVertexAttribArray(attribData[i].index); } else break; @@ -927,18 +818,12 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda else elementsize = element_size; - if (buffer->use_vbo) { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id); - basep = NULL; - } - else { - basep = buffer->pointer; - } + glBindBuffer(GL_ARRAY_BUFFER, buffer->id); for (i = 0; i < numdata; i++) { - glEnableVertexAttribArrayARB(data[i].index); - glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type, - GL_FALSE, elementsize, (void *)(basep + offset)); + glEnableVertexAttribArray(data[i].index); + glVertexAttribPointer(data[i].index, data[i].size, data[i].type, + GL_FALSE, elementsize, BUFFER_OFFSET(offset)); offset += data[i].size * GPU_typesize(data[i].type); attribData[i].index = data[i].index; @@ -954,7 +839,7 @@ void GPU_interleaved_attrib_unbind(void) int i; for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) { if (attribData[i].index != -1) { - glDisableVertexAttribArrayARB(attribData[i].index); + glDisableVertexAttribArray(attribData[i].index); } else break; @@ -979,28 +864,23 @@ void GPU_buffers_unbind(void) } if (GLStates & GPU_BUFFER_COLOR_STATE) glDisableClientState(GL_COLOR_ARRAY); - if (GLStates & GPU_BUFFER_ELEMENT_STATE) { - /* not guaranteed we used VBOs but in that case it's just a no-op */ - if (GLEW_ARB_vertex_buffer_object) { - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - } - } + if (GLStates & GPU_BUFFER_ELEMENT_STATE) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE | GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_2_STATE | GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE); for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) { if (attribData[i].index != -1) { - glDisableVertexAttribArrayARB(attribData[i].index); + glDisableVertexAttribArray(attribData[i].index); } else break; } attribData[0].index = -1; - /* not guaranteed we used VBOs but in that case it's just a no-op */ - if (GLEW_ARB_vertex_buffer_object) - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); } void GPU_color_switch(int mode) @@ -1019,82 +899,65 @@ void GPU_color_switch(int mode) static int gpu_binding_type_gl[] = { - GL_ARRAY_BUFFER_ARB, - GL_ELEMENT_ARRAY_BUFFER_ARB + GL_ARRAY_BUFFER, + GL_ELEMENT_ARRAY_BUFFER }; void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding) { float *varray; + int bindtypegl; if (!buffer) return 0; - if (buffer->use_vbo) { - int bindtypegl = gpu_binding_type_gl[binding]; - glBindBufferARB(bindtypegl, buffer->id); - varray = glMapBufferARB(bindtypegl, GL_WRITE_ONLY_ARB); - return varray; - } - else { - return buffer->pointer; - } + bindtypegl = gpu_binding_type_gl[binding]; + glBindBuffer(bindtypegl, buffer->id); + varray = glMapBuffer(bindtypegl, GL_WRITE_ONLY); + return varray; } void *GPU_buffer_lock_stream(GPUBuffer *buffer, GPUBindingType binding) { float *varray; + int bindtypegl; if (!buffer) return 0; - if (buffer->use_vbo) { - int bindtypegl = gpu_binding_type_gl[binding]; - glBindBufferARB(bindtypegl, buffer->id); - /* discard previous data, avoid stalling gpu */ - glBufferDataARB(bindtypegl, buffer->size, 0, GL_STREAM_DRAW_ARB); - varray = glMapBufferARB(bindtypegl, GL_WRITE_ONLY_ARB); - return varray; - } - else { - return buffer->pointer; - } + bindtypegl = gpu_binding_type_gl[binding]; + glBindBuffer(bindtypegl, buffer->id); + /* discard previous data, avoid stalling gpu */ + glBufferData(bindtypegl, buffer->size, 0, GL_STREAM_DRAW); + varray = glMapBuffer(bindtypegl, GL_WRITE_ONLY); + return varray; } -void GPU_buffer_unlock(GPUBuffer *buffer, GPUBindingType binding) +void GPU_buffer_unlock(GPUBuffer *UNUSED(buffer), GPUBindingType binding) { - if (buffer->use_vbo) { - int bindtypegl = gpu_binding_type_gl[binding]; - /* note: this operation can fail, could return + int bindtypegl = gpu_binding_type_gl[binding]; + /* note: this operation can fail, could return * an error code from this function? */ - glUnmapBufferARB(bindtypegl); - glBindBufferARB(bindtypegl, 0); - } + glUnmapBuffer(bindtypegl); + glBindBuffer(bindtypegl, 0); } void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding) { - if (buffer->use_vbo) { - int bindtypegl = gpu_binding_type_gl[binding]; - glBindBufferARB(bindtypegl, buffer->id); - } + int bindtypegl = gpu_binding_type_gl[binding]; + glBindBuffer(bindtypegl, buffer->id); } -void GPU_buffer_unbind(GPUBuffer *buffer, GPUBindingType binding) +void GPU_buffer_unbind(GPUBuffer *UNUSED(buffer), GPUBindingType binding) { - if (buffer->use_vbo) { - int bindtypegl = gpu_binding_type_gl[binding]; - glBindBufferARB(bindtypegl, 0); - } + int bindtypegl = gpu_binding_type_gl[binding]; + glBindBuffer(bindtypegl, 0); } /* used for drawing edges */ -void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count) +void GPU_buffer_draw_elements(GPUBuffer *UNUSED(elements), unsigned int mode, int start, int count) { - glDrawElements(mode, count, GL_UNSIGNED_INT, - (elements->use_vbo ? - (void *)(start * sizeof(unsigned int)) : - ((int *)elements->pointer) + start)); + glDrawElements(mode, count, GL_UNSIGNED_INT, BUFFER_OFFSET(start * sizeof(unsigned int))); } @@ -1139,41 +1002,21 @@ struct GPU_PBVH_Buffers { BLI_bitmap * const *grid_hidden; const int *grid_indices; int totgrid; - int has_hidden; + bool has_hidden; - int use_bmesh; + bool use_bmesh; unsigned int tot_tri, tot_quad; /* The PBVH ensures that either all faces in the node are * smooth-shaded or all faces are flat-shaded */ - int smooth; + bool smooth; bool show_diffuse_color; bool use_matcaps; float diffuse_color[4]; }; -typedef enum { - VBO_ENABLED, - VBO_DISABLED -} VBO_State; - -static void gpu_colors_enable(VBO_State vbo_state) -{ - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - glEnable(GL_COLOR_MATERIAL); - if (vbo_state == VBO_ENABLED) - glEnableClientState(GL_COLOR_ARRAY); -} - -static void gpu_colors_disable(VBO_State vbo_state) -{ - glDisable(GL_COLOR_MATERIAL); - if (vbo_state == VBO_ENABLED) - glDisableClientState(GL_COLOR_ARRAY); -} - static float gpu_color_from_mask(float mask) { return 1.0f - mask * 0.75f; @@ -1237,7 +1080,7 @@ void GPU_update_mesh_pbvh_buffers( /* Build VBO */ if (buffers->vert_buf) GPU_buffer_free(buffers->vert_buf); - buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totelem, false); + buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totelem); vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY); if (vert_data) { @@ -1378,7 +1221,7 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( * shading requires separate vertex normals so an index buffer is * can't be used there. */ if (buffers->smooth) - buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3, false); + buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3); if (buffers->index_buf) { /* Fill the triangle buffer */ @@ -1425,10 +1268,10 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, buffers->show_diffuse_color = show_diffuse_color; buffers->use_matcaps = GPU_material_use_matcaps_get(); + buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; /* Build VBO */ if (buffers->vert_buf) { - int smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; const int has_mask = key->has_mask; float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; @@ -1453,7 +1296,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, CCGElem *elem = CCG_grid_elem(key, grid, x, y); copy_v3_v3(vd->co, CCG_elem_co(key, elem)); - if (smooth) { + if (buffers->smooth) { normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem)); if (has_mask) { @@ -1465,7 +1308,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, } } - if (!smooth) { + if (!buffers->smooth) { /* for flat shading, recalc normals and set the last vertex of * each triangle in the index buffer to have the flat normal as * that is what opengl will use */ @@ -1518,8 +1361,6 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, buffers->grid_flag_mats = grid_flag_mats; buffers->gridkey = *key; - buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; - //printf("node updated %p\n", buffers); } @@ -1530,8 +1371,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, type_ *tri_data; \ int offset = 0; \ int i, j, k; \ - buffer_ = GPU_buffer_alloc(sizeof(type_) * (tot_quad_) * 6, \ - false); \ + buffer_ = GPU_buffer_alloc(sizeof(type_) * (tot_quad_) * 6); \ \ /* Fill the buffer */ \ tri_data = GPU_buffer_lock(buffer_, GPU_BINDING_INDEX); \ @@ -1609,7 +1449,7 @@ static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned #define FILL_FAST_BUFFER(type_) \ { \ type_ *buffer; \ - buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid, false); \ + buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid); \ buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \ if (buffer) { \ int i; \ @@ -1661,7 +1501,7 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, if (totquad == fully_visible_totquad) { buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad); - buffers->has_hidden = 0; + buffers->has_hidden = false; } else { buffers->tot_quad = totquad; @@ -1675,22 +1515,21 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf); } - buffers->has_hidden = 1; + buffers->has_hidden = true; } /* Build coord/normal VBO */ if (buffers->index_buf) - buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area, false); + buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area); - if (GLEW_ARB_draw_elements_base_vertex) { + if (GLEW_ARB_draw_elements_base_vertex /* 3.2 */) { int i; buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray"); buffers->baseindex = MEM_mallocN(sizeof(void *) * totgrid, "GPU_PBVH_Buffers.baseindex"); for (i = 0; i < totgrid; i++) { buffers->baseelemarray[i] = buffers->tot_quad * 6; buffers->baseelemarray[i + totgrid] = i * key->grid_area; - buffers->baseindex[i] = buffers->index_buf && !buffers->index_buf->use_vbo ? - buffers->index_buf->pointer : NULL; + buffers->baseindex[i] = NULL; } } @@ -1822,7 +1661,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, /* Initialize vertex buffer */ if (buffers->vert_buf) GPU_buffer_free(buffers->vert_buf); - buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totvert, false); + buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totvert); /* Fill vertex buffer */ vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY); @@ -1905,7 +1744,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, GPU_buffer_free(buffers->index_buf); buffers->index_buf = GPU_buffer_alloc((use_short ? sizeof(unsigned short) : - sizeof(unsigned int)) * 3 * tottri, false); + sizeof(unsigned int)) * 3 * tottri); /* Fill triangle index buffer */ tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX); @@ -1942,8 +1781,8 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, buffers->tot_tri = tottri; buffers->index_type = (use_short ? - GL_UNSIGNED_SHORT : - GL_UNSIGNED_INT); + GL_UNSIGNED_SHORT : + GL_UNSIGNED_INT); } else { /* Memory map failed */ @@ -1956,7 +1795,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, } } -GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading) +GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading) { GPU_PBVH_Buffers *buffers; @@ -1993,35 +1832,33 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, } } - glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT); - if (buffers->vert_buf) { char *base = NULL; char *index_base = NULL; + int bound_options = 0; glEnableClientState(GL_VERTEX_ARRAY); if (!wireframe) { glEnableClientState(GL_NORMAL_ARRAY); - gpu_colors_enable(VBO_ENABLED); + glEnableClientState(GL_COLOR_ARRAY); + + /* weak inspection of bound options, should not be necessary ideally */ + bound_options = GPU_basic_shader_bound_options(); + GPU_basic_shader_bind(bound_options | GPU_SHADER_USE_COLOR); } GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY); - if (!buffers->vert_buf->use_vbo) - base = (char *)buffers->vert_buf->pointer; - if (do_fast) { GPU_buffer_bind(buffers->index_buf_fast, GPU_BINDING_INDEX); - if (!buffers->index_buf_fast->use_vbo) - index_base = buffers->index_buf_fast->pointer; } else if (buffers->index_buf) { GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX); - if (!buffers->index_buf->use_vbo) - index_base = buffers->index_buf->pointer; } if (wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + else + glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT); if (buffers->tot_quad) { const char *offset = base; @@ -2031,10 +1868,12 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), offset + offsetof(VertexBufferFormat, co)); - glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), - offset + offsetof(VertexBufferFormat, no)); - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), - offset + offsetof(VertexBufferFormat, color)); + if (!wireframe) { + glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), + offset + offsetof(VertexBufferFormat, no)); + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), + offset + offsetof(VertexBufferFormat, color)); + } glMultiDrawElementsBaseVertex(GL_TRIANGLES, buffers->baseelemarray, buffers->index_type, (const void * const *)buffers->baseindex, @@ -2047,10 +1886,12 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, for (i = 0; i < last; i++) { glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), offset + offsetof(VertexBufferFormat, co)); - glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), - offset + offsetof(VertexBufferFormat, no)); - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), - offset + offsetof(VertexBufferFormat, color)); + if (!wireframe) { + glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), + offset + offsetof(VertexBufferFormat, no)); + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), + offset + offsetof(VertexBufferFormat, color)); + } if (do_fast) glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base); @@ -2066,10 +1907,13 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), (void *)(base + offsetof(VertexBufferFormat, co))); - glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), - (void *)(base + offsetof(VertexBufferFormat, no))); - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), - (void *)(base + offsetof(VertexBufferFormat, color))); + + if (!wireframe) { + glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), + (void *)(base + offsetof(VertexBufferFormat, no))); + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), + (void *)(base + offsetof(VertexBufferFormat, color))); + } if (buffers->index_buf) glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, index_base); @@ -2087,7 +1931,8 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, glDisableClientState(GL_VERTEX_ARRAY); if (!wireframe) { glDisableClientState(GL_NORMAL_ARRAY); - gpu_colors_disable(VBO_ENABLED); + glDisableClientState(GL_COLOR_ARRAY); + GPU_basic_shader_bind(bound_options); } } } @@ -2203,8 +2048,6 @@ void GPU_init_draw_pbvh_BB(void) glEnableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); glEnable(GL_BLEND); } |