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:
-rw-r--r--source/blender/draw/DRW_engine.h4
-rw-r--r--source/blender/draw/intern/draw_manager.c20
-rw-r--r--source/blender/gpu/CMakeLists.txt6
-rw-r--r--source/blender/gpu/GPU_buffer_id.h53
-rw-r--r--source/blender/gpu/GPU_material.h5
-rw-r--r--source/blender/gpu/GPU_texture.h5
-rw-r--r--source/blender/gpu/intern/gpu_batch.c3
-rw-r--r--source/blender/gpu/intern/gpu_batch_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_buffer_id.cpp90
-rw-r--r--source/blender/gpu/intern/gpu_context.cpp (renamed from source/blender/gpu/intern/gpu_vertex_array_id.cpp)177
-rw-r--r--source/blender/gpu/intern/gpu_context_private.h (renamed from source/blender/gpu/GPU_vertex_array_id.h)37
-rw-r--r--source/blender/gpu/intern/gpu_element.c7
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c15
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c7
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c5
-rw-r--r--source/blender/gpu/intern/gpu_material.c39
-rw-r--r--source/blender/gpu/intern/gpu_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_shader.c2
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c6
-rw-r--r--source/blender/gpu/intern/gpu_texture.c58
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c7
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.c8
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
-rw-r--r--source/blender/windowmanager/intern/wm_window.c2
24 files changed, 248 insertions, 319 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index eb037d081e1..4d4b486d247 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -136,6 +136,10 @@ void DRW_opengl_context_destroy(void);
void DRW_opengl_context_enable(void);
void DRW_opengl_context_disable(void);
+/* Never use this. Only for closing blender. */
+void DRW_opengl_context_enable_ex(bool restore);
+void DRW_opengl_context_disable_ex(bool restore);
+
void DRW_opengl_render_context_enable(void *re_gl_context);
void DRW_opengl_render_context_disable(void *re_gl_context);
void DRW_gawain_render_context_enable(void *re_gpu_context);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 2793410cd8e..cc4f8ec7947 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2374,21 +2374,21 @@ void DRW_opengl_context_destroy(void)
}
}
-void DRW_opengl_context_enable(void)
+void DRW_opengl_context_enable_ex(bool restore)
{
if (DST.gl_context != NULL) {
/* IMPORTANT: We dont support immediate mode in render mode!
* This shall remain in effect until immediate mode supports
* multiple threads. */
BLI_ticket_mutex_lock(DST.gl_context_mutex);
- if (BLI_thread_is_main()) {
+ if (BLI_thread_is_main() && restore) {
if (!G.background) {
immDeactivate();
}
}
WM_opengl_context_activate(DST.gl_context);
GPU_context_active_set(DST.gpu_context);
- if (BLI_thread_is_main()) {
+ if (BLI_thread_is_main() && restore) {
if (!G.background) {
immActivate();
}
@@ -2397,7 +2397,7 @@ void DRW_opengl_context_enable(void)
}
}
-void DRW_opengl_context_disable(void)
+void DRW_opengl_context_disable_ex(bool restore)
{
if (DST.gl_context != NULL) {
#ifdef __APPLE__
@@ -2406,7 +2406,7 @@ void DRW_opengl_context_disable(void)
glFlush();
#endif
- if (BLI_thread_is_main()) {
+ if (BLI_thread_is_main() && restore) {
wm_window_reset_drawable();
}
else {
@@ -2418,6 +2418,16 @@ void DRW_opengl_context_disable(void)
}
}
+void DRW_opengl_context_enable(void)
+{
+ DRW_opengl_context_enable_ex(true);
+}
+
+void DRW_opengl_context_disable(void)
+{
+ DRW_opengl_context_disable_ex(true);
+}
+
void DRW_opengl_render_context_enable(void *re_gl_context)
{
/* If thread is main you should use DRW_opengl_context_enable(). */
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 58295ae9329..8273f3f1992 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -62,9 +62,9 @@ set(SRC
intern/gpu_batch.c
intern/gpu_batch_presets.c
intern/gpu_batch_utils.c
- intern/gpu_buffer_id.cpp
intern/gpu_buffers.c
intern/gpu_codegen.c
+ intern/gpu_context.cpp
intern/gpu_debug.c
intern/gpu_draw.c
intern/gpu_element.c
@@ -84,7 +84,6 @@ set(SRC
intern/gpu_state.c
intern/gpu_texture.c
intern/gpu_uniformbuffer.c
- intern/gpu_vertex_array_id.cpp
intern/gpu_vertex_buffer.c
intern/gpu_vertex_format.c
intern/gpu_viewport.c
@@ -113,7 +112,6 @@ set(SRC
GPU_attr_binding.h
GPU_basic_shader.h
GPU_batch.h
- GPU_buffer_id.h
GPU_buffers.h
GPU_common.h
GPU_debug.h
@@ -135,7 +133,6 @@ set(SRC
GPU_state.h
GPU_texture.h
GPU_uniformbuffer.h
- GPU_vertex_array_id.h
GPU_vertex_buffer.h
GPU_vertex_format.h
GPU_viewport.h
@@ -143,6 +140,7 @@ set(SRC
intern/gpu_attr_binding_private.h
intern/gpu_batch_private.h
intern/gpu_codegen.h
+ intern/gpu_context_private.h
intern/gpu_primitive_private.h
intern/gpu_private.h
intern/gpu_select_private.h
diff --git a/source/blender/gpu/GPU_buffer_id.h b/source/blender/gpu/GPU_buffer_id.h
deleted file mode 100644
index 4615e9e2c66..00000000000
--- a/source/blender/gpu/GPU_buffer_id.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2016 by Mike Erwin.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/gpu/GPU_buffer_id.h
- * \ingroup gpu
- *
- * GPU buffer IDs
- */
-
-#ifndef __GPU_BUFFER_ID_H__
-#define __GPU_BUFFER_ID_H__
-
-/* Manage GL buffer IDs in a thread-safe way
- * Use these instead of glGenBuffers & its friends
- * - alloc must be called from main thread
- * - free can be called from any thread */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "GPU_common.h"
-
-GLuint GPU_buf_id_alloc(void);
-void GPU_buf_id_free(GLuint buffer_id);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __GPU_BUFFER_ID_H__ */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 4e264defbd4..f2c029f643e 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -254,11 +254,6 @@ void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(struct Main *bmain);
-void GPU_material_orphans_init(void);
-void GPU_material_orphans_exit(void);
-/* This has to be called from a thread with an ogl context bound. */
-void GPU_material_orphans_delete(void);
-
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index e3db18f1358..1ddf801e166 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -198,11 +198,6 @@ void GPU_invalid_tex_free(void);
void GPU_texture_free(GPUTexture *tex);
-void GPU_texture_orphans_init(void);
-void GPU_texture_orphans_exit(void);
-/* This has to be called from a thread with an ogl context bound. */
-void GPU_texture_orphans_delete(void);
-
void GPU_texture_ref(GPUTexture *tex);
void GPU_texture_bind(GPUTexture *tex, int number);
void GPU_texture_unbind(GPUTexture *tex);
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index a11eefee078..9b433a37a72 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -32,12 +32,11 @@
#include "GPU_batch.h"
#include "GPU_batch_presets.h"
-#include "GPU_buffer_id.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
-#include "GPU_vertex_array_id.h"
#include "gpu_batch_private.h"
+#include "gpu_context_private.h"
#include "gpu_primitive_private.h"
#include "gpu_shader_private.h"
diff --git a/source/blender/gpu/intern/gpu_batch_private.h b/source/blender/gpu/intern/gpu_batch_private.h
index 51040ff751a..3a05e243065 100644
--- a/source/blender/gpu/intern/gpu_batch_private.h
+++ b/source/blender/gpu/intern/gpu_batch_private.h
@@ -43,9 +43,6 @@ extern "C" {
void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface);
-void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch);
-void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/intern/gpu_buffer_id.cpp b/source/blender/gpu/intern/gpu_buffer_id.cpp
deleted file mode 100644
index f3faba9c766..00000000000
--- a/source/blender/gpu/intern/gpu_buffer_id.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2016 by Mike Erwin.
- * All rights reserved.
- *
- * Contributor(s): Blender Foundation
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/gpu/intern/gpu_buffer_id.cpp
- * \ingroup gpu
- *
- * GPU buffer IDs
- */
-
-#include "GPU_buffer_id.h"
-
-#include <mutex>
-#include <vector>
-
-#define ORPHAN_DEBUG 0
-
-#if ORPHAN_DEBUG
-# include <cstdio>
-#endif
-
-static std::vector<GLuint> orphaned_buffer_ids;
-
-static std::mutex orphan_mutex;
-
-extern "C" {
-extern int BLI_thread_is_main(void); /* Blender-specific function */
-}
-
-static bool thread_is_main()
-{
- /* "main" here means the GL context's thread */
- return BLI_thread_is_main();
-}
-
-GLuint GPU_buf_id_alloc()
-{
- /* delete orphaned IDs */
- orphan_mutex.lock();
- if (!orphaned_buffer_ids.empty()) {
- const auto orphaned_buffer_len = (uint)orphaned_buffer_ids.size();
-#if ORPHAN_DEBUG
- printf("deleting %u orphaned VBO%s\n", orphaned_buffer_len, orphaned_buffer_len == 1 ? "" : "s");
-#endif
- glDeleteBuffers(orphaned_buffer_len, orphaned_buffer_ids.data());
- orphaned_buffer_ids.clear();
- }
- orphan_mutex.unlock();
-
- GLuint new_buffer_id = 0;
- glGenBuffers(1, &new_buffer_id);
- return new_buffer_id;
-}
-
-void GPU_buf_id_free(GLuint buffer_id)
-{
- if (thread_is_main()) {
- glDeleteBuffers(1, &buffer_id);
- }
- else {
- /* add this ID to the orphaned list */
- orphan_mutex.lock();
-#if ORPHAN_DEBUG
- printf("orphaning VBO %u\n", buffer_id);
-#endif
- orphaned_buffer_ids.emplace_back(buffer_id);
- orphan_mutex.unlock();
- }
-}
diff --git a/source/blender/gpu/intern/gpu_vertex_array_id.cpp b/source/blender/gpu/intern/gpu_context.cpp
index 64f704bb107..6a42552c2fd 100644
--- a/source/blender/gpu/intern/gpu_vertex_array_id.cpp
+++ b/source/blender/gpu/intern/gpu_context.cpp
@@ -34,9 +34,15 @@
* - free can be called from any thread
*/
-#include "gpu_batch_private.h"
-#include "GPU_vertex_array_id.h"
+#include "BLI_assert.h"
+#include "BLI_utildefines.h"
+
#include "GPU_context.h"
+#include "GPU_framebuffer.h"
+
+#include "gpu_batch_private.h"
+#include "gpu_context_private.h"
+
#include <vector>
#include <string.h>
#include <pthread.h>
@@ -56,10 +62,19 @@ static bool thread_is_main() {
#endif
#endif
+static std::vector<GLuint> orphaned_buffer_ids;
+static std::vector<GLuint> orphaned_texture_ids;
+
+static std::mutex orphans_mutex;
+
struct GPUContext {
GLuint default_vao;
std::unordered_set<GPUBatch *> batches; /* Batches that have VAOs from this context */
+#ifdef DEBUG
+ std::unordered_set<GPUFrameBuffer *> framebuffers; /* Framebuffers that have FBO from this context */
+#endif
std::vector<GLuint> orphaned_vertarray_ids;
+ std::vector<GLuint> orphaned_framebuffer_ids;
std::mutex orphans_mutex; /* todo: try spinlock instead */
#if TRUST_NO_ONE
pthread_t thread; /* Thread on which this context is active. */
@@ -78,22 +93,51 @@ thread_local GPUContext *active_ctx = NULL;
static thread_local GPUContext *active_ctx = NULL;
#endif
-static void clear_orphans(GPUContext *ctx)
+static void orphans_add(GPUContext *ctx, std::vector<GLuint> *orphan_list, GLuint id)
{
+ std::mutex *mutex = (ctx) ? &ctx->orphans_mutex : &orphans_mutex;
+
+ mutex->lock();
+ orphan_list->emplace_back(id);
+ mutex->unlock();
+}
+
+static void orphans_clear(GPUContext *ctx)
+{
+ BLI_assert(ctx); /* need at least an active context */
+ BLI_assert(pthread_equal(pthread_self(), ctx->thread)); /* context has been activated by another thread! */
+
ctx->orphans_mutex.lock();
if (!ctx->orphaned_vertarray_ids.empty()) {
uint orphan_len = (uint)ctx->orphaned_vertarray_ids.size();
glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data());
ctx->orphaned_vertarray_ids.clear();
}
+ if (!ctx->orphaned_framebuffer_ids.empty()) {
+ uint orphan_len = (uint)ctx->orphaned_framebuffer_ids.size();
+ glDeleteFramebuffers(orphan_len, ctx->orphaned_framebuffer_ids.data());
+ ctx->orphaned_framebuffer_ids.clear();
+ }
+
ctx->orphans_mutex.unlock();
+
+ orphans_mutex.lock();
+ if (!orphaned_buffer_ids.empty()) {
+ uint orphan_len = (uint)orphaned_buffer_ids.size();
+ glDeleteBuffers(orphan_len, orphaned_buffer_ids.data());
+ orphaned_buffer_ids.clear();
+ }
+ if (!orphaned_texture_ids.empty()) {
+ uint orphan_len = (uint)orphaned_texture_ids.size();
+ glDeleteTextures(orphan_len, orphaned_texture_ids.data());
+ orphaned_texture_ids.clear();
+ }
+ orphans_mutex.unlock();
}
GPUContext *GPU_context_create(void)
{
-#if TRUST_NO_ONE
- /* assert(thread_is_main()); */
-#endif
+ /* BLI_assert(thread_is_main()); */
GPUContext *ctx = new GPUContext;
glGenVertexArrays(1, &ctx->default_vao);
GPU_context_active_set(ctx);
@@ -103,12 +147,12 @@ GPUContext *GPU_context_create(void)
/* to be called after GPU_context_active_set(ctx_to_destroy) */
void GPU_context_discard(GPUContext *ctx)
{
-#if TRUST_NO_ONE
/* Make sure no other thread has locked it. */
- assert(ctx == active_ctx);
- assert(pthread_equal(pthread_self(), ctx->thread));
- assert(ctx->orphaned_vertarray_ids.empty());
-#endif
+ BLI_assert(ctx == active_ctx);
+ BLI_assert(pthread_equal(pthread_self(), ctx->thread));
+ BLI_assert(ctx->orphaned_vertarray_ids.empty());
+ /* For now don't allow GPUFrameBuffers to be reuse in another ctx. */
+ BLI_assert(ctx->framebuffers.empty());
/* delete remaining vaos */
while (!ctx->batches.empty()) {
/* this removes the array entry */
@@ -135,7 +179,7 @@ void GPU_context_active_set(GPUContext *ctx)
}
#endif
if (ctx) {
- clear_orphans(ctx);
+ orphans_clear(ctx);
}
active_ctx = ctx;
}
@@ -147,50 +191,125 @@ GPUContext *GPU_context_active_get(void)
GLuint GPU_vao_default(void)
{
-#if TRUST_NO_ONE
- assert(active_ctx); /* need at least an active context */
- assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */
-#endif
+ BLI_assert(active_ctx); /* need at least an active context */
+ BLI_assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */
return active_ctx->default_vao;
}
GLuint GPU_vao_alloc(void)
{
-#if TRUST_NO_ONE
- assert(active_ctx); /* need at least an active context */
- assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */
-#endif
- clear_orphans(active_ctx);
-
GLuint new_vao_id = 0;
+ orphans_clear(active_ctx);
glGenVertexArrays(1, &new_vao_id);
return new_vao_id;
}
-/* this can be called from multiple thread */
+GLuint GPU_fbo_alloc(void)
+{
+ GLuint new_fbo_id = 0;
+ orphans_clear(active_ctx);
+ glGenFramebuffers(1, &new_fbo_id);
+ return new_fbo_id;
+}
+
+GLuint GPU_buf_alloc(void)
+{
+ GLuint new_buffer_id = 0;
+ orphans_clear(active_ctx);
+ glGenBuffers(1, &new_buffer_id);
+ return new_buffer_id;
+}
+
+GLuint GPU_tex_alloc(void)
+{
+ GLuint new_texture_id = 0;
+ orphans_clear(active_ctx);
+ glGenTextures(1, &new_texture_id);
+ return new_texture_id;
+}
+
void GPU_vao_free(GLuint vao_id, GPUContext *ctx)
{
-#if TRUST_NO_ONE
- assert(ctx);
-#endif
+ BLI_assert(ctx);
if (ctx == active_ctx) {
glDeleteVertexArrays(1, &vao_id);
}
else {
- ctx->orphans_mutex.lock();
- ctx->orphaned_vertarray_ids.emplace_back(vao_id);
- ctx->orphans_mutex.unlock();
+ orphans_add(ctx, &ctx->orphaned_vertarray_ids, vao_id);
}
}
+void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx)
+{
+ BLI_assert(ctx);
+ if (ctx == active_ctx) {
+ glDeleteFramebuffers(1, &fbo_id);
+ }
+ else {
+ orphans_add(ctx, &ctx->orphaned_framebuffer_ids, fbo_id);
+ }
+}
+
+void GPU_buf_free(GLuint buf_id)
+{
+ if (active_ctx) {
+ glDeleteBuffers(1, &buf_id);
+ }
+ else {
+ orphans_add(NULL, &orphaned_buffer_ids, buf_id);
+ }
+}
+
+void GPU_tex_free(GLuint tex_id)
+{
+ if (active_ctx) {
+ glDeleteTextures(1, &tex_id);
+ }
+ else {
+ orphans_add(NULL, &orphaned_texture_ids, tex_id);
+ }
+}
+
+/* GPUBatch & GPUFrameBuffer contains respectively VAO & FBO indices
+ * which are not shared across contexts. So we need to keep track of
+ * ownership. */
+
void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch)
{
+ BLI_assert(ctx);
+ ctx->orphans_mutex.lock();
ctx->batches.emplace(batch);
+ ctx->orphans_mutex.unlock();
}
void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch)
{
+ BLI_assert(ctx);
ctx->orphans_mutex.lock();
ctx->batches.erase(batch);
ctx->orphans_mutex.unlock();
}
+
+void gpu_context_add_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb)
+{
+#ifdef DEBUG
+ BLI_assert(ctx);
+ ctx->orphans_mutex.lock();
+ ctx->framebuffers.emplace(fb);
+ ctx->orphans_mutex.unlock();
+#else
+ UNUSED_VARS(ctx, fb);
+#endif
+}
+
+void gpu_context_remove_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb)
+{
+#ifdef DEBUG
+ BLI_assert(ctx);
+ ctx->orphans_mutex.lock();
+ ctx->framebuffers.erase(fb);
+ ctx->orphans_mutex.unlock();
+#else
+ UNUSED_VARS(ctx, fb);
+#endif
+}
diff --git a/source/blender/gpu/GPU_vertex_array_id.h b/source/blender/gpu/intern/gpu_context_private.h
index ff84a290a5a..4881a892e38 100644
--- a/source/blender/gpu/GPU_vertex_array_id.h
+++ b/source/blender/gpu/intern/gpu_context_private.h
@@ -23,33 +23,46 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/gpu/GPU_vertex_array_id.h
+/** \file blender/gpu/intern/gpu_context_private.h
* \ingroup gpu
*
- * Manage GL vertex array IDs in a thread-safe way
- * Use these instead of glGenBuffers & its friends
- * - alloc must be called from a thread that is bound
- * to the context that will be used for drawing with
- * this vao.
- * - free can be called from any thread
+ * This interface allow GPU to manage GL objects for mutiple context and threads.
*/
-#ifndef __GPU_VERTEX_ARRAY_ID_H__
-#define __GPU_VERTEX_ARRAY_ID_H__
+#ifndef __GPU_CONTEXT_PRIVATE_H__
+#define __GPU_CONTEXT_PRIVATE_H__
#ifdef __cplusplus
extern "C" {
#endif
-#include "GPU_common.h"
#include "GPU_context.h"
+struct GPUFrameBuffer;
+
GLuint GPU_vao_default(void);
+
+/* These require a gl ctx bound. */
+GLuint GPU_buf_alloc(void);
+GLuint GPU_tex_alloc(void);
GLuint GPU_vao_alloc(void);
-void GPU_vao_free(GLuint vao_id, GPUContext *);
+GLuint GPU_fbo_alloc(void);
+
+/* These can be called any threads even without gl ctx. */
+void GPU_buf_free(GLuint buf_id);
+void GPU_tex_free(GLuint tex_id);
+/* These two need the ctx the id was created with. */
+void GPU_vao_free(GLuint vao_id, GPUContext *ctx);
+void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx);
+
+void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch);
+void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch);
+
+void gpu_context_add_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb);
+void gpu_context_remove_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb);
#ifdef __cplusplus
}
#endif
-#endif /* __GPU_VERTEX_ARRAY_ID_H__ */
+#endif /* __GPU_CONTEXT_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c
index 9abfed2db05..901e09443d1 100644
--- a/source/blender/gpu/intern/gpu_element.c
+++ b/source/blender/gpu/intern/gpu_element.c
@@ -30,7 +30,8 @@
*/
#include "GPU_element.h"
-#include "GPU_buffer_id.h"
+
+#include "gpu_context_private.h"
#include <stdlib.h>
@@ -279,7 +280,7 @@ void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *builder, GPUIndexBuf *elem)
#endif
if (elem->vbo_id == 0) {
- elem->vbo_id = GPU_buf_id_alloc();
+ elem->vbo_id = GPU_buf_alloc();
}
/* send data to GPU */
/* GL_ELEMENT_ARRAY_BUFFER changes the state of the last VAO bound,
@@ -302,7 +303,7 @@ void GPU_indexbuf_use(GPUIndexBuf *elem)
void GPU_indexbuf_discard(GPUIndexBuf *elem)
{
if (elem->vbo_id) {
- GPU_buf_id_free(elem->vbo_id);
+ GPU_buf_free(elem->vbo_id);
}
free(elem);
}
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index d28b82ac3cd..ba8dcb04269 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -42,7 +42,8 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "intern/gpu_private.h"
+#include "gpu_private.h"
+#include "gpu_context_private.h"
static ThreadLocal(void *) g_currentfb;
@@ -69,6 +70,7 @@ typedef enum {
#define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type))
struct GPUFrameBuffer {
+ GPUContext *ctx;
GLuint object;
GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT];
uint16_t dirty_flag;
@@ -196,7 +198,9 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
static void gpu_framebuffer_init(GPUFrameBuffer *fb)
{
- glGenFramebuffers(1, &fb->object);
+ fb->object = GPU_fbo_alloc();
+ fb->ctx = GPU_context_active_get();
+ gpu_context_add_framebuffer(fb->ctx, fb);
}
void GPU_framebuffer_free(GPUFrameBuffer *fb)
@@ -207,8 +211,11 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
}
}
- /* This restores the framebuffer if it was bound */
- glDeleteFramebuffers(1, &fb->object);
+ if (fb->object != 0) {
+ /* This restores the framebuffer if it was bound */
+ GPU_fbo_free(fb->object, fb->ctx);
+ gpu_context_remove_framebuffer(fb->ctx, fb);
+ }
if (gpu_framebuffer_current_get() == fb->object) {
gpu_framebuffer_current_set(0);
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index 66a467e339e..9674cf0b9f7 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -32,11 +32,10 @@
#include "UI_resources.h"
#include "GPU_attr_binding.h"
-#include "GPU_buffer_id.h"
#include "GPU_immediate.h"
-#include "GPU_vertex_array_id.h"
#include "gpu_attr_binding_private.h"
+#include "gpu_context_private.h"
#include "gpu_primitive_private.h"
#include "gpu_shader_private.h"
#include "gpu_vertex_format_private.h"
@@ -91,7 +90,7 @@ void immInit(void)
#endif
memset(&imm, 0, sizeof(Immediate));
- imm.vbo_id = GPU_buf_id_alloc();
+ imm.vbo_id = GPU_buf_alloc();
glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
@@ -127,7 +126,7 @@ void immDeactivate(void)
void immDestroy(void)
{
- GPU_buf_id_free(imm.vbo_id);
+ GPU_buf_free(imm.vbo_id);
initialized = false;
}
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 78d4f491b66..55d0466c929 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -57,8 +57,6 @@ void GPU_init(void)
gpu_extensions_init(); /* must come first */
- GPU_texture_orphans_init();
- GPU_material_orphans_init();
gpu_codegen_init();
gpu_framebuffer_module_init();
@@ -84,9 +82,6 @@ void GPU_exit(void)
gpu_batch_exit();
- GPU_texture_orphans_exit();
- GPU_material_orphans_exit();
-
if (G.debug & G_DEBUG_GPU)
gpu_debug_exit();
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 9566f091ada..92aff91da32 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -75,9 +75,6 @@
# include "BKE_DerivedMesh.h"
#endif
-static ListBase g_orphaned_mat = {NULL, NULL};
-static ThreadMutex g_orphan_lock;
-
/* Structs */
struct GPUMaterial {
@@ -175,44 +172,12 @@ void GPU_material_free(ListBase *gpumaterial)
{
for (LinkData *link = gpumaterial->first; link; link = link->next) {
GPUMaterial *material = link->data;
-
- /* TODO(fclem): Check if the thread has an ogl context. */
- if (BLI_thread_is_main()) {
- gpu_material_free_single(material);
- MEM_freeN(material);
- }
- else {
- BLI_mutex_lock(&g_orphan_lock);
- BLI_addtail(&g_orphaned_mat, BLI_genericNodeN(material));
- BLI_mutex_unlock(&g_orphan_lock);
- }
+ gpu_material_free_single(material);
+ MEM_freeN(material);
}
BLI_freelistN(gpumaterial);
}
-void GPU_material_orphans_init(void)
-{
- BLI_mutex_init(&g_orphan_lock);
-}
-
-void GPU_material_orphans_delete(void)
-{
- BLI_mutex_lock(&g_orphan_lock);
- LinkData *link;
- while ((link = BLI_pophead(&g_orphaned_mat))) {
- gpu_material_free_single((GPUMaterial *)link->data);
- MEM_freeN(link->data);
- MEM_freeN(link);
- }
- BLI_mutex_unlock(&g_orphan_lock);
-}
-
-void GPU_material_orphans_exit(void)
-{
- GPU_material_orphans_delete();
- BLI_mutex_end(&g_orphan_lock);
-}
-
GPUBuiltin GPU_get_material_builtins(GPUMaterial *material)
{
return material->builtins;
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
index 996ba9c63a1..df55f7922b3 100644
--- a/source/blender/gpu/intern/gpu_private.h
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -25,6 +25,9 @@
#ifndef __GPU_PRIVATE_H__
#define __GPU_PRIVATE_H__
+struct GPUContext;
+struct GPUFrameBuffer;
+
/* call this before running any of the functions below */
void gpu_extensions_init(void);
void gpu_extensions_exit(void);
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 1eae073d9c0..04b43d03c83 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -38,6 +38,7 @@
#include "DNA_space_types.h"
#include "GPU_extensions.h"
+#include "GPU_context.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -572,6 +573,7 @@ void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader))
void GPU_shader_free(GPUShader *shader)
{
+ BLI_assert(GPU_context_active_get() != NULL);
BLI_assert(shader);
if (shader->vertex)
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index 4b8413d0cc3..54c5f41bbd3 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -29,9 +29,11 @@
* GPU shader interface (C --> GLSL)
*/
-#include "gpu_batch_private.h"
#include "GPU_shader_interface.h"
-#include "GPU_vertex_array_id.h"
+
+#include "gpu_batch_private.h"
+#include "gpu_context_private.h"
+
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 4465136dd0f..5ac746ec9c1 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -38,22 +38,22 @@
#include "BKE_global.h"
#include "GPU_batch.h"
+#include "GPU_context.h"
#include "GPU_debug.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_framebuffer.h"
#include "GPU_glew.h"
+#include "GPU_framebuffer.h"
#include "GPU_texture.h"
+#include "gpu_context_private.h"
+
static struct GPUTextureGlobal {
GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
} GG = {NULL, NULL, NULL};
-static ListBase g_orphaned_tex = {NULL, NULL};
-static ThreadMutex g_orphan_lock;
-
/* Maximum number of FBOs a texture can be attached to. */
#define GPU_TEX_MAX_FBO_ATTACHED 8
@@ -535,7 +535,7 @@ GPUTexture *GPU_texture_create_nD(
gpu_texture_memory_footprint_add(tex);
/* Generate Texture object */
- glGenTextures(1, &tex->bindcode);
+ tex->bindcode = GPU_tex_alloc();
if (!tex->bindcode) {
if (err_out)
@@ -668,7 +668,7 @@ static GPUTexture *GPU_texture_cube_create(
gpu_texture_memory_footprint_add(tex);
/* Generate Texture object */
- glGenTextures(1, &tex->bindcode);
+ tex->bindcode = GPU_tex_alloc();
if (!tex->bindcode) {
if (err_out)
@@ -752,7 +752,7 @@ GPUTexture *GPU_texture_create_buffer(GPUTextureFormat tex_format, const GLuint
}
/* Generate Texture object */
- glGenTextures(1, &tex->bindcode);
+ tex->bindcode = GPU_tex_alloc();
if (!tex->bindcode) {
fprintf(stderr, "GPUTexture: texture create failed\n");
@@ -1301,17 +1301,6 @@ void GPU_texture_filters(GPUTexture *tex, GPUFilterFunction min_filter, GPUFilte
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter));
}
-
-static void gpu_texture_delete(GPUTexture *tex)
-{
- if (tex->bindcode)
- glDeleteTextures(1, &tex->bindcode);
-
- gpu_texture_memory_footprint_remove(tex);
-
- MEM_freeN(tex);
-}
-
void GPU_texture_free(GPUTexture *tex)
{
tex->refcount--;
@@ -1326,38 +1315,13 @@ void GPU_texture_free(GPUTexture *tex)
}
}
- /* TODO(fclem): Check if the thread has an ogl context. */
- if (BLI_thread_is_main()) {
- gpu_texture_delete(tex);
- }
- else {
- BLI_mutex_lock(&g_orphan_lock);
- BLI_addtail(&g_orphaned_tex, BLI_genericNodeN(tex));
- BLI_mutex_unlock(&g_orphan_lock);
- }
- }
-}
+ if (tex->bindcode)
+ GPU_tex_free(tex->bindcode);
-void GPU_texture_orphans_init(void)
-{
- BLI_mutex_init(&g_orphan_lock);
-}
+ gpu_texture_memory_footprint_remove(tex);
-void GPU_texture_orphans_delete(void)
-{
- BLI_mutex_lock(&g_orphan_lock);
- LinkData *link;
- while ((link = BLI_pophead(&g_orphaned_tex))) {
- gpu_texture_delete((GPUTexture *)link->data);
- MEM_freeN(link);
+ MEM_freeN(tex);
}
- BLI_mutex_unlock(&g_orphan_lock);
-}
-
-void GPU_texture_orphans_exit(void)
-{
- GPU_texture_orphans_delete();
- BLI_mutex_end(&g_orphan_lock);
}
void GPU_texture_ref(GPUTexture *tex)
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
index 1e39b2ea5b7..9b8441efd08 100644
--- a/source/blender/gpu/intern/gpu_uniformbuffer.c
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -35,6 +35,7 @@
#include "BLI_blenlib.h"
#include "gpu_codegen.h"
+#include "gpu_context_private.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
@@ -88,7 +89,7 @@ GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_
ubo->bindpoint = -1;
/* Generate Buffer object */
- glGenBuffers(1, &ubo->bindcode);
+ ubo->bindcode = GPU_buf_alloc();
if (!ubo->bindcode) {
if (err_out)
@@ -127,7 +128,7 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou
ubo->flag = GPU_UBO_FLAG_DIRTY;
/* Generate Buffer object. */
- glGenBuffers(1, &ubo->buffer.bindcode);
+ ubo->buffer.bindcode = GPU_buf_alloc();
if (!ubo->buffer.bindcode) {
if (err_out)
@@ -190,7 +191,7 @@ void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
gpu_uniformbuffer_dynamic_free(ubo);
}
- glDeleteBuffers(1, &ubo->bindcode);
+ GPU_buf_free(ubo->bindcode);
MEM_freeN(ubo);
}
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.c b/source/blender/gpu/intern/gpu_vertex_buffer.c
index b25d9fc3a2c..d605378bf0e 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer.c
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.c
@@ -30,8 +30,10 @@
*/
#include "GPU_vertex_buffer.h"
-#include "GPU_buffer_id.h"
+
+#include "gpu_context_private.h"
#include "gpu_vertex_format_private.h"
+
#include <stdlib.h>
#include <string.h>
@@ -88,7 +90,7 @@ void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts, const GPUVertFormat *for
void GPU_vertbuf_discard(GPUVertBuf *verts)
{
if (verts->vbo_id) {
- GPU_buf_id_free(verts->vbo_id);
+ GPU_buf_free(verts->vbo_id);
#if VRAM_USAGE
vbo_memory_usage -= GPU_vertbuf_size_get(verts);
#endif
@@ -117,7 +119,7 @@ void GPU_vertbuf_data_alloc(GPUVertBuf *verts, uint v_len)
#endif
/* only create the buffer the 1st time */
if (verts->vbo_id == 0) {
- verts->vbo_id = GPU_buf_id_alloc();
+ verts->vbo_id = GPU_buf_alloc();
}
/* discard previous data if any */
if (verts->data) {
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 0c7c85e0d94..f7d6561e17f 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -119,6 +119,7 @@
#include "GPU_material.h"
#include "GPU_draw.h"
+#include "GPU_immediate.h"
#include "GPU_init_exit.h"
#include "BKE_sound.h"
@@ -515,9 +516,11 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLF_exit();
if (opengl_is_init) {
+ DRW_opengl_context_enable_ex(false);
GPU_pass_cache_free();
- DRW_opengl_context_destroy();
GPU_exit();
+ DRW_opengl_context_disable_ex(false);
+ DRW_opengl_context_destroy();
}
#ifdef WITH_INTERNATIONAL
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index b87ae7e076c..c1006db34ef 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1921,8 +1921,6 @@ void wm_window_raise(wmWindow *win)
void wm_window_swap_buffers(wmWindow *win)
{
- GPU_texture_orphans_delete(); /* XXX should be done elsewhere. */
- GPU_material_orphans_delete(); /* XXX Amen to that. */
GHOST_SwapWindowBuffers(win->ghostwin);
}