diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 1479 |
1 files changed, 0 insertions, 1479 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c deleted file mode 100644 index 14bbd82c282..00000000000 --- a/source/blender/gpu/intern/gpu_buffers.c +++ /dev/null @@ -1,1479 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2005 Blender Foundation. All rights reserved. */ - -/** \file - * \ingroup gpu - * - * Mesh drawing using OpenGL VBO (Vertex Buffer Objects) - */ - -#include <limits.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_bitmap.h" -#include "BLI_ghash.h" -#include "BLI_math_color.h" -#include "BLI_utildefines.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "BKE_DerivedMesh.h" -#include "BKE_attribute.h" -#include "BKE_ccg.h" -#include "BKE_customdata.h" -#include "BKE_mesh.h" -#include "BKE_paint.h" -#include "BKE_pbvh.h" -#include "BKE_subdiv_ccg.h" - -#include "GPU_batch.h" -#include "GPU_buffers.h" - -#include "DRW_engine.h" - -#include "gpu_private.h" - -#include "bmesh.h" - -struct GPU_PBVH_Buffers { - GPUIndexBuf *index_buf, *index_buf_fast; - GPUIndexBuf *index_lines_buf, *index_lines_buf_fast; - GPUVertBuf *vert_buf; - - GPUBatch *lines; - GPUBatch *lines_fast; - GPUBatch *triangles; - GPUBatch *triangles_fast; - - /* mesh pointers in case buffer allocation fails */ - const MPoly *mpoly; - const MLoop *mloop; - const MLoopTri *looptri; - const MVert *mvert; - - const int *face_indices; - int face_indices_len; - - /* grid pointers */ - CCGKey gridkey; - CCGElem **grids; - const DMFlagMat *grid_flag_mats; - BLI_bitmap *const *grid_hidden; - const int *grid_indices; - int totgrid; - - bool use_bmesh; - bool clear_bmesh_on_flush; - - uint tot_tri, tot_quad; - - short material_index; - - /* The PBVH ensures that either all faces in the node are - * smooth-shaded or all faces are flat-shaded */ - bool smooth; - - bool show_overlay; -}; - -typedef struct GPUAttrRef { - uchar domain, type; - ushort cd_offset; - int layer_idx; -} GPUAttrRef; - -#define MAX_GPU_ATTR 256 - -typedef struct PBVHGPUFormat { - GPUVertFormat format; - uint pos, nor, msk, fset; - uint col[MAX_GPU_ATTR]; - uint uv[MAX_GPU_ATTR]; - int totcol, totuv; - - /* Upload only the active color and UV attributes, - * used for workbench mode. */ - bool active_attrs_only; -} PBVHGPUFormat; - -PBVHGPUFormat *GPU_pbvh_make_format(void) -{ - PBVHGPUFormat *vbo_id = MEM_callocN(sizeof(PBVHGPUFormat), "PBVHGPUFormat"); - - GPU_pbvh_attribute_names_update(PBVH_FACES, vbo_id, NULL, NULL, false); - - return vbo_id; -} - -void GPU_pbvh_free_format(PBVHGPUFormat *vbo_id) -{ - MEM_SAFE_FREE(vbo_id); -} - -static int gpu_pbvh_make_attr_offs(eAttrDomainMask domain_mask, - eCustomDataMask type_mask, - const CustomData *vdata, - const CustomData *edata, - const CustomData *ldata, - const CustomData *pdata, - GPUAttrRef r_cd_attrs[MAX_GPU_ATTR], - bool active_only, - int active_type, - int active_domain, - const CustomDataLayer *active_layer, - const CustomDataLayer *render_layer); - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name PBVH Utils - * \{ */ - -void gpu_pbvh_init() -{ -} - -void gpu_pbvh_exit() -{ - /* Nothing to do. */ -} - -static CustomDataLayer *get_active_layer(const CustomData *cdata, int type) -{ - int idx = CustomData_get_active_layer_index(cdata, type); - return idx != -1 ? cdata->layers + idx : NULL; -} - -static CustomDataLayer *get_render_layer(const CustomData *cdata, int type) -{ - int idx = CustomData_get_render_layer_index(cdata, type); - return idx != -1 ? cdata->layers + idx : NULL; -} - -/* 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(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - uint vert_len) -{ - /* Keep so we can test #GPU_USAGE_DYNAMIC buffer use. - * Not that format initialization match in both blocks. - * Do this to keep braces balanced - otherwise indentation breaks. */ - - if (buffers->vert_buf == NULL) { - /* Initialize vertex buffer (match 'VertexBufferFormat'). */ - buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&vbo_id->format, GPU_USAGE_STATIC); - } - if (GPU_vertbuf_get_data(buffers->vert_buf) == NULL || - GPU_vertbuf_get_vertex_len(buffers->vert_buf) != vert_len) { - /* Allocate buffer if not allocated yet or size changed. */ - GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); - } - - return GPU_vertbuf_get_data(buffers->vert_buf) != NULL; -} - -static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim) -{ - if (buffers->triangles == NULL) { - buffers->triangles = GPU_batch_create(prim, - buffers->vert_buf, - /* can be NULL if buffer is empty */ - buffers->index_buf); - } - - if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) { - buffers->triangles_fast = GPU_batch_create(prim, buffers->vert_buf, buffers->index_buf_fast); - } - - if (buffers->lines == NULL) { - buffers->lines = GPU_batch_create(GPU_PRIM_LINES, - buffers->vert_buf, - /* can be NULL if buffer is empty */ - buffers->index_lines_buf); - } - - if ((buffers->lines_fast == NULL) && buffers->index_lines_buf_fast) { - buffers->lines_fast = GPU_batch_create( - GPU_PRIM_LINES, buffers->vert_buf, buffers->index_lines_buf_fast); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Mesh PBVH - * \{ */ - -static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt, - const MVert *mvert, - const MLoop *mloop, - const int *sculpt_face_sets) -{ - return (!paint_is_face_hidden(lt, mvert, mloop) && sculpt_face_sets && - sculpt_face_sets[lt->poly] > SCULPT_FACE_SET_NONE); -} - -void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - const MVert *mvert, - const CustomData *vdata, - const CustomData *ldata, - const float *vmask, - const int *sculpt_face_sets, - int face_sets_color_seed, - int face_sets_color_default, - int update_flags, - const float (*vert_normals)[3]) -{ - GPUAttrRef vcol_refs[MAX_GPU_ATTR]; - GPUAttrRef cd_uvs[MAX_GPU_ATTR]; - - Mesh me_query; - BKE_id_attribute_copy_domains_temp(ID_ME, vdata, NULL, ldata, NULL, NULL, &me_query.id); - - CustomDataLayer *actcol = BKE_id_attributes_active_color_get(&me_query.id); - eAttrDomain actcol_domain = actcol ? BKE_id_attribute_domain(&me_query.id, actcol) : - ATTR_DOMAIN_AUTO; - - CustomDataLayer *rendercol = BKE_id_attributes_render_color_get(&me_query.id); - - int totcol; - - if (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) { - totcol = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_COLOR, - CD_MASK_COLOR_ALL, - vdata, - NULL, - ldata, - NULL, - vcol_refs, - vbo_id->active_attrs_only, - actcol ? actcol->type : 0, - actcol_domain, - actcol, - rendercol); - } - else { - totcol = 0; - } - - int totuv = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_CORNER, - CD_MASK_MLOOPUV, - NULL, - NULL, - ldata, - NULL, - cd_uvs, - vbo_id->active_attrs_only, - CD_MLOOPUV, - ATTR_DOMAIN_CORNER, - get_active_layer(ldata, CD_MLOOPUV), - get_render_layer(ldata, CD_MLOOPUV)); - - const bool show_mask = vmask && (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - const bool show_face_sets = sculpt_face_sets && - (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0; - bool empty_mask = true; - bool default_face_set = true; - - { - const int totelem = buffers->tot_tri * 3; - - /* Build VBO */ - if (gpu_pbvh_vert_buf_data_set(vbo_id, buffers, totelem)) { - GPUVertBufRaw pos_step = {0}; - GPUVertBufRaw nor_step = {0}; - GPUVertBufRaw msk_step = {0}; - GPUVertBufRaw fset_step = {0}; - GPUVertBufRaw col_step = {0}; - GPUVertBufRaw uv_step = {0}; - - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->pos, &pos_step); - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->nor, &nor_step); - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->msk, &msk_step); - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->fset, &fset_step); - - /* calculate normal for each polygon only once */ - uint mpoly_prev = UINT_MAX; - short no[3] = {0, 0, 0}; - - if (totuv > 0) { - for (int uv_i = 0; uv_i < totuv; uv_i++) { - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->uv[uv_i], &uv_step); - - GPUAttrRef *ref = cd_uvs + uv_i; - CustomDataLayer *layer = ldata->layers + ref->layer_idx; - MLoopUV *muv = layer->data; - - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - - if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) { - continue; - } - - for (uint j = 0; j < 3; j++) { - MLoopUV *muv2 = muv + lt->tri[j]; - - memcpy(GPU_vertbuf_raw_step(&uv_step), muv2->uv, sizeof(muv2->uv)); - } - } - } - } - - for (int col_i = 0; col_i < totcol; col_i++) { - GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, vbo_id->col[col_i], &col_step); - - MPropCol *pcol = NULL; - MLoopCol *mcol = NULL; - - GPUAttrRef *ref = vcol_refs + col_i; - const CustomData *cdata = ref->domain == ATTR_DOMAIN_POINT ? vdata : ldata; - CustomDataLayer *layer = cdata->layers + ref->layer_idx; - - bool color_loops = ref->domain == ATTR_DOMAIN_CORNER; - - if (layer->type == CD_PROP_COLOR) { - pcol = (MPropCol *)layer->data; - } - else { - mcol = (MLoopCol *)layer->data; - } - - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - const uint vtri[3] = { - buffers->mloop[lt->tri[0]].v, - buffers->mloop[lt->tri[1]].v, - buffers->mloop[lt->tri[2]].v, - }; - - if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) { - continue; - } - - for (uint j = 0; j < 3; j++) { - /* Vertex Colors. */ - const uint loop_index = lt->tri[j]; - - ushort scol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - - if (pcol) { - MPropCol *pcol2 = pcol + (color_loops ? loop_index : vtri[j]); - - scol[0] = unit_float_to_ushort_clamp(pcol2->color[0]); - scol[1] = unit_float_to_ushort_clamp(pcol2->color[1]); - scol[2] = unit_float_to_ushort_clamp(pcol2->color[2]); - scol[3] = unit_float_to_ushort_clamp(pcol2->color[3]); - } - else { - const MLoopCol *mcol2 = mcol + (color_loops ? loop_index : vtri[j]); - - scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->r]); - scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->g]); - scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->b]); - scol[3] = unit_float_to_ushort_clamp(mcol2->a * (1.0f / 255.0f)); - } - - memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol)); - } - } - } - - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - const uint vtri[3] = { - buffers->mloop[lt->tri[0]].v, - buffers->mloop[lt->tri[1]].v, - buffers->mloop[lt->tri[2]].v, - }; - - if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) { - continue; - } - - /* Face normal and mask */ - if (lt->poly != mpoly_prev && !buffers->smooth) { - const MPoly *mp = &buffers->mpoly[lt->poly]; - float fno[3]; - BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno); - normal_float_to_short_v3(no, fno); - mpoly_prev = lt->poly; - } - - uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - if (show_face_sets) { - const int fset = abs(sculpt_face_sets[lt->poly]); - /* Skip for the default color Face Set to render it white. */ - if (fset != face_sets_color_default) { - BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); - default_face_set = false; - } - } - - float fmask = 0.0f; - uchar cmask = 0; - if (show_mask && !buffers->smooth) { - fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f; - cmask = (uchar)(fmask * 255); - } - - for (uint j = 0; j < 3; j++) { - const MVert *v = &mvert[vtri[j]]; - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co); - - if (buffers->smooth) { - normal_float_to_short_v3(no, vert_normals[vtri[j]]); - } - copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no); - - if (show_mask && buffers->smooth) { - cmask = (uchar)(vmask[vtri[j]] * 255); - } - - *(uchar *)GPU_vertbuf_raw_step(&msk_step) = cmask; - empty_mask = empty_mask && (cmask == 0); - /* Face Sets. */ - memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar[3])); - } - } - } - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); - } - - /* Get material index from the first face of this buffer. */ - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]]; - const MPoly *mp = &buffers->mpoly[lt->poly]; - buffers->material_index = mp->mat_nr; - - buffers->show_overlay = !empty_mask || !default_face_set; - buffers->mvert = mvert; -} - -GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const MPoly *mpoly, - const MLoop *mloop, - const MLoopTri *looptri, - const MVert *mvert, - const int *face_indices, - const int *sculpt_face_sets, - const int face_indices_len, - const struct Mesh *mesh) -{ - GPU_PBVH_Buffers *buffers; - int i, tottri; - int tot_real_edges = 0; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - - /* smooth or flat for all */ - buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH; - - buffers->show_overlay = false; - - /* Count the number of visible triangles */ - for (i = 0, tottri = 0; i < face_indices_len; i++) { - const MLoopTri *lt = &looptri[face_indices[i]]; - if (gpu_pbvh_is_looptri_visible(lt, mvert, mloop, sculpt_face_sets)) { - int r_edges[3]; - BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges); - for (int j = 0; j < 3; j++) { - if (r_edges[j] != -1) { - tot_real_edges++; - } - } - tottri++; - } - } - - if (tottri == 0) { - buffers->tot_tri = 0; - - buffers->mpoly = mpoly; - buffers->mloop = mloop; - buffers->looptri = looptri; - buffers->face_indices = face_indices; - buffers->face_indices_len = 0; - - return buffers; - } - - /* Fill the only the line buffer. */ - GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tot_real_edges, INT_MAX); - int vert_idx = 0; - - for (i = 0; i < face_indices_len; i++) { - const MLoopTri *lt = &looptri[face_indices[i]]; - - /* Skip hidden faces */ - if (!gpu_pbvh_is_looptri_visible(lt, mvert, mloop, sculpt_face_sets)) { - continue; - } - - int r_edges[3]; - BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges); - if (r_edges[0] != -1) { - GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 0, vert_idx * 3 + 1); - } - if (r_edges[1] != -1) { - GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 1, vert_idx * 3 + 2); - } - if (r_edges[2] != -1) { - GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 2, vert_idx * 3 + 0); - } - - vert_idx++; - } - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - - buffers->tot_tri = tottri; - - buffers->mpoly = mpoly; - buffers->mloop = mloop; - buffers->looptri = looptri; - - buffers->face_indices = face_indices; - buffers->face_indices_len = face_indices_len; - - return buffers; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Grid PBVH - * \{ */ - -static void gpu_pbvh_grid_fill_index_buffers(GPU_PBVH_Buffers *buffers, - SubdivCCG *UNUSED(subdiv_ccg), - const int *UNUSED(face_sets), - const int *grid_indices, - uint visible_quad_len, - int totgrid, - int gridsize) -{ - GPUIndexBufBuilder elb, elb_lines; - GPUIndexBufBuilder elb_fast, elb_lines_fast; - - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * visible_quad_len, INT_MAX); - GPU_indexbuf_init(&elb_fast, GPU_PRIM_TRIS, 2 * totgrid, INT_MAX); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, 2 * totgrid * gridsize * (gridsize - 1), INT_MAX); - GPU_indexbuf_init(&elb_lines_fast, GPU_PRIM_LINES, 4 * totgrid, INT_MAX); - - if (buffers->smooth) { - uint offset = 0; - const uint grid_vert_len = gridsize * gridsize; - for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { - uint v0, v1, v2, v3; - bool grid_visible = false; - - BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; - - for (int j = 0; j < gridsize - 1; j++) { - for (int k = 0; k < gridsize - 1; k++) { - /* Skip hidden grid face */ - if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) { - continue; - } - /* Indices in a Clockwise QUAD disposition. */ - v0 = offset + j * gridsize + k; - v1 = v0 + 1; - v2 = v1 + gridsize; - v3 = v2 - 1; - - GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); - - if (j + 2 == gridsize) { - GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); - } - grid_visible = true; - } - - if (grid_visible) { - GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); - } - } - - if (grid_visible) { - /* Grid corners */ - v0 = offset; - v1 = offset + gridsize - 1; - v2 = offset + grid_vert_len - 1; - v3 = offset + grid_vert_len - gridsize; - - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); - } - } - } - else { - uint offset = 0; - const uint grid_vert_len = square_uint(gridsize - 1) * 4; - for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { - bool grid_visible = false; - BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; - - uint v0, v1, v2, v3; - for (int j = 0; j < gridsize - 1; j++) { - for (int k = 0; k < gridsize - 1; k++) { - /* Skip hidden grid face */ - if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) { - continue; - } - /* VBO data are in a Clockwise QUAD disposition. */ - v0 = offset + (j * (gridsize - 1) + k) * 4; - v1 = v0 + 1; - v2 = v0 + 2; - v3 = v0 + 3; - - GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); - - if (j + 2 == gridsize) { - GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); - } - grid_visible = true; - } - - if (grid_visible) { - GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); - } - } - - if (grid_visible) { - /* Grid corners */ - v0 = offset; - v1 = offset + (gridsize - 1) * 4 - 3; - v2 = offset + grid_vert_len - 2; - v3 = offset + grid_vert_len - (gridsize - 1) * 4 + 3; - - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); - } - } - } - - buffers->index_buf = GPU_indexbuf_build(&elb); - buffers->index_buf_fast = GPU_indexbuf_build(&elb_fast); - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - buffers->index_lines_buf_fast = GPU_indexbuf_build(&elb_lines_fast); -} - -void GPU_pbvh_grid_buffers_update_free(GPU_PBVH_Buffers *buffers, - const struct DMFlagMat *grid_flag_mats, - const int *grid_indices) -{ - const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; - - if (buffers->smooth != smooth) { - buffers->smooth = smooth; - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); - } -} - -void GPU_pbvh_grid_buffers_update(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - SubdivCCG *subdiv_ccg, - CCGElem **grids, - const struct DMFlagMat *grid_flag_mats, - int *grid_indices, - int totgrid, - const int *sculpt_face_sets, - const int face_sets_color_seed, - const int face_sets_color_default, - const struct CCGKey *key, - const int update_flags) -{ - const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0; - const bool show_face_sets = sculpt_face_sets && - (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0; - bool empty_mask = true; - bool default_face_set = true; - - int i, j, k, x, y; - - /* Build VBO */ - const int has_mask = key->has_mask; - - uint vert_per_grid = (buffers->smooth) ? key->grid_area : (square_i(key->grid_size - 1) * 4); - uint vert_count = totgrid * vert_per_grid; - - if (buffers->index_buf == NULL) { - uint visible_quad_len = BKE_pbvh_count_grid_quads( - (BLI_bitmap **)buffers->grid_hidden, grid_indices, totgrid, key->grid_size); - - /* totally hidden node, return here to avoid BufferData with zero below. */ - if (visible_quad_len == 0) { - return; - } - - gpu_pbvh_grid_fill_index_buffers(buffers, - subdiv_ccg, - sculpt_face_sets, - grid_indices, - visible_quad_len, - totgrid, - key->grid_size); - } - - uint vbo_index_offset = 0; - /* Build VBO */ - if (gpu_pbvh_vert_buf_data_set(vbo_id, buffers, vert_count)) { - GPUIndexBufBuilder elb_lines; - - if (buffers->index_lines_buf == NULL) { - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, totgrid * key->grid_area * 2, vert_count); - } - - for (i = 0; i < totgrid; i++) { - const int grid_index = grid_indices[i]; - CCGElem *grid = grids[grid_index]; - int vbo_index = vbo_index_offset; - - uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - - if (show_face_sets && subdiv_ccg && sculpt_face_sets) { - const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, grid_index); - - const int fset = abs(sculpt_face_sets[face_index]); - /* Skip for the default color Face Set to render it white. */ - if (fset != face_sets_color_default) { - BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); - default_face_set = false; - } - } - - if (buffers->smooth) { - 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); - GPU_vertbuf_attr_set( - buffers->vert_buf, vbo_id->pos, vbo_index, CCG_elem_co(key, elem)); - - short no_short[3]; - normal_float_to_short_v3(no_short, CCG_elem_no(key, elem)); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index, no_short); - - if (has_mask && show_mask) { - float fmask = *CCG_elem_mask(key, elem); - uchar cmask = (uchar)(fmask * 255); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index, &cmask); - empty_mask = empty_mask && (cmask == 0); - } - - if (show_vcol) { - const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index, &vcol); - } - - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index, &face_set_color); - - vbo_index += 1; - } - } - vbo_index_offset += key->grid_area; - } - else { - for (j = 0; j < key->grid_size - 1; j++) { - for (k = 0; k < key->grid_size - 1; k++) { - CCGElem *elems[4] = { - CCG_grid_elem(key, grid, k, j), - CCG_grid_elem(key, grid, k + 1, j), - CCG_grid_elem(key, grid, k + 1, j + 1), - CCG_grid_elem(key, grid, k, j + 1), - }; - float *co[4] = { - CCG_elem_co(key, elems[0]), - CCG_elem_co(key, elems[1]), - CCG_elem_co(key, elems[2]), - CCG_elem_co(key, elems[3]), - }; - - float fno[3]; - short no_short[3]; - /* NOTE: Clockwise indices ordering, that's why we invert order here. */ - normal_quad_v3(fno, co[3], co[2], co[1], co[0]); - normal_float_to_short_v3(no_short, fno); - - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 0, co[0]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 0, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 1, co[1]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 1, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 2, co[2]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 2, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->pos, vbo_index + 3, co[3]); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->nor, vbo_index + 3, no_short); - - if (has_mask && show_mask) { - float fmask = (*CCG_elem_mask(key, elems[0]) + *CCG_elem_mask(key, elems[1]) + - *CCG_elem_mask(key, elems[2]) + *CCG_elem_mask(key, elems[3])) * - 0.25f; - uchar cmask = (uchar)(fmask * 255); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 0, &cmask); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 1, &cmask); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 2, &cmask); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->msk, vbo_index + 3, &cmask); - empty_mask = empty_mask && (cmask == 0); - } - - const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 0, &vcol); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 1, &vcol); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 2, &vcol); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->col[0], vbo_index + 3, &vcol); - - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 0, &face_set_color); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 1, &face_set_color); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 2, &face_set_color); - GPU_vertbuf_attr_set(buffers->vert_buf, vbo_id->fset, vbo_index + 3, &face_set_color); - - vbo_index += 4; - } - } - vbo_index_offset += square_i(key->grid_size - 1) * 4; - } - } - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); - } - - /* Get material index from the first face of this buffer. */ - buffers->material_index = grid_flag_mats[grid_indices[0]].mat_nr; - - buffers->grids = grids; - buffers->grid_indices = grid_indices; - buffers->totgrid = totgrid; - buffers->grid_flag_mats = grid_flag_mats; - buffers->gridkey = *key; - buffers->show_overlay = !empty_mask || !default_face_set; -} - -GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hidden, bool smooth) -{ - GPU_PBVH_Buffers *buffers; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - buffers->grid_hidden = grid_hidden; - buffers->totgrid = totgrid; - buffers->smooth = smooth; - - buffers->show_overlay = false; - - return buffers; -} - -#undef FILL_QUAD_BUFFER - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name BMesh PBVH - * \{ */ - -/* Output a BMVert into a VertexBufferFormat array at v_index. */ -static void gpu_bmesh_vert_to_buffer_copy(PBVHGPUFormat *vbo_id, - BMVert *v, - GPUVertBuf *vert_buf, - int v_index, - const float fno[3], - const float *fmask, - const int cd_vert_mask_offset, - const bool show_mask, - const bool show_vcol, - bool *empty_mask) -{ - /* Vertex should always be visible if it's used by a visible face. */ - BLI_assert(!BM_elem_flag_test(v, BM_ELEM_HIDDEN)); - - /* Set coord, normal, and mask */ - GPU_vertbuf_attr_set(vert_buf, vbo_id->pos, v_index, v->co); - - short no_short[3]; - normal_float_to_short_v3(no_short, fno ? fno : v->no); - GPU_vertbuf_attr_set(vert_buf, vbo_id->nor, v_index, no_short); - - if (show_mask) { - float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); - uchar cmask = (uchar)(effective_mask * 255); - GPU_vertbuf_attr_set(vert_buf, vbo_id->msk, v_index, &cmask); - *empty_mask = *empty_mask && (cmask == 0); - } - - if (show_vcol) { - const ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; - GPU_vertbuf_attr_set(vert_buf, vbo_id->col[0], v_index, &vcol); - } - - /* Add default face sets color to avoid artifacts. */ - const uchar face_set[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; - GPU_vertbuf_attr_set(vert_buf, vbo_id->fset, v_index, &face_set); -} - -/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */ -static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts, GSet *bm_other_verts) -{ - GSetIterator gs_iter; - int totvert = 0; - - GSET_ITER (gs_iter, bm_unique_verts) { - BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - totvert++; - } - } - GSET_ITER (gs_iter, bm_other_verts) { - BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - totvert++; - } - } - - return totvert; -} - -/* Return the total number of visible faces */ -static int gpu_bmesh_face_visible_count(GSet *bm_faces) -{ - GSetIterator gh_iter; - int totface = 0; - - GSET_ITER (gh_iter, bm_faces) { - BMFace *f = BLI_gsetIterator_getKey(&gh_iter); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - totface++; - } - } - - return totface; -} - -void GPU_pbvh_bmesh_buffers_update_free(GPU_PBVH_Buffers *buffers) -{ - if (buffers->smooth) { - /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */ - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - } - else { - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - } -} - -void GPU_pbvh_bmesh_buffers_update(PBVHGPUFormat *vbo_id, - GPU_PBVH_Buffers *buffers, - BMesh *bm, - GSet *bm_faces, - GSet *bm_unique_verts, - GSet *bm_other_verts, - const int update_flags) -{ - const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0; - int tottri, totvert; - bool empty_mask = true; - BMFace *f = NULL; - - /* Count visible triangles */ - tottri = gpu_bmesh_face_visible_count(bm_faces); - - if (buffers->smooth) { - /* Count visible vertices */ - totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts); - } - else { - totvert = tottri * 3; - } - - if (!tottri) { - if (BLI_gset_len(bm_faces) != 0) { - /* Node is just hidden. */ - } - else { - buffers->clear_bmesh_on_flush = true; - } - buffers->tot_tri = 0; - return; - } - - /* TODO: make mask layer optional for bmesh buffer. */ - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - - /* Fill vertex buffer */ - if (!gpu_pbvh_vert_buf_data_set(vbo_id, buffers, totvert)) { - /* Memory map failed */ - return; - } - - int v_index = 0; - - if (buffers->smooth) { - /* Fill the vertex and triangle buffer in one pass over faces. */ - GPUIndexBufBuilder elb, elb_lines; - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, totvert); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert); - - GHash *bm_vert_to_index = BLI_ghash_int_new_ex("bm_vert_to_index", totvert); - - GSetIterator gs_iter; - GSET_ITER (gs_iter, bm_faces) { - f = BLI_gsetIterator_getKey(&gs_iter); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; - BM_face_as_array_vert_tri(f, v); - - uint idx[3]; - for (int i = 0; i < 3; i++) { - void **idx_p; - if (!BLI_ghash_ensure_p(bm_vert_to_index, v[i], &idx_p)) { - /* Add vertex to the vertex buffer each time a new one is encountered */ - *idx_p = POINTER_FROM_UINT(v_index); - - gpu_bmesh_vert_to_buffer_copy(vbo_id, - v[i], - buffers->vert_buf, - v_index, - NULL, - NULL, - cd_vert_mask_offset, - show_mask, - show_vcol, - &empty_mask); - - idx[i] = v_index; - v_index++; - } - else { - /* Vertex already in the vertex buffer, just get the index. */ - idx[i] = POINTER_AS_UINT(*idx_p); - } - } - - GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); - - GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]); - } - } - - BLI_ghash_free(bm_vert_to_index, NULL, NULL); - - buffers->tot_tri = tottri; - if (buffers->index_buf == NULL) { - buffers->index_buf = GPU_indexbuf_build(&elb); - } - else { - GPU_indexbuf_build_in_place(&elb, buffers->index_buf); - } - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - } - else { - GSetIterator gs_iter; - - GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3); - - GSET_ITER (gs_iter, bm_faces) { - f = BLI_gsetIterator_getKey(&gs_iter); - - BLI_assert(f->len == 3); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; - float fmask = 0.0f; - int i; - - BM_face_as_array_vert_tri(f, v); - - /* Average mask value */ - for (i = 0; i < 3; i++) { - fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset); - } - fmask /= 3.0f; - - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0); - - for (i = 0; i < 3; i++) { - gpu_bmesh_vert_to_buffer_copy(vbo_id, - v[i], - buffers->vert_buf, - v_index++, - f->no, - &fmask, - cd_vert_mask_offset, - show_mask, - show_vcol, - &empty_mask); - } - } - } - - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - buffers->tot_tri = tottri; - } - - /* Get material index from the last face we iterated on. */ - buffers->material_index = (f) ? f->mat_nr : 0; - - buffers->show_overlay = !empty_mask; - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Generic - * \{ */ - -GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) -{ - GPU_PBVH_Buffers *buffers; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - buffers->use_bmesh = true; - buffers->smooth = smooth_shading; - buffers->show_overlay = true; - - return buffers; -} - -/** - * Builds a list of attributes from a set of domains and a set of - * customdata types. - * - * \param active_only: Returns only one item, a #GPUAttrRef to active_layer. - * \param active_layer: #CustomDataLayer to use for the active layer. - * \param active_layer: #CustomDataLayer to use for the render layer. - */ -static int gpu_pbvh_make_attr_offs(eAttrDomainMask domain_mask, - eCustomDataMask type_mask, - const CustomData *vdata, - const CustomData *edata, - const CustomData *ldata, - const CustomData *pdata, - GPUAttrRef r_cd_attrs[MAX_GPU_ATTR], - bool active_only, - int active_type, - int active_domain, - const CustomDataLayer *active_layer, - const CustomDataLayer *render_layer) -{ - const CustomData *cdata_active = active_domain == ATTR_DOMAIN_POINT ? vdata : ldata; - - if (!cdata_active) { - return 0; - } - - if (active_only) { - int idx = active_layer ? active_layer - cdata_active->layers : -1; - - if (idx >= 0 && idx < cdata_active->totlayer) { - r_cd_attrs[0].cd_offset = cdata_active->layers[idx].offset; - r_cd_attrs[0].domain = active_domain; - r_cd_attrs[0].type = active_type; - r_cd_attrs[0].layer_idx = idx; - - return 1; - } - - return 0; - } - - const CustomData *datas[4] = {vdata, edata, pdata, ldata}; - - int count = 0; - for (eAttrDomain domain = 0; domain < 4; domain++) { - const CustomData *cdata = datas[domain]; - - if (!cdata || !((1 << domain) & domain_mask)) { - continue; - } - - CustomDataLayer *cl = cdata->layers; - - for (int i = 0; count < MAX_GPU_ATTR && i < cdata->totlayer; i++, cl++) { - if ((CD_TYPE_AS_MASK(cl->type) & type_mask) && !(cl->flag & CD_FLAG_TEMPORARY)) { - GPUAttrRef *ref = r_cd_attrs + count; - - ref->cd_offset = cl->offset; - ref->type = cl->type; - ref->layer_idx = i; - ref->domain = domain; - - count++; - } - } - } - - /* ensure render layer is last - draw cache code seems to need this - */ - - for (int i = 0; i < count; i++) { - GPUAttrRef *ref = r_cd_attrs + i; - const CustomData *cdata = datas[ref->domain]; - - if (cdata->layers + ref->layer_idx == render_layer) { - SWAP(GPUAttrRef, r_cd_attrs[i], r_cd_attrs[count - 1]); - break; - } - } - - return count; -} - -static bool gpu_pbvh_format_equals(PBVHGPUFormat *a, PBVHGPUFormat *b) -{ - bool bad = false; - - bad |= a->active_attrs_only != b->active_attrs_only; - - bad |= a->pos != b->pos; - bad |= a->fset != b->fset; - bad |= a->msk != b->msk; - bad |= a->nor != b->nor; - - for (int i = 0; i < MIN2(a->totuv, b->totuv); i++) { - bad |= a->uv[i] != b->uv[i]; - } - - for (int i = 0; i < MIN2(a->totcol, b->totcol); i++) { - bad |= a->col[i] != b->col[i]; - } - - bad |= a->totuv != b->totuv; - bad |= a->totcol != b->totcol; - - return !bad; -} - -bool GPU_pbvh_attribute_names_update(PBVHType pbvh_type, - PBVHGPUFormat *vbo_id, - const CustomData *vdata, - const CustomData *ldata, - bool active_attrs_only) -{ - const bool active_only = active_attrs_only; - PBVHGPUFormat old_format = *vbo_id; - - GPU_vertformat_clear(&vbo_id->format); - - vbo_id->active_attrs_only = active_attrs_only; - - if (vbo_id->format.attr_len == 0) { - vbo_id->pos = GPU_vertformat_attr_add( - &vbo_id->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - vbo_id->nor = GPU_vertformat_attr_add( - &vbo_id->format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - - /* TODO: Do not allocate these `.msk` and `.col` when they are not used. */ - vbo_id->msk = GPU_vertformat_attr_add( - &vbo_id->format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); - - vbo_id->totcol = 0; - if (pbvh_type == PBVH_FACES) { - int ci = 0; - - Mesh me_query; - - BKE_id_attribute_copy_domains_temp(ID_ME, vdata, NULL, ldata, NULL, NULL, &me_query.id); - - CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me_query.id); - CustomDataLayer *render_color_layer = BKE_id_attributes_render_color_get(&me_query.id); - eAttrDomain active_color_domain = active_color_layer ? - BKE_id_attribute_domain(&me_query.id, - active_color_layer) : - ATTR_DOMAIN_NUM; - - GPUAttrRef vcol_layers[MAX_GPU_ATTR]; - int totlayer = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_COLOR, - CD_MASK_COLOR_ALL, - vdata, - NULL, - ldata, - NULL, - vcol_layers, - active_only, - active_color_layer ? active_color_layer->type : -1, - active_color_domain, - active_color_layer, - render_color_layer); - - for (int i = 0; i < totlayer; i++) { - GPUAttrRef *ref = vcol_layers + i; - const CustomData *cdata = ref->domain == ATTR_DOMAIN_POINT ? vdata : ldata; - - const CustomDataLayer *layer = cdata->layers + ref->layer_idx; - - if (vbo_id->totcol < MAX_GPU_ATTR) { - vbo_id->col[ci++] = GPU_vertformat_attr_add( - &vbo_id->format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - vbo_id->totcol++; - - bool is_render = render_color_layer == layer; - bool is_active = active_color_layer == layer; - - DRW_cdlayer_attr_aliases_add(&vbo_id->format, "c", cdata, layer, is_render, is_active); - } - } - } - - /* ensure at least one vertex color layer */ - if (vbo_id->totcol == 0) { - vbo_id->col[0] = GPU_vertformat_attr_add( - &vbo_id->format, "c", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - vbo_id->totcol = 1; - - GPU_vertformat_alias_add(&vbo_id->format, "ac"); - } - - vbo_id->fset = GPU_vertformat_attr_add( - &vbo_id->format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - - vbo_id->totuv = 0; - if (pbvh_type == PBVH_FACES && ldata && CustomData_has_layer(ldata, CD_MLOOPUV)) { - GPUAttrRef uv_layers[MAX_GPU_ATTR]; - CustomDataLayer *active = NULL, *render = NULL; - - active = get_active_layer(ldata, CD_MLOOPUV); - render = get_render_layer(ldata, CD_MLOOPUV); - - int totlayer = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_CORNER, - CD_MASK_MLOOPUV, - NULL, - NULL, - ldata, - NULL, - uv_layers, - active_only, - CD_MLOOPUV, - ATTR_DOMAIN_CORNER, - active, - render); - - vbo_id->totuv = totlayer; - - for (int i = 0; i < totlayer; i++) { - GPUAttrRef *ref = uv_layers + i; - - vbo_id->uv[i] = GPU_vertformat_attr_add( - &vbo_id->format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - CustomDataLayer *cl = ldata->layers + ref->layer_idx; - bool is_active = ref->layer_idx == CustomData_get_active_layer_index(ldata, CD_MLOOPUV); - - DRW_cdlayer_attr_aliases_add(&vbo_id->format, "u", ldata, cl, cl == render, is_active); - - /* Apparently the render attribute is 'a' while active is 'au', - * at least going by the draw cache extractor code. - */ - if (cl == render) { - GPU_vertformat_alias_add(&vbo_id->format, "a"); - } - } - } - } - - if (!gpu_pbvh_format_equals(&old_format, vbo_id)) { - return true; - } - - return false; -} - -GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool wires) -{ - if (wires) { - return (fast && buffers->lines_fast) ? buffers->lines_fast : buffers->lines; - } - - return (fast && buffers->triangles_fast) ? buffers->triangles_fast : buffers->triangles; -} - -bool GPU_pbvh_buffers_has_overlays(GPU_PBVH_Buffers *buffers) -{ - return buffers->show_overlay; -} - -short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers) -{ - return buffers->material_index; -} - -static void gpu_pbvh_buffers_clear(GPU_PBVH_Buffers *buffers) -{ - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); -} - -void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers) -{ - /* Free empty bmesh node buffers. */ - if (buffers->clear_bmesh_on_flush) { - gpu_pbvh_buffers_clear(buffers); - buffers->clear_bmesh_on_flush = false; - } - - /* Force flushing to the GPU. */ - if (buffers->vert_buf && GPU_vertbuf_get_data(buffers->vert_buf)) { - GPU_vertbuf_use(buffers->vert_buf); - } -} - -void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers) -{ - if (buffers) { - gpu_pbvh_buffers_clear(buffers); - MEM_freeN(buffers); - } -} - -/** \} */ |