Blender V4.3
gl_context.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_assert.h"
10#include "BLI_utildefines.h"
11
12#include "BKE_global.hh"
13
14#include "GPU_framebuffer.hh"
15
16#include "GHOST_C-api.h"
17
20
21#include "gl_debug.hh"
22#include "gl_immediate.hh"
23#include "gl_state.hh"
24#include "gl_uniform_buffer.hh"
25
26#include "gl_backend.hh" /* TODO: remove. */
27#include "gl_context.hh"
28
29using namespace blender;
30using namespace blender::gpu;
31
32/* -------------------------------------------------------------------- */
36GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list)
37 : shared_orphan_list_(shared_orphan_list)
38{
39 if (G.debug & G_DEBUG_GPU) {
41 }
42
43 float data[4] = {0.0f, 0.0f, 0.0f, 1.0f};
44 glGenBuffers(1, &default_attr_vbo_);
45 glBindBuffer(GL_ARRAY_BUFFER, default_attr_vbo_);
46 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
47 glBindBuffer(GL_ARRAY_BUFFER, 0);
48
50 imm = new GLImmediate();
51 ghost_window_ = ghost_window;
52
53 if (ghost_window) {
54 GLuint default_fbo = GHOST_GetDefaultGPUFramebuffer((GHOST_WindowHandle)ghost_window);
55 GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window);
56 int w = GHOST_GetWidthRectangle(bounds);
57 int h = GHOST_GetHeightRectangle(bounds);
59
60 if (default_fbo != 0) {
61 /* Bind default framebuffer, otherwise state might be undefined because of
62 * detect_mip_render_workaround(). */
63 glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
64 front_left = new GLFrameBuffer("front_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h);
65 back_left = new GLFrameBuffer("back_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h);
66 }
67 else {
68 front_left = new GLFrameBuffer("front_left", this, GL_FRONT_LEFT, 0, w, h);
69 back_left = new GLFrameBuffer("back_left", this, GL_BACK_LEFT, 0, w, h);
70 }
71
72 GLboolean supports_stereo_quad_buffer = GL_FALSE;
73 glGetBooleanv(GL_STEREO, &supports_stereo_quad_buffer);
74 if (supports_stereo_quad_buffer) {
75 front_right = new GLFrameBuffer("front_right", this, GL_FRONT_RIGHT, 0, w, h);
76 back_right = new GLFrameBuffer("back_right", this, GL_BACK_RIGHT, 0, w, h);
77 }
78 }
79 else {
80 /* For off-screen contexts. Default frame-buffer is null. */
81 back_left = new GLFrameBuffer("back_left", this, GL_NONE, 0, 0, 0);
82 }
83
85 static_cast<GLStateManager *>(state_manager)->active_fb = static_cast<GLFrameBuffer *>(
86 active_fb);
87
89}
90
92{
93 BLI_assert(orphaned_framebuffers_.is_empty());
94 BLI_assert(orphaned_vertarrays_.is_empty());
95 /* For now don't allow GPUFrameBuffers to be reuse in another context. */
96 BLI_assert(framebuffers_.is_empty());
97 /* Delete VAO's so the batch can be reused in another context. */
98 for (GLVaoCache *cache : vao_caches_) {
99 cache->clear();
100 }
101 glDeleteBuffers(1, &default_attr_vbo_);
102}
103
106/* -------------------------------------------------------------------- */
111{
112 /* Make sure no other context is already bound to this thread. */
113 BLI_assert(is_active_ == false);
114
115 is_active_ = true;
116 thread_ = pthread_self();
117
118 /* Clear accumulated orphans. */
119 orphans_clear();
120
121 if (ghost_window_) {
122 /* Get the correct framebuffer size for the internal framebuffers. */
123 GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window_);
124 int w = GHOST_GetWidthRectangle(bounds);
125 int h = GHOST_GetHeightRectangle(bounds);
127
128 if (front_left) {
129 front_left->size_set(w, h);
130 }
131 if (back_left) {
132 back_left->size_set(w, h);
133 }
134 if (front_right) {
136 }
137 if (back_right) {
138 back_right->size_set(w, h);
139 }
140 }
141
142 /* Not really following the state but we should consider
143 * no ubo bound when activating a context. */
144 bound_ubo_slots = 0;
146
147 immActivate();
148}
149
151{
153 is_active_ = false;
154}
155
157{
158 /* No-op. */
159}
160
162{
163 /* No-op. */
164}
165
168/* -------------------------------------------------------------------- */
173{
174 glFlush();
175}
176
178{
179 glFinish();
180}
181
184/* -------------------------------------------------------------------- */
192{
193 /* Check if any context is active on this thread! */
195
196 lists_mutex.lock();
197 if (!buffers.is_empty()) {
198 glDeleteBuffers(uint(buffers.size()), buffers.data());
199 buffers.clear();
200 }
201 if (!textures.is_empty()) {
202 glDeleteTextures(uint(textures.size()), textures.data());
203 textures.clear();
204 }
205 lists_mutex.unlock();
206};
207
208void GLContext::orphans_clear()
209{
210 /* Check if context has been activated by another thread! */
212
213 lists_mutex_.lock();
214 if (!orphaned_vertarrays_.is_empty()) {
215 glDeleteVertexArrays(uint(orphaned_vertarrays_.size()), orphaned_vertarrays_.data());
216 orphaned_vertarrays_.clear();
217 }
218 if (!orphaned_framebuffers_.is_empty()) {
219 glDeleteFramebuffers(uint(orphaned_framebuffers_.size()), orphaned_framebuffers_.data());
220 orphaned_framebuffers_.clear();
221 }
222 lists_mutex_.unlock();
223
224 shared_orphan_list_.orphans_clear();
225};
226
227void GLContext::orphans_add(Vector<GLuint> &orphan_list, std::mutex &list_mutex, GLuint id)
228{
229 list_mutex.lock();
230 orphan_list.append(id);
231 list_mutex.unlock();
232}
233
234void GLContext::vao_free(GLuint vao_id)
235{
236 if (this == GLContext::get()) {
237 glDeleteVertexArrays(1, &vao_id);
238 }
239 else {
240 orphans_add(orphaned_vertarrays_, lists_mutex_, vao_id);
241 }
242}
243
244void GLContext::fbo_free(GLuint fbo_id)
245{
246 if (this == GLContext::get()) {
247 glDeleteFramebuffers(1, &fbo_id);
248 }
249 else {
250 orphans_add(orphaned_framebuffers_, lists_mutex_, fbo_id);
251 }
252}
253
254void GLContext::buf_free(GLuint buf_id)
255{
256 /* Any context can free. */
257 if (GLContext::get()) {
258 glDeleteBuffers(1, &buf_id);
259 }
260 else {
262 orphans_add(orphan_list.buffers, orphan_list.lists_mutex, buf_id);
263 }
264}
265
266void GLContext::tex_free(GLuint tex_id)
267{
268 /* Any context can free. */
269 if (GLContext::get()) {
270 glDeleteTextures(1, &tex_id);
271 }
272 else {
274 orphans_add(orphan_list.textures, orphan_list.lists_mutex, tex_id);
275 }
276}
277
280/* -------------------------------------------------------------------- */
289{
290 lists_mutex_.lock();
291 vao_caches_.add(cache);
292 lists_mutex_.unlock();
293}
294
296{
297 lists_mutex_.lock();
298 vao_caches_.remove(cache);
299 lists_mutex_.unlock();
300}
301
304/* -------------------------------------------------------------------- */
308void GLContext::memory_statistics_get(int *r_total_mem, int *r_free_mem)
309{
310 if (epoxy_has_gl_extension("GL_NVX_gpu_memory_info")) {
311 /* Returned value in Kb. */
312 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, r_total_mem);
313 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, r_free_mem);
314 }
315 else if (epoxy_has_gl_extension("GL_ATI_meminfo")) {
316 int stats[4];
317 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
318
319 *r_total_mem = 0;
320 *r_free_mem = stats[0]; /* Total memory free in the pool. */
321 }
322 else {
323 *r_total_mem = 0;
324 *r_free_mem = 0;
325 }
326}
327
@ G_DEBUG_GPU
#define BLI_assert(a)
Definition BLI_assert.h:50
unsigned int uint
GHOST C-API function and type declarations.
int32_t GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle)
void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle)
int32_t GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle)
unsigned int GHOST_GetDefaultGPUFramebuffer(GHOST_WindowHandle windowhandle)
GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
bool is_empty() const
Definition BLI_set.hh:572
int64_t size() const
void append(const T &value)
bool is_empty() const
void size_set(int width, int height)
GLSharedOrphanLists & shared_orphan_list_get()
GLShaderCompiler * get_compiler()
Definition gl_backend.hh:70
static GLBackend * get()
Definition gl_backend.hh:65
static void buf_free(GLuint buf_id)
void memory_statistics_get(int *r_total_mem, int *r_free_mem) override
void begin_frame() override
void activate() override
void flush() override
GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list)
Definition gl_context.cc:36
void vao_cache_unregister(GLVaoCache *cache)
static GLContext * get()
void finish() override
static void tex_free(GLuint tex_id)
void deactivate() override
void vao_free(GLuint vao_id)
void end_frame() override
void vao_cache_register(GLVaoCache *cache)
void fbo_free(GLuint fbo_id)
void immDeactivate()
void immActivate()
#define G(x, y, z)