diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 958 |
1 files changed, 23 insertions, 935 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index d2a18684e27..bbee252cd20 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -58,52 +58,6 @@ #include "bmesh.h" -/* TODO: gawain support for baseelemarray */ -// #define USE_BASE_ELEM - -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 */ @@ -113,834 +67,6 @@ typedef struct GridCommonGPUBuffer { 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 */ @@ -982,7 +108,6 @@ struct GPU_PBVH_Buffers { bool show_diffuse_color; bool show_mask; - bool use_matcaps; float diffuse_color[4]; }; @@ -990,6 +115,15 @@ 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) @@ -1086,19 +220,16 @@ void GPU_pbvh_mesh_buffers_update( 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); @@ -1210,7 +341,6 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( 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) { @@ -1283,7 +413,6 @@ void GPU_pbvh_grid_buffers_update( 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 */ @@ -1291,13 +420,10 @@ void GPU_pbvh_grid_buffers_update( 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); @@ -1504,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); @@ -1661,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); @@ -1678,15 +802,13 @@ 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); @@ -1823,44 +945,10 @@ 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) -{ - UNUSED_VARS(wireframe, fast, setMaterial); - bool do_fast = fast && buffers->triangles_fast; - Gwn_Batch *triangles = do_fast ? buffers->triangles_fast : buffers->triangles; - - if (triangles) { - - /* Simple Shader: use when drawing without the draw-manager (old 2.7x viewport) */ - if (triangles->interface == NULL) { - GPUBuiltinShader shader_id = - buffers->smooth ? GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR : GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR; - GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); - - GWN_batch_program_set( - triangles, - GPU_shader_get_program(shader), GPU_shader_get_interface(shader)); - - static float light[3] = {-0.3f, 0.5f, 1.0f}; - static float alpha = 1.0f; - static float world_light = 1.0f; - - GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "light"), 3, 1, light); - GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "alpha"), 1, 1, &alpha); - GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "global"), 1, 1, &world_light); - - } - GWN_batch_draw(triangles); - } -} - Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast) { return (fast && buffers->triangles_fast) ? @@ -1870,22 +958,18 @@ Gwn_Batch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast) 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 */ @@ -1895,7 +979,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, 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; @@ -1904,7 +988,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, 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); @@ -2007,3 +1091,7 @@ void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos) immEnd(); } + +void GPU_pbvh_fix_linking() +{ +} |