diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 1694 |
1 files changed, 332 insertions, 1362 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index a35f678f8dc..df8dbb03284 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -35,8 +35,6 @@ #include <stddef.h> #include <string.h> -#include "GPU_glew.h" - #include "MEM_guardedalloc.h" #include "BLI_bitmap.h" @@ -55,914 +53,29 @@ #include "GPU_buffers.h" #include "GPU_draw.h" -#include "GPU_basic_shader.h" +#include "GPU_immediate.h" +#include "GPU_batch.h" #include "bmesh.h" -typedef enum { - GPU_BUFFER_VERTEX_STATE = (1 << 0), - GPU_BUFFER_NORMAL_STATE = (1 << 1), - GPU_BUFFER_TEXCOORD_UNIT_0_STATE = (1 << 2), - GPU_BUFFER_TEXCOORD_UNIT_2_STATE = (1 << 3), - GPU_BUFFER_COLOR_STATE = (1 << 4), - GPU_BUFFER_ELEMENT_STATE = (1 << 5), -} GPUBufferState; - -typedef struct { - GLenum gl_buffer_type; - int num_components; /* number of data components for one vertex */ -} GPUBufferTypeSettings; - - -static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type); - -static const GPUBufferTypeSettings gpu_buffer_type_settings[] = { - /* vertex */ - {GL_ARRAY_BUFFER, 3}, - /* normal */ - {GL_ARRAY_BUFFER, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */ - /* mcol */ - {GL_ARRAY_BUFFER, 4}, - /* uv */ - {GL_ARRAY_BUFFER, 2}, - /* uv for texpaint */ - {GL_ARRAY_BUFFER, 4}, - /* edge */ - {GL_ELEMENT_ARRAY_BUFFER, 2}, - /* uv edge */ - {GL_ELEMENT_ARRAY_BUFFER, 4}, - /* triangles, 1 point since we are allocating from tottriangle points, which account for all points */ - {GL_ELEMENT_ARRAY_BUFFER, 1}, -}; - -#define MAX_GPU_ATTRIB_DATA 32 - -#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n)) - -static GPUBufferState GLStates = 0; -static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } }; - static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER; /* multires global buffer, can be used for many grids having the same grid size */ typedef struct GridCommonGPUBuffer { - GPUBuffer *mres_buffer; + Gwn_IndexBuf *mres_buffer; int mres_prev_gridsize; - GLenum mres_prev_index_type; unsigned mres_prev_totquad; } GridCommonGPUBuffer; -void GPU_buffer_material_finalize(GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat) -{ - int i, curmat, curelement; - - /* count the number of materials used by this DerivedMesh */ - for (i = 0; i < totmat; i++) { - if (matinfo[i].totelements > 0) - gdo->totmaterial++; - } - - /* allocate an array of materials used by this DerivedMesh */ - gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial, - "GPUDrawObject.materials"); - - /* initialize the materials array */ - for (i = 0, curmat = 0, curelement = 0; i < totmat; i++) { - if (matinfo[i].totelements > 0) { - gdo->materials[curmat] = matinfo[i]; - gdo->materials[curmat].start = curelement; - gdo->materials[curmat].mat_nr = i; - gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * matinfo[i].totpolys, "GPUBufferMaterial.polys"); - - curelement += matinfo[i].totelements; - curmat++; - } - } - - MEM_freeN(matinfo); -} - - -/* stores recently-deleted buffers so that new buffers won't have to - * be recreated as often - * - * only one instance of this pool is created, stored in - * gpu_buffer_pool - * - * note that the number of buffers in the pool is usually limited to - * MAX_FREE_GPU_BUFFERS, but this limit may be exceeded temporarily - * when a GPUBuffer is released outside the main thread; due to OpenGL - * restrictions it cannot be immediately released - */ -typedef struct GPUBufferPool { - /* number of allocated buffers stored */ - int totbuf; - /* actual allocated length of the arrays */ - int maxsize; - GPUBuffer **buffers; -} GPUBufferPool; -#define MAX_FREE_GPU_BUFFERS 8 - -/* create a new GPUBufferPool */ -static GPUBufferPool *gpu_buffer_pool_new(void) -{ - GPUBufferPool *pool; - - pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer_Pool"); - - pool->maxsize = MAX_FREE_GPU_BUFFERS; - pool->buffers = MEM_mallocN(sizeof(*pool->buffers) * pool->maxsize, - "GPUBufferPool.buffers"); - return pool; -} - -/* remove a GPUBuffer from the pool (does not free the GPUBuffer) */ -static void gpu_buffer_pool_remove_index(GPUBufferPool *pool, int index) -{ - int i; - - if (!pool || index < 0 || index >= pool->totbuf) - return; - - /* shift entries down, overwriting the buffer at `index' */ - for (i = index; i < pool->totbuf - 1; i++) - pool->buffers[i] = pool->buffers[i + 1]; - - /* clear the last entry */ - if (pool->totbuf > 0) - pool->buffers[pool->totbuf - 1] = NULL; - - pool->totbuf--; -} - -/* delete the last entry in the pool */ -static void gpu_buffer_pool_delete_last(GPUBufferPool *pool) -{ - GPUBuffer *last; - - if (pool->totbuf <= 0) - return; - - /* get the last entry */ - if (!(last = pool->buffers[pool->totbuf - 1])) - return; - - /* delete the buffer's data */ - glDeleteBuffers(1, &last->id); - - /* delete the buffer and remove from pool */ - MEM_freeN(last); - pool->totbuf--; - pool->buffers[pool->totbuf] = NULL; -} - -/* free a GPUBufferPool; also frees the data in the pool's - * GPUBuffers */ -static void gpu_buffer_pool_free(GPUBufferPool *pool) -{ - if (!pool) - return; - - while (pool->totbuf) - gpu_buffer_pool_delete_last(pool); - - MEM_freeN(pool->buffers); - MEM_freeN(pool); -} - -static void gpu_buffer_pool_free_unused(GPUBufferPool *pool) -{ - if (!pool) - return; - - BLI_mutex_lock(&buffer_mutex); - - while (pool->totbuf) - gpu_buffer_pool_delete_last(pool); - - BLI_mutex_unlock(&buffer_mutex); -} - -static GPUBufferPool *gpu_buffer_pool = NULL; -static GPUBufferPool *gpu_get_global_buffer_pool(void) -{ - /* initialize the pool */ - if (!gpu_buffer_pool) - gpu_buffer_pool = gpu_buffer_pool_new(); - - return gpu_buffer_pool; -} - -void GPU_global_buffer_pool_free(void) -{ - gpu_buffer_pool_free(gpu_buffer_pool); - gpu_buffer_pool = NULL; -} - -void GPU_global_buffer_pool_free_unused(void) -{ - gpu_buffer_pool_free_unused(gpu_buffer_pool); -} - -/* get a GPUBuffer of at least `size' bytes; uses one from the buffer - * pool if possible, otherwise creates a new one - * - * Thread-unsafe version for internal usage only. - */ -static GPUBuffer *gpu_buffer_alloc_intern(size_t size) -{ - GPUBufferPool *pool; - GPUBuffer *buf; - int i, bestfit = -1; - size_t bufsize; - - /* bad case, leads to leak of buf since buf->pointer will allocate - * NULL, leading to return without cleanup. In any case better detect early - * psy-fi */ - if (size == 0) - return NULL; - - pool = gpu_get_global_buffer_pool(); - - /* not sure if this buffer pool code has been profiled much, - * seems to me that the graphics driver and system memory - * management might do this stuff anyway. --nicholas - */ - - /* check the global buffer pool for a recently-deleted buffer - * that is at least as big as the request, but not more than - * twice as big */ - for (i = 0; i < pool->totbuf; i++) { - bufsize = pool->buffers[i]->size; - - /* check for an exact size match */ - if (bufsize == size) { - bestfit = i; - break; - } - /* smaller buffers won't fit data and buffers at least - * twice as big are a waste of memory */ - else if (bufsize > size && size > (bufsize / 2)) { - /* is it closer to the required size than the - * last appropriate buffer found. try to save - * memory */ - if (bestfit == -1 || pool->buffers[bestfit]->size > bufsize) { - bestfit = i; - } - } - } - - /* if an acceptable buffer was found in the pool, remove it - * from the pool and return it */ - if (bestfit != -1) { - buf = pool->buffers[bestfit]; - gpu_buffer_pool_remove_index(pool, bestfit); - return buf; - } - - /* no acceptable buffer found in the pool, create a new one */ - buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer"); - buf->size = size; - - 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) -{ - GPUBuffer *buffer; - - if (size == 0) { - /* Early out, no lock needed in this case. */ - return NULL; - } - - BLI_mutex_lock(&buffer_mutex); - buffer = gpu_buffer_alloc_intern(size); - BLI_mutex_unlock(&buffer_mutex); - - return buffer; -} - -/* release a GPUBuffer; does not free the actual buffer or its data, - * but rather moves it to the pool of recently-freed buffers for - * possible re-use - * - * Thread-unsafe version for internal usage only. - */ -static void gpu_buffer_free_intern(GPUBuffer *buffer) -{ - GPUBufferPool *pool; - int i; - - if (!buffer) - return; - - pool = gpu_get_global_buffer_pool(); - - /* free the last used buffer in the queue if no more space, but only - * if we are in the main thread. for e.g. rendering or baking it can - * happen that we are in other thread and can't call OpenGL, in that - * case cleanup will be done GPU_buffer_pool_free_unused */ - if (BLI_thread_is_main()) { - /* in main thread, safe to decrease size of pool back - * down to MAX_FREE_GPU_BUFFERS */ - while (pool->totbuf >= MAX_FREE_GPU_BUFFERS) - gpu_buffer_pool_delete_last(pool); - } - else { - /* outside of main thread, can't safely delete the - * buffer, so increase pool size */ - if (pool->maxsize == pool->totbuf) { - pool->maxsize += MAX_FREE_GPU_BUFFERS; - pool->buffers = MEM_reallocN(pool->buffers, - sizeof(GPUBuffer *) * pool->maxsize); - } - } - - /* shift pool entries up by one */ - for (i = pool->totbuf; i > 0; i--) - pool->buffers[i] = pool->buffers[i - 1]; - - /* insert the buffer into the beginning of the pool */ - pool->buffers[0] = buffer; - pool->totbuf++; -} - -/* Same as above, but safe for threading. */ -void GPU_buffer_free(GPUBuffer *buffer) -{ - if (!buffer) { - /* Early output, no need to lock in this case, */ - return; - } - - BLI_mutex_lock(&buffer_mutex); - gpu_buffer_free_intern(buffer); - BLI_mutex_unlock(&buffer_mutex); -} - -void GPU_drawobject_free(DerivedMesh *dm) -{ - GPUDrawObject *gdo; - int i; - - if (!dm || !(gdo = dm->drawObject)) - return; - - for (i = 0; i < gdo->totmaterial; i++) { - if (gdo->materials[i].polys) - MEM_freeN(gdo->materials[i].polys); - } - - MEM_freeN(gdo->materials); - if (gdo->vert_points) - MEM_freeN(gdo->vert_points); -#ifdef USE_GPU_POINT_LINK - MEM_freeN(gdo->vert_points_mem); -#endif - GPU_buffer_free(gdo->points); - GPU_buffer_free(gdo->normals); - GPU_buffer_free(gdo->uv); - GPU_buffer_free(gdo->uv_tex); - GPU_buffer_free(gdo->colors); - GPU_buffer_free(gdo->edges); - GPU_buffer_free(gdo->uvedges); - GPU_buffer_free(gdo->triangles); - - MEM_freeN(gdo); - dm->drawObject = NULL; -} - -static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, size_t size) -{ - /* try freeing an entry from the pool - * and reallocating the buffer */ - gpu_buffer_free_intern(buffer); - - buffer = NULL; - - while (pool->totbuf && !buffer) { - gpu_buffer_pool_delete_last(pool); - buffer = gpu_buffer_alloc_intern(size); - } - - return buffer; -} - -static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, - int type, void *user, GPUBuffer *buffer) -{ - GPUBufferPool *pool; - 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); - GLboolean uploaded; - - pool = gpu_get_global_buffer_pool(); - - BLI_mutex_lock(&buffer_mutex); - - /* alloc a GPUBuffer; fall back to legacy mode on failure */ - 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, - "GPU_buffer_setup.mat_orig_to_new"); - for (i = 0; i < object->totmaterial; i++) { - /* map from original material index to new - * GPUBufferMaterial index */ - mat_orig_to_new[object->materials[i].mat_nr] = i; - } - - /* bind the buffer and discard previous data, - * avoids stalling gpu */ - glBindBuffer(target, buffer->id); - glBufferData(target, buffer->size, NULL, GL_STATIC_DRAW); - - /* attempt to map the buffer */ - if (!(varray = glMapBuffer(target, GL_WRITE_ONLY))) { - buffer = gpu_try_realloc(pool, buffer, size); - - /* 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; - } - } - - 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); - - BLI_mutex_unlock(&buffer_mutex); - - return buffer; -} - -/* get the GPUDrawObject buffer associated with a type */ -static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type) -{ - switch (type) { - case GPU_BUFFER_VERTEX: - return &gdo->points; - case GPU_BUFFER_NORMAL: - return &gdo->normals; - case GPU_BUFFER_COLOR: - return &gdo->colors; - case GPU_BUFFER_UV: - return &gdo->uv; - case GPU_BUFFER_UV_TEXPAINT: - return &gdo->uv_tex; - case GPU_BUFFER_EDGE: - return &gdo->edges; - case GPU_BUFFER_UVEDGE: - return &gdo->uvedges; - case GPU_BUFFER_TRIANGLES: - return &gdo->triangles; - default: - return NULL; - } -} - -/* 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) * components * (dm->drawObject->tot_loop_verts + dm->drawObject->tot_loose_point); - case GPU_BUFFER_NORMAL: - return sizeof(short) * components * dm->drawObject->tot_loop_verts; - case GPU_BUFFER_COLOR: - return sizeof(char) * components * dm->drawObject->tot_loop_verts; - case GPU_BUFFER_UV: - return sizeof(float) * components * dm->drawObject->tot_loop_verts; - case GPU_BUFFER_UV_TEXPAINT: - return sizeof(float) * components * dm->drawObject->tot_loop_verts; - case GPU_BUFFER_EDGE: - return sizeof(int) * components * dm->drawObject->totedge; - case GPU_BUFFER_UVEDGE: - return sizeof(int) * components * dm->drawObject->tot_loop_verts; - case GPU_BUFFER_TRIANGLES: - 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, GPUBuffer *buf) -{ - void *user_data = NULL; - - /* special handling for MCol and UV buffers */ - if (type == GPU_BUFFER_COLOR) { - if (!(user_data = DM_get_loop_data_layer(dm, dm->drawObject->colType))) - return NULL; - } - else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) { - if (!DM_get_loop_data_layer(dm, CD_MLOOPUV)) - return NULL; - } - - 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, bool update) -{ - GPUBuffer **buf; - - if (!dm->drawObject) - dm->drawObject = dm->gpuObjectNew(dm); - - buf = gpu_drawobject_buffer_from_type(dm->drawObject, type); - if (!(*buf)) - *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, false)) - return; - - glEnableClientState(GL_VERTEX_ARRAY); - 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, false)) - return; - - glEnableClientState(GL_NORMAL_ARRAY); - 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, false)) - return; - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - 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, false)) - return; - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - 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; -} - - -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. */ - dm->drawObject = dm->gpuObjectNew(dm); - dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW; - dm->drawObject->colType = 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)) { - update = true; - dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW; - dm->drawObject->colType = colType; - } - - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR, update)) - return; - - glEnableClientState(GL_COLOR_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->colors->id); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0); - - GLStates |= GPU_BUFFER_COLOR_STATE; -} - -void GPU_buffer_bind_as_color(GPUBuffer *buffer) -{ - glEnableClientState(GL_COLOR_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, buffer->id); - glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0); - - GLStates |= GPU_BUFFER_COLOR_STATE; -} - - -void GPU_edge_setup(DerivedMesh *dm) -{ - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE, false)) - return; - - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX, false)) - return; - - glEnableClientState(GL_VERTEX_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, dm->drawObject->points->id); - glVertexPointer(3, GL_FLOAT, 0, 0); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dm->drawObject->edges->id); - - GLStates |= (GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_ELEMENT_STATE); -} - -void GPU_uvedge_setup(DerivedMesh *dm) -{ - if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UVEDGE, false)) - return; - - glEnableClientState(GL_VERTEX_ARRAY); - 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, false)) - return; - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dm->drawObject->triangles->id); - GLStates |= GPU_BUFFER_ELEMENT_STATE; -} - -static int gpu_typesize(int type) -{ - switch (type) { - case GL_FLOAT: - return sizeof(float); - case GL_INT: - return sizeof(int); - case GL_UNSIGNED_INT: - return sizeof(unsigned int); - case GL_BYTE: - return sizeof(char); - case GL_UNSIGNED_BYTE: - return sizeof(unsigned char); - default: - return 0; - } -} - -int GPU_attrib_element_size(GPUAttrib data[], int numdata) -{ - int i, elementsize = 0; - - for (i = 0; i < numdata; i++) { - int typesize = gpu_typesize(data[i].type); - if (typesize != 0) - elementsize += typesize * data[i].size; - } - return elementsize; -} - -void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size) -{ - int i; - int elementsize; - size_t offset = 0; - - for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) { - if (attribData[i].index != -1) { - glDisableVertexAttribArray(attribData[i].index); - } - else - break; - } - if (element_size == 0) - elementsize = GPU_attrib_element_size(data, numdata); - else - elementsize = element_size; - - glBindBuffer(GL_ARRAY_BUFFER, buffer->id); - - for (i = 0; i < numdata; i++) { - glEnableVertexAttribArray(data[i].index); - int info = 0; - if (data[i].type == GL_UNSIGNED_BYTE) { - info |= GPU_ATTR_INFO_SRGB; - } - glUniform1i(data[i].info_index, info); - - glVertexAttribPointer(data[i].index, data[i].size, data[i].type, - GL_TRUE, elementsize, BUFFER_OFFSET(offset)); - offset += data[i].size * gpu_typesize(data[i].type); - - attribData[i].index = data[i].index; - attribData[i].size = data[i].size; - attribData[i].type = data[i].type; - } - - attribData[numdata].index = -1; -} - -void GPU_interleaved_attrib_unbind(void) -{ - int i; - for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) { - if (attribData[i].index != -1) { - glDisableVertexAttribArray(attribData[i].index); - } - else - break; - } - attribData[0].index = -1; -} - -void GPU_buffers_unbind(void) -{ - int i; - - if (GLStates & GPU_BUFFER_VERTEX_STATE) - glDisableClientState(GL_VERTEX_ARRAY); - if (GLStates & GPU_BUFFER_NORMAL_STATE) - glDisableClientState(GL_NORMAL_ARRAY); - if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_0_STATE) - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_2_STATE) { - glClientActiveTexture(GL_TEXTURE2); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glClientActiveTexture(GL_TEXTURE0); - } - if (GLStates & GPU_BUFFER_COLOR_STATE) - glDisableClientState(GL_COLOR_ARRAY); - 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) { - glDisableVertexAttribArray(attribData[i].index); - } - else - break; - } - attribData[0].index = -1; - - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void GPU_color_switch(int mode) -{ - if (mode) { - if (!(GLStates & GPU_BUFFER_COLOR_STATE)) - glEnableClientState(GL_COLOR_ARRAY); - GLStates |= GPU_BUFFER_COLOR_STATE; - } - else { - if (GLStates & GPU_BUFFER_COLOR_STATE) - glDisableClientState(GL_COLOR_ARRAY); - GLStates &= ~GPU_BUFFER_COLOR_STATE; - } -} - -static int gpu_binding_type_gl[] = -{ - GL_ARRAY_BUFFER, - GL_ELEMENT_ARRAY_BUFFER -}; - -void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding) -{ - float *varray; - int bindtypegl; - - if (!buffer) - return 0; - - 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; - - 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 *UNUSED(buffer), GPUBindingType binding) -{ - int bindtypegl = gpu_binding_type_gl[binding]; - /* note: this operation can fail, could return - * an error code from this function? */ - glUnmapBuffer(bindtypegl); - glBindBuffer(bindtypegl, 0); -} - -void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding) -{ - int bindtypegl = gpu_binding_type_gl[binding]; - glBindBuffer(bindtypegl, buffer->id); -} - -void GPU_buffer_unbind(GPUBuffer *UNUSED(buffer), GPUBindingType binding) -{ - int bindtypegl = gpu_binding_type_gl[binding]; - glBindBuffer(bindtypegl, 0); -} - -/* used for drawing edges */ -void GPU_buffer_draw_elements(GPUBuffer *UNUSED(elements), unsigned int mode, int start, int count) -{ - glDrawElements(mode, count, GL_UNSIGNED_INT, BUFFER_OFFSET(start * sizeof(unsigned int))); -} - - /* XXX: the rest of the code in this file is used for optimized PBVH * drawing and doesn't interact at all with the buffer code above */ -/* Convenience struct for building the VBO. */ -typedef struct { - float co[3]; - short no[3]; - - /* inserting this to align the 'color' field to a four-byte - * boundary; drastically increases viewport performance on my - * drivers (Gallium/Radeon) --nicholasbishop */ - char pad[2]; - - unsigned char color[3]; -} VertexBufferFormat; - struct GPU_PBVH_Buffers { - /* opengl buffer handles */ - GPUBuffer *vert_buf, *index_buf, *index_buf_fast; - GLenum index_type; + Gwn_IndexBuf *index_buf, *index_buf_fast; + Gwn_VertBuf *vert_buf; - int *baseelemarray; - void **baseindex; + Gwn_Batch *triangles; + Gwn_Batch *triangles_fast; /* mesh pointers in case buffer allocation fails */ const MPoly *mpoly; @@ -995,10 +108,73 @@ struct GPU_PBVH_Buffers { bool show_diffuse_color; bool show_mask; - bool use_matcaps; float diffuse_color[4]; }; +static struct { + uint pos, nor, col; +} g_vbo_id = {0}; + +static void gpu_material_diffuse_get(int UNUSED(nr), float diff[4]) +{ + /* TODO: sculpt diffuse color option not supported in 2.8 yet. */ + diff[0] = 0.8f; + diff[1] = 0.8f; + diff[2] = 0.8f; + diff[3] = 1.0f; +} + +/* Allocates a non-initialized buffer to be sent to GPU. + * Return is false it indicates that the memory map failed. */ +static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, unsigned int vert_ct) +{ + if (buffers->vert_buf == NULL) { + /* Initialize vertex buffer */ + /* match 'VertexBufferFormat' */ + + static Gwn_VertFormat format = {0}; + if (format.attrib_ct == 0) { + g_vbo_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + g_vbo_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + g_vbo_id.col = GWN_vertformat_attr_add(&format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + } +#if 0 + buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_DYNAMIC); + GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct); + } + else if (vert_ct != buffers->vert_buf->vertex_ct) { + GWN_vertbuf_data_resize(buffers->vert_buf, vert_ct); + } +#else + buffers->vert_buf = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC); + } + GWN_vertbuf_data_alloc(buffers->vert_buf, vert_ct); +#endif + return buffers->vert_buf->data != NULL; +} + +static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers) +{ + /* force flushing to the GPU */ + if (buffers->vert_buf->data) { + GWN_vertbuf_use(buffers->vert_buf); + } + + if (buffers->triangles == NULL) { + buffers->triangles = GWN_batch_create( + GWN_PRIM_TRIS, buffers->vert_buf, + /* can be NULL */ + buffers->index_buf); + } + + if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) { + buffers->triangles_fast = GWN_batch_create( + GWN_PRIM_TRIS, buffers->vert_buf, + /* can be NULL */ + buffers->index_buf_fast); + } +} + static float gpu_color_from_mask(float mask) { return 1.0f - mask * 0.75f; @@ -1040,25 +216,20 @@ void GPU_pbvh_mesh_buffers_update( { const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0; const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - VertexBufferFormat *vert_data; - int i; buffers->vmask = vmask; buffers->show_diffuse_color = show_diffuse_color; buffers->show_mask = show_mask; - buffers->use_matcaps = GPU_material_use_matcaps_get(); { int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f}; - if (buffers->use_matcaps) - diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; - else if (show_diffuse_color) { + if (show_diffuse_color) { const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; const MPoly *mp = &buffers->mpoly[lt->poly]; - GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color); + gpu_material_diffuse_get(mp->mat_nr + 1, diffuse_color); } copy_v4_v4(buffers->diffuse_color, diffuse_color); @@ -1067,35 +238,29 @@ void GPU_pbvh_mesh_buffers_update( rgba_float_to_uchar(diffuse_color_ub, diffuse_color); /* Build VBO */ - if (buffers->vert_buf) - GPU_buffer_free(buffers->vert_buf); - buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totelem); - vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY); - - if (vert_data) { + if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) { /* Vertex data is shared if smooth-shaded, but separate * copies are made for flat shading because normals * shouldn't be shared. */ if (buffers->smooth) { - for (i = 0; i < totvert; ++i) { + for (uint i = 0; i < totvert; ++i) { const 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); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no); } - for (i = 0; i < buffers->face_indices_len; i++) { + for (uint i = 0; i < buffers->face_indices_len; i++) { const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; for (uint j = 0; j < 3; j++) { - VertexBufferFormat *out = vert_data + face_vert_indices[i][j]; - + int vidx = face_vert_indices[i][j]; if (vmask && show_mask) { - uint v_index = buffers->mloop[lt->tri[j]].v; - gpu_color_from_mask_copy(vmask[v_index], diffuse_color, out->color); + int v_index = buffers->mloop[lt->tri[j]].v; + uchar color_ub[3]; + gpu_color_from_mask_copy(vmask[v_index], diffuse_color, color_ub); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, color_ub); } else { - copy_v3_v3_uchar(out->color, diffuse_color_ub); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, diffuse_color_ub); } } } @@ -1104,8 +269,9 @@ void GPU_pbvh_mesh_buffers_update( /* calculate normal for each polygon only once */ unsigned int mpoly_prev = UINT_MAX; short no[3]; + int vbo_index = 0; - for (i = 0; i < buffers->face_indices_len; ++i) { + for (uint i = 0; i < buffers->face_indices_len; i++) { const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; const unsigned int vtri[3] = { buffers->mloop[lt->tri[0]].v, @@ -1136,22 +302,17 @@ void GPU_pbvh_mesh_buffers_update( for (uint j = 0; j < 3; j++) { const MVert *v = &mvert[vtri[j]]; - VertexBufferFormat *out = vert_data; - copy_v3_v3(out->co, v->co); - copy_v3_v3_short(out->no, no); - copy_v3_v3_uchar(out->color, color_ub); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub); - vert_data++; + vbo_index++; } } } - GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY); - } - else { - GPU_buffer_free(buffers->vert_buf); - buffers->vert_buf = NULL; + gpu_pbvh_batch_init(buffers); } } @@ -1166,16 +327,20 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( const int face_indices_len) { GPU_PBVH_Buffers *buffers; - unsigned short *tri_data; - int i, j, tottri; + int i, tottri; buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - buffers->index_type = GL_UNSIGNED_SHORT; + + /* smooth or flat for all */ +#if 0 buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH; +#else + /* for DrawManager we dont support mixed smooth/flat */ + buffers->smooth = (mpoly[0].flag & ME_SMOOTH) != 0; +#endif buffers->show_diffuse_color = false; buffers->show_mask = true; - buffers->use_matcaps = false; /* Count the number of visible triangles */ for (i = 0, tottri = 0; i < face_indices_len; ++i) { @@ -1200,35 +365,28 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( * 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); - buffers->is_index_buf_global = false; - } - - if (buffers->index_buf) { /* Fill the triangle buffer */ - tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX); - if (tri_data) { - for (i = 0; i < face_indices_len; ++i) { - const MLoopTri *lt = &looptri[face_indices[i]]; - - /* Skip hidden faces */ - if (paint_is_face_hidden(lt, mvert, mloop)) - continue; - - for (j = 0; j < 3; ++j) { - *tri_data = face_vert_indices[i][j]; - tri_data++; - } - } - GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX); + buffers->index_buf = NULL; + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, INT_MAX); + + for (i = 0; i < face_indices_len; ++i) { + const MLoopTri *lt = &looptri[face_indices[i]]; + + /* Skip hidden faces */ + if (paint_is_face_hidden(lt, mvert, mloop)) + continue; + + GWN_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i])); } - else { - if (!buffers->is_index_buf_global) { - GPU_buffer_free(buffers->index_buf); - } - buffers->index_buf = NULL; - buffers->is_index_buf_global = false; + buffers->index_buf = GWN_indexbuf_build(&elb); + } + else { + if (!buffers->is_index_buf_global) { + GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf); } + buffers->index_buf = NULL; + buffers->is_index_buf_global = false; } buffers->tot_tri = tottri; @@ -1251,61 +409,59 @@ void GPU_pbvh_grid_buffers_update( { const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0; const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - VertexBufferFormat *vert_data; int i, j, k, x, y; buffers->show_diffuse_color = show_diffuse_color; buffers->show_mask = show_mask; - 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) { + if (buffers->index_buf) { const int has_mask = key->has_mask; float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; - if (buffers->use_matcaps) - diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; - else if (show_diffuse_color) { + if (show_diffuse_color) { const DMFlagMat *flags = &grid_flag_mats[grid_indices[0]]; - GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); + gpu_material_diffuse_get(flags->mat_nr + 1, diffuse_color); } copy_v4_v4(buffers->diffuse_color, diffuse_color); - vert_data = GPU_buffer_lock_stream(buffers->vert_buf, GPU_BINDING_ARRAY); - if (vert_data) { + uint vbo_index_offset = 0; + /* Build VBO */ + if (gpu_pbvh_vert_buf_data_set(buffers, totgrid * key->grid_area)) { for (i = 0; i < totgrid; ++i) { - VertexBufferFormat *vd = vert_data; CCGElem *grid = grids[grid_indices[i]]; + int vbo_index = vbo_index_offset; for (y = 0; y < key->grid_size; y++) { for (x = 0; x < key->grid_size; x++) { CCGElem *elem = CCG_grid_elem(key, grid, x, y); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem)); - copy_v3_v3(vd->co, CCG_elem_co(key, elem)); if (buffers->smooth) { - normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem)); + short no_short[3]; + normal_float_to_short_v3(no_short, CCG_elem_no(key, elem)); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); if (has_mask) { + uchar color_ub[3]; if (show_mask) { gpu_color_from_mask_copy(*CCG_elem_mask(key, elem), - diffuse_color, vd->color); + diffuse_color, color_ub); } else { - unit_float_to_uchar_clamp_v3(vd->color, diffuse_color); + unit_float_to_uchar_clamp_v3(color_ub, diffuse_color); } + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub); } } - vd++; + vbo_index += 1; } } 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 */ for (j = 0; j < key->grid_size - 1; j++) { for (k = 0; k < key->grid_size - 1; k++) { CCGElem *elems[4] = { @@ -1322,10 +478,13 @@ void GPU_pbvh_grid_buffers_update( CCG_elem_co(key, elems[2]), CCG_elem_co(key, elems[3])); - vd = vert_data + (j + 1) * key->grid_size + k; - normal_float_to_short_v3(vd->no, fno); + vbo_index = vbo_index_offset + ((j + 1) * key->grid_size + k); + short no_short[3]; + normal_float_to_short_v3(no_short, fno); + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); if (has_mask) { + uchar color_ub[3]; if (show_mask) { gpu_color_from_mask_quad_copy(key, elems[0], @@ -1333,24 +492,21 @@ void GPU_pbvh_grid_buffers_update( elems[2], elems[3], diffuse_color, - vd->color); + color_ub); } else { - unit_float_to_uchar_clamp_v3(vd->color, diffuse_color); + unit_float_to_uchar_clamp_v3(color_ub, diffuse_color); } + GWN_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, color_ub); } } } } - vert_data += key->grid_area; + vbo_index_offset += key->grid_area; } - GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY); - } - else { - GPU_buffer_free(buffers->vert_buf); - buffers->vert_buf = NULL; + gpu_pbvh_batch_init(buffers); } } @@ -1365,57 +521,54 @@ void GPU_pbvh_grid_buffers_update( /* Build the element array buffer of grid indices using either * unsigned shorts or unsigned ints. */ -#define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \ +#define FILL_QUAD_BUFFER(max_vert_, tot_quad_, buffer_) \ { \ - type_ *tri_data; \ int offset = 0; \ int i, j, k; \ - buffer_ = GPU_buffer_alloc(sizeof(type_) * (tot_quad_) * 6); \ + \ + Gwn_IndexBufBuilder elb; \ + GWN_indexbuf_init( \ + &elb, GWN_PRIM_TRIS, tot_quad_ * 2, max_vert_); \ \ /* Fill the buffer */ \ - tri_data = GPU_buffer_lock(buffer_, GPU_BINDING_INDEX); \ - if (tri_data) { \ - for (i = 0; i < totgrid; ++i) { \ - BLI_bitmap *gh = NULL; \ - if (grid_hidden) \ - gh = grid_hidden[(grid_indices)[i]]; \ + for (i = 0; i < totgrid; ++i) { \ + BLI_bitmap *gh = NULL; \ + if (grid_hidden) \ + gh = grid_hidden[(grid_indices)[i]]; \ \ - for (j = 0; j < gridsize - 1; ++j) { \ - for (k = 0; k < gridsize - 1; ++k) { \ - /* Skip hidden grid face */ \ - if (gh && \ - paint_is_grid_face_hidden(gh, \ - gridsize, k, j)) \ - continue; \ - \ - *(tri_data++) = offset + j * gridsize + k + 1; \ - *(tri_data++) = offset + j * gridsize + k; \ - *(tri_data++) = offset + (j + 1) * gridsize + k; \ - \ - *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \ - *(tri_data++) = offset + j * gridsize + k + 1; \ - *(tri_data++) = offset + (j + 1) * gridsize + k; \ - } \ - } \ - \ - offset += gridsize * gridsize; \ + for (j = 0; j < gridsize - 1; ++j) { \ + for (k = 0; k < gridsize - 1; ++k) { \ + /* Skip hidden grid face */ \ + if (gh && paint_is_grid_face_hidden( \ + gh, gridsize, k, j)) \ + { \ + continue; \ + } \ + GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \ + GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k); \ + GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \ + \ + GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k + 1); \ + GWN_indexbuf_add_generic_vert(&elb, offset + j * gridsize + k + 1); \ + GWN_indexbuf_add_generic_vert(&elb, offset + (j + 1) * gridsize + k); \ + } \ } \ - GPU_buffer_unlock(buffer_, GPU_BINDING_INDEX); \ - } \ - else { \ - GPU_buffer_free(buffer_); \ - (buffer_) = NULL; \ + \ + offset += gridsize * gridsize; \ } \ + buffer_ = GWN_indexbuf_build(&elb); \ } (void)0 /* end FILL_QUAD_BUFFER */ -static GPUBuffer *gpu_get_grid_buffer( - int gridsize, GLenum *index_type, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer) +static Gwn_IndexBuf *gpu_get_grid_buffer( + int gridsize, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer, + /* remove this arg when gawain gets base-vertex support! */ + int totgrid) { /* used in the FILL_QUAD_BUFFER macro */ BLI_bitmap * const *grid_hidden = NULL; const int *grid_indices = NULL; - int totgrid = 1; + // int totgrid = 1; GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer; @@ -1423,65 +576,48 @@ static GPUBuffer *gpu_get_grid_buffer( *grid_common_gpu_buffer = gridbuff = MEM_mallocN(sizeof(GridCommonGPUBuffer), __func__); gridbuff->mres_buffer = NULL; gridbuff->mres_prev_gridsize = -1; - gridbuff->mres_prev_index_type = 0; gridbuff->mres_prev_totquad = 0; } /* VBO is already built */ if (gridbuff->mres_buffer && gridbuff->mres_prev_gridsize == gridsize) { - *index_type = gridbuff->mres_prev_index_type; *totquad = gridbuff->mres_prev_totquad; return gridbuff->mres_buffer; } /* we can't reuse old, delete the existing buffer */ else if (gridbuff->mres_buffer) { - GPU_buffer_free(gridbuff->mres_buffer); + GWN_indexbuf_discard(gridbuff->mres_buffer); + gridbuff->mres_buffer = NULL; } /* Build new VBO */ - *totquad = (gridsize - 1) * (gridsize - 1); + *totquad = (gridsize - 1) * (gridsize - 1) * totgrid; + int max_vert = gridsize * gridsize * totgrid; - if (gridsize * gridsize < USHRT_MAX) { - *index_type = GL_UNSIGNED_SHORT; - FILL_QUAD_BUFFER(unsigned short, *totquad, gridbuff->mres_buffer); - } - else { - *index_type = GL_UNSIGNED_INT; - FILL_QUAD_BUFFER(unsigned int, *totquad, gridbuff->mres_buffer); - } + FILL_QUAD_BUFFER(max_vert, *totquad, gridbuff->mres_buffer); gridbuff->mres_prev_gridsize = gridsize; - gridbuff->mres_prev_index_type = *index_type; gridbuff->mres_prev_totquad = *totquad; return gridbuff->mres_buffer; } -#define FILL_FAST_BUFFER(type_) \ +#define FILL_FAST_BUFFER() \ { \ - type_ *buffer; \ - 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; \ - for (i = 0; i < totgrid; i++) { \ - int currentquad = i * 6; \ - buffer[currentquad] = i * gridsize * gridsize + gridsize - 1; \ - buffer[currentquad + 1] = i * gridsize * gridsize; \ - buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \ - buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \ - buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \ - buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \ - } \ - GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \ - } \ - else { \ - GPU_buffer_free(buffers->index_buf_fast); \ - buffers->index_buf_fast = NULL; \ + Gwn_IndexBufBuilder elb; \ + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, 6 * totgrid, INT_MAX); \ + for (int i = 0; i < totgrid; i++) { \ + GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \ + GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize); \ + GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \ + GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - 1); \ + GWN_indexbuf_add_generic_vert(&elb, i * gridsize * gridsize + gridsize - 1); \ + GWN_indexbuf_add_generic_vert(&elb, (i + 1) * gridsize * gridsize - gridsize); \ } \ + buffers->index_buf_fast = GWN_indexbuf_build(&elb); \ } (void)0 GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( - int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key, + int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *UNUSED(key), GridCommonGPUBuffer **grid_common_gpu_buffer) { GPU_PBVH_Buffers *buffers; @@ -1494,7 +630,6 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( buffers->show_diffuse_color = false; buffers->show_mask = true; - buffers->use_matcaps = false; /* Count the number of quads */ totquad = BKE_pbvh_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize); @@ -1504,39 +639,26 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( return buffers; /* create and fill indices of the fast buffer too */ - if (totgrid * gridsize * gridsize < USHRT_MAX) { - FILL_FAST_BUFFER(unsigned short); - } - else { - FILL_FAST_BUFFER(unsigned int); - } + FILL_FAST_BUFFER(); if (totquad == fully_visible_totquad) { buffers->index_buf = gpu_get_grid_buffer( - gridsize, &buffers->index_type, &buffers->tot_quad, grid_common_gpu_buffer); + gridsize, &buffers->tot_quad, grid_common_gpu_buffer, totgrid); buffers->has_hidden = false; buffers->is_index_buf_global = true; } else { + uint max_vert = totgrid * gridsize * gridsize; buffers->tot_quad = totquad; - if (totgrid * gridsize * gridsize < USHRT_MAX) { - buffers->index_type = GL_UNSIGNED_SHORT; - FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf); - } - else { - buffers->index_type = GL_UNSIGNED_INT; - FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf); - } + FILL_QUAD_BUFFER(max_vert, totquad, buffers->index_buf); - buffers->has_hidden = true; + buffers->has_hidden = false; buffers->is_index_buf_global = false; } +#ifdef USE_BASE_ELEM /* Build coord/normal VBO */ - if (buffers->index_buf) - buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area); - if (GLEW_ARB_draw_elements_base_vertex /* 3.2 */) { int i; buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray"); @@ -1547,6 +669,7 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( buffers->baseindex[i] = NULL; } } +#endif return buffers; } @@ -1559,32 +682,44 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( * index '*v_index' in the 'vert_data' array and '*v_index' is * incremented. */ -static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, - VertexBufferFormat *vert_data, - int *v_index, - const float fno[3], - const float *fmask, - const int cd_vert_mask_offset, - const float diffuse_color[4], - const bool show_mask) +static void gpu_bmesh_vert_to_buffer_copy__gwn( + BMVert *v, + Gwn_VertBuf *vert_buf, + int *v_index, + const float fno[3], + const float *fmask, + const int cd_vert_mask_offset, + const float diffuse_color[4], + const bool show_mask) { if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - VertexBufferFormat *vd = &vert_data[*v_index]; /* Set coord, normal, and mask */ - copy_v3_v3(vd->co, v->co); - normal_float_to_short_v3(vd->no, fno ? fno : v->no); + GWN_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co); - float effective_mask; - if (show_mask) { - effective_mask = fmask ? *fmask - : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); - } - else { - effective_mask = 0.0f; + { + short no_short[3]; + normal_float_to_short_v3(no_short, fno ? fno : v->no); + GWN_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short); } - gpu_color_from_mask_copy(effective_mask, diffuse_color, vd->color); + { + uchar color_ub[3]; + float effective_mask; + if (show_mask) { + effective_mask = fmask ? *fmask + : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); + } + else { + effective_mask = 0.0f; + } + + gpu_color_from_mask_copy( + effective_mask, + diffuse_color, + color_ub); + GWN_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, color_ub); + } /* Assign index for use in the triangle index buffer */ /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */ @@ -1643,8 +778,6 @@ void GPU_pbvh_bmesh_buffers_update( { const bool show_diffuse_color = (update_flags & GPU_PBVH_BUFFERS_SHOW_DIFFUSE_COLOR) != 0; const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - VertexBufferFormat *vert_data; - void *tri_data; int tottri, totvert, maxvert = 0; float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; @@ -1653,7 +786,6 @@ void GPU_pbvh_bmesh_buffers_update( buffers->show_diffuse_color = show_diffuse_color; buffers->show_mask = show_mask; - buffers->use_matcaps = GPU_material_use_matcaps_get(); /* Count visible triangles */ tottri = gpu_bmesh_face_visible_count(bm_faces); @@ -1670,27 +802,19 @@ void GPU_pbvh_bmesh_buffers_update( return; } - if (buffers->use_matcaps) - diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0; - else if (show_diffuse_color) { + if (show_diffuse_color) { /* due to dynamic nature of dyntopo, only get first material */ GSetIterator gs_iter; BMFace *f; BLI_gsetIterator_init(&gs_iter, bm_faces); f = BLI_gsetIterator_getKey(&gs_iter); - GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + gpu_material_diffuse_get(f->mat_nr + 1, diffuse_color); } copy_v4_v4(buffers->diffuse_color, diffuse_color); - /* Initialize vertex buffer */ - if (buffers->vert_buf) - GPU_buffer_free(buffers->vert_buf); - buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totvert); - /* Fill vertex buffer */ - vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY); - if (vert_data) { + if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) { int v_index = 0; if (buffers->smooth) { @@ -1701,17 +825,19 @@ void GPU_pbvh_bmesh_buffers_update( bm->elem_index_dirty |= BM_VERT; GSET_ITER (gs_iter, bm_unique_verts) { - gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter), - vert_data, &v_index, NULL, NULL, - cd_vert_mask_offset, diffuse_color, - show_mask); + gpu_bmesh_vert_to_buffer_copy__gwn( + BLI_gsetIterator_getKey(&gs_iter), + buffers->vert_buf, &v_index, NULL, NULL, + cd_vert_mask_offset, diffuse_color, + show_mask); } GSET_ITER (gs_iter, bm_other_verts) { - gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter), - vert_data, &v_index, NULL, NULL, - cd_vert_mask_offset, diffuse_color, - show_mask); + gpu_bmesh_vert_to_buffer_copy__gwn( + BLI_gsetIterator_getKey(&gs_iter), + buffers->vert_buf, &v_index, NULL, NULL, + cd_vert_mask_offset, diffuse_color, + show_mask); } maxvert = v_index; @@ -1741,10 +867,11 @@ void GPU_pbvh_bmesh_buffers_update( fmask /= 3.0f; for (i = 0; i < 3; i++) { - gpu_bmesh_vert_to_buffer_copy(v[i], vert_data, - &v_index, f->no, &fmask, - cd_vert_mask_offset, diffuse_color, - show_mask); + gpu_bmesh_vert_to_buffer_copy__gwn( + v[i], buffers->vert_buf, + &v_index, f->no, &fmask, + cd_vert_mask_offset, diffuse_color, + show_mask); } } } @@ -1752,32 +879,26 @@ void GPU_pbvh_bmesh_buffers_update( buffers->tot_tri = tottri; } - GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY); - /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */ bm->elem_index_dirty |= BM_VERT; } else { /* Memory map failed */ - GPU_buffer_free(buffers->vert_buf); - buffers->vert_buf = NULL; return; } if (buffers->smooth) { - const int use_short = (maxvert < USHRT_MAX); + /* Fill the triangle buffer */ + buffers->index_buf = NULL; + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tottri, maxvert); /* Initialize triangle index buffer */ - if (buffers->index_buf && !buffers->is_index_buf_global) - GPU_buffer_free(buffers->index_buf); buffers->is_index_buf_global = false; - buffers->index_buf = GPU_buffer_alloc((use_short ? - sizeof(unsigned short) : - sizeof(unsigned int)) * 3 * tottri); /* Fill triangle index buffer */ - tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX); - if (tri_data) { + + { GSetIterator gs_iter; GSET_ITER (gs_iter, bm_faces) { @@ -1789,46 +910,30 @@ void GPU_pbvh_bmesh_buffers_update( l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - BMVert *v = l_iter->v; - if (use_short) { - unsigned short *elem = tri_data; - (*elem) = BM_elem_index_get(v); - elem++; - tri_data = elem; - } - else { - unsigned int *elem = tri_data; - (*elem) = BM_elem_index_get(v); - elem++; - tri_data = elem; - } + GWN_indexbuf_add_generic_vert(&elb, BM_elem_index_get(l_iter->v)); } while ((l_iter = l_iter->next) != l_first); } } - GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX); - buffers->tot_tri = tottri; - buffers->index_type = (use_short ? - GL_UNSIGNED_SHORT : - GL_UNSIGNED_INT); - } - else { - /* Memory map failed */ - if (!buffers->is_index_buf_global) { - GPU_buffer_free(buffers->index_buf); + + if (buffers->index_buf == NULL) { + buffers->index_buf = GWN_indexbuf_build(&elb); + } + else { + GWN_indexbuf_build_in_place(&elb, buffers->index_buf); } - buffers->index_buf = NULL; - buffers->is_index_buf_global = false; } } else if (buffers->index_buf) { if (!buffers->is_index_buf_global) { - GPU_buffer_free(buffers->index_buf); + GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf); } buffers->index_buf = NULL; buffers->is_index_buf_global = false; } + + gpu_pbvh_batch_init(buffers); } GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) @@ -1840,172 +945,31 @@ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) buffers->smooth = smooth_shading; buffers->show_diffuse_color = false; buffers->show_mask = true; - buffers->use_matcaps = false; return buffers; } -void GPU_pbvh_buffers_draw( - GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, - bool wireframe, bool fast) +Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast) { - bool do_fast = fast && buffers->index_buf_fast; - /* sets material from the first face, to solve properly face would need to - * be sorted in buckets by materials */ - if (setMaterial) { - if (buffers->face_indices_len) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; - const MPoly *mp = &buffers->mpoly[lt->poly]; - if (!setMaterial(mp->mat_nr + 1, NULL)) - return; - } - else if (buffers->totgrid) { - const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]]; - if (!setMaterial(f->mat_nr + 1, NULL)) - return; - } - else { - if (!setMaterial(1, NULL)) - return; - } - } - - if (buffers->vert_buf) { - char *base = NULL; - char *index_base = NULL; - /* weak inspection of bound options, should not be necessary ideally */ - const int bound_options_old = GPU_basic_shader_bound_options(); - int bound_options_new = 0; - glEnableClientState(GL_VERTEX_ARRAY); - if (!wireframe) { - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - bound_options_new |= GPU_SHADER_USE_COLOR; - } - - GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY); - - if (do_fast) { - GPU_buffer_bind(buffers->index_buf_fast, GPU_BINDING_INDEX); - } - else if (buffers->index_buf) { - GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX); - } - - if (wireframe) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - else { - if ((buffers->smooth == false) && (buffers->face_indices_len == 0)) { - bound_options_new |= GPU_SHADER_FLAT_NORMAL; - } - } - - if (bound_options_new & ~bound_options_old) { - GPU_basic_shader_bind(bound_options_old | bound_options_new); - } - - if (buffers->tot_quad) { - const char *offset = base; - const bool drawall = !(buffers->has_hidden || do_fast); - - if (GLEW_ARB_draw_elements_base_vertex && drawall) { - - glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), - offset + offsetof(VertexBufferFormat, co)); - 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, - buffers->totgrid, &buffers->baseelemarray[buffers->totgrid]); - } - else { - int i, last = drawall ? buffers->totgrid : 1; - - /* we could optimize this to one draw call, but it would need more memory */ - for (i = 0; i < last; i++) { - glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), - offset + offsetof(VertexBufferFormat, co)); - 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); - else - glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base); - - offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat); - } - } - } - else if (buffers->tot_tri) { - int totelem = buffers->tot_tri * 3; - - glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), - (void *)(base + offsetof(VertexBufferFormat, co))); - - 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); - else - glDrawArrays(GL_TRIANGLES, 0, totelem); - } - - if (wireframe) - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - GPU_buffer_unbind(buffers->vert_buf, GPU_BINDING_ARRAY); - if (buffers->index_buf || do_fast) - GPU_buffer_unbind(do_fast ? buffers->index_buf_fast : buffers->index_buf, GPU_BINDING_INDEX); - - glDisableClientState(GL_VERTEX_ARRAY); - if (!wireframe) { - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - } - - if (bound_options_new & ~bound_options_old) { - GPU_basic_shader_bind(bound_options_old); - } - } + return (fast && buffers->triangles_fast) ? + buffers->triangles_fast : buffers->triangles; } -bool GPU_pbvh_buffers_diffuse_changed( - GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color) +bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color) { float diffuse_color[4]; - bool use_matcaps = GPU_material_use_matcaps_get(); if (buffers->show_diffuse_color != show_diffuse_color) return true; - if (buffers->use_matcaps != use_matcaps) - return true; - - if ((buffers->show_diffuse_color == false) || use_matcaps) + if (buffers->show_diffuse_color == false) return false; if (buffers->looptri) { const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; const MPoly *mp = &buffers->mpoly[lt->poly]; - GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color); + gpu_material_diffuse_get(mp->mat_nr + 1, diffuse_color); } else if (buffers->use_bmesh) { /* due to dynamic nature of dyntopo, only get first material */ @@ -2015,7 +979,7 @@ bool GPU_pbvh_buffers_diffuse_changed( BLI_gsetIterator_init(&gs_iter, bm_faces); f = BLI_gsetIterator_getKey(&gs_iter); - GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + gpu_material_diffuse_get(f->mat_nr + 1, diffuse_color); } else { return false; @@ -2024,7 +988,7 @@ bool GPU_pbvh_buffers_diffuse_changed( else { const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]]; - GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); + gpu_material_diffuse_get(flags->mat_nr + 1, diffuse_color); } return !equals_v3v3(diffuse_color, buffers->diffuse_color); @@ -2038,16 +1002,20 @@ bool GPU_pbvh_buffers_mask_changed(GPU_PBVH_Buffers *buffers, bool show_mask) void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers) { if (buffers) { - if (buffers->vert_buf) - GPU_buffer_free(buffers->vert_buf); - if (buffers->index_buf && !buffers->is_index_buf_global) - GPU_buffer_free(buffers->index_buf); - if (buffers->index_buf_fast) - GPU_buffer_free(buffers->index_buf_fast); + GWN_BATCH_DISCARD_SAFE(buffers->triangles); + GWN_BATCH_DISCARD_SAFE(buffers->triangles_fast); + if (!buffers->is_index_buf_global) { + GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + } + GWN_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); + GWN_VERTBUF_DISCARD_SAFE(buffers->vert_buf); + +#ifdef USE_BASE_ELEM if (buffers->baseelemarray) MEM_freeN(buffers->baseelemarray); if (buffers->baseindex) MEM_freeN(buffers->baseindex); +#endif MEM_freeN(buffers); } @@ -2060,7 +1028,7 @@ void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer if (gridbuff) { if (gridbuff->mres_buffer) { BLI_mutex_lock(&buffer_mutex); - gpu_buffer_free_intern(gridbuff->mres_buffer); + GWN_INDEXBUF_DISCARD_SAFE(gridbuff->mres_buffer); BLI_mutex_unlock(&buffer_mutex); } MEM_freeN(gridbuff); @@ -2069,59 +1037,61 @@ void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer } /* debug function, draws the pbvh BB */ -void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf) +void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos) { - const float quads[4][4][3] = { - { - {min[0], min[1], min[2]}, - {max[0], min[1], min[2]}, - {max[0], min[1], max[2]}, - {min[0], min[1], max[2]} - }, + if (leaf) + immUniformColor4f(0.0, 1.0, 0.0, 0.5); + else + immUniformColor4f(1.0, 0.0, 0.0, 0.5); - { - {min[0], min[1], min[2]}, - {min[0], max[1], min[2]}, - {min[0], max[1], max[2]}, - {min[0], min[1], max[2]} - }, + /* TODO(merwin): revisit this after we have mutable VertexBuffers + * could keep a static batch & index buffer, change the VBO contents per draw + */ - { - {max[0], max[1], min[2]}, - {max[0], min[1], min[2]}, - {max[0], min[1], max[2]}, - {max[0], max[1], max[2]} - }, + immBegin(GWN_PRIM_LINES, 24); - { - {max[0], max[1], min[2]}, - {min[0], max[1], min[2]}, - {min[0], max[1], max[2]}, - {max[0], max[1], max[2]} - }, - }; + /* top */ + immVertex3f(pos, min[0], min[1], max[2]); + immVertex3f(pos, min[0], max[1], max[2]); - if (leaf) - glColor4f(0.0, 1.0, 0.0, 0.5); - else - glColor4f(1.0, 0.0, 0.0, 0.5); + immVertex3f(pos, min[0], max[1], max[2]); + immVertex3f(pos, max[0], max[1], max[2]); - glVertexPointer(3, GL_FLOAT, 0, &quads[0][0][0]); - glDrawArrays(GL_QUADS, 0, 16); -} + immVertex3f(pos, max[0], max[1], max[2]); + immVertex3f(pos, max[0], min[1], max[2]); -void GPU_pbvh_BB_draw_init(void) -{ - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_CULL_FACE); - glEnableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glEnable(GL_BLEND); + immVertex3f(pos, max[0], min[1], max[2]); + immVertex3f(pos, min[0], min[1], max[2]); + + /* bottom */ + immVertex3f(pos, min[0], min[1], min[2]); + immVertex3f(pos, min[0], max[1], min[2]); + + immVertex3f(pos, min[0], max[1], min[2]); + immVertex3f(pos, max[0], max[1], min[2]); + + immVertex3f(pos, max[0], max[1], min[2]); + immVertex3f(pos, max[0], min[1], min[2]); + + immVertex3f(pos, max[0], min[1], min[2]); + immVertex3f(pos, min[0], min[1], min[2]); + + /* sides */ + immVertex3f(pos, min[0], min[1], min[2]); + immVertex3f(pos, min[0], min[1], max[2]); + + immVertex3f(pos, min[0], max[1], min[2]); + immVertex3f(pos, min[0], max[1], max[2]); + + immVertex3f(pos, max[0], max[1], min[2]); + immVertex3f(pos, max[0], max[1], max[2]); + + immVertex3f(pos, max[0], min[1], min[2]); + immVertex3f(pos, max[0], min[1], max[2]); + + immEnd(); } -void GPU_pbvh_BB_draw_end(void) +void GPU_pbvh_fix_linking() { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glPopAttrib(); } |