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/opengl/gl_context.cc')
-rw-r--r--source/blender/gpu/opengl/gl_context.cc191
1 files changed, 188 insertions, 3 deletions
diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc
index 9fe283131fd..696603ab070 100644
--- a/source/blender/gpu/opengl/gl_context.cc
+++ b/source/blender/gpu/opengl/gl_context.cc
@@ -30,24 +30,209 @@
#include "gpu_context_private.h"
+#include "gl_backend.hh" /* TODO remove */
#include "gl_context.hh"
-// TODO(fclem) this requires too much refactor for now.
-// using namespace blender::gpu;
+using namespace blender::gpu;
/* -------------------------------------------------------------------- */
/** \name Constructor / Destructor
* \{ */
-GLContext::GLContext(void *ghost_window) : GPUContext()
+GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list)
+ : shared_orphan_list_(shared_orphan_list)
{
default_framebuffer_ = ghost_window ?
GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window) :
0;
+
+ glGenVertexArrays(1, &default_vao_);
+
+ float data[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ glGenBuffers(1, &default_attr_vbo_);
+ glBindBuffer(GL_ARRAY_BUFFER, default_attr_vbo_);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
GLContext::~GLContext()
{
+ BLI_assert(orphaned_framebuffers_.is_empty());
+ BLI_assert(orphaned_vertarrays_.is_empty());
+ /* For now don't allow GPUFrameBuffers to be reuse in another context. */
+ BLI_assert(framebuffers_.is_empty());
+ /* Delete vaos so the batch can be reused in another context. */
+ for (GPUBatch *batch : batches_) {
+ GPU_batch_vao_cache_clear(batch);
+ }
+ glDeleteVertexArrays(1, &default_vao_);
+ glDeleteBuffers(1, &default_attr_vbo_);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Activate / Deactivate context
+ * \{ */
+
+void GLContext::activate(void)
+{
+ /* Make sure no other context is already bound to this thread. */
+ BLI_assert(is_active_ == false);
+
+ is_active_ = true;
+ thread_ = pthread_self();
+
+ /* Clear accumulated orphans. */
+ orphans_clear();
+}
+
+void GLContext::deactivate(void)
+{
+ is_active_ = false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Safe object deletion
+ *
+ * GPU objects can be freed when the context is not bound.
+ * In this case we delay the deletion until the context is bound again.
+ * \{ */
+
+void GLSharedOrphanLists::orphans_clear(void)
+{
+ /* Check if any context is active on this thread! */
+ BLI_assert(GPU_context_active_get());
+
+ lists_mutex.lock();
+ if (!buffers.is_empty()) {
+ glDeleteBuffers((uint)buffers.size(), buffers.data());
+ buffers.clear();
+ }
+ if (!textures.is_empty()) {
+ glDeleteTextures((uint)textures.size(), textures.data());
+ textures.clear();
+ }
+ lists_mutex.unlock();
+};
+
+void GLContext::orphans_clear(void)
+{
+ /* Check if context has been activated by another thread! */
+ BLI_assert(this->is_active_on_thread());
+
+ lists_mutex_.lock();
+ if (!orphaned_vertarrays_.is_empty()) {
+ glDeleteVertexArrays((uint)orphaned_vertarrays_.size(), orphaned_vertarrays_.data());
+ orphaned_vertarrays_.clear();
+ }
+ if (!orphaned_framebuffers_.is_empty()) {
+ glDeleteFramebuffers((uint)orphaned_framebuffers_.size(), orphaned_framebuffers_.data());
+ orphaned_framebuffers_.clear();
+ }
+ lists_mutex_.unlock();
+
+ shared_orphan_list_.orphans_clear();
+};
+
+void GLContext::orphans_add(Vector<GLuint> &orphan_list, std::mutex &list_mutex, GLuint id)
+{
+ list_mutex.lock();
+ orphan_list.append(id);
+ list_mutex.unlock();
+}
+
+void GLContext::vao_free(GLuint vao_id)
+{
+ if (this == GPU_context_active_get()) {
+ glDeleteVertexArrays(1, &vao_id);
+ }
+ else {
+ orphans_add(orphaned_vertarrays_, lists_mutex_, vao_id);
+ }
+}
+
+void GLContext::fbo_free(GLuint fbo_id)
+{
+ if (this == GPU_context_active_get()) {
+ glDeleteFramebuffers(1, &fbo_id);
+ }
+ else {
+ orphans_add(orphaned_framebuffers_, lists_mutex_, fbo_id);
+ }
+}
+
+void GLBackend::buf_free(GLuint buf_id)
+{
+ /* Any context can free. */
+ if (GPU_context_active_get()) {
+ glDeleteBuffers(1, &buf_id);
+ }
+ else {
+ orphans_add(shared_orphan_list_.buffers, shared_orphan_list_.lists_mutex, buf_id);
+ }
+}
+
+void GLBackend::tex_free(GLuint tex_id)
+{
+ /* Any context can free. */
+ if (GPU_context_active_get()) {
+ glDeleteTextures(1, &tex_id);
+ }
+ else {
+ orphans_add(shared_orphan_list_.textures, shared_orphan_list_.lists_mutex, tex_id);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Linked object deletion
+ *
+ * These objects contain data that are stored per context. We
+ * need to do some cleanup if they are used accross context or if context
+ * is discarded.
+ * \{ */
+
+void GLContext::batch_register(struct GPUBatch *batch)
+{
+ lists_mutex_.lock();
+ batches_.add(batch);
+ lists_mutex_.unlock();
+}
+
+void GLContext::batch_unregister(struct GPUBatch *batch)
+{
+ /* vao_cache_clear() can acquire lists_mutex_ so avoid deadlock. */
+ // reinterpret_cast<GLBatch *>(batch)->vao_cache_clear();
+
+ lists_mutex_.lock();
+ batches_.remove(batch);
+ lists_mutex_.unlock();
+}
+
+void GLContext::framebuffer_register(struct GPUFrameBuffer *fb)
+{
+#ifdef DEBUG
+ lists_mutex_.lock();
+ framebuffers_.add(fb);
+ lists_mutex_.unlock();
+#else
+ UNUSED_VARS(fb);
+#endif
+}
+
+void GLContext::framebuffer_unregister(struct GPUFrameBuffer *fb)
+{
+#ifdef DEBUG
+ lists_mutex_.lock();
+ framebuffers_.remove(fb);
+ lists_mutex_.unlock();
+#else
+ UNUSED_VARS(fb);
+#endif
}
/** \} */