| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright 2020, Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup gpu | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_assert.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-25 14:47:23 +02:00
										 |  |  | #include "BLI_system.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 22:41:04 +02:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | #include "GPU_framebuffer.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "GHOST_C-api.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 03:01:45 +02:00
										 |  |  | #include "gpu_context_private.hh"
 | 
					
						
							| 
									
										
										
										
											2020-09-08 03:18:49 +02:00
										 |  |  | #include "gpu_immediate_private.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 22:41:04 +02:00
										 |  |  | #include "gl_debug.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-31 15:14:47 +02:00
										 |  |  | #include "gl_immediate.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-16 20:56:39 +02:00
										 |  |  | #include "gl_state.hh"
 | 
					
						
							| 
									
										
										
										
											2020-09-01 02:41:29 +02:00
										 |  |  | #include "gl_uniform_buffer.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-16 20:56:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | #include "gl_backend.hh" /* TODO remove */
 | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | #include "gl_context.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 18:04:46 -06:00
										 |  |  | using namespace blender; | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | using namespace blender::gpu; | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Constructor / Destructor
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | GLContext::GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list) | 
					
						
							|  |  |  |     : shared_orphan_list_(shared_orphan_list) | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-31 22:41:04 +02:00
										 |  |  |   if (G.debug & G_DEBUG_GPU) { | 
					
						
							|  |  |  |     debug::init_gl_callbacks(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   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); | 
					
						
							| 
									
										
										
										
											2020-08-16 20:56:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  |   state_manager = new GLStateManager(); | 
					
						
							| 
									
										
										
										
											2020-08-31 15:14:47 +02:00
										 |  |  |   imm = new GLImmediate(); | 
					
						
							| 
									
										
										
										
											2020-08-29 14:03:15 +02:00
										 |  |  |   ghost_window_ = ghost_window; | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (ghost_window) { | 
					
						
							|  |  |  |     GLuint default_fbo = GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window); | 
					
						
							|  |  |  |     GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window); | 
					
						
							|  |  |  |     int w = GHOST_GetWidthRectangle(bounds); | 
					
						
							|  |  |  |     int h = GHOST_GetHeightRectangle(bounds); | 
					
						
							|  |  |  |     GHOST_DisposeRectangle(bounds); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (default_fbo != 0) { | 
					
						
							| 
									
										
										
										
											2020-09-09 00:47:59 +02:00
										 |  |  |       /* Bind default framebuffer, otherwise state might be undefined because of
 | 
					
						
							|  |  |  |        * detect_mip_render_workaround(). */ | 
					
						
							|  |  |  |       glBindFramebuffer(GL_FRAMEBUFFER, default_fbo); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |       front_left = new GLFrameBuffer("front_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h); | 
					
						
							|  |  |  |       back_left = new GLFrameBuffer("back_left", this, GL_COLOR_ATTACHMENT0, default_fbo, w, h); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       front_left = new GLFrameBuffer("front_left", this, GL_FRONT_LEFT, 0, w, h); | 
					
						
							|  |  |  |       back_left = new GLFrameBuffer("back_left", this, GL_BACK_LEFT, 0, w, h); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-09-09 00:47:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 19:52:22 +02:00
										 |  |  |     GLboolean supports_stereo_quad_buffer = GL_FALSE; | 
					
						
							|  |  |  |     glGetBooleanv(GL_STEREO, &supports_stereo_quad_buffer); | 
					
						
							| 
									
										
										
										
											2020-08-29 01:13:54 +02:00
										 |  |  |     if (supports_stereo_quad_buffer) { | 
					
						
							|  |  |  |       front_right = new GLFrameBuffer("front_right", this, GL_FRONT_RIGHT, 0, w, h); | 
					
						
							|  |  |  |       back_right = new GLFrameBuffer("back_right", this, GL_BACK_RIGHT, 0, w, h); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* For offscreen contexts. Default framebuffer is NULL. */ | 
					
						
							|  |  |  |     back_left = new GLFrameBuffer("back_left", this, GL_NONE, 0, 0, 0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   active_fb = back_left; | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  |   static_cast<GLStateManager *>(state_manager)->active_fb = static_cast<GLFrameBuffer *>( | 
					
						
							| 
									
										
										
										
											2020-09-09 00:47:59 +02:00
										 |  |  |       active_fb); | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GLContext::~GLContext() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   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. */ | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   for (GLVaoCache *cache : vao_caches_) { | 
					
						
							|  |  |  |     cache->clear(); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   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(); | 
					
						
							| 
									
										
										
										
											2020-08-29 14:03:15 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (ghost_window_) { | 
					
						
							|  |  |  |     /* Get the correct framebuffer size for the internal framebuffers. */ | 
					
						
							|  |  |  |     GHOST_RectangleHandle bounds = GHOST_GetClientBounds((GHOST_WindowHandle)ghost_window_); | 
					
						
							|  |  |  |     int w = GHOST_GetWidthRectangle(bounds); | 
					
						
							|  |  |  |     int h = GHOST_GetHeightRectangle(bounds); | 
					
						
							|  |  |  |     GHOST_DisposeRectangle(bounds); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (front_left) { | 
					
						
							|  |  |  |       front_left->size_set(w, h); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (back_left) { | 
					
						
							|  |  |  |       back_left->size_set(w, h); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (front_right) { | 
					
						
							|  |  |  |       front_right->size_set(w, h); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (back_right) { | 
					
						
							|  |  |  |       back_right->size_set(w, h); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-01 02:41:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Not really following the state but we should consider
 | 
					
						
							|  |  |  |    * no ubo bound when activating a context. */ | 
					
						
							|  |  |  |   bound_ubo_slots = 0; | 
					
						
							| 
									
										
										
										
											2020-09-08 03:18:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   immActivate(); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLContext::deactivate(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 03:18:49 +02:00
										 |  |  |   immDeactivate(); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   is_active_ = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 00:10:37 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Flush, Finish & sync
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLContext::flush(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   glFlush(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLContext::finish(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   glFinish(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \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! */ | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   BLI_assert(GLContext::get()); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   if (this == GLContext::get()) { | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |     glDeleteVertexArrays(1, &vao_id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     orphans_add(orphaned_vertarrays_, lists_mutex_, vao_id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLContext::fbo_free(GLuint fbo_id) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   if (this == GLContext::get()) { | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |     glDeleteFramebuffers(1, &fbo_id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     orphans_add(orphaned_framebuffers_, lists_mutex_, fbo_id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 20:08:25 +02:00
										 |  |  | void GLContext::buf_free(GLuint buf_id) | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /* Any context can free. */ | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   if (GLContext::get()) { | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |     glDeleteBuffers(1, &buf_id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-09-07 20:08:25 +02:00
										 |  |  |     GLSharedOrphanLists &orphan_list = GLBackend::get()->shared_orphan_list_get(); | 
					
						
							|  |  |  |     orphans_add(orphan_list.buffers, orphan_list.lists_mutex, buf_id); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 20:08:25 +02:00
										 |  |  | void GLContext::tex_free(GLuint tex_id) | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /* Any context can free. */ | 
					
						
							| 
									
										
										
										
											2020-09-08 04:12:12 +02:00
										 |  |  |   if (GLContext::get()) { | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |     glDeleteTextures(1, &tex_id); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-09-07 20:08:25 +02:00
										 |  |  |     GLSharedOrphanLists &orphan_list = GLBackend::get()->shared_orphan_list_get(); | 
					
						
							|  |  |  |     orphans_add(orphan_list.textures, orphan_list.lists_mutex, tex_id); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Linked object deletion
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * These objects contain data that are stored per context. We | 
					
						
							| 
									
										
										
										
											2020-08-13 16:21:10 +10:00
										 |  |  |  * need to do some cleanup if they are used across context or if context | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |  * is discarded. | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | void GLContext::vao_cache_register(GLVaoCache *cache) | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   lists_mutex_.lock(); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   vao_caches_.add(cache); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   lists_mutex_.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  | void GLContext::vao_cache_unregister(GLVaoCache *cache) | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   lists_mutex_.lock(); | 
					
						
							| 
									
										
										
										
											2020-08-11 01:31:40 +02:00
										 |  |  |   vao_caches_.remove(cache); | 
					
						
							| 
									
										
										
										
											2020-08-08 01:18:18 +02:00
										 |  |  |   lists_mutex_.unlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 17:00:28 +02:00
										 |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2020-09-07 19:53:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Memory statistics
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLContext::memory_statistics_get(int *r_total_mem, int *r_free_mem) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* TODO(merwin): use Apple's platform API to get this info. */ | 
					
						
							|  |  |  |   if (GLEW_NVX_gpu_memory_info) { | 
					
						
							|  |  |  |     /* Teturned value in Kb. */ | 
					
						
							|  |  |  |     glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, r_total_mem); | 
					
						
							|  |  |  |     glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, r_free_mem); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (GLEW_ATI_meminfo) { | 
					
						
							|  |  |  |     int stats[4]; | 
					
						
							|  |  |  |     glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *r_total_mem = 0; | 
					
						
							|  |  |  |     *r_free_mem = stats[0]; /* Total memory free in the pool. */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     *r_total_mem = 0; | 
					
						
							|  |  |  |     *r_free_mem = 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ |