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/blenkernel/intern/CCGSubSurf_opensubdiv.c')
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c103
1 files changed, 98 insertions, 5 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index 006cebf4573..2bb55c2d1ed 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -28,12 +28,15 @@
#include "BLI_sys_types.h" // for intptr_t support
#include "BLI_utildefines.h" /* for BLI_assert */
+#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_threads.h"
#include "CCGSubSurf.h"
#include "CCGSubSurf_intern.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_subsurf.h"
#include "DNA_userdef_types.h"
@@ -41,6 +44,7 @@
#include "opensubdiv_converter_capi.h"
#include "GL/glew.h"
+#include "GPU_extensions.h"
#define OSD_LOG if (false) printf
@@ -236,7 +240,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
if (ss->osd_mesh_invalid) {
if (ss->osd_mesh != NULL) {
- openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+ ccgSubSurf__delete_osdGLMesh(ss->osd_mesh);
ss->osd_mesh = NULL;
}
ss->osd_mesh_invalid = false;
@@ -314,9 +318,12 @@ int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss)
if (ss->osd_topology_refiner != NULL) {
topology_refiner = ss->osd_topology_refiner;
}
- else {
+ else if (ss->osd_mesh != NULL) {
topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
}
+ else {
+ return 0;
+ }
return openSubdiv_topologyRefinerGetNumFaces(topology_refiner);
}
@@ -327,9 +334,12 @@ int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face)
if (ss->osd_topology_refiner != NULL) {
topology_refiner = ss->osd_topology_refiner;
}
- else {
+ else if (ss->osd_mesh != NULL) {
topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh);
}
+ else {
+ return 0;
+ }
return openSubdiv_topologyRefinerGetNumFaceVerts(topology_refiner, face);
}
@@ -891,8 +901,7 @@ void ccgSubSurf__sync_opensubdiv(CCGSubSurf *ss)
void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss)
{
if (ss->osd_mesh != NULL) {
- /* TODO(sergey): Make sure free happens form the main thread! */
- openSubdiv_deleteOsdGLMesh(ss->osd_mesh);
+ ccgSubSurf__delete_osdGLMesh(ss->osd_mesh);
ss->osd_mesh = NULL;
}
if (ss->osd_vao != 0) {
@@ -905,10 +914,94 @@ void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3])
{
int i;
BLI_assert(ss->skip_grids == true);
+ if (ss->osd_num_coarse_coords == 0) {
+ zero_v3(r_min);
+ zero_v3(r_max);
+ }
for (i = 0; i < ss->osd_num_coarse_coords; i++) {
/* Coarse coordinates has normals interleaved into the array. */
DO_MINMAX(ss->osd_coarse_coords[2 * i], r_min, r_max);
}
}
+/* ** Delayed delete routines ** */
+
+typedef struct OsdDeletePendingItem {
+ struct OsdDeletePendingItem *next, *prev;
+ OpenSubdiv_GLMesh *osd_mesh;
+ unsigned int vao;
+} OsdDeletePendingItem;
+
+static SpinLock delete_spin;
+static ListBase delete_pool = {NULL, NULL};
+
+static void delete_pending_push(OpenSubdiv_GLMesh *osd_mesh,
+ unsigned int vao)
+{
+ OsdDeletePendingItem *new_entry = MEM_mallocN(sizeof(OsdDeletePendingItem),
+ "opensubdiv delete entry");
+ new_entry->osd_mesh = osd_mesh;
+ new_entry->vao = vao;
+ BLI_spin_lock(&delete_spin);
+ BLI_addtail(&delete_pool, new_entry);
+ BLI_spin_unlock(&delete_spin);
+}
+
+void ccgSubSurf__delete_osdGLMesh(OpenSubdiv_GLMesh *osd_mesh)
+{
+ if (BLI_thread_is_main()) {
+ openSubdiv_deleteOsdGLMesh(osd_mesh);
+ }
+ else {
+ delete_pending_push(osd_mesh, 0);
+ }
+}
+
+void ccgSubSurf__delete_vertex_array(unsigned int vao)
+{
+ if (BLI_thread_is_main()) {
+ glDeleteVertexArrays(1, &vao);
+ }
+ else {
+ delete_pending_push(NULL, vao);
+ }
+}
+
+void ccgSubSurf__delete_pending(void)
+{
+ OsdDeletePendingItem *entry;
+ BLI_assert(BLI_thread_is_main());
+ BLI_spin_lock(&delete_spin);
+ for (entry = delete_pool.first; entry != NULL; entry = entry->next) {
+ if (entry->osd_mesh != NULL) {
+ openSubdiv_deleteOsdGLMesh(entry->osd_mesh);
+ }
+ if (entry->vao != 0) {
+ glDeleteVertexArrays(1, &entry->vao);
+ }
+ }
+ BLI_freelistN(&delete_pool);
+ BLI_spin_unlock(&delete_spin);
+}
+
+/* ** Public API ** */
+
+void BKE_subsurf_osd_init(void)
+{
+ openSubdiv_init(GPU_legacy_support());
+ BLI_spin_init(&delete_spin);
+}
+
+void BKE_subsurf_free_unused_buffers(void)
+{
+ ccgSubSurf__delete_pending();
+}
+
+void BKE_subsurf_osd_cleanup(void)
+{
+ openSubdiv_cleanup();
+ ccgSubSurf__delete_pending();
+ BLI_spin_end(&delete_spin);
+}
+
#endif /* WITH_OPENSUBDIV */