| 
									
										
										
										
											2020-08-16 14:01:07 +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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup gpu | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:35:38 +02:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | #include "BLI_math_base.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:35:38 +02:00
										 |  |  | #include "BLI_math_bits.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-07 19:35:56 +02:00
										 |  |  | #include "GPU_capabilities.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "glew-mx.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 18:18:43 +02:00
										 |  |  | #include "gl_context.hh"
 | 
					
						
							| 
									
										
										
										
											2020-09-09 00:47:59 +02:00
										 |  |  | #include "gl_debug.hh"
 | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | #include "gl_framebuffer.hh"
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | #include "gl_texture.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | #include "gl_state.hh"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | namespace blender::gpu { | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | /** \name GLStateManager
 | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | GLStateManager::GLStateManager() | 
					
						
							| 
									
										
										
										
											2020-08-17 20:32:20 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /* Set other states that never change. */ | 
					
						
							|  |  |  |   glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); | 
					
						
							|  |  |  |   glEnable(GL_MULTISAMPLE); | 
					
						
							|  |  |  |   glEnable(GL_PRIMITIVE_RESTART); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   glDisable(GL_DITHER); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 
					
						
							|  |  |  |   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   glPrimitiveRestartIndex((GLuint)0xFFFFFFFF); | 
					
						
							|  |  |  |   /* TODO: Should become default. But needs at least GL 4.3 */ | 
					
						
							| 
									
										
										
										
											2020-09-10 14:18:19 +02:00
										 |  |  |   if (GLContext::fixed_restart_index_support) { | 
					
						
							| 
									
										
										
										
											2020-09-06 01:45:38 +10:00
										 |  |  |     /* Takes precedence over #GL_PRIMITIVE_RESTART. */ | 
					
						
							| 
									
										
										
										
											2020-08-17 20:32:20 +02:00
										 |  |  |     glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 18:18:43 +02:00
										 |  |  |   /* Limits. */ | 
					
						
							|  |  |  |   glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, line_width_range_); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 20:32:20 +02:00
										 |  |  |   /* Force update using default state. */ | 
					
						
							|  |  |  |   current_ = ~state; | 
					
						
							|  |  |  |   current_mutable_ = ~mutable_state; | 
					
						
							|  |  |  |   set_state(state); | 
					
						
							|  |  |  |   set_mutable_state(mutable_state); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLStateManager::apply_state() | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-09 15:12:28 +02:00
										 |  |  |   if (!this->use_bgl) { | 
					
						
							|  |  |  |     this->set_state(this->state); | 
					
						
							|  |  |  |     this->set_mutable_state(this->mutable_state); | 
					
						
							|  |  |  |     this->texture_bind_apply(); | 
					
						
							|  |  |  |     this->image_bind_apply(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /* This is needed by gpu_py_offscreen. */ | 
					
						
							| 
									
										
										
										
											2020-08-29 15:17:13 +02:00
										 |  |  |   active_fb->apply_state(); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-09 15:12:28 +02:00
										 |  |  | /* Will set all the states regardless of the current ones. */ | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLStateManager::force_state() | 
					
						
							| 
									
										
										
										
											2020-09-12 17:29:37 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /* Little exception for clip distances since they need to keep the old count correct. */ | 
					
						
							|  |  |  |   uint32_t clip_distances = current_.clip_distances; | 
					
						
							|  |  |  |   current_ = ~this->state; | 
					
						
							|  |  |  |   current_.clip_distances = clip_distances; | 
					
						
							|  |  |  |   current_mutable_ = ~this->mutable_state; | 
					
						
							|  |  |  |   this->set_state(this->state); | 
					
						
							|  |  |  |   this->set_mutable_state(this->mutable_state); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_state(const GPUState &state) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GPUState changed = state ^ current_; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 20:56:39 +02:00
										 |  |  |   if (changed.blend != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-19 17:10:18 +02:00
										 |  |  |     set_blend((eGPUBlend)state.blend); | 
					
						
							| 
									
										
										
										
											2020-08-16 20:56:39 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   if (changed.write_mask != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-19 17:10:18 +02:00
										 |  |  |     set_write_mask((eGPUWriteMask)state.write_mask); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (changed.depth_test != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-19 17:10:18 +02:00
										 |  |  |     set_depth_test((eGPUDepthTest)state.depth_test); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (changed.stencil_test != 0 || changed.stencil_op != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-19 17:10:18 +02:00
										 |  |  |     set_stencil_test((eGPUStencilTest)state.stencil_test, (eGPUStencilOp)state.stencil_op); | 
					
						
							|  |  |  |     set_stencil_mask((eGPUStencilTest)state.stencil_test, mutable_state); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (changed.clip_distances != 0) { | 
					
						
							|  |  |  |     set_clip_distances(state.clip_distances, current_.clip_distances); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (changed.culling_test != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-19 17:10:18 +02:00
										 |  |  |     set_backface_culling((eGPUFaceCullTest)state.culling_test); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (changed.logic_op_xor != 0) { | 
					
						
							|  |  |  |     set_logic_op(state.logic_op_xor); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (changed.invert_facing != 0) { | 
					
						
							|  |  |  |     set_facing(state.invert_facing); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (changed.provoking_vert != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-19 17:10:18 +02:00
										 |  |  |     set_provoking_vert((eGPUProvokingVertex)state.provoking_vert); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (changed.shadow_bias != 0) { | 
					
						
							|  |  |  |     set_shadow_bias(state.shadow_bias); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* TODO remove */ | 
					
						
							|  |  |  |   if (changed.polygon_smooth) { | 
					
						
							|  |  |  |     if (state.polygon_smooth) { | 
					
						
							|  |  |  |       glEnable(GL_POLYGON_SMOOTH); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       glDisable(GL_POLYGON_SMOOTH); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (changed.line_smooth) { | 
					
						
							|  |  |  |     if (state.line_smooth) { | 
					
						
							|  |  |  |       glEnable(GL_LINE_SMOOTH); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       glDisable(GL_LINE_SMOOTH); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   current_ = state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_mutable_state(const GPUStateMutable &state) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GPUStateMutable changed = state ^ current_mutable_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* TODO remove, should be uniform. */ | 
					
						
							| 
									
										
										
										
											2020-09-10 23:55:22 +02:00
										 |  |  |   if (float_as_uint(changed.point_size) != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  |     if (state.point_size > 0.0f) { | 
					
						
							|  |  |  |       glEnable(GL_PROGRAM_POINT_SIZE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       glDisable(GL_PROGRAM_POINT_SIZE); | 
					
						
							| 
									
										
										
										
											2020-09-10 15:51:20 +02:00
										 |  |  |       glPointSize(fabsf(state.point_size)); | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (changed.line_width != 0) { | 
					
						
							|  |  |  |     /* TODO remove, should use wide line shader. */ | 
					
						
							| 
									
										
										
										
											2020-08-25 18:18:43 +02:00
										 |  |  |     glLineWidth(clamp_f(state.line_width, line_width_range_[0], line_width_range_[1])); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (changed.depth_range[0] != 0 || changed.depth_range[1] != 0) { | 
					
						
							|  |  |  |     /* TODO remove, should modify the projection matrix instead. */ | 
					
						
							|  |  |  |     glDepthRange(UNPACK2(state.depth_range)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (changed.stencil_compare_mask != 0 || changed.stencil_reference != 0 || | 
					
						
							|  |  |  |       changed.stencil_write_mask != 0) { | 
					
						
							| 
									
										
										
										
											2020-08-19 17:10:18 +02:00
										 |  |  |     set_stencil_mask((eGPUStencilTest)current_.stencil_test, state); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   current_mutable_ = state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name State set functions
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_write_mask(const eGPUWriteMask value) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   glDepthMask((value & GPU_WRITE_DEPTH) != 0); | 
					
						
							|  |  |  |   glColorMask((value & GPU_WRITE_RED) != 0, | 
					
						
							|  |  |  |               (value & GPU_WRITE_GREEN) != 0, | 
					
						
							|  |  |  |               (value & GPU_WRITE_BLUE) != 0, | 
					
						
							|  |  |  |               (value & GPU_WRITE_ALPHA) != 0); | 
					
						
							| 
									
										
										
										
											2020-08-17 18:11:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (value == GPU_WRITE_NONE) { | 
					
						
							|  |  |  |     glEnable(GL_RASTERIZER_DISCARD); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glDisable(GL_RASTERIZER_DISCARD); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_depth_test(const eGPUDepthTest value) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GLenum func; | 
					
						
							|  |  |  |   switch (value) { | 
					
						
							|  |  |  |     case GPU_DEPTH_LESS: | 
					
						
							|  |  |  |       func = GL_LESS; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_DEPTH_LESS_EQUAL: | 
					
						
							|  |  |  |       func = GL_LEQUAL; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_DEPTH_EQUAL: | 
					
						
							|  |  |  |       func = GL_EQUAL; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_DEPTH_GREATER: | 
					
						
							|  |  |  |       func = GL_GREATER; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_DEPTH_GREATER_EQUAL: | 
					
						
							|  |  |  |       func = GL_GEQUAL; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_DEPTH_ALWAYS: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       func = GL_ALWAYS; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (value != GPU_DEPTH_NONE) { | 
					
						
							|  |  |  |     glEnable(GL_DEPTH_TEST); | 
					
						
							|  |  |  |     glDepthFunc(func); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glDisable(GL_DEPTH_TEST); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_stencil_test(const eGPUStencilTest test, const eGPUStencilOp operation) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   switch (operation) { | 
					
						
							|  |  |  |     case GPU_STENCIL_OP_REPLACE: | 
					
						
							|  |  |  |       glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_STENCIL_OP_COUNT_DEPTH_PASS: | 
					
						
							|  |  |  |       glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP); | 
					
						
							|  |  |  |       glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_STENCIL_OP_COUNT_DEPTH_FAIL: | 
					
						
							|  |  |  |       glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); | 
					
						
							|  |  |  |       glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_STENCIL_OP_NONE: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (test != GPU_STENCIL_NONE) { | 
					
						
							|  |  |  |     glEnable(GL_STENCIL_TEST); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glDisable(GL_STENCIL_TEST); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_stencil_mask(const eGPUStencilTest test, const GPUStateMutable state) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GLenum func; | 
					
						
							|  |  |  |   switch (test) { | 
					
						
							|  |  |  |     case GPU_STENCIL_NEQUAL: | 
					
						
							|  |  |  |       func = GL_NOTEQUAL; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_STENCIL_EQUAL: | 
					
						
							|  |  |  |       func = GL_EQUAL; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_STENCIL_ALWAYS: | 
					
						
							|  |  |  |       func = GL_ALWAYS; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case GPU_STENCIL_NONE: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       glStencilMask(0x00); | 
					
						
							|  |  |  |       glStencilFunc(GL_ALWAYS, 0x00, 0x00); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   glStencilMask(state.stencil_write_mask); | 
					
						
							|  |  |  |   glStencilFunc(func, state.stencil_reference, state.stencil_compare_mask); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_clip_distances(const int new_dist_len, const int old_dist_len) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   for (int i = 0; i < new_dist_len; i++) { | 
					
						
							|  |  |  |     glEnable(GL_CLIP_DISTANCE0 + i); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   for (int i = new_dist_len; i < old_dist_len; i++) { | 
					
						
							|  |  |  |     glDisable(GL_CLIP_DISTANCE0 + i); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_logic_op(const bool enable) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   if (enable) { | 
					
						
							|  |  |  |     glEnable(GL_COLOR_LOGIC_OP); | 
					
						
							|  |  |  |     glLogicOp(GL_XOR); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glDisable(GL_COLOR_LOGIC_OP); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_facing(const bool invert) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   glFrontFace((invert) ? GL_CW : GL_CCW); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_backface_culling(const eGPUFaceCullTest test) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   if (test != GPU_CULL_NONE) { | 
					
						
							|  |  |  |     glEnable(GL_CULL_FACE); | 
					
						
							|  |  |  |     glCullFace((test == GPU_CULL_FRONT) ? GL_FRONT : GL_BACK); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-17 20:32:20 +02:00
										 |  |  |   else { | 
					
						
							|  |  |  |     glDisable(GL_CULL_FACE); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_provoking_vert(const eGPUProvokingVertex vert) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   GLenum value = (vert == GPU_VERTEX_FIRST) ? GL_FIRST_VERTEX_CONVENTION : | 
					
						
							|  |  |  |                                               GL_LAST_VERTEX_CONVENTION; | 
					
						
							|  |  |  |   glProvokingVertex(value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_shadow_bias(const bool enable) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   if (enable) { | 
					
						
							|  |  |  |     glEnable(GL_POLYGON_OFFSET_FILL); | 
					
						
							|  |  |  |     glEnable(GL_POLYGON_OFFSET_LINE); | 
					
						
							|  |  |  |     /* 2.0 Seems to be the lowest possible slope bias that works in every case. */ | 
					
						
							|  |  |  |     glPolygonOffset(2.0f, 1.0f); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glDisable(GL_POLYGON_OFFSET_FILL); | 
					
						
							|  |  |  |     glDisable(GL_POLYGON_OFFSET_LINE); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-17 00:34:06 +02:00
										 |  |  | void GLStateManager::set_blend(const eGPUBlend value) | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   /**
 | 
					
						
							|  |  |  |    * Factors to the equation. | 
					
						
							|  |  |  |    * SRC is fragment shader output. | 
					
						
							| 
									
										
										
										
											2020-09-06 02:21:27 +10:00
										 |  |  |    * DST is frame-buffer color. | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |    * final.rgb = SRC.rgb * src_rgb + DST.rgb * dst_rgb; | 
					
						
							|  |  |  |    * final.a = SRC.a * src_alpha + DST.a * dst_alpha; | 
					
						
							| 
									
										
										
										
											2021-01-04 12:00:18 +11:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   GLenum src_rgb, src_alpha, dst_rgb, dst_alpha; | 
					
						
							|  |  |  |   switch (value) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case GPU_BLEND_ALPHA: { | 
					
						
							|  |  |  |       src_rgb = GL_SRC_ALPHA; | 
					
						
							|  |  |  |       dst_rgb = GL_ONE_MINUS_SRC_ALPHA; | 
					
						
							|  |  |  |       src_alpha = GL_ONE; | 
					
						
							|  |  |  |       dst_alpha = GL_ONE_MINUS_SRC_ALPHA; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case GPU_BLEND_ALPHA_PREMULT: { | 
					
						
							|  |  |  |       src_rgb = GL_ONE; | 
					
						
							|  |  |  |       dst_rgb = GL_ONE_MINUS_SRC_ALPHA; | 
					
						
							|  |  |  |       src_alpha = GL_ONE; | 
					
						
							|  |  |  |       dst_alpha = GL_ONE_MINUS_SRC_ALPHA; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case GPU_BLEND_ADDITIVE: { | 
					
						
							|  |  |  |       /* Do not let alpha accumulate but premult the source RGB by it. */ | 
					
						
							|  |  |  |       src_rgb = GL_SRC_ALPHA; | 
					
						
							|  |  |  |       dst_rgb = GL_ONE; | 
					
						
							|  |  |  |       src_alpha = GL_ZERO; | 
					
						
							|  |  |  |       dst_alpha = GL_ONE; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case GPU_BLEND_SUBTRACT: | 
					
						
							|  |  |  |     case GPU_BLEND_ADDITIVE_PREMULT: { | 
					
						
							|  |  |  |       /* Let alpha accumulate. */ | 
					
						
							|  |  |  |       src_rgb = GL_ONE; | 
					
						
							|  |  |  |       dst_rgb = GL_ONE; | 
					
						
							|  |  |  |       src_alpha = GL_ONE; | 
					
						
							|  |  |  |       dst_alpha = GL_ONE; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case GPU_BLEND_MULTIPLY: { | 
					
						
							|  |  |  |       src_rgb = GL_DST_COLOR; | 
					
						
							|  |  |  |       dst_rgb = GL_ZERO; | 
					
						
							|  |  |  |       src_alpha = GL_DST_ALPHA; | 
					
						
							|  |  |  |       dst_alpha = GL_ZERO; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case GPU_BLEND_INVERT: { | 
					
						
							|  |  |  |       src_rgb = GL_ONE_MINUS_DST_COLOR; | 
					
						
							|  |  |  |       dst_rgb = GL_ZERO; | 
					
						
							|  |  |  |       src_alpha = GL_ZERO; | 
					
						
							|  |  |  |       dst_alpha = GL_ONE; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case GPU_BLEND_OIT: { | 
					
						
							|  |  |  |       src_rgb = GL_ONE; | 
					
						
							|  |  |  |       dst_rgb = GL_ONE; | 
					
						
							|  |  |  |       src_alpha = GL_ZERO; | 
					
						
							|  |  |  |       dst_alpha = GL_ONE_MINUS_SRC_ALPHA; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case GPU_BLEND_BACKGROUND: { | 
					
						
							|  |  |  |       src_rgb = GL_ONE_MINUS_DST_ALPHA; | 
					
						
							|  |  |  |       dst_rgb = GL_SRC_ALPHA; | 
					
						
							|  |  |  |       src_alpha = GL_ZERO; | 
					
						
							|  |  |  |       dst_alpha = GL_SRC_ALPHA; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-03 14:39:50 +01:00
										 |  |  |     case GPU_BLEND_ALPHA_UNDER_PREMUL: { | 
					
						
							|  |  |  |       src_rgb = GL_ONE_MINUS_DST_ALPHA; | 
					
						
							|  |  |  |       dst_rgb = GL_ONE; | 
					
						
							|  |  |  |       src_alpha = GL_ONE_MINUS_DST_ALPHA; | 
					
						
							|  |  |  |       dst_alpha = GL_ONE; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |     case GPU_BLEND_CUSTOM: { | 
					
						
							|  |  |  |       src_rgb = GL_ONE; | 
					
						
							|  |  |  |       dst_rgb = GL_SRC1_COLOR; | 
					
						
							|  |  |  |       src_alpha = GL_ONE; | 
					
						
							|  |  |  |       dst_alpha = GL_SRC1_ALPHA; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 14:12:02 +01:00
										 |  |  |   if (value == GPU_BLEND_SUBTRACT) { | 
					
						
							|  |  |  |     glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glBlendEquation(GL_FUNC_ADD); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 12:40:27 +02:00
										 |  |  |   /* Always set the blend function. This avoid a rendering error when blending is disabled but
 | 
					
						
							| 
									
										
										
										
											2020-09-06 02:21:27 +10:00
										 |  |  |    * GPU_BLEND_CUSTOM was used just before and the frame-buffer is using more than 1 color target. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:40:27 +02:00
										 |  |  |   glBlendFuncSeparate(src_rgb, dst_rgb, src_alpha, dst_alpha); | 
					
						
							| 
									
										
										
										
											2020-08-16 14:01:07 +02:00
										 |  |  |   if (value != GPU_BLEND_NONE) { | 
					
						
							|  |  |  |     glEnable(GL_BLEND); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     glDisable(GL_BLEND); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							| 
									
										
										
										
											2020-09-06 02:21:27 +10:00
										 |  |  | /** \name Texture State Management
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:31:53 +02:00
										 |  |  | void GLStateManager::texture_bind(Texture *tex_, eGPUSamplerState sampler_type, int unit) | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   BLI_assert(unit < GPU_max_textures()); | 
					
						
							|  |  |  |   GLTexture *tex = static_cast<GLTexture *>(tex_); | 
					
						
							| 
									
										
										
										
											2020-09-05 17:36:13 +02:00
										 |  |  |   if (G.debug & G_DEBUG_GPU) { | 
					
						
							|  |  |  |     tex->check_feedback_loop(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-05 17:35:38 +02:00
										 |  |  |   /* Eliminate redundant binds. */ | 
					
						
							|  |  |  |   if ((textures_[unit] == tex->tex_id_) && | 
					
						
							|  |  |  |       (samplers_[unit] == GLTexture::samplers_[sampler_type])) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |   targets_[unit] = tex->target_; | 
					
						
							|  |  |  |   textures_[unit] = tex->tex_id_; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:31:53 +02:00
										 |  |  |   samplers_[unit] = GLTexture::samplers_[sampler_type]; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |   tex->is_bound_ = true; | 
					
						
							| 
									
										
										
										
											2020-09-05 18:47:02 +02:00
										 |  |  |   dirty_texture_binds_ |= 1ULL << unit; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Bind the texture to slot 0 for editing purpose. Used by legacy pipeline. */ | 
					
						
							|  |  |  | void GLStateManager::texture_bind_temp(GLTexture *tex) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   glActiveTexture(GL_TEXTURE0); | 
					
						
							|  |  |  |   glBindTexture(tex->target_, tex->tex_id_); | 
					
						
							| 
									
										
										
										
											2020-09-06 02:21:27 +10:00
										 |  |  |   /* Will reset the first texture that was originally bound to slot 0 back before drawing. */ | 
					
						
							| 
									
										
										
										
											2020-09-05 18:47:02 +02:00
										 |  |  |   dirty_texture_binds_ |= 1ULL; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |   /* NOTE: This might leave this texture attached to this target even after update.
 | 
					
						
							|  |  |  |    * In practice it is not causing problems as we have incorrect binding detection | 
					
						
							|  |  |  |    * at higher level. */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLStateManager::texture_unbind(Texture *tex_) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GLTexture *tex = static_cast<GLTexture *>(tex_); | 
					
						
							|  |  |  |   if (!tex->is_bound_) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GLuint tex_id = tex->tex_id_; | 
					
						
							|  |  |  |   for (int i = 0; i < ARRAY_SIZE(textures_); i++) { | 
					
						
							|  |  |  |     if (textures_[i] == tex_id) { | 
					
						
							|  |  |  |       textures_[i] = 0; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:31:53 +02:00
										 |  |  |       samplers_[i] = 0; | 
					
						
							| 
									
										
										
										
											2020-09-05 18:47:02 +02:00
										 |  |  |       dirty_texture_binds_ |= 1ULL << i; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   tex->is_bound_ = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLStateManager::texture_unbind_all() | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   for (int i = 0; i < ARRAY_SIZE(textures_); i++) { | 
					
						
							|  |  |  |     if (textures_[i] != 0) { | 
					
						
							|  |  |  |       textures_[i] = 0; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:31:53 +02:00
										 |  |  |       samplers_[i] = 0; | 
					
						
							| 
									
										
										
										
											2020-09-05 18:47:02 +02:00
										 |  |  |       dirty_texture_binds_ |= 1ULL << i; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   this->texture_bind_apply(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLStateManager::texture_bind_apply() | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   if (dirty_texture_binds_ == 0) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-09-05 17:35:38 +02:00
										 |  |  |   uint64_t dirty_bind = dirty_texture_binds_; | 
					
						
							|  |  |  |   dirty_texture_binds_ = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int first = bitscan_forward_uint64(dirty_bind); | 
					
						
							|  |  |  |   int last = 64 - bitscan_reverse_uint64(dirty_bind); | 
					
						
							|  |  |  |   int count = last - first; | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-10 14:18:19 +02:00
										 |  |  |   if (GLContext::multi_bind_support) { | 
					
						
							| 
									
										
										
										
											2020-09-05 17:35:38 +02:00
										 |  |  |     glBindTextures(first, count, textures_ + first); | 
					
						
							|  |  |  |     glBindSamplers(first, count, samplers_ + first); | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-09-05 17:35:38 +02:00
										 |  |  |     for (int unit = first; unit < last; unit++) { | 
					
						
							|  |  |  |       if ((dirty_bind >> unit) & 1UL) { | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |         glActiveTexture(GL_TEXTURE0 + unit); | 
					
						
							|  |  |  |         glBindTexture(targets_[unit], textures_[unit]); | 
					
						
							| 
									
										
										
										
											2020-09-05 17:31:53 +02:00
										 |  |  |         glBindSampler(unit, samplers_[unit]); | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-08 00:30:38 +02:00
										 |  |  | void GLStateManager::texture_unpack_row_length_set(uint len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   glPixelStorei(GL_UNPACK_ROW_LENGTH, len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | uint64_t GLStateManager::bound_texture_slots() | 
					
						
							| 
									
										
										
										
											2020-09-04 22:19:36 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   uint64_t bound_slots = 0; | 
					
						
							|  |  |  |   for (int i = 0; i < ARRAY_SIZE(textures_); i++) { | 
					
						
							|  |  |  |     if (textures_[i] != 0) { | 
					
						
							| 
									
										
										
										
											2020-09-05 18:47:02 +02:00
										 |  |  |       bound_slots |= 1ULL << i; | 
					
						
							| 
									
										
										
										
											2020-09-04 22:19:36 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return bound_slots; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-05 17:29:51 +02:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-12 06:10:11 +02:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Image Binding (from image load store)
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLStateManager::image_bind(Texture *tex_, int unit) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Minimum support is 8 image in the fragment shader. No image for other stages. */ | 
					
						
							|  |  |  |   BLI_assert(GPU_shader_image_load_store_support() && unit < 8); | 
					
						
							|  |  |  |   GLTexture *tex = static_cast<GLTexture *>(tex_); | 
					
						
							|  |  |  |   if (G.debug & G_DEBUG_GPU) { | 
					
						
							|  |  |  |     tex->check_feedback_loop(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   images_[unit] = tex->tex_id_; | 
					
						
							|  |  |  |   formats_[unit] = to_gl_internal_format(tex->format_); | 
					
						
							|  |  |  |   tex->is_bound_ = true; | 
					
						
							|  |  |  |   dirty_image_binds_ |= 1ULL << unit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLStateManager::image_unbind(Texture *tex_) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GLTexture *tex = static_cast<GLTexture *>(tex_); | 
					
						
							|  |  |  |   if (!tex->is_bound_) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   GLuint tex_id = tex->tex_id_; | 
					
						
							|  |  |  |   for (int i = 0; i < ARRAY_SIZE(images_); i++) { | 
					
						
							|  |  |  |     if (images_[i] == tex_id) { | 
					
						
							|  |  |  |       images_[i] = 0; | 
					
						
							|  |  |  |       dirty_image_binds_ |= 1ULL << i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   tex->is_bound_ = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLStateManager::image_unbind_all() | 
					
						
							| 
									
										
										
										
											2020-09-12 06:10:11 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   for (int i = 0; i < ARRAY_SIZE(images_); i++) { | 
					
						
							|  |  |  |     if (images_[i] != 0) { | 
					
						
							|  |  |  |       images_[i] = 0; | 
					
						
							|  |  |  |       dirty_image_binds_ |= 1ULL << i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   this->image_bind_apply(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | void GLStateManager::image_bind_apply() | 
					
						
							| 
									
										
										
										
											2020-09-12 06:10:11 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   if (dirty_image_binds_ == 0) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   uint32_t dirty_bind = dirty_image_binds_; | 
					
						
							|  |  |  |   dirty_image_binds_ = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int first = bitscan_forward_uint(dirty_bind); | 
					
						
							|  |  |  |   int last = 32 - bitscan_reverse_uint(dirty_bind); | 
					
						
							|  |  |  |   int count = last - first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (GLContext::multi_bind_support) { | 
					
						
							|  |  |  |     glBindImageTextures(first, count, images_ + first); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     for (int unit = first; unit < last; unit++) { | 
					
						
							|  |  |  |       if ((dirty_bind >> unit) & 1UL) { | 
					
						
							|  |  |  |         glBindImageTexture(unit, images_[unit], 0, GL_TRUE, 0, GL_READ_WRITE, formats_[unit]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 13:18:48 +01:00
										 |  |  | uint8_t GLStateManager::bound_image_slots() | 
					
						
							| 
									
										
										
										
											2020-09-12 06:10:11 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   uint8_t bound_slots = 0; | 
					
						
							|  |  |  |   for (int i = 0; i < ARRAY_SIZE(images_); i++) { | 
					
						
							|  |  |  |     if (images_[i] != 0) { | 
					
						
							|  |  |  |       bound_slots |= 1ULL << i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return bound_slots; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /** \name Memory barrier
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void GLStateManager::issue_barrier(eGPUBarrier barrier_bits) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   glMemoryBarrier(to_gl(barrier_bits)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-06 01:45:38 +10:00
										 |  |  | }  // namespace blender::gpu
 |