From e2dfc935a1001eefd7f65989884549506900db48 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 21 May 2015 14:16:45 +0200 Subject: [PATCH] Various refactoring, esp. of GLSL input system --- dtool/src/dtoolutil/string_utils.I | 5 + dtool/src/dtoolutil/string_utils.h | 1 + .../interfaceMakerPythonNative.cxx | 30 +- .../interrogate/interfaceMakerPythonNative.h | 2 +- panda/src/glstuff/glCgShaderContext_src.cxx | 4 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 17 + .../src/glstuff/glGraphicsStateGuardian_src.h | 4 + panda/src/glstuff/glShaderContext_src.cxx | 1901 ++++++++++------- panda/src/glstuff/glShaderContext_src.h | 17 +- panda/src/glstuff/glmisc_src.cxx | 6 + panda/src/glstuff/glmisc_src.h | 1 + panda/src/gobj/geomVertexColumn.I | 13 +- panda/src/gobj/geomVertexColumn.cxx | 23 +- panda/src/gobj/geomVertexColumn.h | 17 +- panda/src/linmath/lcast_to_src.I | 45 + panda/src/linmath/lcast_to_src.h | 27 + panda/src/pgraph/shaderAttrib.cxx | 35 +- panda/src/pgraph/shaderAttrib.h | 3 +- panda/src/pgraph/shaderInput.I | 229 +- panda/src/pgraph/shaderInput.cxx | 68 +- panda/src/pgraph/shaderInput.h | 21 +- panda/src/x11display/x11GraphicsWindow.cxx | 4 +- panda/src/x11display/x11GraphicsWindow.h | 1 + 23 files changed, 1379 insertions(+), 1095 deletions(-) diff --git a/dtool/src/dtoolutil/string_utils.I b/dtool/src/dtoolutil/string_utils.I index abbfbbfd94..a69497c97f 100644 --- a/dtool/src/dtoolutil/string_utils.I +++ b/dtool/src/dtoolutil/string_utils.I @@ -26,6 +26,11 @@ format_string(const string &value) { return value; } +INLINE string +format_string(bool value) { + return string(value ? "true" : "false"); +} + INLINE string format_string(float value) { char buffer[32]; diff --git a/dtool/src/dtoolutil/string_utils.h b/dtool/src/dtoolutil/string_utils.h index afeb91c422..10ebad4720 100644 --- a/dtool/src/dtoolutil/string_utils.h +++ b/dtool/src/dtoolutil/string_utils.h @@ -69,6 +69,7 @@ INLINE string format_string(const Thing &thing); // Fast specializations for some primitive types. INLINE string format_string(const string &value); +INLINE string format_string(bool value); INLINE string format_string(float value); INLINE string format_string(double value); INLINE string format_string(unsigned int value); diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index ecd2460d7c..db8a3e8e03 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -720,11 +720,16 @@ get_valid_child_classes(std::map &answer, CPPStructTyp /////////////////////////////////////////////////////////////////////////////// void InterfaceMakerPythonNative:: write_python_instance(ostream &out, int indent_level, const string &return_expr, - bool owns_memory, const string &class_name, - CPPType *ctype, bool is_const) { + bool owns_memory, const InterrogateType &itype, bool is_const) { out << boolalpha; - if (IsPandaTypedObject(ctype->as_struct_type())) { + if (!isExportThisRun(itype._cpptype)) { + _external_imports.insert(itype._cpptype); + } + + string class_name = itype.get_scoped_name(); + + if (IsPandaTypedObject(itype._cpptype->as_struct_type())) { // We can't let DTool_CreatePyInstanceTyped do the NULL check since we // will be grabbing the type index (which would obviously crash when called // on a NULL pointer), so we do it here. @@ -6046,31 +6051,19 @@ pack_return_value(ostream &out, int indent_level, FunctionRemap *remap, TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(type)),false); const InterrogateType &itype = idb->get_type(type_index); - if (!isExportThisRun(itype._cpptype)) { - _external_imports.insert(itype._cpptype); - } - - write_python_instance(out, indent_level, return_expr, owns_memory, itype.get_scoped_name(), itype._cpptype, is_const); + write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const); } else { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); const InterrogateType &itype = idb->get_type(type_index); - if (!isExportThisRun(itype._cpptype)) { - _external_imports.insert(itype._cpptype); - } - - write_python_instance(out, indent_level, return_expr, owns_memory, itype.get_scoped_name(), itype._cpptype, is_const); + write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const); } } else if (TypeManager::is_struct(orig_type->as_pointer_type()->_pointing_at)) { TypeIndex type_index = builder.get_type(TypeManager::unwrap(TypeManager::resolve_type(orig_type)),false); const InterrogateType &itype = idb->get_type(type_index); - if (!isExportThisRun(itype._cpptype)) { - _external_imports.insert(itype._cpptype); - } - - write_python_instance(out, indent_level, return_expr, owns_memory, itype.get_scoped_name(), itype._cpptype, is_const); + write_python_instance(out, indent_level, return_expr, owns_memory, itype, is_const); } else { indent(out, indent_level) << "Should Never Reach This InterfaceMakerPythonNative::pack_python_value"; @@ -6638,6 +6631,7 @@ HasAGetClassTypeFunction(const InterrogateType &itype_class) { int num_methods = itype_class.number_of_methods(); int mi; + for (mi = 0; mi < num_methods; mi++) { FunctionIndex func_index = itype_class.get_method(mi); const InterrogateFunction &ifunc = idb->get_function(func_index); diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.h b/dtool/src/interrogate/interfaceMakerPythonNative.h index aa3aa5071c..2eb7e64b5e 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.h +++ b/dtool/src/interrogate/interfaceMakerPythonNative.h @@ -198,7 +198,7 @@ public: void get_valid_child_classes(std::map &answer, CPPStructType *inclass, const std::string &upcast_seed = "", bool can_downcast = true); bool DoesInheritFromIsClass(const CPPStructType * inclass, const std::string &name); bool IsPandaTypedObject(CPPStructType * inclass) { return DoesInheritFromIsClass(inclass,"TypedObject"); }; - void write_python_instance(ostream &out, int indent_level, const std::string &return_expr, bool owns_memory, const std::string &class_name, CPPType *ctype, bool is_const); + void write_python_instance(ostream &out, int indent_level, const std::string &return_expr, bool owns_memory, const InterrogateType &itype, bool is_const); bool HasAGetClassTypeFunction(const InterrogateType &itype_class); int NeedsAStrFunction(const InterrogateType &itype_class); int NeedsAReprFunction(const InterrogateType &itype_class); diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx index 4afda4b921..69f40aca60 100644 --- a/panda/src/glstuff/glCgShaderContext_src.cxx +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -643,9 +643,7 @@ update_shader_texture_bindings(ShaderContext *prev) { SamplerState sampler; if (id != NULL) { - const ShaderInput *input = _glgsg->_target_shader->get_shader_input(id); - tex = input->get_texture(); - sampler = input->get_sampler(); + tex = _glgsg->_target_shader->get_shader_input_texture(id, &sampler); } else { if (_shader->_tex_spec[i]._stage >= texattrib->get_num_on_stages()) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 5a1752932e..6de2521d3a 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1461,6 +1461,23 @@ reset() { } #endif +#ifndef OPENGLES + // Check for uniform buffers. + if (is_at_least_gl_version(3, 1) || has_extension("GL_ARB_uniform_buffer_object")) { + _supports_uniform_buffers = true; + _glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) + get_extension_func("glGetActiveUniformsiv"); + _glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) + get_extension_func("glGetActiveUniformBlockiv"); + _glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) + get_extension_func("glGetActiveUniformBlockName"); + } else { + _supports_uniform_buffers = false; + } +#else + _supports_uniform_buffers = false; +#endif + // Check whether we support geometry instancing and instanced vertex attribs. #if defined(OPENGLES_1) _supports_vertex_attrib_divisor = false; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 93cc526fd6..7d1b8f2fe8 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -636,6 +636,7 @@ protected: GLint _max_image_units; bool _supports_multi_bind; bool _supports_get_program_binary; + bool _supports_uniform_buffers; #ifdef OPENGLES bool _supports_depth24; @@ -845,6 +846,9 @@ public: PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced; #endif // !OPENGLES_1 #ifndef OPENGLES + PFNGLGETACTIVEUNIFORMSIVPROC _glGetActiveUniformsiv; + PFNGLGETACTIVEUNIFORMBLOCKIVPROC _glGetActiveUniformBlockiv; + PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC _glGetActiveUniformBlockName; PFNGLGENSAMPLERSPROC _glGenSamplers; PFNGLDELETESAMPLERSPROC _glDeleteSamplers; PFNGLBINDSAMPLERPROC _glBindSampler; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 60e1c7d2cc..5774db6909 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -179,6 +179,19 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, Shader *objSha if (!objShader->cp_parse_eol(p, pieces, next)) { return false; } + + // clip == apiclip in OpenGL, and the apiclip matrices are cached. + if (bind._part[0] == Shader::SMO_view_to_clip) { + bind._part[0] = Shader::SMO_view_to_apiclip; + } else if (bind._part[0] == Shader::SMO_clip_to_view) { + bind._part[0] = Shader::SMO_apiclip_to_view; + } + if (bind._part[1] == Shader::SMO_view_to_clip) { + bind._part[1] = Shader::SMO_view_to_apiclip; + } else if (bind._part[1] == Shader::SMO_clip_to_view) { + bind._part[1] = Shader::SMO_apiclip_to_view; + } + objShader->cp_optimize_mat_spec(bind); objShader->_mat_spec.push_back(bind); return true; @@ -198,795 +211,1017 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext _uses_standard_vertex_arrays = false; _has_divisor = false; _color_attrib_index = -1; + _validated = !gl_validate_shaders; nassertv(s->get_language() == Shader::SL_GLSL); - // We compile and analyze the shader here, instead of in shader.cxx, to avoid gobj getting a dependency on GL stuff. + // We compile and analyze the shader here, instead of in shader.cxx, + // to avoid gobj getting a dependency on GL stuff. if (!glsl_compile_and_link()) { release_resources(); s->_error_flag = true; return; } - _glgsg->_glUseProgram(_glsl_program); - // Analyze the uniforms and put them in _glsl_parameter_map - if (_glsl_parameter_map.size() == 0) { - int seqno = 0, texunitno = 0, imgunitno = 0; - string noprefix; - GLint param_count, param_maxlength, param_size; - GLenum param_type; - _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count); - _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, ¶m_maxlength); - char* param_name_cstr = (char *)alloca(param_maxlength); + // Create a buffer the size of the longest uniform name. + GLint name_buflen = 0; + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &name_buflen); + char* name_buffer = (char *)alloca(max(64, name_buflen)); - for (int i = 0; i < param_count; ++i) { - param_name_cstr[0] = 0; - _glgsg->_glGetActiveUniform(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); - string param_name(param_name_cstr); - GLint p = _glgsg->_glGetUniformLocation(_glsl_program, param_name_cstr); - - if (GLCAT.is_debug()) { - GLCAT.debug() - << "Active uniform " << param_name << " with size " << param_size - << " and type " << param_type << " is bound to location " << p << "\n"; - } - - if (p > -1) { - // Strip off [0] suffix that some drivers append to arrays. - size_t size = param_name.size(); - if (size > 3 && param_name.substr(size - 3, 3) == "[0]") { - param_name = param_name.substr(0, size - 3); - } - - Shader::ShaderArgId arg_id; - arg_id._name = param_name; - arg_id._seqno = seqno++; - _glsl_parameter_map.push_back(p); - - // Check for inputs with p3d_ prefix. - if (param_name.substr(0, 4) == "p3d_") { - noprefix = param_name.substr(4); - - // Check for matrix inputs. - bool transpose = false; - bool inverse = false; - string matrix_name (noprefix); - - // Check for and chop off any "Transpose" or "Inverse" suffix. - if (size > 15 && matrix_name.compare(size - 9, 9, "Transpose") == 0) { - transpose = true; - matrix_name = matrix_name.substr(0, size - 9); - } - size = matrix_name.size(); - if (size > 13 && matrix_name.compare(size - 7, 7, "Inverse") == 0) { - inverse = true; - matrix_name = matrix_name.substr(0, size - 7); - } - size = matrix_name.size(); - - // Now if the suffix that is left over is "Matrix", - // we know that it is supposed to be a matrix input. - if (size > 6 && matrix_name.compare(size - 6, 6, "Matrix") == 0) { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_compose; - if (param_type == GL_FLOAT_MAT3) { - if (transpose) { - bind._piece = Shader::SMP_upper3x3; - } else { - bind._piece = Shader::SMP_transpose3x3; - } - } else { - if (transpose) { - bind._piece = Shader::SMP_transpose; - } else { - bind._piece = Shader::SMP_whole; - } - } - bind._arg[0] = NULL; - bind._arg[1] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - - if (matrix_name == "ModelViewProjectionMatrix") { - if (inverse) { - bind._part[0] = Shader::SMO_apiclip_to_apiview; - bind._part[1] = Shader::SMO_apiview_to_model; - } else { - bind._part[0] = Shader::SMO_model_to_apiview; - bind._part[1] = Shader::SMO_apiview_to_apiclip; - } - - } else if (matrix_name == "ModelViewMatrix") { - bind._func = Shader::SMF_first; - bind._part[0] = inverse ? Shader::SMO_apiview_to_model - : Shader::SMO_model_to_apiview; - bind._part[1] = Shader::SMO_identity; - - } else if (matrix_name == "ProjectionMatrix") { - bind._func = Shader::SMF_first; - bind._part[0] = inverse ? Shader::SMO_apiclip_to_apiview - : Shader::SMO_apiview_to_apiclip; - bind._part[1] = Shader::SMO_identity; - - } else if (matrix_name == "NormalMatrix") { - // This is really the upper 3x3 of the ModelViewMatrixInverseTranspose. - bind._func = Shader::SMF_first; - bind._part[0] = inverse ? Shader::SMO_model_to_apiview - : Shader::SMO_apiview_to_model; - bind._part[1] = Shader::SMO_identity; - - if (param_type != GL_FLOAT_MAT3) { - GLCAT.error() << "p3d_NormalMatrix input should be mat3, not mat4!\n"; - } - - } else if (matrix_name == "ModelMatrix") { - if (inverse) { - bind._part[0] = Shader::SMO_world_to_view; - bind._part[1] = Shader::SMO_view_to_model; - } else { - bind._part[0] = Shader::SMO_model_to_view; - bind._part[1] = Shader::SMO_view_to_world; - } - - } else if (matrix_name == "ViewMatrix") { - if (inverse) { - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_world; - } else { - bind._part[0] = Shader::SMO_world_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - } - - } else if (matrix_name == "ViewProjectionMatrix") { - if (inverse) { - bind._part[0] = Shader::SMO_apiclip_to_view; - bind._part[1] = Shader::SMO_view_to_world; - } else { - bind._part[0] = Shader::SMO_world_to_view; - bind._part[1] = Shader::SMO_view_to_apiclip; - } - - } else { - GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; - continue; - } - s->_mat_spec.push_back(bind); - continue; - } - if (size > 7 && noprefix.substr(0, 7) == "Texture") { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = 0; - - string tail; - bind._stage = string_to_int(noprefix.substr(7), tail); - if (!tail.empty()) { - GLCAT.error() - << "Error parsing shader input name: unexpected '" - << tail << "' in '" << param_name << "'\n"; - continue; - } - - if (get_sampler_texture_type(bind._desired_type, param_type)) { - _glgsg->_glUniform1i(p, s->_tex_spec.size()); - s->_tex_spec.push_back(bind); - } else { - GLCAT.error() - << "Could not bind texture input " << param_name << "\n"; - } - continue; - } - if (size > 9 && noprefix.substr(0, 9) == "Material.") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_attr_material; - bind._arg[0] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_material; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - - if (noprefix == "Material.ambient") { - if (param_type != GL_FLOAT_VEC4) { - GLCAT.error() - << "p3d_Material.ambient should be vec4\n"; - } - bind._piece = Shader::SMP_row0; - s->_mat_spec.push_back(bind); - continue; - - } else if (noprefix == "Material.diffuse") { - if (param_type != GL_FLOAT_VEC4) { - GLCAT.error() - << "p3d_Material.diffuse should be vec4\n"; - } - bind._piece = Shader::SMP_row1; - s->_mat_spec.push_back(bind); - continue; - - } else if (noprefix == "Material.emission") { - if (param_type != GL_FLOAT_VEC4) { - GLCAT.error() - << "p3d_Material.emission should be vec4\n"; - } - bind._piece = Shader::SMP_row2; - s->_mat_spec.push_back(bind); - continue; - - } else if (noprefix == "Material.specular") { - if (param_type != GL_FLOAT_VEC3) { - GLCAT.error() - << "p3d_Material.specular should be vec3\n"; - } - bind._piece = Shader::SMP_row3x3; - s->_mat_spec.push_back(bind); - continue; - - } else if (noprefix == "Material.shininess") { - if (param_type != GL_FLOAT) { - GLCAT.error() - << "p3d_Material.shininess should be float\n"; - } - bind._piece = Shader::SMP_cell15; - s->_mat_spec.push_back(bind); - continue; - } - } - if (noprefix == "ColorScale") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_attr_colorscale; - bind._arg[0] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_colorscale; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - - if (param_type == GL_FLOAT_VEC3) { - bind._piece = Shader::SMP_row3x3; - } else if (param_type == GL_FLOAT_VEC4) { - bind._piece = Shader::SMP_row3; - } else { - GLCAT.error() - << "p3d_ColorScale should be vec3 or vec4\n"; - continue; - } - s->_mat_spec.push_back(bind); - continue; - } - if (noprefix == "Color") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_attr_color; - bind._arg[0] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_color; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - - if (param_type == GL_FLOAT_VEC3) { - bind._piece = Shader::SMP_row3x3; - } else if (param_type == GL_FLOAT_VEC4) { - bind._piece = Shader::SMP_row3; - } else { - GLCAT.error() - << "p3d_Color should be vec3 or vec4\n"; - continue; - } - s->_mat_spec.push_back(bind); - continue; - } - if (noprefix == "ClipPlane") { - if (param_type != GL_FLOAT_VEC4) { - GLCAT.error() - << "p3d_ClipPlane should be vec4 or vec4[]\n"; - continue; - } - for (int i = 0; i < param_size; ++i) { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._id._seqno = seqno++; - bind._piece = Shader::SMP_row3; - bind._func = Shader::SMF_first; - bind._index = i; - bind._part[0] = Shader::SMO_apiview_clipplane_i; - bind._arg[0] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_clip_planes; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - _glsl_parameter_map.push_back(p + i); - } - continue; - } - if (noprefix == "LightModel.ambient") { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_light_ambient; - bind._arg[0] = NULL; - bind._dep[0] = Shader::SSD_general | Shader::SSD_light; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - - if (param_type == GL_FLOAT_VEC3) { - bind._piece = Shader::SMP_row3x3; - } else if (param_type == GL_FLOAT_VEC4) { - bind._piece = Shader::SMP_row3; - } else { - GLCAT.error() - << "p3d_LightModel.ambient should be vec3 or vec4\n"; - continue; - } - s->_mat_spec.push_back(bind); - continue; - } - GLCAT.error() << "Unrecognized uniform name '" << param_name_cstr << "'!\n"; - continue; - - } else if (param_name.substr(0, 4) == "osg_") { - // These inputs are supported by OpenSceneGraph. We can support - // them as well, to increase compatibility. - // Other inputs we may support in the future: - // int osg_FrameNumber - - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._arg[0] = NULL; - bind._arg[1] = NULL; - - if (param_name == "osg_ViewMatrix") { - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_compose; - bind._part[0] = Shader::SMO_world_to_view; - bind._part[1] = Shader::SMO_view_to_apiview; - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - s->_mat_spec.push_back(bind); - continue; - - } else if (param_name == "osg_InverseViewMatrix") { - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_compose; - bind._part[0] = Shader::SMO_apiview_to_view; - bind._part[1] = Shader::SMO_view_to_world; - bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; - bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; - s->_mat_spec.push_back(bind); - continue; - - } else if (param_name == "osg_FrameTime") { - bind._piece = Shader::SMP_row3x1; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_frame_time; - bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; - - } else if (param_name == "osg_DeltaFrameTime") { - bind._piece = Shader::SMP_row3x1; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_frame_delta; - bind._part[1] = Shader::SMO_identity; - bind._dep[0] = Shader::SSD_general; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; - } - } - - //Tries to parse shorthand notations like mspos_XXX and trans_model_to_clip_of_XXX - if (parse_and_set_short_hand_shader_vars(arg_id, s)) { - continue; - } - - if (param_size == 1) { - switch (param_type) { #ifndef OPENGLES - case GL_INT_SAMPLER_1D: - case GL_INT_SAMPLER_2D: - case GL_INT_SAMPLER_3D: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_CUBE: - case GL_INT_SAMPLER_BUFFER: - case GL_UNSIGNED_INT_SAMPLER_1D: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_BUFFER: - case GL_SAMPLER_1D_SHADOW: - case GL_SAMPLER_1D: - case GL_SAMPLER_CUBE_SHADOW: - case GL_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_ARRAY_SHADOW: - case GL_SAMPLER_BUFFER: -#endif // !OPENGLES - case GL_SAMPLER_2D: - case GL_SAMPLER_2D_SHADOW: - case GL_SAMPLER_3D: - case GL_SAMPLER_CUBE: { - Shader::ShaderTexSpec bind; - bind._id = arg_id; - bind._name = InternalName::make(param_name); - bind._desired_type = Texture::TT_2d_texture; - bind._stage = texunitno++; - if (get_sampler_texture_type(bind._desired_type, param_type)) { - _glgsg->_glUniform1i(p, s->_tex_spec.size()); - s->_tex_spec.push_back(bind); - } - continue; - } - case GL_FLOAT_MAT2: -#ifndef OPENGLES - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: -#endif - GLCAT.warning() << "GLSL shader requested an unsupported matrix type\n"; - continue; - case GL_FLOAT_MAT3: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._piece = Shader::SMP_upper3x3; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_mat_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; - } - case GL_FLOAT_MAT4: { - Shader::ShaderMatSpec bind; - bind._id = arg_id; - bind._piece = Shader::SMP_whole; - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_mat_constant_x; - bind._arg[0] = InternalName::make(param_name); - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; - } - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: { - PT(InternalName) iname = InternalName::make(param_name); - if (iname->get_parent() != InternalName::get_root()) { - // It might be something like an attribute of a shader - // input, like a light parameter. It might also just be - // a custom struct parameter. We can't know yet, sadly. - Shader::ShaderMatSpec bind; - bind._id = arg_id; - switch (param_type) { - case GL_FLOAT: - bind._piece = Shader::SMP_row3x1; - break; - case GL_FLOAT_VEC2: - bind._piece = Shader::SMP_row3x2; - break; - case GL_FLOAT_VEC3: - bind._piece = Shader::SMP_row3x3; - break; - default: - bind._piece = Shader::SMP_row3; - } - bind._func = Shader::SMF_first; - bind._part[0] = Shader::SMO_vec_constant_x_attrib; - bind._arg[0] = iname; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._part[1] = Shader::SMO_identity; - bind._arg[1] = NULL; - bind._dep[1] = Shader::SSD_NONE; - s->_mat_spec.push_back(bind); - continue; - } // else fall through - } - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: { - Shader::ShaderPtrSpec bind; - bind._id = arg_id; - switch (param_type) { - case GL_BOOL: - case GL_INT: - case GL_FLOAT: bind._dim[1] = 1; break; - case GL_BOOL_VEC2: - case GL_INT_VEC2: - case GL_FLOAT_VEC2: bind._dim[1] = 2; break; - case GL_BOOL_VEC3: - case GL_INT_VEC3: - case GL_FLOAT_VEC3: bind._dim[1] = 3; break; - case GL_BOOL_VEC4: - case GL_INT_VEC4: - case GL_FLOAT_VEC4: bind._dim[1] = 4; break; - case GL_FLOAT_MAT3: bind._dim[1] = 9; break; - case GL_FLOAT_MAT4: bind._dim[1] = 16; break; - } - switch (param_type) { - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - bind._type = Shader::SPT_int; - break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - bind._type = Shader::SPT_float; - break; - } - bind._arg = InternalName::make(param_name); - bind._dim[0] = 1; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._dep[1] = Shader::SSD_NONE; - s->_ptr_spec.push_back(bind); - continue; - } -#ifndef OPENGLES - case GL_IMAGE_1D_EXT: - case GL_IMAGE_2D_EXT: - case GL_IMAGE_3D_EXT: - case GL_IMAGE_CUBE_EXT: - case GL_IMAGE_2D_ARRAY_EXT: - case GL_IMAGE_BUFFER_EXT: - case GL_INT_IMAGE_1D_EXT: - case GL_INT_IMAGE_2D_EXT: - case GL_INT_IMAGE_3D_EXT: - case GL_INT_IMAGE_CUBE_EXT: - case GL_INT_IMAGE_2D_ARRAY_EXT: - case GL_INT_IMAGE_BUFFER_EXT: - case GL_UNSIGNED_INT_IMAGE_1D_EXT: - case GL_UNSIGNED_INT_IMAGE_2D_EXT: - case GL_UNSIGNED_INT_IMAGE_3D_EXT: - case GL_UNSIGNED_INT_IMAGE_CUBE_EXT: - case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT: - case GL_UNSIGNED_INT_IMAGE_BUFFER_EXT: - // This won't really change at runtime, so we might as well - // bind once and then forget about it. - _glgsg->_glUniform1i(p, imgunitno++); - _glsl_img_inputs.push_back(InternalName::make(param_name)); - _glsl_img_textures.push_back(NULL); - continue; -#endif - default: - GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n"; - } - } else { - switch (param_type) { - case GL_FLOAT_MAT2: -#ifndef OPENGLES - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: -#endif - GLCAT.warning() << "GLSL shader requested an unrecognized matrix array type\n"; - continue; - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: { - Shader::ShaderPtrSpec bind; - bind._id = arg_id; - switch (param_type) { - case GL_BOOL: - case GL_INT: - case GL_FLOAT: bind._dim[1] = 1; break; - case GL_BOOL_VEC2: - case GL_INT_VEC2: - case GL_FLOAT_VEC2: bind._dim[1] = 2; break; - case GL_BOOL_VEC3: - case GL_INT_VEC3: - case GL_FLOAT_VEC3: bind._dim[1] = 3; break; - case GL_BOOL_VEC4: - case GL_INT_VEC4: - case GL_FLOAT_VEC4: bind._dim[1] = 4; break; - case GL_FLOAT_MAT3: bind._dim[1] = 9; break; - case GL_FLOAT_MAT4: bind._dim[1] = 16; break; - } - switch (param_type) { - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - bind._type = Shader::SPT_int; - break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - bind._type = Shader::SPT_float; - break; - } - bind._arg = InternalName::make(param_name); - bind._dim[0] = param_size; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; - bind._dep[1] = Shader::SSD_NONE; - s->_ptr_spec.push_back(bind); - continue; - } - default: - GLCAT.warning() << "Ignoring unrecognized GLSL parameter array type!\n"; - } - } - } - } + // Get the used uniform blocks. + if (_glgsg->_supports_uniform_buffers) { + GLint block_count, block_maxlength; + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_BLOCKS, &block_count); + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &block_maxlength); + char *block_name_cstr = (char *)alloca(max(64, block_maxlength)); - // Now we've processed the uniforms, we'll process the attribs. - _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count); - _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, ¶m_maxlength); - param_name_cstr = (char *)alloca(param_maxlength); + for (int i = 0; i < block_count; ++i) { + block_name_cstr[0] = 0; + _glgsg->_glGetActiveUniformBlockName(_glsl_program, i, block_maxlength, NULL, block_name_cstr); - for (int i = 0; i < param_count; ++i) { - param_name_cstr[0] = 0; - _glgsg->_glGetActiveAttrib(_glsl_program, i, param_maxlength, NULL, ¶m_size, ¶m_type, param_name_cstr); - string param_name(param_name_cstr); - - // Get the attrib location. - GLint p = _glgsg->_glGetAttribLocation(_glsl_program, param_name_cstr); - - GLCAT.debug() << - "Active attribute " << param_name << " is bound to location " << p << "\n"; - - if (p == -1) { - // A gl_ attribute such as gl_Vertex requires us to pass the - // standard vertex arrays as we would do without shader. - // This is not always the case, though -- see below. - _uses_standard_vertex_arrays = true; - continue; - } - - Shader::ShaderArgId arg_id; - arg_id._name = param_name; - arg_id._seqno = seqno++; - _glsl_parameter_map.push_back(p); - - Shader::ShaderVarSpec bind; - bind._id = arg_id; - bind._name = NULL; - bind._append_uv = -1; - bind._elements = 1; - - if (param_name.substr(0, 3) == "gl_") { - // Not all drivers return -1 in glGetAttribLocation - // for gl_ prefixed attributes. - _uses_standard_vertex_arrays = true; - continue; - } else if (param_name.substr(0, 4) == "p3d_") { - noprefix = param_name.substr(4); - } else { - noprefix = ""; - } - - bind._integer = (param_type == GL_BOOL || - param_type == GL_BOOL_VEC2 || - param_type == GL_BOOL_VEC3 || - param_type == GL_BOOL_VEC4 || - param_type == GL_INT || - param_type == GL_INT_VEC2 || - param_type == GL_INT_VEC3 || - param_type == GL_INT_VEC4 || -#ifndef OPENGLES - param_type == GL_UNSIGNED_INT_VEC2 || - param_type == GL_UNSIGNED_INT_VEC3 || - param_type == GL_UNSIGNED_INT_VEC4 || -#endif - param_type == GL_UNSIGNED_INT); - - if (noprefix.empty()) { - // Arbitrarily named attribute. - bind._name = InternalName::make(param_name); - - } else if (noprefix == "Vertex") { - bind._name = InternalName::get_vertex(); - - } else if (noprefix == "Normal") { - bind._name = InternalName::get_normal(); - - } else if (noprefix == "Color") { - bind._name = InternalName::get_color(); - - // Save the index, so we can apply special handling to this attrib. - _color_attrib_index = p; - - } else if (noprefix.substr(0, 7) == "Tangent") { - bind._name = InternalName::get_tangent(); - if (noprefix.size() > 7) { - bind._append_uv = atoi(noprefix.substr(7).c_str()); - } - - } else if (noprefix.substr(0, 8) == "Binormal") { - bind._name = InternalName::get_binormal(); - if (noprefix.size() > 8) { - bind._append_uv = atoi(noprefix.substr(8).c_str()); - } - - } else if (noprefix.substr(0, 13) == "MultiTexCoord") { - bind._name = InternalName::get_texcoord(); - bind._append_uv = atoi(noprefix.substr(13).c_str()); - - } else { - GLCAT.error() << "Unrecognized vertex attrib '" << param_name << "'!\n"; - continue; - } - - // Get the number of bind points. - switch (param_type) { - case GL_FLOAT_MAT3: -#ifndef OPENGLES - case GL_DOUBLE_MAT3: -#endif - bind._elements = 3 * param_size; - break; - - case GL_FLOAT_MAT4: -#ifndef OPENGLES - case GL_DOUBLE_MAT4: -#endif - bind._elements = 4 * param_size; - break; - - default: - bind._elements = param_size; - break; - } - - s->_var_spec.push_back(bind); + reflect_uniform_block(i, block_name_cstr, name_buffer, name_buflen); } } - _glgsg->_glUseProgram(0); +#endif // !OPENGLES + // Bind the program, so that we can call glUniform1i for the textures. + _glgsg->_glUseProgram(_glsl_program); + + // Analyze the uniforms. + GLint param_count = 0; + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count); + + _shader->_ptr_spec.clear(); + _shader->_mat_spec.clear(); + _shader->_tex_spec.clear(); + for (int i = 0; i < param_count; ++i) { + reflect_uniform(i, name_buffer, name_buflen); + } + + // Now we've processed the uniforms, we'll process the attribs. + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTES, ¶m_count); + _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &name_buflen); + name_buffer = (char *)alloca(max(64, name_buflen)); + + _shader->_var_spec.clear(); + for (int i = 0; i < param_count; ++i) { + reflect_attribute(i, name_buffer, name_buflen); + } + + _glgsg->_glUseProgram(0); _glgsg->report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLShaderContext::reflect_attribute +// Access: Public +// Description: Analyzes the vertex attribute and stores the +// information it needs to remember. +//////////////////////////////////////////////////////////////////// +void CLP(ShaderContext):: +reflect_attribute(int i, char *name_buffer, GLsizei name_buflen) { + GLint param_size; + GLenum param_type; + + // Get the name, size, and type of this attribute. + name_buffer[0] = 0; + _glgsg->_glGetActiveAttrib(_glsl_program, i, name_buflen, NULL, + ¶m_size, ¶m_type, name_buffer); + + // Get the attrib location. + GLint p = _glgsg->_glGetAttribLocation(_glsl_program, name_buffer); + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Active attribute " << name_buffer << " with size " << param_size + << " and type 0x" << hex << param_type << dec + << " is bound to location " << p << "\n"; + } + + if (p == -1 || strncmp(name_buffer, "gl_", 3) == 0) { + // A gl_ attribute such as gl_Vertex requires us to pass the standard + // vertex arrays as we would do without shader. Not all drivers return + // -1 in glGetAttribLocation for gl_ prefixed attributes, so we check the + // prefix of the input ourselves, just to be sure. + _uses_standard_vertex_arrays = true; + return; + } + + Shader::ShaderArgId arg_id; + arg_id._name = name_buffer; + arg_id._seqno = p; + + Shader::ShaderVarSpec bind; + bind._id = arg_id; + bind._name = NULL; + bind._append_uv = -1; + bind._elements = 1; + + // Check if this is an integer input- if so, we have to bind it differently. + bind._integer = (param_type == GL_BOOL || + param_type == GL_BOOL_VEC2 || + param_type == GL_BOOL_VEC3 || + param_type == GL_BOOL_VEC4 || + param_type == GL_INT || + param_type == GL_INT_VEC2 || + param_type == GL_INT_VEC3 || + param_type == GL_INT_VEC4 || +#ifndef OPENGLES + param_type == GL_UNSIGNED_INT_VEC2 || + param_type == GL_UNSIGNED_INT_VEC3 || + param_type == GL_UNSIGNED_INT_VEC4 || +#endif + param_type == GL_UNSIGNED_INT); + + // Check if it has a p3d_ prefix - if so, assign special meaning. + if (strncmp(name_buffer, "p3d_", 4) == 0) { + string noprefix(name_buffer + 4); + + if (noprefix == "Vertex") { + bind._name = InternalName::get_vertex(); + + } else if (noprefix == "Normal") { + bind._name = InternalName::get_normal(); + + } else if (noprefix == "Color") { + bind._name = InternalName::get_color(); + + // Save the index, so we can apply special handling to this attrib. + _color_attrib_index = p; + + } else if (noprefix.substr(0, 7) == "Tangent") { + bind._name = InternalName::get_tangent(); + if (noprefix.size() > 7) { + bind._append_uv = atoi(noprefix.substr(7).c_str()); + } + + } else if (noprefix.substr(0, 8) == "Binormal") { + bind._name = InternalName::get_binormal(); + if (noprefix.size() > 8) { + bind._append_uv = atoi(noprefix.substr(8).c_str()); + } + + } else if (noprefix.substr(0, 13) == "MultiTexCoord") { + bind._name = InternalName::get_texcoord(); + bind._append_uv = atoi(noprefix.substr(13).c_str()); + + } else { + GLCAT.error() << "Unrecognized vertex attrib '" << name_buffer << "'!\n"; + return; + } + } else { + // Arbitrarily named attribute. + bind._name = InternalName::make(name_buffer); + } + + // Get the number of bind points for arrays and matrices. + switch (param_type) { + case GL_FLOAT_MAT3: +#ifndef OPENGLES + case GL_DOUBLE_MAT3: +#endif + bind._elements = 3 * param_size; + break; + + case GL_FLOAT_MAT4: +#ifndef OPENGLES + case GL_DOUBLE_MAT4: +#endif + bind._elements = 4 * param_size; + break; + + default: + bind._elements = param_size; + break; + } + + _shader->_var_spec.push_back(bind); +} + +#ifndef OPENGLES +//////////////////////////////////////////////////////////////////// +// Function: GLShaderContext::reflect_uniform_block +// Access: Public +// Description: Analyzes the uniform block and stores its format. +//////////////////////////////////////////////////////////////////// +void CLP(ShaderContext):: +reflect_uniform_block(int i, const char *name, char *name_buffer, GLsizei name_buflen) { + //GLint offset = 0; + + GLint data_size = 0; + GLint param_count = 0; + GLsizei param_size; + _glgsg->_glGetActiveUniformBlockiv(_glsl_program, i, GL_UNIFORM_BLOCK_DATA_SIZE, &data_size); + _glgsg->_glGetActiveUniformBlockiv(_glsl_program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, ¶m_count); + + if (param_count <= 0) { + return; + } + + // We use a GeomVertexArrayFormat to describe the uniform buffer layout. + //GeomVertexArrayFormat block_format; + //block_format.set_pad_to(data_size); + + // Get an array containing the indices of all the uniforms in this block. + GLuint *indices = (GLuint *)alloca(param_count * sizeof(GLint)); + _glgsg->_glGetActiveUniformBlockiv(_glsl_program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, (GLint *)indices); + + // Acquire information about the way the uniforms in this block are packed. + GLint *offsets = (GLint *)alloca(param_count * sizeof(GLint)); + GLint *mstrides = (GLint *)alloca(param_count * sizeof(GLint)); + GLint *astrides = (GLint *)alloca(param_count * sizeof(GLint)); + _glgsg->_glGetActiveUniformsiv(_glsl_program, param_count, indices, GL_UNIFORM_OFFSET, offsets); + _glgsg->_glGetActiveUniformsiv(_glsl_program, param_count, indices, GL_UNIFORM_MATRIX_STRIDE, mstrides); + _glgsg->_glGetActiveUniformsiv(_glsl_program, param_count, indices, GL_UNIFORM_ARRAY_STRIDE, astrides); + + for (int ui = 0; ui < param_count; ++ui) { + name_buffer[0] = 0; + GLint param_size; + GLenum param_type; + _glgsg->_glGetActiveUniform(_glsl_program, indices[ui], name_buflen, NULL, ¶m_size, ¶m_type, name_buffer); + + // Strip off [0] suffix that some drivers append to arrays. + size_t size = strlen(name_buffer); + if (size > 3 && strncmp(name_buffer + (size - 3), "[0]", 3) == 0) { + name_buffer[size - 3] = 0; + } + + GeomEnums::NumericType numeric_type; + GeomEnums::Contents contents = GeomEnums::C_other; + int num_components = 1; + + switch (param_type) { + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + numeric_type = GeomEnums::NT_int32; + break; + + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_VEC2: + case GL_UNSIGNED_INT_VEC3: + case GL_UNSIGNED_INT_VEC4: + numeric_type = GeomEnums::NT_uint32; + break; + + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + numeric_type = GeomEnums::NT_float32; + break; + + case GL_DOUBLE: + case GL_DOUBLE_VEC2: + case GL_DOUBLE_VEC3: + case GL_DOUBLE_VEC4: + case GL_DOUBLE_MAT2: + case GL_DOUBLE_MAT3: + case GL_DOUBLE_MAT4: + numeric_type = GeomEnums::NT_float64; + break; + + default: + GLCAT.warning() << "Ignoring uniform '" << name_buffer + << "' with unsupported type 0x" << hex << param_type << dec << "\n"; + continue; + } + + switch (param_type) { + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_FLOAT_VEC2: + case GL_DOUBLE_VEC2: + num_components = 2; + break; + + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_FLOAT_VEC3: + case GL_DOUBLE_VEC3: + num_components = 3; + break; + + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + case GL_FLOAT_VEC4: + case GL_DOUBLE_VEC4: + num_components = 4; + break; + + case GL_FLOAT_MAT3: + case GL_DOUBLE_MAT3: + num_components = 3; + contents = GeomEnums::C_matrix; + nassertd(param_size <= 1 || astrides[ui] == mstrides[ui] * 3) continue; + param_size *= 3; + break; + + case GL_FLOAT_MAT4: + case GL_DOUBLE_MAT4: + num_components = 4; + contents = GeomEnums::C_matrix; + nassertd(param_size <= 1 || astrides[ui] == mstrides[ui] * 4) continue; + param_size *= 4; + break; + } + + //GeomVertexColumn column(InternalName::make(name_buffer), + // num_components, numeric_type, contents, + // offsets[ui], 4, param_size, astrides[ui]); + //block_format.add_column(column); + } + + //if (GLCAT.is_debug()) { + // GLCAT.debug() << "Active uniform block " << name << " has format:\n"; + // block_format.write(GLCAT.debug(false), 2); + //} + + //UniformBlock block; + //block._name = InternalName::make(name); + //block._format = GeomVertexArrayFormat::register_format(&block_format); + //block._buffer = 0; + + //_uniform_blocks.push_back(block); +} +#endif // !OPENGLES + +//////////////////////////////////////////////////////////////////// +// Function: GLShaderContext::reflect_uniform +// Access: Public +// Description: Analyzes a single uniform variable and considers +// how it should be handled and bound. +//////////////////////////////////////////////////////////////////// +void CLP(ShaderContext):: +reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { + GLint param_size; + GLenum param_type; + + // Get the name, location, type and size of this uniform. + name_buffer[0] = 0; + _glgsg->_glGetActiveUniform(_glsl_program, i, name_buflen, NULL, ¶m_size, ¶m_type, name_buffer); + GLint p = _glgsg->_glGetUniformLocation(_glsl_program, name_buffer); + + if (GLCAT.is_debug()) { + GLCAT.debug() + << "Active uniform " << name_buffer << " with size " << param_size + << " and type 0x" << hex << param_type << dec + << " is bound to location " << p << "\n"; + } + + if (p < 0) { + // Special meaning, or it's in a uniform block. Let it go. + return; + } + + // Strip off [0] suffix that some drivers append to arrays. + size_t size = strlen(name_buffer); + if (size > 3 && strncmp(name_buffer + (size - 3), "[0]", 3) == 0) { + name_buffer[size - 3] = 0; + } + + string param_name(name_buffer); + + Shader::ShaderArgId arg_id; + arg_id._name = param_name; + arg_id._seqno = p; + + // Check if it has a p3d_ prefix - if so, assign special meaning. + if (strncmp(name_buffer, "p3d_", 4) == 0) { + string noprefix(name_buffer + 4); + + // Check for matrix inputs. + bool transpose = false; + bool inverse = false; + string matrix_name(noprefix); + + // Check for and chop off any "Transpose" or "Inverse" suffix. + if (size > 15 && matrix_name.compare(size - 9, 9, "Transpose") == 0) { + transpose = true; + matrix_name = matrix_name.substr(0, size - 9); + } + size = matrix_name.size(); + if (size > 13 && matrix_name.compare(size - 7, 7, "Inverse") == 0) { + inverse = true; + matrix_name = matrix_name.substr(0, size - 7); + } + size = matrix_name.size(); + + // Now if the suffix that is left over is "Matrix", + // we know that it is supposed to be a matrix input. + if (size > 6 && matrix_name.compare(size - 6, 6, "Matrix") == 0) { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_compose; + if (param_type == GL_FLOAT_MAT3) { + if (transpose) { + bind._piece = Shader::SMP_upper3x3; + } else { + bind._piece = Shader::SMP_transpose3x3; + } + } else { + if (transpose) { + bind._piece = Shader::SMP_transpose; + } else { + bind._piece = Shader::SMP_whole; + } + } + bind._arg[0] = NULL; + bind._arg[1] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; + + if (matrix_name == "ModelViewProjectionMatrix") { + if (inverse) { + bind._part[0] = Shader::SMO_apiclip_to_apiview; + bind._part[1] = Shader::SMO_apiview_to_model; + } else { + bind._part[0] = Shader::SMO_model_to_apiview; + bind._part[1] = Shader::SMO_apiview_to_apiclip; + } + + } else if (matrix_name == "ModelViewMatrix") { + bind._func = Shader::SMF_first; + bind._part[0] = inverse ? Shader::SMO_apiview_to_model + : Shader::SMO_model_to_apiview; + bind._part[1] = Shader::SMO_identity; + + } else if (matrix_name == "ProjectionMatrix") { + bind._func = Shader::SMF_first; + bind._part[0] = inverse ? Shader::SMO_apiclip_to_apiview + : Shader::SMO_apiview_to_apiclip; + bind._part[1] = Shader::SMO_identity; + + } else if (matrix_name == "NormalMatrix") { + // This is really the upper 3x3 of the ModelViewMatrixInverseTranspose. + bind._func = Shader::SMF_first; + bind._part[0] = inverse ? Shader::SMO_model_to_apiview + : Shader::SMO_apiview_to_model; + bind._part[1] = Shader::SMO_identity; + + if (param_type != GL_FLOAT_MAT3) { + GLCAT.error() << "p3d_NormalMatrix input should be mat3, not mat4!\n"; + } + + } else if (matrix_name == "ModelMatrix") { + if (inverse) { + bind._part[0] = Shader::SMO_world_to_view; + bind._part[1] = Shader::SMO_view_to_model; + } else { + bind._part[0] = Shader::SMO_model_to_view; + bind._part[1] = Shader::SMO_view_to_world; + } + + } else if (matrix_name == "ViewMatrix") { + if (inverse) { + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_world; + } else { + bind._part[0] = Shader::SMO_world_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + } + + } else if (matrix_name == "ViewProjectionMatrix") { + if (inverse) { + bind._part[0] = Shader::SMO_apiclip_to_view; + bind._part[1] = Shader::SMO_view_to_world; + } else { + bind._part[0] = Shader::SMO_world_to_view; + bind._part[1] = Shader::SMO_view_to_apiclip; + } + + } else { + GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; + return; + } + _shader->_mat_spec.push_back(bind); + return; + } + if (size > 7 && noprefix.substr(0, 7) == "Texture") { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = 0; + + string tail; + bind._stage = string_to_int(noprefix.substr(7), tail); + if (!tail.empty()) { + GLCAT.error() + << "Error parsing shader input name: unexpected '" + << tail << "' in '" << param_name << "'\n"; + return; + } + + if (get_sampler_texture_type(bind._desired_type, param_type)) { + _glgsg->_glUniform1i(p, _shader->_tex_spec.size()); + _shader->_tex_spec.push_back(bind); + } else { + GLCAT.error() + << "Could not bind texture input " << param_name << "\n"; + } + return; + } + if (size > 9 && noprefix.substr(0, 9) == "Material.") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_attr_material; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_material; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + + if (noprefix == "Material.ambient") { + if (param_type != GL_FLOAT_VEC4) { + GLCAT.error() + << "p3d_Material.ambient should be vec4\n"; + } + bind._piece = Shader::SMP_row0; + _shader->_mat_spec.push_back(bind); + return; + + } else if (noprefix == "Material.diffuse") { + if (param_type != GL_FLOAT_VEC4) { + GLCAT.error() + << "p3d_Material.diffuse should be vec4\n"; + } + bind._piece = Shader::SMP_row1; + _shader->_mat_spec.push_back(bind); + return; + + } else if (noprefix == "Material.emission") { + if (param_type != GL_FLOAT_VEC4) { + GLCAT.error() + << "p3d_Material.emission should be vec4\n"; + } + bind._piece = Shader::SMP_row2; + _shader->_mat_spec.push_back(bind); + return; + + } else if (noprefix == "Material.specular") { + if (param_type != GL_FLOAT_VEC3) { + GLCAT.error() + << "p3d_Material.specular should be vec3\n"; + } + bind._piece = Shader::SMP_row3x3; + _shader->_mat_spec.push_back(bind); + return; + + } else if (noprefix == "Material.shininess") { + if (param_type != GL_FLOAT) { + GLCAT.error() + << "p3d_Material.shininess should be float\n"; + } + bind._piece = Shader::SMP_cell15; + _shader->_mat_spec.push_back(bind); + return; + } + } + if (noprefix == "ColorScale") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_attr_colorscale; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_colorscale; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + + if (param_type == GL_FLOAT_VEC3) { + bind._piece = Shader::SMP_row3x3; + } else if (param_type == GL_FLOAT_VEC4) { + bind._piece = Shader::SMP_row3; + } else { + GLCAT.error() + << "p3d_ColorScale should be vec3 or vec4\n"; + return; + } + _shader->_mat_spec.push_back(bind); + return; + } + if (noprefix == "Color") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_attr_color; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_color; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + + if (param_type == GL_FLOAT_VEC3) { + bind._piece = Shader::SMP_row3x3; + } else if (param_type == GL_FLOAT_VEC4) { + bind._piece = Shader::SMP_row3; + } else { + GLCAT.error() + << "p3d_Color should be vec3 or vec4\n"; + return; + } + _shader->_mat_spec.push_back(bind); + return; + } + if (noprefix == "ClipPlane") { + if (param_type != GL_FLOAT_VEC4) { + GLCAT.error() + << "p3d_ClipPlane should be vec4 or vec4[]\n"; + return; + } + for (int i = 0; i < param_size; ++i) { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._id._seqno = p + i; + bind._piece = Shader::SMP_row3; + bind._func = Shader::SMF_first; + bind._index = i; + bind._part[0] = Shader::SMO_apiview_clipplane_i; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_clip_planes; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + _shader->_mat_spec.push_back(bind); + } + return; + } + if (noprefix == "LightModel.ambient") { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_light_ambient; + bind._arg[0] = NULL; + bind._dep[0] = Shader::SSD_general | Shader::SSD_light; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + + if (param_type == GL_FLOAT_VEC3) { + bind._piece = Shader::SMP_row3x3; + } else if (param_type == GL_FLOAT_VEC4) { + bind._piece = Shader::SMP_row3; + } else { + GLCAT.error() + << "p3d_LightModel.ambient should be vec3 or vec4\n"; + return; + } + _shader->_mat_spec.push_back(bind); + return; + } + GLCAT.error() << "Unrecognized uniform name '" << param_name << "'!\n"; + return; + + } else if (strncmp(name_buffer, "osg_", 4) == 0) { + string noprefix(name_buffer + 4); + // These inputs are supported by OpenSceneGraph. We can support + // them as well, to increase compatibility. + // Other inputs we may support in the future: + // int osg_FrameNumber + + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._arg[0] = NULL; + bind._arg[1] = NULL; + + if (noprefix == "ViewMatrix") { + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_compose; + bind._part[0] = Shader::SMO_world_to_view; + bind._part[1] = Shader::SMO_view_to_apiview; + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; + _shader->_mat_spec.push_back(bind); + return; + + } else if (noprefix == "InverseViewMatrix") { + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_compose; + bind._part[0] = Shader::SMO_apiview_to_view; + bind._part[1] = Shader::SMO_view_to_world; + bind._dep[0] = Shader::SSD_general | Shader::SSD_transform; + bind._dep[1] = Shader::SSD_general | Shader::SSD_transform; + _shader->_mat_spec.push_back(bind); + return; + + } else if (noprefix == "FrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_time; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + _shader->_mat_spec.push_back(bind); + return; + + } else if (noprefix == "DeltaFrameTime") { + bind._piece = Shader::SMP_row3x1; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_frame_delta; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general; + bind._dep[1] = Shader::SSD_NONE; + _shader->_mat_spec.push_back(bind); + return; + } + + } else { + // Tries to parse shorthand notations like mspos_XXX and trans_model_to_clip_of_XXX + if (parse_and_set_short_hand_shader_vars(arg_id, _shader)) { + return; + } + } + + if (param_size == 1) { + // A single uniform (not an array, or an array of size 1). + switch (param_type) { +#ifndef OPENGLES + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_1D: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_BUFFER: +#endif // !OPENGLES + case GL_SAMPLER_2D: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: { + Shader::ShaderTexSpec bind; + bind._id = arg_id; + bind._name = InternalName::make(param_name); + bind._desired_type = Texture::TT_2d_texture; + bind._stage = 0; + if (get_sampler_texture_type(bind._desired_type, param_type)) { + _glgsg->_glUniform1i(p, _shader->_tex_spec.size()); + _shader->_tex_spec.push_back(bind); + } + return; + } + case GL_FLOAT_MAT2: +#ifndef OPENGLES + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: +#endif + GLCAT.warning() << "GLSL shader requested an unsupported matrix type\n"; + return; + case GL_FLOAT_MAT3: { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_upper3x3; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_mat_constant_x; + bind._arg[0] = InternalName::make(param_name); + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + _shader->_mat_spec.push_back(bind); + return; + } + case GL_FLOAT_MAT4: { + Shader::ShaderMatSpec bind; + bind._id = arg_id; + bind._piece = Shader::SMP_whole; + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_mat_constant_x; + bind._arg[0] = InternalName::make(param_name); + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + _shader->_mat_spec.push_back(bind); + return; + } + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: { + PT(InternalName) iname = InternalName::make(param_name); + if (iname->get_parent() != InternalName::get_root()) { + // It might be something like an attribute of a shader + // input, like a light parameter. It might also just be + // a custom struct parameter. We can't know yet, sadly. + Shader::ShaderMatSpec bind; + bind._id = arg_id; + switch (param_type) { + case GL_FLOAT: + bind._piece = Shader::SMP_row3x1; + break; + case GL_FLOAT_VEC2: + bind._piece = Shader::SMP_row3x2; + break; + case GL_FLOAT_VEC3: + bind._piece = Shader::SMP_row3x3; + break; + default: + bind._piece = Shader::SMP_row3; + } + bind._func = Shader::SMF_first; + bind._part[0] = Shader::SMO_vec_constant_x_attrib; + bind._arg[0] = iname; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._part[1] = Shader::SMO_identity; + bind._arg[1] = NULL; + bind._dep[1] = Shader::SSD_NONE; + _shader->_mat_spec.push_back(bind); + return; + } // else fall through + } + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: { + Shader::ShaderPtrSpec bind; + bind._id = arg_id; + switch (param_type) { + case GL_BOOL: + case GL_INT: + case GL_FLOAT: bind._dim[1] = 1; break; + case GL_BOOL_VEC2: + case GL_INT_VEC2: + case GL_FLOAT_VEC2: bind._dim[1] = 2; break; + case GL_BOOL_VEC3: + case GL_INT_VEC3: + case GL_FLOAT_VEC3: bind._dim[1] = 3; break; + case GL_BOOL_VEC4: + case GL_INT_VEC4: + case GL_FLOAT_VEC4: bind._dim[1] = 4; break; + case GL_FLOAT_MAT3: bind._dim[1] = 9; break; + case GL_FLOAT_MAT4: bind._dim[1] = 16; break; + } + switch (param_type) { + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + bind._type = Shader::SPT_int; + break; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + bind._type = Shader::SPT_float; + break; + } + bind._arg = InternalName::make(param_name); + bind._dim[0] = 1; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[1] = Shader::SSD_NONE; + _shader->_ptr_spec.push_back(bind); + return; + } +#ifndef OPENGLES + case GL_IMAGE_1D_EXT: + case GL_IMAGE_2D_EXT: + case GL_IMAGE_3D_EXT: + case GL_IMAGE_CUBE_EXT: + case GL_IMAGE_2D_ARRAY_EXT: + case GL_IMAGE_BUFFER_EXT: + case GL_INT_IMAGE_1D_EXT: + case GL_INT_IMAGE_2D_EXT: + case GL_INT_IMAGE_3D_EXT: + case GL_INT_IMAGE_CUBE_EXT: + case GL_INT_IMAGE_2D_ARRAY_EXT: + case GL_INT_IMAGE_BUFFER_EXT: + case GL_UNSIGNED_INT_IMAGE_1D_EXT: + case GL_UNSIGNED_INT_IMAGE_2D_EXT: + case GL_UNSIGNED_INT_IMAGE_3D_EXT: + case GL_UNSIGNED_INT_IMAGE_CUBE_EXT: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT: + case GL_UNSIGNED_INT_IMAGE_BUFFER_EXT: + // This won't really change at runtime, so we might as well + // bind once and then forget about it. + _glgsg->_glUniform1i(p, _glsl_img_inputs.size()); + { + ImageInput input; + input._name = InternalName::make(param_name); + input._writable = false; + input._gtc = NULL; + _glsl_img_inputs.push_back(input); + } + return; +#endif + default: + GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n"; + } + } else { + // A uniform array. + switch (param_type) { + case GL_FLOAT_MAT2: +#ifndef OPENGLES + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: +#endif + GLCAT.warning() << "GLSL shader requested an unrecognized matrix array type\n"; + return; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: { + Shader::ShaderPtrSpec bind; + bind._id = arg_id; + switch (param_type) { + case GL_BOOL: + case GL_INT: + case GL_FLOAT: bind._dim[1] = 1; break; + case GL_BOOL_VEC2: + case GL_INT_VEC2: + case GL_FLOAT_VEC2: bind._dim[1] = 2; break; + case GL_BOOL_VEC3: + case GL_INT_VEC3: + case GL_FLOAT_VEC3: bind._dim[1] = 3; break; + case GL_BOOL_VEC4: + case GL_INT_VEC4: + case GL_FLOAT_VEC4: bind._dim[1] = 4; break; + case GL_FLOAT_MAT3: bind._dim[1] = 9; break; + case GL_FLOAT_MAT4: bind._dim[1] = 16; break; + } + switch (param_type) { + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + bind._type = Shader::SPT_int; + break; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + bind._type = Shader::SPT_float; + break; + } + bind._arg = InternalName::make(param_name); + bind._dim[0] = param_size; + bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs; + bind._dep[1] = Shader::SSD_NONE; + _shader->_ptr_spec.push_back(bind); + return; + } + default: + GLCAT.warning() << "Ignoring unrecognized GLSL parameter array type!\n"; + } + } +} + //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::get_sampler_texture_type // Access: Public @@ -1159,6 +1394,12 @@ bind(bool reissue_parameters) { issue_parameters(Shader::SSD_general); } + if (!_validated) { + _glgsg->_glValidateProgram(_glsl_program); + glsl_report_program_errors(_glsl_program, false); + _validated = true; + } + _glgsg->report_my_gl_errors(); } @@ -1207,7 +1448,7 @@ issue_parameters(int altered) { return; } - GLint p = _glsl_parameter_map[spec._id._seqno]; + GLint p = spec._id._seqno; switch (spec._type) { case Shader::SPT_float: { @@ -1298,7 +1539,7 @@ issue_parameters(int altered) { const PN_float32 *data = valf.get_data(); #endif - GLint p = _glsl_parameter_map[spec._id._seqno]; + GLint p = spec._id._seqno; switch (spec._piece) { case Shader::SMP_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; case Shader::SMP_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; @@ -1356,7 +1597,7 @@ disable_shader_vertex_arrays() { for (int i=0; i<(int)_shader->_var_spec.size(); i++) { const Shader::ShaderVarSpec &bind = _shader->_var_spec[i]; - const GLint p = _glsl_parameter_map[bind._id._seqno]; + GLint p = bind._id._seqno; if (_has_divisor) { _glgsg->_glVertexAttribDivisor(p, 0); } @@ -1414,7 +1655,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { name = name->append(texname->get_basename()); } } - GLint p = _glsl_parameter_map[bind._id._seqno]; + GLint p = bind._id._seqno; // Don't apply vertex colors if they are disabled with a ColorAttrib. int num_elements, element_stride, divisor; @@ -1494,7 +1735,7 @@ disable_shader_texture_bindings() { #ifndef OPENGLES // Check if bindless was used, if so, there's nothing to unbind. if (_glgsg->_supports_bindless_texture) { - GLint p = _glsl_parameter_map[_shader->_tex_spec[i]._id._seqno]; + GLint p = _shader->_tex_spec[i]._id._seqno; if (_glsl_uniform_handles.count(p) > 0) { continue; @@ -1563,15 +1804,12 @@ disable_shader_texture_bindings() { if (gl_enable_memory_barriers) { for (int i = 0; i < num_image_units; ++i) { - const InternalName *name = _glsl_img_inputs[i]; - const ShaderInput *input = _glgsg->_target_shader->get_shader_input(name); + ImageInput &input = _glsl_img_inputs[i]; - if ((input->_access & ShaderInput::A_write) != 0) { - _glsl_img_textures[i]->mark_incoherent(true); - } else { - _glsl_img_textures[i]->mark_incoherent(false); + if (input._gtc != NULL) { + input._gtc->mark_incoherent(input._writable); + input._gtc = NULL; } - _glsl_img_textures[i] = NULL; } } } @@ -1609,9 +1847,26 @@ update_shader_texture_bindings(ShaderContext *prev) { if (num_image_units > 0) { for (int i = 0; i < num_image_units; ++i) { - const InternalName *name = _glsl_img_inputs[i]; - const ShaderInput *input = _glgsg->_target_shader->get_shader_input(name); - Texture *tex = input->get_texture(); + ImageInput &input = _glsl_img_inputs[i]; + const ParamTextureImage *param = NULL; + Texture *tex; + + const ShaderInput *sinp = _glgsg->_target_shader->get_shader_input(input._name); + if (sinp->get_value_type() == ShaderInput::M_texture_image) { + param = (const ParamTextureImage *)sinp->get_param(); + tex = param->get_texture(); + + } else if (sinp->get_value_type() == ShaderInput::M_texture) { + // This used to be legal, so just issue a warning. + tex = sinp->get_texture(); + GLCAT.warning() + << "Texture input " << *input._name << " was not specified as an image binding\n"; + + } else { + GLCAT.error() + << "Mismatching type for parameter " << *input._name << ", expected texture image binding\n"; + continue; + } GLuint gl_tex = 0; CLP(TextureContext) *gtc; @@ -1621,7 +1876,7 @@ update_shader_texture_bindings(ShaderContext *prev) { gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg)); if (gtc != (TextureContext*)NULL) { - _glsl_img_textures[i] = gtc; + input._gtc = gtc; gl_tex = gtc->_index; _glgsg->update_texture(gtc, true); @@ -1631,9 +1886,11 @@ update_shader_texture_bindings(ShaderContext *prev) { } } } + input._writable = false; if (gl_tex == 0) { _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8); + } else { //TODO: automatically convert to sized type instead of plain GL_RGBA // If a base type is used, it will crash. @@ -1648,24 +1905,35 @@ update_shader_texture_bindings(ShaderContext *prev) { } GLenum access = GL_READ_ONLY; - GLboolean layered = (input->_access & ShaderInput::A_layered) != 0; + GLint bind_level = 0; + GLint bind_layer = 0; + GLboolean layered = GL_TRUE; - if ((input->_access & ShaderInput::A_read) != 0 && - (input->_access & ShaderInput::A_write) != 0) { - access = GL_READ_WRITE; + if (param != NULL) { + layered = param->get_bind_layered(); + bind_level = param->get_bind_level(); + bind_layer = param->get_bind_layer(); - } else if ((input->_access & ShaderInput::A_read) != 0) { - access = GL_READ_ONLY; + bool has_read = param->has_read_access(); + bool has_write = param->has_write_access(); + input._writable = has_write; - } else if ((input->_access & ShaderInput::A_write) != 0) { - access = GL_WRITE_ONLY; + if (has_read && has_write) { + access = GL_READ_WRITE; - } else { - access = GL_READ_ONLY; - gl_tex = 0; + } else if (has_read) { + access = GL_READ_ONLY; + + } else if (has_write) { + access = GL_WRITE_ONLY; + + } else { + access = GL_READ_ONLY; + gl_tex = 0; + } } - _glgsg->_glBindImageTexture(i, gl_tex, input->_bind_level, layered, - input->_bind_layer, access, gtc->_internal_format); + _glgsg->_glBindImageTexture(i, gl_tex, bind_level, layered, bind_layer, + access, gtc->_internal_format); } } } @@ -1679,22 +1947,27 @@ update_shader_texture_bindings(ShaderContext *prev) { for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { Shader::ShaderTexSpec &spec = _shader->_tex_spec[i]; const InternalName *id = spec._name; - int texunit = spec._stage; Texture *tex = NULL; int view = _glgsg->get_current_tex_view_offset(); SamplerState sampler; if (id != NULL) { - const ShaderInput *input = _glgsg->_target_shader->get_shader_input(id); - tex = input->get_texture(); - sampler = input->get_sampler(); - - } else { - if (texunit >= texattrib->get_num_on_stages()) { + // Named texture input. + if (!_glgsg->_target_shader->has_shader_input(id)) { + // This used to be legal for some reason, so don't trigger the assert. + GLCAT.error() + << "Shader input " << *id << " is not present.\n"; continue; } - TextureStage *stage = texattrib->get_on_stage(texunit); + tex = _glgsg->_target_shader->get_shader_input_texture(id, &sampler); + + } else { + // Numbered texture input. + if (spec._stage >= texattrib->get_num_on_stages()) { + continue; + } + TextureStage *stage = texattrib->get_on_stage(spec._stage); tex = texattrib->get_on_texture(stage); sampler = texattrib->get_on_sampler(stage); view += stage->get_tex_view_offset(); @@ -1711,7 +1984,7 @@ update_shader_texture_bindings(ShaderContext *prev) { "match type of texture " << *tex << ".\n"; } else { GLCAT.error() - << "Sampler type of GLSL shader input p3d_Texture" << texunit + << "Sampler type of GLSL shader input p3d_Texture" << spec._stage << " does not match type of texture " << *tex << ".\n"; } //TODO: also check whether shadow sampler textures have shadow filter enabled. @@ -1722,7 +1995,7 @@ update_shader_texture_bindings(ShaderContext *prev) { continue; } - GLint p = _glsl_parameter_map[spec._id._seqno]; + GLint p = spec._id._seqno; #ifndef OPENGLES // If it was recently written to, we will have to issue a memory barrier soon. @@ -1820,7 +2093,7 @@ glsl_report_shader_errors(GLuint shader, Shader::ShaderType type, bool fatal) { << "ERROR: " << fn << ":" << lineno << ": " << (line.c_str() + prefixlen) << "\n"; } else if (sscanf(line.c_str(), "WARNING: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2 - && prefixlen > 0) { + && prefixlen > 0) { Filename fn = _shader->get_filename_from_index(fileno, type); GLCAT.warning(false) @@ -1860,9 +2133,13 @@ glsl_report_program_errors(GLuint program, bool fatal) { info_log = (char *) alloca(length); _glgsg->_glGetProgramInfoLog(program, length, &num_chars, info_log); - if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) { + if (strcmp(info_log, "Success.\n") != 0 && + strcmp(info_log, "No errors.\n") != 0 && + strcmp(info_log, "Validation successful.\n") != 0) { if (!fatal) { - GLCAT.warning(false) << info_log << "\n"; + GLCAT.warning() + << "Shader " << _shader->get_filename() << " produced the " + << "following warnings:\n" << info_log << "\n"; } else { GLCAT.error(false) << info_log << "\n"; } diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index f9ca285572..48a74f99cb 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -20,6 +20,7 @@ #include "shader.h" #include "shaderContext.h" #include "deletedChain.h" +#include "paramTexture.h" class CLP(GraphicsStateGuardian); @@ -35,6 +36,12 @@ public: ~CLP(ShaderContext)(); ALLOC_DELETED_CHAIN(CLP(ShaderContext)); + void reflect_attribute(int i, char *name_buf, GLsizei name_buflen); +#ifndef OPENGLES + void reflect_uniform_block(int i, const char *block_name, + char *name_buffer, GLsizei name_buflen); +#endif + void reflect_uniform(int i, char *name_buffer, GLsizei name_buflen); bool get_sampler_texture_type(int &out, GLenum param_type); INLINE bool valid(void); @@ -51,6 +58,7 @@ public: INLINE bool uses_custom_texture_bindings(void); private: + bool _validated; GLuint _glsl_program; typedef pvector GLSLShaders; GLSLShaders _glsl_shaders; @@ -66,11 +74,14 @@ private: //ParamContexts _params; GLint _color_attrib_index; - pvector _glsl_parameter_map; pmap _glsl_uniform_handles; - pvector _glsl_img_inputs; - pvector _glsl_img_textures; + struct ImageInput { + CPT(InternalName) _name; + CLP(TextureContext) *_gtc; + bool _writable; + }; + pvector _glsl_img_inputs; CLP(GraphicsStateGuardian) *_glgsg; diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 2358603e04..1511c68d1d 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -222,6 +222,12 @@ ConfigVariableBool gl_dump_compiled_shaders "programs to disk with a filename like glsl_program0.dump " "into the current directory.")); +ConfigVariableBool gl_validate_shaders + ("gl-validate-shaders", true, + PRC_DESC("Set this to true to enable glValidateShader the first time " + "a shader is bound. This may cause helpful information about " + "shaders to be printed.")); + ConfigVariableBool gl_immutable_texture_storage ("gl-immutable-texture-storage", false, PRC_DESC("This configures Panda to pre-allocate immutable storage " diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index dd6f21d4c6..65e489a3ea 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -70,6 +70,7 @@ extern ConfigVariableBool gl_force_flush; extern ConfigVariableBool gl_separate_specular_color; extern ConfigVariableBool gl_cube_map_seamless; extern ConfigVariableBool gl_dump_compiled_shaders; +extern ConfigVariableBool gl_validate_shaders; extern ConfigVariableBool gl_immutable_texture_storage; extern ConfigVariableBool gl_use_bindless_texture; extern ConfigVariableBool gl_enable_memory_barriers; diff --git a/panda/src/gobj/geomVertexColumn.I b/panda/src/gobj/geomVertexColumn.I index f9a33bfaf6..50268cd3f2 100644 --- a/panda/src/gobj/geomVertexColumn.I +++ b/panda/src/gobj/geomVertexColumn.I @@ -33,13 +33,16 @@ GeomVertexColumn() : INLINE GeomVertexColumn:: GeomVertexColumn(CPT_InternalName name, int num_components, NumericType numeric_type, Contents contents, - int start, int column_alignment) : + int start, int column_alignment, int num_elements, + int element_stride) : _name(MOVE(name)), _num_components(num_components), _numeric_type(numeric_type), _contents(contents), _start(start), _column_alignment(column_alignment), + _num_elements(num_elements), + _element_stride(element_stride), _packer(NULL) { setup(); @@ -58,6 +61,8 @@ GeomVertexColumn(const GeomVertexColumn ©) : _contents(copy._contents), _start(copy._start), _column_alignment(copy._column_alignment), + _num_elements(copy._num_elements), + _element_stride(copy._element_stride), _packer(NULL) { setup(); @@ -317,6 +322,12 @@ compare_to(const GeomVertexColumn &other) const { if (_column_alignment != other._column_alignment) { return _column_alignment - other._column_alignment; } + if (_num_elements != other._num_elements) { + return _num_elements - other._num_elements; + } + if (_element_stride != other._element_stride) { + return _element_stride - other._element_stride; + } return 0; } diff --git a/panda/src/gobj/geomVertexColumn.cxx b/panda/src/gobj/geomVertexColumn.cxx index e5cbe29e27..9ea21fcd51 100644 --- a/panda/src/gobj/geomVertexColumn.cxx +++ b/panda/src/gobj/geomVertexColumn.cxx @@ -30,6 +30,8 @@ operator = (const GeomVertexColumn ©) { _contents = copy._contents; _start = copy._start; _column_alignment = copy._column_alignment; + _num_elements = copy._num_elements; + _element_stride = copy._element_stride; setup(); } @@ -159,6 +161,10 @@ output(ostream &out) const { } out << ")"; + + if (_num_elements > 1) { + out << "[" << _num_elements << "]"; + } } //////////////////////////////////////////////////////////////////// @@ -172,7 +178,6 @@ setup() { nassertv(_num_components > 0 && _start >= 0); _num_values = _num_components; - _num_elements = 1; if (_numeric_type == NT_stdfloat) { if (vertices_float64) { @@ -222,8 +227,13 @@ setup() { break; } - if (_contents == C_matrix) { - _num_elements = _num_components; + if (_num_elements == 0) { + // Matrices are assumed to be square. + if (_contents == C_matrix) { + _num_elements = _num_components; + } else { + _num_elements = 1; + } } if (_column_alignment < 1) { @@ -236,7 +246,9 @@ setup() { // Enforce the column alignment requirements on the _start byte. _start = ((_start + _column_alignment - 1) / _column_alignment) * _column_alignment; - _element_stride = _component_bytes * _num_components; + if (_element_stride < 1) { + _element_stride = _component_bytes * _num_components; + } _total_bytes = _element_stride * _num_elements; if (_packer != NULL) { @@ -433,6 +445,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { _column_alignment = scan.get_uint8(); } + _num_elements = 0; + _element_stride = 0; + setup(); } diff --git a/panda/src/gobj/geomVertexColumn.h b/panda/src/gobj/geomVertexColumn.h index 8629c786d5..8fab9952aa 100644 --- a/panda/src/gobj/geomVertexColumn.h +++ b/panda/src/gobj/geomVertexColumn.h @@ -43,7 +43,8 @@ private: PUBLISHED: INLINE GeomVertexColumn(CPT_InternalName name, int num_components, NumericType numeric_type, Contents contents, - int start, int column_alignment = 0); + int start, int column_alignment = 0, + int num_elements = 0, int element_stride = 0); INLINE GeomVertexColumn(const GeomVertexColumn ©); void operator = (const GeomVertexColumn ©); INLINE ~GeomVertexColumn(); @@ -346,7 +347,7 @@ private: } }; - class Packer_nativedouble_3 : public Packer_float64_3 { + class Packer_nativedouble_3 FINAL : public Packer_float64_3 { public: virtual const LVecBase3d &get_data3d(const unsigned char *pointer); @@ -355,7 +356,7 @@ private: } }; - class Packer_point_nativedouble_2 : public Packer_point_float64_2 { + class Packer_point_nativedouble_2 FINAL : public Packer_point_float64_2 { public: virtual const LVecBase2d &get_data2d(const unsigned char *pointer); @@ -364,7 +365,7 @@ private: } }; - class Packer_point_nativedouble_3 : public Packer_point_float64_3 { + class Packer_point_nativedouble_3 FINAL : public Packer_point_float64_3 { public: virtual const LVecBase3d &get_data3d(const unsigned char *pointer); @@ -382,7 +383,7 @@ private: } }; - class Packer_argb_packed : public Packer_color { + class Packer_argb_packed FINAL : public Packer_color { public: virtual const LVecBase4f &get_data4f(const unsigned char *pointer); virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value); @@ -392,7 +393,7 @@ private: } }; - class Packer_rgba_uint8_4 : public Packer_color { + class Packer_rgba_uint8_4 FINAL : public Packer_color { public: virtual const LVecBase4f &get_data4f(const unsigned char *pointer); virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value); @@ -412,7 +413,7 @@ private: } }; - class Packer_rgba_nativefloat_4 : public Packer_rgba_float32_4 { + class Packer_rgba_nativefloat_4 FINAL : public Packer_rgba_float32_4 { public: virtual const LVecBase4f &get_data4f(const unsigned char *pointer); @@ -421,7 +422,7 @@ private: } }; - class Packer_uint16_1 : public Packer { + class Packer_uint16_1 FINAL : public Packer { public: virtual int get_data1i(const unsigned char *pointer); virtual void set_data1i(unsigned char *pointer, int value); diff --git a/panda/src/linmath/lcast_to_src.I b/panda/src/linmath/lcast_to_src.I index acfcad19d5..b5253a111e 100644 --- a/panda/src/linmath/lcast_to_src.I +++ b/panda/src/linmath/lcast_to_src.I @@ -138,3 +138,48 @@ lcast_to(FLOATTYPE2 *, const FLOATNAME(LMatrix4) &source) { source(2, 0), source(2, 1), source(2, 2), source(2, 3), source(3, 0), source(3, 1), source(3, 2), source(3, 3)); } + +INLINE_LINMATH FLOATNAME2(LVecBase2) +lcast_to(FLOATTYPE2 *, const LVecBase2i &source) { + return FLOATNAME2(LVecBase2)(source[0], source[1]); +} + +INLINE_LINMATH FLOATNAME2(LVecBase3) +lcast_to(FLOATTYPE2 *, const LVecBase3i &source) { + return FLOATNAME2(LVecBase3)(source[0], source[1], source[2]); +} + +INLINE_LINMATH FLOATNAME2(LVecBase4) +lcast_to(FLOATTYPE2 *, const LVecBase4i &source) { + return FLOATNAME2(LVecBase4)(source[0], source[1], source[2], source[3]); +} + +INLINE_LINMATH FLOATNAME2(LVector2) +lcast_to(FLOATTYPE2 *, const LVector2i &source) { + return FLOATNAME2(LVector2)(source[0], source[1]); +} + +INLINE_LINMATH FLOATNAME2(LVector3) +lcast_to(FLOATTYPE2 *, const LVector3i &source) { + return FLOATNAME2(LVector3)(source[0], source[1], source[2]); +} + +INLINE_LINMATH FLOATNAME2(LVector4) +lcast_to(FLOATTYPE2 *, const LVector4i &source) { + return FLOATNAME2(LVector4)(source[0], source[1], source[2], source[3]); +} + +INLINE_LINMATH FLOATNAME2(LPoint2) +lcast_to(FLOATTYPE2 *, const LPoint2i &source) { + return FLOATNAME2(LPoint2)(source[0], source[1]); +} + +INLINE_LINMATH FLOATNAME2(LPoint3) +lcast_to(FLOATTYPE2 *, const LPoint3i &source) { + return FLOATNAME2(LPoint3)(source[0], source[1], source[2]); +} + +INLINE_LINMATH FLOATNAME2(LPoint4) +lcast_to(FLOATTYPE2 *, const LPoint4i &source) { + return FLOATNAME2(LPoint4)(source[0], source[1], source[2], source[3]); +} diff --git a/panda/src/linmath/lcast_to_src.h b/panda/src/linmath/lcast_to_src.h index 9fa5b9e0cd..c61044d2da 100644 --- a/panda/src/linmath/lcast_to_src.h +++ b/panda/src/linmath/lcast_to_src.h @@ -86,6 +86,33 @@ lcast_to(FLOATTYPE2 *, const FLOATNAME(LMatrix3) &source); INLINE_LINMATH FLOATNAME2(LMatrix4) lcast_to(FLOATTYPE2 *, const FLOATNAME(LMatrix4) &source); +INLINE_LINMATH FLOATNAME2(LVecBase2) +lcast_to(FLOATTYPE2 *, const LVecBase2i &source); + +INLINE_LINMATH FLOATNAME2(LVecBase3) +lcast_to(FLOATTYPE2 *, const LVecBase3i &source); + +INLINE_LINMATH FLOATNAME2(LVecBase4) +lcast_to(FLOATTYPE2 *, const LVecBase4i &source); + +INLINE_LINMATH FLOATNAME2(LVector2) +lcast_to(FLOATTYPE2 *, const LVector2i &source); + +INLINE_LINMATH FLOATNAME2(LVector3) +lcast_to(FLOATTYPE2 *, const LVector3i &source); + +INLINE_LINMATH FLOATNAME2(LVector4) +lcast_to(FLOATTYPE2 *, const LVector4i &source); + +INLINE_LINMATH FLOATNAME2(LPoint2) +lcast_to(FLOATTYPE2 *, const LPoint2i &source); + +INLINE_LINMATH FLOATNAME2(LPoint3) +lcast_to(FLOATTYPE2 *, const LPoint3i &source); + +INLINE_LINMATH FLOATNAME2(LPoint4) +lcast_to(FLOATTYPE2 *, const LPoint4i &source); + #include "lcast_to_src.I" #endif // CPPPARSER diff --git a/panda/src/pgraph/shaderAttrib.cxx b/panda/src/pgraph/shaderAttrib.cxx index ad9b1a6eef..1cfb112b93 100644 --- a/panda/src/pgraph/shaderAttrib.cxx +++ b/panda/src/pgraph/shaderAttrib.cxx @@ -429,9 +429,12 @@ get_shader_input_ptr(const InternalName *id) const { // Access: Published // Description: Returns the ShaderInput as a texture. Assertion // fails if there is none, or if it is not a texture. +// +// If sampler is not NULL, the sampler state to use +// for this texture is assigned to it. //////////////////////////////////////////////////////////////////// Texture *ShaderAttrib:: -get_shader_input_texture(const InternalName *id) const { +get_shader_input_texture(const InternalName *id, SamplerState *sampler) const { Inputs::const_iterator i = _inputs.find(id); if (i == _inputs.end()) { ostringstream strm; @@ -447,34 +450,10 @@ get_shader_input_texture(const InternalName *id) const { nassert_raise(strm.str()); return NULL; } - return p->get_texture(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: ShaderAttrib::get_shader_input_sampler -// Access: Published -// Description: Returns the ShaderInput as a sampler. Assertion -// fails if there is none, or if it is not a texture. -//////////////////////////////////////////////////////////////////// -const SamplerState &ShaderAttrib:: -get_shader_input_sampler(const InternalName *id) const { - Inputs::const_iterator i = _inputs.find(id); - if (i == _inputs.end()) { - ostringstream strm; - strm << "Shader input " << id->get_name() << " is not present.\n"; - nassert_raise(strm.str()); - return SamplerState::get_default(); - } else { - const ShaderInput *p = (*i).second; - if (p->get_value_type() != ShaderInput::M_texture && - p->get_value_type() != ShaderInput::M_texture_sampler) { - ostringstream strm; - strm << "Shader input " << id->get_name() << " is not a texture.\n"; - nassert_raise(strm.str()); - return SamplerState::get_default(); + if (sampler != NULL) { + *sampler = p->get_sampler(); } - return p->get_sampler(); + return p->get_texture(); } } diff --git a/panda/src/pgraph/shaderAttrib.h b/panda/src/pgraph/shaderAttrib.h index c6bb2eb583..7bf605f9bd 100644 --- a/panda/src/pgraph/shaderAttrib.h +++ b/panda/src/pgraph/shaderAttrib.h @@ -106,8 +106,7 @@ PUBLISHED: const NodePath &get_shader_input_nodepath(const InternalName *id) const; LVecBase4 get_shader_input_vector(InternalName *id) const; - Texture *get_shader_input_texture(const InternalName *id) const; - const SamplerState &get_shader_input_sampler(const InternalName *id) const; + Texture *get_shader_input_texture(const InternalName *id, SamplerState *sampler=NULL) const; const Shader::ShaderPtrData *get_shader_input_ptr(const InternalName *id) const; const LMatrix4 &get_shader_input_matrix(const InternalName *id, LMatrix4 &matrix) const; diff --git a/panda/src/pgraph/shaderInput.I b/panda/src/pgraph/shaderInput.I index c7aed1de80..5a060bb0e6 100644 --- a/panda/src/pgraph/shaderInput.I +++ b/panda/src/pgraph/shaderInput.I @@ -31,10 +31,7 @@ INLINE ShaderInput:: ShaderInput(CPT_InternalName name, int priority) : _name(MOVE(name)), _type(M_invalid), - _priority(priority), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _priority(priority) { } @@ -48,60 +45,10 @@ ShaderInput(CPT_InternalName name, Texture *tex, int priority) : _name(MOVE(name)), _type(M_texture), _priority(priority), - _value(tex), - _bind_layer(0), - _bind_level(0), - _access(A_read | A_write | A_layered) + _value(tex) { } -//////////////////////////////////////////////////////////////////// -// Function: ShaderInput::Constructor -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE ShaderInput:: -ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority) : - _name(MOVE(name)), - _type(M_texture_sampler), - _priority(priority), - _value(tex), - _sampler(sampler), - _bind_layer(0), - _bind_level(0), - _access(A_read | A_layered) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: ShaderInput::Constructor -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE ShaderInput:: -ShaderInput(CPT_InternalName name, Texture *tex, bool read, bool write, int z, int n, int priority) : - _name(MOVE(name)), - _type(M_texture), - _priority(priority), - _value(tex), - _bind_layer(z), - _bind_level(n), - _access(0) -{ - if (read) { - _access |= A_read; - } - if (write) { - _access |= A_write; - } - if (z >= 0) { - _bind_layer = z; - } else { - _bind_layer = 0; - _access |= A_layered; - } -} - //////////////////////////////////////////////////////////////////// // Function: ShaderInput::Constructor // Access: Published @@ -112,10 +59,7 @@ ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority) : _name(MOVE(name)), _type(M_param), _priority(priority), - _value(param), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _value(param) { } @@ -129,10 +73,7 @@ ShaderInput(CPT_InternalName name, const PTA_float &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -146,10 +87,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase4f &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -163,10 +101,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase3f &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -180,10 +115,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase2f &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -198,10 +130,7 @@ ShaderInput(CPT_InternalName name, const LVecBase4f &vec, int priority) : _type(M_vector), _priority(priority), _stored_ptr(vec), - _stored_vector(LCAST(PN_stdfloat, vec)), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector(LCAST(PN_stdfloat, vec)) { } @@ -216,10 +145,7 @@ ShaderInput(CPT_InternalName name, const LVecBase3f &vec, int priority) : _type(M_vector), _priority(priority), _stored_ptr(vec), - _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0) { } @@ -234,10 +160,7 @@ ShaderInput(CPT_InternalName name, const LVecBase2f &vec, int priority) : _type(M_vector), _priority(priority), _stored_ptr(vec), - _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0) { } @@ -251,10 +174,7 @@ ShaderInput(CPT_InternalName name, const PTA_LMatrix4f &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -268,10 +188,7 @@ ShaderInput(CPT_InternalName name, const PTA_LMatrix3f &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -285,10 +202,7 @@ ShaderInput(CPT_InternalName name, const LMatrix4f &mat, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(mat), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(mat) { } @@ -302,10 +216,7 @@ ShaderInput(CPT_InternalName name, const LMatrix3f &mat, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(mat), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(mat) { } @@ -319,10 +230,7 @@ ShaderInput(CPT_InternalName name, const PTA_double &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -336,10 +244,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase4d &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -353,10 +258,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase3d &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -370,10 +272,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase2d &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -388,10 +287,7 @@ ShaderInput(CPT_InternalName name, const LVecBase4d &vec, int priority) : _type(M_numeric), _priority(priority), _stored_ptr(vec), - _stored_vector(LCAST(PN_stdfloat, vec)), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector(LCAST(PN_stdfloat, vec)) { } @@ -406,10 +302,7 @@ ShaderInput(CPT_InternalName name, const LVecBase3d &vec, int priority) : _type(M_numeric), _priority(priority), _stored_ptr(vec), - _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0) { } @@ -424,10 +317,7 @@ ShaderInput(CPT_InternalName name, const LVecBase2d &vec, int priority) : _type(M_numeric), _priority(priority), _stored_ptr(vec), - _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0) { } @@ -441,10 +331,7 @@ ShaderInput(CPT_InternalName name, const PTA_LMatrix4d &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -458,10 +345,7 @@ ShaderInput(CPT_InternalName name, const PTA_LMatrix3d &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -475,10 +359,7 @@ ShaderInput(CPT_InternalName name, const LMatrix4d &mat, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(mat), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(mat) { } @@ -492,10 +373,7 @@ ShaderInput(CPT_InternalName name, const LMatrix3d &mat, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(mat), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(mat) { } @@ -509,10 +387,7 @@ ShaderInput(CPT_InternalName name, const PTA_int &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -526,10 +401,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase4i &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -543,10 +415,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase3i &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -560,10 +429,7 @@ ShaderInput(CPT_InternalName name, const PTA_LVecBase2i &ptr, int priority) : _name(MOVE(name)), _type(M_numeric), _priority(priority), - _stored_ptr(ptr), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_ptr(ptr) { } @@ -578,10 +444,7 @@ ShaderInput(CPT_InternalName name, const LVecBase4i &vec, int priority) : _type(M_numeric), _priority(priority), _stored_ptr(vec), - _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), (int)vec.get_w()), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), (int)vec.get_w()) { } @@ -596,10 +459,7 @@ ShaderInput(CPT_InternalName name, const LVecBase3i &vec, int priority) : _type(M_numeric), _priority(priority), _stored_ptr(vec), - _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), 0.0), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), 0.0) { } @@ -614,10 +474,7 @@ ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority) : _type(M_numeric), _priority(priority), _stored_ptr(vec), - _stored_vector((int)vec.get_x(), (int)vec.get_y(), 0.0, 0.0), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _stored_vector((int)vec.get_x(), (int)vec.get_y(), 0.0, 0.0) { } @@ -651,16 +508,6 @@ get_priority() const { return _priority; } -//////////////////////////////////////////////////////////////////// -// Function: ShaderInput::get_texture -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE Texture *ShaderInput:: -get_texture() const { - return DCAST(Texture, _value); -} - //////////////////////////////////////////////////////////////////// // Function: ShaderInput::get_vector // Access: Published @@ -681,18 +528,6 @@ get_ptr() const { return _stored_ptr; } -//////////////////////////////////////////////////////////////////// -// Function: ShaderInput::get_sampler -// Access: Published -// Description: -//////////////////////////////////////////////////////////////////// -INLINE const SamplerState &ShaderInput:: -get_sampler() const { - return (_type == M_texture) - ? get_texture()->get_default_sampler() - : _sampler; -} - //////////////////////////////////////////////////////////////////// // Function: ShaderInput::get_param // Access: Public diff --git a/panda/src/pgraph/shaderInput.cxx b/panda/src/pgraph/shaderInput.cxx index 8ab7ef3b1a..ecb281f6f3 100644 --- a/panda/src/pgraph/shaderInput.cxx +++ b/panda/src/pgraph/shaderInput.cxx @@ -14,6 +14,7 @@ #include "shaderInput.h" #include "paramNodePath.h" +#include "paramTexture.h" TypeHandle ShaderInput::_type_handle; @@ -43,10 +44,35 @@ ShaderInput(CPT_InternalName name, const NodePath &np, int priority) : _name(MOVE(name)), _type(M_nodepath), _priority(priority), - _value(new ParamNodePath(np)), - _bind_layer(0), - _bind_level(0), - _access(A_read) + _value(new ParamNodePath(np)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +ShaderInput:: +ShaderInput(CPT_InternalName name, Texture *tex, bool read, bool write, int z, int n, int priority) : + _name(MOVE(name)), + _type(M_texture_image), + _priority(priority), + _value(new ParamTextureImage(tex, read, write, z, n)) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +ShaderInput:: +ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority) : + _name(MOVE(name)), + _type(M_texture_sampler), + _priority(priority), + _value(new ParamTextureSampler(tex, sampler)) { } @@ -61,6 +87,40 @@ get_nodepath() const { return DCAST(ParamNodePath, _value)->get_value(); } +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::get_texture +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +Texture *ShaderInput:: +get_texture() const { + switch (_type) { + case M_texture_sampler: + return DCAST(ParamTextureSampler, _value)->get_texture(); + + case M_texture_image: + return DCAST(ParamTextureImage, _value)->get_texture(); + + case M_texture: + return DCAST(Texture, _value); + + default: + return NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: ShaderInput::get_sampler +// Access: Published +// Description: Warning: no error checking is done. +//////////////////////////////////////////////////////////////////// +const SamplerState &ShaderInput:: +get_sampler() const { + return (_type == M_texture_sampler) + ? DCAST(ParamTextureSampler, _value)->get_sampler() + : get_texture()->get_default_sampler(); +} + //////////////////////////////////////////////////////////////////// // Function: ShaderInput::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/shaderInput.h b/panda/src/pgraph/shaderInput.h index 26c7e2e375..11b4630a53 100644 --- a/panda/src/pgraph/shaderInput.h +++ b/panda/src/pgraph/shaderInput.h @@ -53,8 +53,6 @@ PUBLISHED: static const ShaderInput *get_blank(); INLINE ShaderInput(CPT_InternalName name, int priority=0); INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0); - INLINE ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority=0); - INLINE ShaderInput(CPT_InternalName name, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0); INLINE ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority=0); INLINE ShaderInput(CPT_InternalName name, const PTA_float &ptr, int priority=0); INLINE ShaderInput(CPT_InternalName name, const PTA_LVecBase4f &ptr, int priority=0); @@ -89,6 +87,8 @@ PUBLISHED: INLINE ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority=0); ShaderInput(CPT_InternalName name, const NodePath &np, int priority=0); + ShaderInput(CPT_InternalName name, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0); + ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority=0); enum ShaderInputType { M_invalid = 0, @@ -97,19 +97,20 @@ PUBLISHED: M_vector, M_numeric, M_texture_sampler, - M_param + M_param, + M_texture_image }; INLINE const InternalName *get_name() const; INLINE int get_value_type() const; INLINE int get_priority() const; - INLINE Texture *get_texture() const; INLINE const LVecBase4 &get_vector() const; INLINE const Shader::ShaderPtrData &get_ptr() const; - INLINE const SamplerState &get_sampler() const; const NodePath &get_nodepath() const; + Texture *get_texture() const; + const SamplerState &get_sampler() const; public: INLINE ParamValueBase *get_param() const; @@ -117,25 +118,19 @@ public: static void register_with_read_factory(); private: - SamplerState _sampler; LVecBase4 _stored_vector; Shader::ShaderPtrData _stored_ptr; CPT_InternalName _name; PT(TypedWritableReferenceCount) _value; int _priority; - -public: - int _type : 8; - int _access : 8; - int _bind_level : 16; - int _bind_layer; + int _type; public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - ReferenceCount::init_type(); + TypedWritableReferenceCount::init_type(); register_type(_type_handle, "ShaderInput", TypedWritableReferenceCount::get_class_type()); } diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index 5195b8ac5d..a443e95426 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -104,6 +104,7 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, _awaiting_configure = false; _dga_mouse_enabled = false; + _override_redirect = False; _wm_delete_window = x11_pipe->_wm_delete_window; GraphicsWindowInputDevice device = @@ -946,9 +947,10 @@ open_window() { wa.border_pixel = 0; wa.colormap = _colormap; wa.event_mask = _event_mask; + wa.override_redirect = _override_redirect; unsigned long attrib_mask = - CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; _xwindow = XCreateWindow (_display, parent_window, diff --git a/panda/src/x11display/x11GraphicsWindow.h b/panda/src/x11display/x11GraphicsWindow.h index 9fc7210f60..8f59a9534d 100644 --- a/panda/src/x11display/x11GraphicsWindow.h +++ b/panda/src/x11display/x11GraphicsWindow.h @@ -99,6 +99,7 @@ protected: long _event_mask; bool _awaiting_configure; bool _dga_mouse_enabled; + Bool _override_redirect; Atom _wm_delete_window; struct MouseDeviceInfo {