diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 120caff983..286db3e2f3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -506,17 +506,21 @@ reset() { glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); } - GLCAT.debug() << "gl-debug enabled.\n"; + GLCAT.info() << "gl-debug enabled.\n"; } else { - GLCAT.debug() << "gl-debug enabled, but NOT supported.\n"; + GLCAT.warning() << "gl-debug enabled, but NOT supported.\n"; } } else { - GLCAT.debug() << "gl-debug NOT enabled.\n"; - // However, still check if it is supported. _supports_debug = is_at_least_gl_version(4, 3) || has_extension("GL_KHR_debug") || has_extension("GL_ARB_debug_output"); + + if (_supports_debug) { + GLCAT.debug() << "gl-debug supported, but NOT enabled.\n"; + } else { + GLCAT.debug() << "gl-debug disabled and unsupported.\n"; + } } #endif // OPENGLES_1 @@ -561,7 +565,8 @@ reset() { #elif defined(OPENGLES_1) _supports_point_sprite = has_extension("GL_OES_point_sprite"); #else - _supports_point_sprite = has_extension("GL_ARB_point_sprite"); + _supports_point_sprite = is_at_least_gl_version(2, 0) || + has_extension("GL_ARB_point_sprite"); #endif if (_supports_point_sprite) { @@ -852,7 +857,8 @@ reset() { _supports_cube_map = true; #else _supports_cube_map = - has_extension("GL_ARB_texture_cube_map") || is_at_least_gl_version(1, 3) || + is_at_least_gl_version(1, 3) || + has_extension("GL_ARB_texture_cube_map") || has_extension("GL_OES_texture_cube_map"); #endif @@ -872,8 +878,6 @@ reset() { _supports_texture_srgb = true; } - _supports_compressed_texture = false; - #ifdef OPENGLES _supports_compressed_texture = true; @@ -931,6 +935,9 @@ reset() { get_extension_func("glCompressedTexSubImage3DARB"); _glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) get_extension_func("glGetCompressedTexImageARB"); + + } else { + _supports_compressed_texture = false; } if (_supports_compressed_texture) { @@ -955,7 +962,7 @@ reset() { GLint num_compressed_formats = 0; glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats); - GLint *formats = (GLint *)PANDA_MALLOC_ARRAY(num_compressed_formats * sizeof(GLint)); + GLint *formats = (GLint *)alloca(num_compressed_formats * sizeof(GLint)); glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); for (int i = 0; i < num_compressed_formats; ++i) { switch (formats[i]) { @@ -991,7 +998,6 @@ reset() { break; } } - PANDA_FREE_ARRAY(formats); } #ifdef OPENGLES_2 @@ -1024,18 +1030,20 @@ reset() { _supports_multisample = has_extension("GL_ARB_multisample") || is_at_least_gl_version(1, 3); -#ifdef OPENGLES_2 +#ifdef OPENGLES_1 + _supports_generate_mipmap = is_at_least_gles_version(1, 1); +#elif defined(OPENGLES) _supports_generate_mipmap = true; #else - _supports_generate_mipmap = - has_extension("GL_SGIS_generate_mipmap") || is_at_least_gl_version(1, 4) || is_at_least_gles_version(1, 1); + _supports_generate_mipmap = is_at_least_gl_version(1, 4) || + has_extension("GL_SGIS_generate_mipmap"); #endif #ifdef OPENGLES _supports_tex_non_pow2 = has_extension("GL_OES_texture_npot"); #else - _supports_tex_non_pow2 = + _supports_tex_non_pow2 = is_at_least_gl_version(2, 0) || has_extension("GL_ARB_texture_non_power_of_two"); #endif @@ -1142,7 +1150,7 @@ reset() { #else if (gl_support_shadow_filter && _supports_depth_texture && - has_extension("GL_ARB_shadow") && + (is_at_least_gl_version(1, 4) || has_extension("GL_ARB_shadow")) && has_extension("GL_ARB_fragment_program_shadow")) { _supports_shadow_filter = true; } @@ -1405,7 +1413,8 @@ reset() { } else { _glVertexAttribIPointer = NULL; } - if (has_extension("GL_ARB_vertex_attrib_64bit")) { + if (is_at_least_gl_version(4, 1) || + has_extension("GL_ARB_vertex_attrib_64bit")) { _glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC) get_extension_func("glVertexAttribLPointer"); } else { @@ -1691,7 +1700,7 @@ reset() { #endif _supports_framebuffer_multisample = false; - if ( has_extension("GL_EXT_framebuffer_multisample") ) { + if (has_extension("GL_EXT_framebuffer_multisample")) { _supports_framebuffer_multisample = true; _glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) get_extension_func("glRenderbufferStorageMultisampleEXT"); @@ -1699,7 +1708,7 @@ reset() { #ifndef OPENGLES _supports_framebuffer_multisample_coverage_nv = false; - if ( has_extension("GL_NV_framebuffer_multisample_coverage") ) { + if (has_extension("GL_NV_framebuffer_multisample_coverage")) { _supports_framebuffer_multisample_coverage_nv = true; _glRenderbufferStorageMultisampleCoverage = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) get_extension_func("glRenderbufferStorageMultisampleCoverageNV"); @@ -1708,7 +1717,7 @@ reset() { #ifndef OPENGLES_1 _supports_framebuffer_blit = false; - if ( has_extension("GL_EXT_framebuffer_blit") ) { + if (has_extension("GL_EXT_framebuffer_blit")) { _supports_framebuffer_blit = true; _glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC) get_extension_func("glBlitFramebufferEXT"); @@ -1922,8 +1931,8 @@ reset() { _edge_clamp = GL_CLAMP_TO_EDGE; #else _edge_clamp = GL_CLAMP; - if (has_extension("GL_SGIS_texture_edge_clamp") || - is_at_least_gl_version(1, 2) || is_at_least_gles_version(1, 1)) { + if (is_at_least_gl_version(1, 2) || is_at_least_gles_version(1, 1) || + has_extension("GL_SGIS_texture_edge_clamp")) { _edge_clamp = GL_CLAMP_TO_EDGE; } #endif @@ -1959,6 +1968,20 @@ reset() { } #endif +#ifndef OPENGLES + _supports_texture_lod = false; + _supports_texture_lod_bias = false; + + if (gl_support_texture_lod && + (is_at_least_gl_version(1, 2) || has_extension("GL_SGIS_texture_lod"))) { + _supports_texture_lod = true; + + if (is_at_least_gl_version(1, 4) || has_extension("GL_EXT_texture_lod_bias")) { + _supports_texture_lod_bias = true; + } + } +#endif + if (_supports_multisample) { GLint sample_buffers = 0; glGetIntegerv(GL_SAMPLE_BUFFERS, &sample_buffers); @@ -4762,9 +4785,14 @@ prepare_sampler(const SamplerState &sampler) { } } - _glSamplerParameterf(index, GL_TEXTURE_MIN_LOD, sampler.get_min_lod()); - _glSamplerParameterf(index, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); - _glSamplerParameterf(index, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); + if (_supports_texture_lod) { + _glSamplerParameterf(index, GL_TEXTURE_MIN_LOD, sampler.get_min_lod()); + _glSamplerParameterf(index, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); + } + + if (_supports_texture_lod_bias) { + _glSamplerParameterf(index, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); + } gsc->enqueue_lru(&_prepared_objects->_sampler_object_lru); @@ -6880,13 +6908,15 @@ get_error_string(GLenum error_code) { // We used to use gluErrorString here, but I (rdb) took it out // because that was really the only function we used from GLU. // The idea with the error table was taken from SGI's sample implementation. - static const char *error_strings[GL_OUT_OF_MEMORY - GL_INVALID_ENUM + 1] = { + static const char *error_strings[] = { "invalid enumerant", "invalid value", "invalid operation", "stack overflow", "stack underflow", "out of memory", + "invalid framebuffer operation", + "context lost", }; if (error_code == GL_NO_ERROR) { @@ -6895,8 +6925,8 @@ get_error_string(GLenum error_code) { } else if (error_code == GL_TABLE_TOO_LARGE) { return "table too large"; #endif - } else if (error_code >= GL_INVALID_ENUM && error_code <= GL_OUT_OF_MEMORY) { - return error_strings[error_code - GL_INVALID_ENUM]; + } else if (error_code >= 0x0500 && error_code <= 0x0507) { + return error_strings[error_code - 0x0500]; } // Other error, somehow? Just display the error code then. @@ -7019,7 +7049,7 @@ query_gl_version() { _gl_shadlang_ver_minor = 0; const char *verstr = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION); if (verstr == NULL || - sscanf(verstr, "OpenGL ES GLSL %d.%d", &_gl_shadlang_ver_major, + sscanf(verstr, "OpenGL ES GLSL ES %d.%d", &_gl_shadlang_ver_major, &_gl_shadlang_ver_minor) != 2) { GLCAT.warning() << "Invalid GL_SHADING_LANGUAGE_VERSION format.\n"; } @@ -10402,9 +10432,14 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { #endif #ifndef OPENGLES - glTexParameterf(target, GL_TEXTURE_MIN_LOD, sampler.get_min_lod()); - glTexParameterf(target, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); - glTexParameterf(target, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); + if (_supports_texture_lod) { + glTexParameterf(target, GL_TEXTURE_MIN_LOD, sampler.get_min_lod()); + glTexParameterf(target, GL_TEXTURE_MAX_LOD, sampler.get_max_lod()); + } + + if (_supports_texture_lod_bias) { + glTexParameterf(target, GL_TEXTURE_LOD_BIAS, sampler.get_lod_bias()); + } #endif report_my_gl_errors(); @@ -10771,7 +10806,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) { } #ifndef OPENGLES // OpenGL ES doesn't have GL_TEXTURE_MAX_LEVEL. - if (is_at_least_gl_version(1, 2)) { + if (_supports_texture_lod) { // By the time we get here, we have a pretty good prediction for // the number of mipmaps we're going to have, so tell the GL that's // all it's going to get. @@ -11227,12 +11262,12 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload, GLCAT.warning() << "No mipmap level " << n << " defined for " << tex->get_name() << "\n"; - #ifndef OPENGLES - if (is_at_least_gl_version(1, 2)) { +#ifndef OPENGLES + if (_supports_texture_lod) { // Tell the GL we have no more mipmaps for it to use. glTexParameteri(texture_target, GL_TEXTURE_MAX_LEVEL, n - mipmap_bias); } - #endif +#endif break; } @@ -11409,10 +11444,8 @@ upload_simple_texture(CLP(TextureContext) *gtc) { #ifndef OPENGLES // Turn off mipmaps for the simple texture. - if (tex->uses_mipmaps()) { - if (is_at_least_gl_version(1, 2)) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - } + if (tex->uses_mipmaps() && _supports_texture_lod) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); } #endif @@ -12046,7 +12079,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { GLint num_expected_levels = tex->get_expected_num_mipmap_levels(); GLint highest_level = num_expected_levels; #ifndef OPENGLES - if (is_at_least_gl_version(1, 2)) { + if (_supports_texture_lod) { glGetTexParameteriv(target, GL_TEXTURE_MAX_LEVEL, &highest_level); highest_level = min(highest_level, num_expected_levels); } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 35e5b2d338..f8ec534eb2 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -875,6 +875,12 @@ public: GLenum _mirror_clamp; GLenum _mirror_edge_clamp; GLenum _mirror_border_clamp; + +#ifndef OPENGLES + bool _supports_texture_lod; + bool _supports_texture_lod_bias; +#endif + #ifndef OPENGLES_1 GLsizei _instance_count; #endif diff --git a/panda/src/glstuff/glmisc_src.cxx b/panda/src/glstuff/glmisc_src.cxx index 2358603e04..542bcaf310 100644 --- a/panda/src/glstuff/glmisc_src.cxx +++ b/panda/src/glstuff/glmisc_src.cxx @@ -44,6 +44,12 @@ ConfigVariableBool gl_support_rescale_normal "it even if it appears to be available. (This appears to be " "buggy on some drivers.)")); +ConfigVariableBool gl_support_texture_lod + ("gl-support-texture-lod", true, + PRC_DESC("Configure this true to enable the use of minmax LOD settings " + "and texture LOD bias settings. Set this to false if you " + "suspect a driver bug.")); + ConfigVariableBool gl_ignore_filters ("gl-ignore-filters", false, PRC_DESC("Configure this true to disable any texture filters at all (forcing " diff --git a/panda/src/glstuff/glmisc_src.h b/panda/src/glstuff/glmisc_src.h index dd6f21d4c6..f050863bd2 100644 --- a/panda/src/glstuff/glmisc_src.h +++ b/panda/src/glstuff/glmisc_src.h @@ -45,6 +45,7 @@ extern EXPCL_PANDAGL ConfigVariableBool gl_support_fbo; extern ConfigVariableBool gl_cheap_textures; extern ConfigVariableBool gl_ignore_clamp; extern ConfigVariableBool gl_support_clamp_to_border; +extern ConfigVariableBool gl_support_texture_lod; extern ConfigVariableBool gl_ignore_filters; extern ConfigVariableBool gl_ignore_mipmaps; extern ConfigVariableBool gl_force_mipmaps;