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:
authorClément Foucault <foucault.clem@gmail.com>2020-07-31 12:56:29 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-07-31 19:57:56 +0300
commit41406fcacf74b7aad7f1c842cb9fa19eb886caac (patch)
tree5e5eabd247036f2c55cdd30cfc3b98d192ce6bab
parent510d009f53705e0dccff5d5f792aa34a481addc9 (diff)
GPU: Hide GL context specificitied behind class methodstmp-gpu-context-isolation
-rw-r--r--source/blender/gpu/CMakeLists.txt9
-rw-r--r--source/blender/gpu/intern/gpu_batch.cc97
-rw-r--r--source/blender/gpu/intern/gpu_context.cc265
-rw-r--r--source/blender/gpu/intern/gpu_context_private.h68
-rw-r--r--source/blender/gpu/intern/gpu_context_private.hh98
-rw-r--r--source/blender/gpu/intern/gpu_element.cc2
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.cc18
-rw-r--r--source/blender/gpu/intern/gpu_immediate.cc2
-rw-r--r--source/blender/gpu/intern/gpu_matrix.cc16
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.cc2
-rw-r--r--source/blender/gpu/intern/gpu_texture.cc2
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.cc2
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.cc2
-rw-r--r--source/blender/gpu/opengl/gl_batch.cc124
-rw-r--r--source/blender/gpu/opengl/gl_context.cc188
-rw-r--r--source/blender/gpu/opengl/gl_context.hh93
16 files changed, 573 insertions, 415 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 3ea18f72166..c18fa5f508c 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -28,6 +28,7 @@ endif()
set(INC
.
+ ./opengl
../blenkernel
../blenlib
../bmesh
@@ -85,6 +86,12 @@ set(SRC
intern/gpu_vertex_format.cc
intern/gpu_viewport.c
+ # opengl/ogl_context.cc
+ opengl/gl_context.hh
+
+ # vulkan/vk_context.cc
+ # vulkan/vk_context.hh
+
GPU_attr_binding.h
GPU_batch.h
GPU_batch_presets.h
@@ -118,7 +125,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_context_private.hh
intern/gpu_material_library.h
intern/gpu_matrix_private.h
intern/gpu_node_graph.h
diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc
index 9f9adcacfa6..d354d828044 100644
--- a/source/blender/gpu/intern/gpu_batch.cc
+++ b/source/blender/gpu/intern/gpu_batch.cc
@@ -34,7 +34,7 @@
#include "GPU_shader.h"
#include "gpu_batch_private.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include "gpu_primitive_private.h"
#include "gpu_shader_private.h"
#include "gpu_vertex_format_private.h"
@@ -81,7 +81,7 @@ void GPU_batch_vao_cache_clear(GPUBatch *batch)
batch->static_vaos.vao_ids[i] = 0;
batch->static_vaos.interfaces[i] = NULL;
}
- gpu_context_remove_batch(batch->context, batch);
+ batch->context->batch_remove(batch);
batch->context = NULL;
}
@@ -294,7 +294,7 @@ static GLuint batch_vao_get(GPUBatch *batch)
* Until then it can only be drawn with this context. */
if (batch->context == NULL) {
batch->context = GPU_context_active_get();
- gpu_context_add_batch(batch->context, batch);
+ batch->context->batch_add(batch);
}
#if TRUST_NO_ONE
else {
@@ -634,16 +634,6 @@ void GPU_batch_uniform_mat4(GPUBatch *batch, const char *name, const float data[
glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (const float *)data);
}
-static void *elem_offset(const GPUIndexBuf *el, int v_first)
-{
-#if GPU_TRACK_INDEX_RANGE
- if (el->index_type == GPU_INDEX_U16) {
- return (GLushort *)0 + v_first + el->index_start;
- }
-#endif
- return (GLuint *)0 + v_first + el->index_start;
-}
-
/* Use when drawing with GPU_batch_draw_advanced */
void GPU_batch_bind(GPUBatch *batch)
{
@@ -704,90 +694,13 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi
return;
}
- /* Verify there is enough data do draw. */
- /* TODO(fclem) Nice to have but this is invalid when using procedural draw-calls.
- * The right assert would be to check if there is an enabled attribute from each VBO
- * and check their length. */
- // BLI_assert(i_first + i_count <= (batch->inst ? batch->inst->vertex_len : INT_MAX));
- // BLI_assert(v_first + v_count <=
- // (batch->elem ? batch->elem->index_len : batch->verts[0]->vertex_len));
-
-#ifdef __APPLE__
- GLuint vao = 0;
-#endif
-
- if (!GPU_arb_base_instance_is_supported()) {
- if (i_first > 0) {
-#ifdef __APPLE__
- /**
- * There seems to be a nasty bug when drawing using the same VAO reconfiguring. (see T71147)
- * We just use a throwaway VAO for that. Note that this is likely to degrade performance.
- **/
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
-#else
- /* If using offset drawing with instancing, we must
- * use the default VAO and redo bindings. */
- glBindVertexArray(GPU_vao_default());
-#endif
- batch_update_program_bindings(batch, i_first);
- }
- else {
- /* Previous call could have bind the default vao
- * see above. */
- glBindVertexArray(batch->vao_id);
- }
- }
-
- if (batch->elem) {
- const GPUIndexBuf *el = batch->elem;
- GLenum index_type = INDEX_TYPE(el);
- GLint base_index = BASE_INDEX(el);
- void *v_first_ofs = elem_offset(el, v_first);
-
- if (GPU_arb_base_instance_is_supported()) {
- glDrawElementsInstancedBaseVertexBaseInstance(
- batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index, i_first);
- }
- else {
- glDrawElementsInstancedBaseVertex(
- batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index);
- }
- }
- else {
-#ifdef __APPLE__
- glDisable(GL_PRIMITIVE_RESTART);
-#endif
- if (GPU_arb_base_instance_is_supported()) {
- glDrawArraysInstancedBaseInstance(batch->gl_prim_type, v_first, v_count, i_count, i_first);
- }
- else {
- glDrawArraysInstanced(batch->gl_prim_type, v_first, v_count, i_count);
- }
-#ifdef __APPLE__
- glEnable(GL_PRIMITIVE_RESTART);
-#endif
- }
-
-#ifdef __APPLE__
- if (vao != 0) {
- glDeleteVertexArrays(1, &vao);
- }
-#endif
+ GPU_ctx()->draw_batch(batch, v_first, v_count, i_first, i_count);
}
/* just draw some vertices and let shader place them where we want. */
void GPU_draw_primitive(GPUPrimType prim_type, int v_count)
{
- /* we cannot draw without vao ... annoying ... */
- glBindVertexArray(GPU_vao_default());
-
- GLenum type = convert_prim_type_to_gl(prim_type);
- glDrawArrays(type, 0, v_count);
-
- /* Performance hog if you are drawing with the same vao multiple time.
- * Only activate for debugging.*/
- // glBindVertexArray(0);
+ GPU_ctx()->draw_primitive(prim_type, v_count);
}
/* -------------------------------------------------------------------- */
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index 0b9104e5349..16e52cab0bd 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -35,137 +35,46 @@
#include "GPU_framebuffer.h"
#include "gpu_batch_private.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include "gpu_matrix_private.h"
+#include "gl_context.hh"
+
#include <mutex>
#include <pthread.h>
#include <string.h>
#include <unordered_set>
#include <vector>
-#if TRUST_NO_ONE
-# if 0
-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();
-}
-# 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;
- GLuint default_framebuffer;
- GPUFrameBuffer *current_fbo;
- 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
- struct GPUMatrixState *matrix_state;
- 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. */
- bool thread_is_used;
-#endif
-
- GPUContext()
- {
-#if TRUST_NO_ONE
- thread_is_used = false;
-#endif
- current_fbo = 0;
- }
-};
+// TODO
+// using namespace blender::gpu;
static thread_local GPUContext *active_ctx = NULL;
-static void orphans_add(GPUContext *ctx, std::vector<GLuint> *orphan_list, GLuint id)
+GPUContext::GPUContext()
{
- std::mutex *mutex = (ctx) ? &ctx->orphans_mutex : &orphans_mutex;
-
- mutex->lock();
- orphan_list->emplace_back(id);
- mutex->unlock();
+ thread_ = pthread_self();
+ matrix_state = GPU_matrix_state_create();
}
-static void orphans_clear(GPUContext *ctx)
+GPUContext *GPU_context_create(GLuint)
{
- /* need at least an active context */
- BLI_assert(ctx);
-
- /* context has been activated by another thread! */
- BLI_assert(pthread_equal(pthread_self(), ctx->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 *ctx = new GLContext();
+ GPU_context_active_set(ctx);
+ return ctx;
}
-GPUContext *GPU_context_create(GLuint default_framebuffer)
+bool GPUContext::is_active_on_thread(void)
{
- /* BLI_assert(thread_is_main()); */
- GPUContext *ctx = new GPUContext;
- glGenVertexArrays(1, &ctx->default_vao);
- ctx->default_framebuffer = default_framebuffer;
- ctx->matrix_state = GPU_matrix_state_create();
- GPU_context_active_set(ctx);
- return ctx;
+ return (this == active_ctx) && pthread_equal(pthread_self(), thread_);
}
/* to be called after GPU_context_active_set(ctx_to_destroy) */
void GPU_context_discard(GPUContext *ctx)
{
/* Make sure no other thread has locked it. */
- BLI_assert(ctx == active_ctx);
- BLI_assert(pthread_equal(pthread_self(), ctx->thread));
- BLI_assert(ctx->orphaned_vertarray_ids.empty());
-#ifdef DEBUG
- /* For now don't allow GPUFrameBuffers to be reuse in another ctx. */
- BLI_assert(ctx->framebuffers.empty());
-#endif
- /* delete remaining vaos */
- while (!ctx->batches.empty()) {
- /* this removes the array entry */
- GPU_batch_vao_cache_clear(*ctx->batches.begin());
- }
- GPU_matrix_state_discard(ctx->matrix_state);
- glDeleteVertexArrays(1, &ctx->default_vao);
+ BLI_assert(ctx->is_active_on_thread());
+
delete ctx;
active_ctx = NULL;
}
@@ -173,175 +82,69 @@ void GPU_context_discard(GPUContext *ctx)
/* ctx can be NULL */
void GPU_context_active_set(GPUContext *ctx)
{
-#if TRUST_NO_ONE
if (active_ctx) {
- active_ctx->thread_is_used = false;
- }
- /* Make sure no other context is already bound to this thread. */
- if (ctx) {
- /* Make sure no other thread has locked it. */
- assert(ctx->thread_is_used == false);
- ctx->thread = pthread_self();
- ctx->thread_is_used = true;
+ active_ctx->deactivate();
}
-#endif
if (ctx) {
- orphans_clear(ctx);
+ ctx->activate();
}
active_ctx = ctx;
}
-GPUContext *GPU_context_active_get(void)
+GPUContext *GPU_ctx(void)
{
+ /* Context has been activated by another thread! */
+ BLI_assert(active_ctx->is_active_on_thread());
return active_ctx;
}
-GLuint GPU_vao_default(void)
-{
- 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_framebuffer_default(void)
+GPUContext *GPU_context_active_get(void)
{
- 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_framebuffer;
+ return active_ctx;
}
GLuint GPU_vao_alloc(void)
{
- GLuint new_vao_id = 0;
- orphans_clear(active_ctx);
- glGenVertexArrays(1, &new_vao_id);
- return new_vao_id;
+ return active_ctx->vao_alloc();
}
GLuint GPU_fbo_alloc(void)
{
- GLuint new_fbo_id = 0;
- orphans_clear(active_ctx);
- glGenFramebuffers(1, &new_fbo_id);
- return new_fbo_id;
+ return active_ctx->fbo_alloc();
}
GLuint GPU_buf_alloc(void)
{
- GLuint new_buffer_id = 0;
- orphans_clear(active_ctx);
- glGenBuffers(1, &new_buffer_id);
- return new_buffer_id;
+ return active_ctx->buf_alloc();
}
GLuint GPU_tex_alloc(void)
{
- GLuint new_texture_id = 0;
- orphans_clear(active_ctx);
- glGenTextures(1, &new_texture_id);
- return new_texture_id;
+ return active_ctx->tex_alloc();
}
void GPU_vao_free(GLuint vao_id, GPUContext *ctx)
{
BLI_assert(ctx);
- if (ctx == active_ctx) {
- glDeleteVertexArrays(1, &vao_id);
- }
- else {
- orphans_add(ctx, &ctx->orphaned_vertarray_ids, vao_id);
- }
+ ctx->vao_free(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);
- }
+ ctx->fbo_free(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);
- }
+ /* FIXME active_ctx can be NULL */
+ BLI_assert(active_ctx);
+ active_ctx->buf_free(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
-}
-
-void gpu_context_active_framebuffer_set(GPUContext *ctx, GPUFrameBuffer *fb)
-{
- ctx->current_fbo = fb;
-}
-
-GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx)
-{
- return ctx->current_fbo;
-}
-
-struct GPUMatrixState *gpu_context_active_matrix_state_get()
-{
+ /* FIXME active_ctx can be NULL */
BLI_assert(active_ctx);
- return active_ctx->matrix_state;
+ active_ctx->tex_free(tex_id);
}
diff --git a/source/blender/gpu/intern/gpu_context_private.h b/source/blender/gpu/intern/gpu_context_private.h
deleted file mode 100644
index f64cdf439a1..00000000000
--- a/source/blender/gpu/intern/gpu_context_private.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup gpu
- *
- * This interface allow GPU to manage GL objects for multiple context and threads.
- */
-
-#ifndef __GPU_CONTEXT_PRIVATE_H__
-#define __GPU_CONTEXT_PRIVATE_H__
-
-#include "GPU_context.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct GPUFrameBuffer;
-
-GLuint GPU_vao_default(void);
-GLuint GPU_framebuffer_default(void);
-
-/* These require a gl ctx bound. */
-GLuint GPU_buf_alloc(void);
-GLuint GPU_tex_alloc(void);
-GLuint GPU_vao_alloc(void);
-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);
-
-void gpu_context_active_framebuffer_set(GPUContext *ctx, struct GPUFrameBuffer *fb);
-struct GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx);
-
-struct GPUMatrixState *gpu_context_active_matrix_state_get(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __GPU_CONTEXT_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh
new file mode 100644
index 00000000000..57e58d474a5
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_context_private.hh
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * This interface allow GPU to manage GL objects for multiple context and threads.
+ */
+
+#pragma once
+
+#include "GPU_context.h"
+
+#include <pthread.h>
+
+struct GPUBatch;
+struct GPUFrameBuffer;
+struct GPUMatrixState;
+
+// TODO(fclem) this requires too much refactor for now.
+// namespace blender {
+// namespace gpu {
+
+class GPUContext {
+ public:
+ GPUContext();
+ virtual ~GPUContext(){};
+
+ virtual void activate(void) = 0;
+ virtual void deactivate(void) = 0;
+
+ virtual void draw_batch(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count) = 0;
+ virtual void draw_primitive(GPUPrimType prim_type, int v_count) = 0;
+
+ virtual void batch_add(GPUBatch *){};
+ virtual void batch_remove(GPUBatch *){};
+
+ virtual void framebuffer_add(struct GPUFrameBuffer *){};
+ virtual void framebuffer_remove(struct GPUFrameBuffer *){};
+
+ /* TODO(fclem) These are gl specifics. To be hidden inside the gl backend. */
+ virtual GLuint default_framebuffer_get(void) = 0;
+ virtual GLuint buf_alloc(void) = 0;
+ virtual GLuint tex_alloc(void) = 0;
+ virtual GLuint vao_alloc(void) = 0;
+ virtual GLuint fbo_alloc(void) = 0;
+ virtual void vao_free(GLuint vao_id) = 0;
+ virtual void fbo_free(GLuint fbo_id) = 0;
+ virtual void buf_free(GLuint buf_id) = 0;
+ virtual void tex_free(GLuint tex_id) = 0;
+
+ /** State managment */
+ GPUFrameBuffer *current_fbo = NULL;
+ GPUMatrixState *matrix_state = NULL;
+
+ bool is_active_on_thread(void);
+
+ protected:
+ /** Thread on which this context is active. */
+ pthread_t thread_;
+ bool thread_is_used_;
+};
+
+/* Return context currently bound to the caller's thread.
+ * Note: this assume a context is active! */
+GPUContext *GPU_ctx(void);
+
+/* These require a gl ctx bound. */
+GLuint GPU_buf_alloc(void);
+GLuint GPU_tex_alloc(void);
+GLuint GPU_vao_alloc(void);
+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);
+
+// } // namespace gpu
+// } // namespace blender
diff --git a/source/blender/gpu/intern/gpu_element.cc b/source/blender/gpu/intern/gpu_element.cc
index 9f104ab3fec..e71eb805548 100644
--- a/source/blender/gpu/intern/gpu_element.cc
+++ b/source/blender/gpu/intern/gpu_element.cc
@@ -28,7 +28,7 @@
#include "GPU_element.h"
#include "GPU_glew.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include <stdlib.h>
diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc
index 056a449ac6d..657aef0a6c0 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.cc
+++ b/source/blender/gpu/intern/gpu_framebuffer.cc
@@ -33,7 +33,7 @@
#include "GPU_shader.h"
#include "GPU_texture.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include "gpu_private.h"
typedef enum {
@@ -188,10 +188,10 @@ GPUFrameBuffer *GPU_framebuffer_active_get(void)
{
GPUContext *ctx = GPU_context_active_get();
if (ctx) {
- return gpu_context_active_framebuffer_get(ctx);
+ return ctx->current_fbo;
}
else {
- return 0;
+ return NULL;
}
}
@@ -199,7 +199,7 @@ static void gpu_framebuffer_current_set(GPUFrameBuffer *fb)
{
GPUContext *ctx = GPU_context_active_get();
if (ctx) {
- gpu_context_active_framebuffer_set(ctx, fb);
+ ctx->current_fbo = fb;
}
}
@@ -216,7 +216,7 @@ static void gpu_framebuffer_init(GPUFrameBuffer *fb)
{
fb->object = GPU_fbo_alloc();
fb->ctx = GPU_context_active_get();
- gpu_context_add_framebuffer(fb->ctx, fb);
+ fb->ctx->framebuffer_add(fb);
}
void GPU_framebuffer_free(GPUFrameBuffer *fb)
@@ -231,7 +231,7 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
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);
+ fb->ctx->framebuffer_remove(fb);
}
if (GPU_framebuffer_active_get() == fb) {
@@ -560,7 +560,7 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
void GPU_framebuffer_restore(void)
{
if (GPU_framebuffer_active_get() != NULL) {
- glBindFramebuffer(GL_FRAMEBUFFER, GPU_framebuffer_default());
+ glBindFramebuffer(GL_FRAMEBUFFER, GPU_ctx()->default_framebuffer_get());
gpu_framebuffer_current_set(NULL);
glDisable(GL_FRAMEBUFFER_SRGB);
GPU_shader_set_framebuffer_srgb_target(false);
@@ -796,7 +796,7 @@ void GPU_framebuffer_blit(GPUFrameBuffer *fb_read,
gpu_framebuffer_current_set(prev_fb);
}
else {
- glBindFramebuffer(GL_FRAMEBUFFER, GPU_framebuffer_default());
+ glBindFramebuffer(GL_FRAMEBUFFER, GPU_ctx()->default_framebuffer_get());
gpu_framebuffer_current_set(NULL);
}
}
@@ -1037,7 +1037,7 @@ void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y)
gpu_print_framebuffer_error(status, NULL);
}
- glBindFramebuffer(GL_READ_FRAMEBUFFER, GPU_framebuffer_default());
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, GPU_ctx()->default_framebuffer_get());
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, eGPUDataFormat type, void *pixels)
diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc
index ac3e653c9ff..73ef511af96 100644
--- a/source/blender/gpu/intern/gpu_immediate.cc
+++ b/source/blender/gpu/intern/gpu_immediate.cc
@@ -33,7 +33,7 @@
#include "GPU_texture.h"
#include "gpu_attr_binding_private.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include "gpu_primitive_private.h"
#include "gpu_shader_private.h"
#include "gpu_vertex_format_private.h"
diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc
index c15bb1fba19..23505213cb4 100644
--- a/source/blender/gpu/intern/gpu_matrix.cc
+++ b/source/blender/gpu/intern/gpu_matrix.cc
@@ -23,7 +23,7 @@
#include "GPU_shader_interface.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include "gpu_matrix_private.h"
#define SUPPRESS_GENERIC_MATRIX_API
@@ -61,10 +61,10 @@ typedef struct GPUMatrixState {
*/
} GPUMatrixState;
-#define ModelViewStack gpu_context_active_matrix_state_get()->model_view_stack
+#define ModelViewStack GPU_ctx()->matrix_state->model_view_stack
#define ModelView ModelViewStack.stack[ModelViewStack.top]
-#define ProjectionStack gpu_context_active_matrix_state_get()->projection_stack
+#define ProjectionStack GPU_ctx()->matrix_state->projection_stack
#define Projection ProjectionStack.stack[ProjectionStack.top]
GPUMatrixState *GPU_matrix_state_create(void)
@@ -95,13 +95,13 @@ void GPU_matrix_state_discard(GPUMatrixState *state)
static void gpu_matrix_state_active_set_dirty(bool value)
{
- GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ GPUMatrixState *state = GPU_ctx()->matrix_state;
state->dirty = value;
}
void GPU_matrix_reset(void)
{
- GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ GPUMatrixState *state = GPU_ctx()->matrix_state;
state->model_view_stack.top = 0;
state->projection_stack.top = 0;
unit_m4(ModelView);
@@ -693,7 +693,7 @@ void GPU_matrix_bind(const GPUShaderInterface *shaderface)
bool GPU_matrix_dirty_get(void)
{
- GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ GPUMatrixState *state = GPU_ctx()->matrix_state;
return state->dirty;
}
@@ -706,13 +706,13 @@ BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mis
int GPU_matrix_stack_level_get_model_view(void)
{
- GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ GPUMatrixState *state = GPU_ctx()->matrix_state;
return (int)state->model_view_stack.top;
}
int GPU_matrix_stack_level_get_projection(void)
{
- GPUMatrixState *state = gpu_context_active_matrix_state_get();
+ GPUMatrixState *state = GPU_ctx()->matrix_state;
return (int)state->projection_stack.top;
}
diff --git a/source/blender/gpu/intern/gpu_shader_interface.cc b/source/blender/gpu/intern/gpu_shader_interface.cc
index b37c8176a16..ec14a59211c 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.cc
+++ b/source/blender/gpu/intern/gpu_shader_interface.cc
@@ -33,7 +33,7 @@
#include "GPU_shader_interface.h"
#include "gpu_batch_private.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include <stddef.h>
#include <stdlib.h>
diff --git a/source/blender/gpu/intern/gpu_texture.cc b/source/blender/gpu/intern/gpu_texture.cc
index 8a3a8a382f8..3f3316fc1b5 100644
--- a/source/blender/gpu/intern/gpu_texture.cc
+++ b/source/blender/gpu/intern/gpu_texture.cc
@@ -43,7 +43,7 @@
#include "GPU_platform.h"
#include "GPU_texture.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#define WARN_NOT_BOUND(_tex) \
{ \
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.cc b/source/blender/gpu/intern/gpu_uniformbuffer.cc
index b2e31894f9d..15bc412ce8d 100644
--- a/source/blender/gpu/intern/gpu_uniformbuffer.cc
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.cc
@@ -27,7 +27,7 @@
#include "BLI_blenlib.h"
#include "BLI_math_base.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include "gpu_node_graph.h"
#include "GPU_extensions.h"
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc
index eda6d1c7300..67ad8835b6a 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer.cc
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc
@@ -27,7 +27,7 @@
#include "GPU_vertex_buffer.h"
-#include "gpu_context_private.h"
+#include "gpu_context_private.hh"
#include "gpu_vertex_format_private.h"
#include <stdlib.h>
diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc
new file mode 100644
index 00000000000..9522a8f851d
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_batch.cc
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "BLI_assert.h"
+#include "BLI_utildefines.h"
+
+#include "GPU_glew.h"
+
+#include "gl_context.hh"
+
+using namespace blender::gpu;
+
+void GLContext::draw_batch(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count)
+{
+ /* Verify there is enough data do draw. */
+ /* TODO(fclem) Nice to have but this is invalid when using procedural draw-calls.
+ * The right assert would be to check if there is an enabled attribute from each VBO
+ * and check their length. */
+ // BLI_assert(i_first + i_count <= (batch->inst ? batch->inst->vertex_len : INT_MAX));
+ // BLI_assert(v_first + v_count <=
+ // (batch->elem ? batch->elem->index_len : batch->verts[0]->vertex_len));
+
+#ifdef __APPLE__
+ GLuint vao = 0;
+#endif
+
+ if (!GPU_arb_base_instance_is_supported()) {
+ if (i_first > 0) {
+#ifdef __APPLE__
+ /**
+ * There seems to be a nasty bug when drawing using the same VAO reconfiguring. (see T71147)
+ * We just use a throwaway VAO for that. Note that this is likely to degrade performance.
+ **/
+ glGenVertexArrays(1, &vao);
+ glBindVertexArray(vao);
+#else
+ /* If using offset drawing with instancing, we must
+ * use the default VAO and redo bindings. */
+ glBindVertexArray(default_vao_);
+#endif
+ batch_update_program_bindings(batch, i_first);
+ }
+ else {
+ /* Previous call could have bind the default vao
+ * see above. */
+ glBindVertexArray(batch->vao_id);
+ }
+ }
+
+ if (batch->elem) {
+ const GPUIndexBuf *el = batch->elem;
+ GLenum index_type = INDEX_TYPE(el);
+ GLint base_index = BASE_INDEX(el);
+ void *v_first_ofs = (GLuint *)0 + v_first + el->index_start;
+
+#if GPU_TRACK_INDEX_RANGE
+ if (el->index_type == GPU_INDEX_U16) {
+ v_first_ofs = (GLushort *)0 + v_first + el->index_start;
+ }
+#endif
+
+ if (GPU_arb_base_instance_is_supported()) {
+ glDrawElementsInstancedBaseVertexBaseInstance(
+ batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index, i_first);
+ }
+ else {
+ glDrawElementsInstancedBaseVertex(
+ batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index);
+ }
+ }
+ else {
+#ifdef __APPLE__
+ glDisable(GL_PRIMITIVE_RESTART);
+#endif
+ if (GPU_arb_base_instance_is_supported()) {
+ glDrawArraysInstancedBaseInstance(batch->gl_prim_type, v_first, v_count, i_count, i_first);
+ }
+ else {
+ glDrawArraysInstanced(batch->gl_prim_type, v_first, v_count, i_count);
+ }
+#ifdef __APPLE__
+ glEnable(GL_PRIMITIVE_RESTART);
+#endif
+ }
+
+#ifdef __APPLE__
+ if (vao != 0) {
+ glDeleteVertexArrays(1, &vao);
+ }
+#endif
+}
+
+void GLContext::draw_primitive(GPUPrimType prim_type, int v_count)
+{
+ /* we cannot draw without vao ... annoying ... */
+ glBindVertexArray(default_vao_);
+
+ GLenum type = convert_prim_type_to_gl(prim_type);
+ glDrawArrays(type, 0, v_count);
+
+ /* Performance hog if you are drawing with the same vao multiple time.
+ * Only activate for debugging.*/
+ // glBindVertexArray(0);
+} \ No newline at end of file
diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc
new file mode 100644
index 00000000000..918650e10c5
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_context.cc
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \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
+ */
+
+#include "BLI_assert.h"
+#include "BLI_utildefines.h"
+
+#include "GPU_framebuffer.h"
+
+#include "gpu_context_private.hh"
+
+#include "gl_context.hh"
+
+// TODO(fclem) this requires too much refactor for now.
+// using namespace blender::gpu;
+
+GLContext::GLContext() : GPUContext()
+{
+ glGenVertexArrays(1, &default_vao_);
+ /* TODO(fclem) call ghost here. */
+ // GHOST_GetDefaultOpenGLFramebuffer(g_WS.ghost_window);
+ default_framebuffer_ = 0;
+}
+
+GLContext::~GLContext()
+{
+ 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 */
+ GPU_batch_vao_cache_clear(*ctx->batches.begin());
+ }
+ GPU_matrix_state_discard(ctx->matrix_state);
+ glDeleteVertexArrays(1, &ctx->default_vao);
+}
+
+void GLContext::activate(void)
+{
+#ifdef DEBUG
+ /* Make sure no other context is already bound to this thread. */
+ BLI_assert(pthread_equal(pthread_self(), thread_));
+ /* Make sure no other thread has locked it. */
+ BLI_assert(thread_is_used_ == false);
+ thread_ = pthread_self();
+ thread_is_used_ = true;
+#endif
+ orphans_clear();
+};
+
+void GLContext::deactivate(void)
+{
+#ifdef DEBUG
+ thread_is_used_ = false;
+#endif
+};
+
+void GLContext::orphans_clear(void) override
+{
+ /* Check if context has been activated by another thread! */
+ BLI_assert(pthread_equal(pthread_self(), ctx->thread));
+
+ orphans_mutex_.lock();
+ if (!orphaned_vertarrays_.empty()) {
+ glDeleteVertexArrays((uint)orphaned_vertarrays_.size(), orphaned_vertarrays_.data());
+ orphaned_vertarrays_.clear();
+ }
+ if (!orphaned_framebuffers_.empty()) {
+ glDeleteFramebuffers((uint)orphaned_framebuffers_.size(), orphaned_framebuffers_.data());
+ orphaned_framebuffers_.clear();
+ }
+ if (!orphaned_buffers_.empty()) {
+ glDeleteBuffers((uint)orphaned_buffers_.size(), orphaned_buffers_.data());
+ orphaned_buffers_.clear();
+ }
+ if (!orphaned_textures_.empty()) {
+ glDeleteTextures((uint)orphaned_textures_.size(), orphaned_textures_.data());
+ orphaned_textures_.clear();
+ }
+ orphans_mutex_.unlock();
+};
+
+void GLContext::orphans_add(std::vector<GLuint> *orphan_list, GLuint id)
+{
+ orphans_mutex_->lock();
+ orphan_list->emplace_back(id);
+ orphans_mutex_->unlock();
+}
+
+void GLContext::vao_free(GLuint vao_id)
+{
+ if (ctx == GPU_context_active_get()) {
+ glDeleteVertexArrays(1, &vao_id);
+ }
+ else {
+ orphans_add(ctx, &ctx->orphaned_vertarray_ids, vao_id);
+ }
+}
+
+void GLContext::fbo_free(GLuint fbo_id)
+{
+ if (ctx == GPU_context_active_get()) {
+ glDeleteFramebuffers(1, &fbo_id);
+ }
+ else {
+ orphans_add(ctx, &ctx->orphaned_framebuffer_ids, fbo_id);
+ }
+}
+
+void GLContext::buf_free(GLuint buf_id)
+{
+ if (GPU_context_active_get()) {
+ glDeleteBuffers(1, &buf_id);
+ }
+ else {
+ orphans_add(&orphaned_buffer_ids, buf_id);
+ }
+}
+
+void GLContext::tex_free(GLuint tex_id)
+{
+ if (GPU_context_active_get()) {
+ glDeleteTextures(1, &tex_id);
+ }
+ else {
+ orphans_add(&orphaned_texture_ids, tex_id);
+ }
+}
+
+GLuint GLContext::vao_alloc(void)
+{
+ GLuint new_vao_id = 0;
+ orphans_clear();
+ glGenVertexArrays(1, &new_vao_id);
+ return new_vao_id;
+}
+
+GLuint GLContext::fbo_alloc(void)
+{
+ GLuint new_fbo_id = 0;
+ orphans_clear();
+ glGenFramebuffers(1, &new_fbo_id);
+ return new_fbo_id;
+}
+
+GLuint GLContext::buf_alloc(void)
+{
+ GLuint new_buffer_id = 0;
+ orphans_clear();
+ glGenBuffers(1, &new_buffer_id);
+ return new_buffer_id;
+}
+
+GLuint GLContext::tex_alloc(void)
+{
+ GLuint new_texture_id = 0;
+ orphans_clear();
+ glGenTextures(1, &new_texture_id);
+ return new_texture_id;
+}
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
new file mode 100644
index 00000000000..26643fb4b39
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -0,0 +1,93 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "../intern/gpu_context_private.hh"
+
+#include "glew-mx.h"
+
+#include <iostream>
+#include <mutex>
+#include <unordered_set>
+#include <vector>
+
+// TODO(fclem) this requires too much refactor for now.
+// namespace blender {
+// namespace gpu {
+
+class GLContext : public GPUContext {
+ public:
+ GLContext();
+ ~GLContext(){};
+
+ void activate(void) override;
+ void deactivate(void) override;
+
+ void draw_batch(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count) override;
+ void draw_primitive(GPUPrimType prim_type, int v_count) override;
+
+ void batch_add(GPUBatch *batch) override;
+ void batch_remove(GPUBatch *batch) override;
+
+ /* TODO remove */
+ GLuint tex_alloc(void) override;
+ GLuint vao_alloc(void) override;
+ GLuint buf_alloc(void) override;
+ GLuint fbo_alloc(void) override;
+ void vao_free(GLuint vao_id) override;
+ void fbo_free(GLuint fbo_id) override;
+ void buf_free(GLuint buf_id) override;
+ void tex_free(GLuint tex_id) override;
+ GLuint default_framebuffer_get(void) override
+ {
+ return default_framebuffer_;
+ };
+
+ private:
+ void orphans_add(std::vector<GLuint> *orphan_list, GLuint id);
+ void orphans_clear(void);
+
+ /**
+ * Batches & Framebuffers are not shared accross contexts.
+ * For this reason we keep a list of them per GPUBatch & GPUFramebuffer.
+ * However this list needs to be updated in the case a GPUContext is destroyed.
+ */
+ std::unordered_set<GPUBatch *> batches;
+ std::unordered_set<GPUFrameBuffer *> framebuffers;
+
+ std::vector<GLuint> orphaned_vertarrays_;
+ std::vector<GLuint> orphaned_framebuffers_;
+ std::vector<GLuint> orphaned_buffers_;
+ std::vector<GLuint> orphaned_textures_;
+
+ /** Mutex for the above structures. */
+ /** todo: try spinlock instead */
+ std::mutex orphans_mutex_;
+
+ GLuint default_vao_;
+ GLuint default_framebuffer_;
+};
+
+// } // namespace gpu
+// } // namespace blender