Blender  V2.93
gl_context.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2020, Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BLI_assert.h"
25 #include "BLI_system.h"
26 #include "BLI_utildefines.h"
27 
28 #include "BKE_global.h"
29 
30 #include "GPU_framebuffer.h"
31 
32 #include "GHOST_C-api.h"
33 
34 #include "gpu_context_private.hh"
35 #include "gpu_immediate_private.hh"
36 
37 #include "gl_debug.hh"
38 #include "gl_immediate.hh"
39 #include "gl_state.hh"
40 #include "gl_uniform_buffer.hh"
41 
42 #include "gl_backend.hh" /* TODO remove */
43 #include "gl_context.hh"
44 
45 using namespace blender;
46 using namespace blender::gpu;
47 
48 /* -------------------------------------------------------------------- */
52 GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list)
53  : shared_orphan_list_(shared_orphan_list)
54 {
55  if (G.debug & G_DEBUG_GPU) {
57  }
58 
59  float data[4] = {0.0f, 0.0f, 0.0f, 1.0f};
60  glGenBuffers(1, &default_attr_vbo_);
61  glBindBuffer(GL_ARRAY_BUFFER, default_attr_vbo_);
62  glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
63  glBindBuffer(GL_ARRAY_BUFFER, 0);
64 
66  imm = new GLImmediate();
67  ghost_window_ = ghost_window;
68 
69  if (ghost_window) {
70  GLuint default_fbo = GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window);
71  GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window);
75 
76  if (default_fbo != 0) {
77  /* Bind default framebuffer, otherwise state might be undefined because of
78  * detect_mip_render_workaround(). */
79  glBindFramebuffer(GL_FRAMEBUFFER, default_fbo);
80  front_left = new GLFrameBuffer("front_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h);
81  back_left = new GLFrameBuffer("back_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h);
82  }
83  else {
84  front_left = new GLFrameBuffer("front_left", this, GL_FRONT_LEFT, 0, w, h);
85  back_left = new GLFrameBuffer("back_left", this, GL_BACK_LEFT, 0, w, h);
86  }
87 
88  GLboolean supports_stereo_quad_buffer = GL_FALSE;
89  glGetBooleanv(GL_STEREO, &supports_stereo_quad_buffer);
90  if (supports_stereo_quad_buffer) {
91  front_right = new GLFrameBuffer("front_right", this, GL_FRONT_RIGHT, 0, w, h);
92  back_right = new GLFrameBuffer("back_right", this, GL_BACK_RIGHT, 0, w, h);
93  }
94  }
95  else {
96  /* For offscreen contexts. Default framebuffer is NULL. */
97  back_left = new GLFrameBuffer("back_left", this, GL_NONE, 0, 0, 0);
98  }
99 
101  static_cast<GLStateManager *>(state_manager)->active_fb = static_cast<GLFrameBuffer *>(
102  active_fb);
103 }
104 
106 {
107  BLI_assert(orphaned_framebuffers_.is_empty());
108  BLI_assert(orphaned_vertarrays_.is_empty());
109  /* For now don't allow GPUFrameBuffers to be reuse in another context. */
110  BLI_assert(framebuffers_.is_empty());
111  /* Delete VAO's so the batch can be reused in another context. */
112  for (GLVaoCache *cache : vao_caches_) {
113  cache->clear();
114  }
115  glDeleteBuffers(1, &default_attr_vbo_);
116 }
117 
120 /* -------------------------------------------------------------------- */
125 {
126  /* Make sure no other context is already bound to this thread. */
127  BLI_assert(is_active_ == false);
128 
129  is_active_ = true;
130  thread_ = pthread_self();
131 
132  /* Clear accumulated orphans. */
133  orphans_clear();
134 
135  if (ghost_window_) {
136  /* Get the correct framebuffer size for the internal framebuffers. */
137  GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window_);
141 
142  if (front_left) {
143  front_left->size_set(w, h);
144  }
145  if (back_left) {
146  back_left->size_set(w, h);
147  }
148  if (front_right) {
149  front_right->size_set(w, h);
150  }
151  if (back_right) {
152  back_right->size_set(w, h);
153  }
154  }
155 
156  /* Not really following the state but we should consider
157  * no ubo bound when activating a context. */
158  bound_ubo_slots = 0;
159 
160  immActivate();
161 }
162 
164 {
165  immDeactivate();
166  is_active_ = false;
167 }
168 
171 /* -------------------------------------------------------------------- */
176 {
177  glFlush();
178 }
179 
181 {
182  glFinish();
183 }
184 
187 /* -------------------------------------------------------------------- */
195 {
196  /* Check if any context is active on this thread! */
198 
199  lists_mutex.lock();
200  if (!buffers.is_empty()) {
201  glDeleteBuffers((uint)buffers.size(), buffers.data());
202  buffers.clear();
203  }
204  if (!textures.is_empty()) {
205  glDeleteTextures((uint)textures.size(), textures.data());
206  textures.clear();
207  }
208  lists_mutex.unlock();
209 };
210 
211 void GLContext::orphans_clear()
212 {
213  /* Check if context has been activated by another thread! */
215 
216  lists_mutex_.lock();
217  if (!orphaned_vertarrays_.is_empty()) {
218  glDeleteVertexArrays((uint)orphaned_vertarrays_.size(), orphaned_vertarrays_.data());
219  orphaned_vertarrays_.clear();
220  }
221  if (!orphaned_framebuffers_.is_empty()) {
222  glDeleteFramebuffers((uint)orphaned_framebuffers_.size(), orphaned_framebuffers_.data());
223  orphaned_framebuffers_.clear();
224  }
225  lists_mutex_.unlock();
226 
227  shared_orphan_list_.orphans_clear();
228 };
229 
230 void GLContext::orphans_add(Vector<GLuint> &orphan_list, std::mutex &list_mutex, GLuint id)
231 {
232  list_mutex.lock();
233  orphan_list.append(id);
234  list_mutex.unlock();
235 }
236 
237 void GLContext::vao_free(GLuint vao_id)
238 {
239  if (this == GLContext::get()) {
240  glDeleteVertexArrays(1, &vao_id);
241  }
242  else {
243  orphans_add(orphaned_vertarrays_, lists_mutex_, vao_id);
244  }
245 }
246 
247 void GLContext::fbo_free(GLuint fbo_id)
248 {
249  if (this == GLContext::get()) {
250  glDeleteFramebuffers(1, &fbo_id);
251  }
252  else {
253  orphans_add(orphaned_framebuffers_, lists_mutex_, fbo_id);
254  }
255 }
256 
257 void GLContext::buf_free(GLuint buf_id)
258 {
259  /* Any context can free. */
260  if (GLContext::get()) {
261  glDeleteBuffers(1, &buf_id);
262  }
263  else {
265  orphans_add(orphan_list.buffers, orphan_list.lists_mutex, buf_id);
266  }
267 }
268 
269 void GLContext::tex_free(GLuint tex_id)
270 {
271  /* Any context can free. */
272  if (GLContext::get()) {
273  glDeleteTextures(1, &tex_id);
274  }
275  else {
277  orphans_add(orphan_list.textures, orphan_list.lists_mutex, tex_id);
278  }
279 }
280 
283 /* -------------------------------------------------------------------- */
292 {
293  lists_mutex_.lock();
294  vao_caches_.add(cache);
295  lists_mutex_.unlock();
296 }
297 
299 {
300  lists_mutex_.lock();
301  vao_caches_.remove(cache);
302  lists_mutex_.unlock();
303 }
304 
307 /* -------------------------------------------------------------------- */
311 void GLContext::memory_statistics_get(int *r_total_mem, int *r_free_mem)
312 {
313  /* TODO(merwin): use Apple's platform API to get this info. */
314  if (GLEW_NVX_gpu_memory_info) {
315  /* Returned value in Kb. */
316  glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, r_total_mem);
317  glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, r_free_mem);
318  }
319  else if (GLEW_ATI_meminfo) {
320  int stats[4];
321  glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
322 
323  *r_total_mem = 0;
324  *r_free_mem = stats[0]; /* Total memory free in the pool. */
325  }
326  else {
327  *r_total_mem = 0;
328  *r_free_mem = 0;
329  }
330 }
331 
@ G_DEBUG_GPU
Definition: BKE_global.h:151
#define BLI_assert(a)
Definition: BLI_assert.h:58
unsigned int uint
Definition: BLI_sys_types.h:83
ThreadMutex mutex
GHOST C-API function and type declarations.
GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle)
void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle)
GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle)
unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windwHandle)
GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
bool is_empty() const
Definition: BLI_set.hh:534
int64_t size() const
Definition: BLI_vector.hh:662
void append(const T &value)
Definition: BLI_vector.hh:438
bool is_empty() const
Definition: BLI_vector.hh:674
bool is_active_on_thread(void)
Definition: gpu_context.cc:83
void size_set(int width, int height)
static GLBackend * get(void)
Definition: gl_backend.hh:64
GLSharedOrphanLists & shared_orphan_list_get(void)
Definition: gl_backend.hh:124
static void buf_free(GLuint buf_id)
Definition: gl_context.cc:257
void finish(void) override
Definition: gl_context.cc:180
void flush(void) override
Definition: gl_context.cc:175
void memory_statistics_get(int *total_mem, int *free_mem) override
Definition: gl_context.cc:311
void deactivate(void) override
Definition: gl_context.cc:163
void activate(void) override
Definition: gl_context.cc:124
GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list)
Definition: gl_context.cc:52
void vao_cache_unregister(GLVaoCache *cache)
Definition: gl_context.cc:298
static GLContext * get()
Definition: gl_context.hh:118
static void tex_free(GLuint tex_id)
Definition: gl_context.cc:269
void vao_free(GLuint vao_id)
Definition: gl_context.cc:237
void vao_cache_register(GLVaoCache *cache)
Definition: gl_context.cc:291
void fbo_free(GLuint fbo_id)
Definition: gl_context.cc:247
void immDeactivate()
void immActivate()
void init_gl_callbacks()
Definition: gl_debug.cc:144
#define G(x, y, z)