Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c185
1 files changed, 146 insertions, 39 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 62843f0905f..8b4e16c76ff 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -69,6 +69,34 @@ typedef enum {
GPU_BUFFER_ELEMENT_STATE = (1 << 5),
} GPUBufferState;
+typedef struct {
+ GPUBufferCopyFunc copy;
+ GLenum gl_buffer_type;
+ int vector_size;
+} GPUBufferTypeSettings;
+
+static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+static void GPU_buffer_copy_facemap(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *user);
+
+static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
+
+const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
+ {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
+ {GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
+ {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
+ {GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
+ {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
+ {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
+ {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
+ {GPU_buffer_copy_facemap, GL_ELEMENT_ARRAY_BUFFER_ARB, 3}
+};
+
#define MAX_GPU_ATTRIB_DATA 32
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
@@ -505,7 +533,7 @@ static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int to
/* see GPUDrawObject's structure definition for a description of the
* data being initialized here */
-GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
+static GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
{
GPUDrawObject *gdo;
MFace *mface;
@@ -572,8 +600,14 @@ void GPU_drawobject_free(DerivedMesh *dm)
return;
MEM_freeN(gdo->materials);
- MEM_freeN(gdo->triangle_to_mface);
- MEM_freeN(gdo->vert_points);
+ if (gdo->triangle_to_mface)
+ MEM_freeN(gdo->triangle_to_mface);
+ if (gdo->vert_points)
+ MEM_freeN(gdo->vert_points);
+ if (gdo->facemap_count)
+ MEM_freeN(gdo->facemap_count);
+ if (gdo->facemap_start)
+ MEM_freeN(gdo->facemap_start);
#ifdef USE_GPU_POINT_LINK
MEM_freeN(gdo->vert_points_mem);
#endif
@@ -584,6 +618,7 @@ void GPU_drawobject_free(DerivedMesh *dm)
GPU_buffer_free(gdo->colors);
GPU_buffer_free(gdo->edges);
GPU_buffer_free(gdo->uvedges);
+ GPU_buffer_free(gdo->facemapindices);
MEM_freeN(gdo);
dm->drawObject = NULL;
@@ -609,8 +644,7 @@ typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
int *mat_orig_to_new, void *user_data);
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
- int vector_size, int size, GLenum target,
- void *user, GPUBufferCopyFunc copy_f)
+ int type, void *user)
{
GPUBufferPool *pool;
GPUBuffer *buffer;
@@ -618,6 +652,10 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
int *mat_orig_to_new;
int *cur_index_per_mat;
int i;
+ const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type];
+ GLenum target = ts->gl_buffer_type;
+ int vector_size = ts->vector_size;
+ int size = gpu_buffer_size_from_type(dm, type);
bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
GLboolean uploaded;
@@ -674,7 +712,10 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
uploaded = GL_FALSE;
/* attempt to upload the data to the VBO */
while (uploaded == GL_FALSE) {
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ if (dm->copy_gpu_data)
+ dm->copy_gpu_data(dm, type, varray, cur_index_per_mat, mat_orig_to_new, user);
+ else
+ ts->copy(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
/* glUnmapBuffer returns GL_FALSE if
* the data store is corrupted; retry
* in that case */
@@ -691,7 +732,10 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
if (buffer) {
varray = buffer->pointer;
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ if (dm->copy_gpu_data)
+ dm->copy_gpu_data(dm, type, varray, cur_index_per_mat, mat_orig_to_new, user);
+ else
+ ts->copy(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
}
}
@@ -948,6 +992,8 @@ static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(in
medge_base = medge = dm->getEdgeArray(dm);
totedge = dm->getNumEdges(dm);
+
+ /* two passes, one to count number of faces per facemap, one to actually copy the data */
for (i = 0; i < totedge; i++, medge++) {
if (medge->flag & ME_EDGEDRAW) {
@@ -1032,31 +1078,63 @@ static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(i
}
}
-typedef enum {
- GPU_BUFFER_VERTEX = 0,
- GPU_BUFFER_NORMAL,
- GPU_BUFFER_COLOR,
- GPU_BUFFER_UV,
- GPU_BUFFER_UV_TEXPAINT,
- GPU_BUFFER_EDGE,
- GPU_BUFFER_UVEDGE,
-} GPUBufferType;
+static void GPU_buffer_copy_facemap(DerivedMesh *dm, float *varray_, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
+{
+ GPUDrawObject *gdo = dm->drawObject;
+ int facemap;
+ int *facemap_po = CustomData_get_layer(&dm->polyData, CD_FACEMAP);
+ unsigned int *varray = (unsigned int *)varray_;
+ int i, totface, offset = 0;
+ MFace *f, *f_base = dm->getTessFaceArray(dm);
+ int *facemap_offset;
+ int *orig_index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
+
+ totface = dm->getNumTessFaces(dm);
-typedef struct {
- GPUBufferCopyFunc copy;
- GLenum gl_buffer_type;
- int vector_size;
-} GPUBufferTypeSettings;
+ gdo->totfacemaps = dm->totfmaps;
-const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
- {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
- {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
-};
+ gdo->facemap_start = MEM_callocN(gdo->totfacemaps * sizeof(*gdo->facemap_start), "GDO_facemap_start");
+ gdo->facemap_count = MEM_callocN(gdo->totfacemaps * sizeof(*gdo->facemap_count), "GDO_facemap_count");
+ facemap_offset = MEM_callocN(gdo->totfacemaps * sizeof(*facemap_offset), "facemap_offset");
+
+ f = f_base;
+ for (i = 0; i < totface; i++, f++) {
+ facemap = facemap_po[orig_index[i]];
+ if (facemap != -1)
+ gdo->facemap_count[facemap] += (f->v4) ? 6 : 3;
+ }
+
+ for (i = 0; i < gdo->totfacemaps; i++) {
+ gdo->facemap_start[i] = offset;
+ offset += gdo->facemap_count[i];
+ }
+
+ f = f_base;
+ for (i = 0; i < totface; i++, f++) {
+ int fmap_offset;
+ facemap = facemap_po[orig_index[i]];
+
+ if (facemap == -1)
+ continue;
+ fmap_offset = gdo->facemap_start[facemap] + facemap_offset[facemap];
+
+ varray[fmap_offset] = gdo->vert_points[f->v1].point_index;
+ varray[fmap_offset + 1] = gdo->vert_points[f->v2].point_index;
+ varray[fmap_offset + 2] = gdo->vert_points[f->v3].point_index;
+
+ facemap_offset[facemap] += 3;
+
+ if (f->v4) {
+ varray[fmap_offset + 3] = dm->drawObject->vert_points[f->v3].point_index;
+ varray[fmap_offset + 4] = dm->drawObject->vert_points[f->v4].point_index;
+ varray[fmap_offset + 5] = dm->drawObject->vert_points[f->v1].point_index;
+
+ facemap_offset[facemap] += 3;
+ }
+ }
+
+ MEM_freeN(facemap_offset);
+}
/* get the GPUDrawObject buffer associated with a type */
static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
@@ -1076,6 +1154,8 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
return &gdo->uvedges;
+ case GPU_BUFFER_FACEMAP:
+ return &gdo->facemapindices;
default:
return NULL;
}
@@ -1104,6 +1184,8 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
* less so here we can over allocate and assume all
* tris. */
return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
+ case GPU_BUFFER_FACEMAP:
+ return sizeof(int) * 3 * dm->drawObject->tot_triangle_point;
default:
return -1;
}
@@ -1112,12 +1194,9 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
/* call gpu_buffer_setup with settings for a particular type of buffer */
static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
{
- const GPUBufferTypeSettings *ts;
void *user_data = NULL;
GPUBuffer *buf;
- ts = &gpu_buffer_type_settings[type];
-
/* special handling for MCol and UV buffers */
if (type == GPU_BUFFER_COLOR) {
if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
@@ -1128,9 +1207,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
return NULL;
}
- buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size,
- gpu_buffer_size_from_type(dm, type),
- ts->gl_buffer_type, user_data, ts->copy);
+ buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data);
return buf;
}
@@ -1141,9 +1218,13 @@ static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type)
{
GPUBuffer **buf;
- if (!dm->drawObject)
- dm->drawObject = GPU_drawobject_new(dm);
-
+ if (!dm->drawObject) {
+ if (dm->gpuObjectNew)
+ dm->drawObject = dm->gpuObjectNew(dm);
+ else
+ dm->drawObject = GPU_drawobject_new(dm);
+ }
+
buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
if (!(*buf))
*buf = gpu_buffer_setup_type(dm, type);
@@ -1307,6 +1388,32 @@ void GPU_uvedge_setup(DerivedMesh *dm)
GLStates |= GPU_BUFFER_VERTEX_STATE;
}
+void GPU_facemap_setup(DerivedMesh *dm)
+{
+ if (!gpu_buffer_setup_common(dm, GPU_BUFFER_FACEMAP))
+ return;
+
+ if (!gpu_buffer_setup_common(dm, GPU_BUFFER_VERTEX))
+ return;
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ if (dm->drawObject->points->use_vbo) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
+ glVertexPointer(3, GL_FLOAT, 0, 0);
+ }
+ else {
+ glVertexPointer(3, GL_FLOAT, 0, dm->drawObject->points->pointer);
+ }
+
+ GLStates |= GPU_BUFFER_VERTEX_STATE;
+ if (dm->drawObject->facemapindices->use_vbo) {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->facemapindices->id);
+ }
+
+ GLStates |= GPU_BUFFER_ELEMENT_STATE;
+}
+
+
static int GPU_typesize(int type)
{
switch (type) {