From f20d859fe248d777b78739a81083993ee222ba11 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 16 Jan 2021 14:05:43 +0100 Subject: [PATCH 01/10] pgraph: Fix bug passing non-tuple sequence to shader input --- panda/src/pgraph/shaderInput_ext.cxx | 2 +- tests/pgraph/test_shaderinput.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/panda/src/pgraph/shaderInput_ext.cxx b/panda/src/pgraph/shaderInput_ext.cxx index 72a4d74de3..62b66777cc 100644 --- a/panda/src/pgraph/shaderInput_ext.cxx +++ b/panda/src/pgraph/shaderInput_ext.cxx @@ -282,7 +282,7 @@ __init__(CPT_InternalName name, PyObject *value, int priority) { return; } - Py_ssize_t num_items = PySequence_Fast_GET_SIZE(value); + Py_ssize_t num_items = PySequence_Fast_GET_SIZE(fast); if (num_items <= 0) { // We can't determine the type of a list of size 0. _this->_type = ShaderInput::M_numeric; diff --git a/tests/pgraph/test_shaderinput.py b/tests/pgraph/test_shaderinput.py index 68bb6b2e24..2792148dd0 100644 --- a/tests/pgraph/test_shaderinput.py +++ b/tests/pgraph/test_shaderinput.py @@ -1,4 +1,9 @@ from panda3d.core import ShaderInput, Vec4 +from array import array + + +def test_shaderinput_construct_sequence_int(): + i = ShaderInput('test', array('I', [1, 2, 3, 4])) def test_shaderinput_vector_compare(): From 38d304f2fe187e4a748cc811b9b4569e15d5b606 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 12:10:42 +0100 Subject: [PATCH 02/10] glgsg: Force nearest filtering on isampler/usampler Without this, Intel drivers will sample (0, 0, 0, 1) --- .../glstuff/glGraphicsStateGuardian_src.cxx | 18 ++++++++++++++---- panda/src/glstuff/glShaderContext_src.cxx | 5 +++++ panda/src/gobj/texture.cxx | 19 +++++++++++++++++++ panda/src/gobj/texture.h | 1 + 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index bb2dfdc6fb..38f6ccb24f 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -12409,10 +12409,20 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) { } } - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, - get_texture_filter_type(minfilter, !uses_mipmaps)); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, - get_texture_filter_type(magfilter, true)); + if (Texture::is_integer(tex->get_format())) { + // Integer format textures can't have filtering enabled, and in fact, some + // drivers (looking at you, Intel) will always sample (0, 0, 0, 1) if we + // don't set this correctly! + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, + uses_mipmaps ? GL_NEAREST_MIPMAP_NEAREST + : GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } else { + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, + get_texture_filter_type(minfilter, !uses_mipmaps)); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, + get_texture_filter_type(magfilter, true)); + } // Set anisotropic filtering. if (_supports_anisotropy) { diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index b0dfd4531b..424cf2ca83 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -2849,6 +2849,11 @@ update_shader_texture_bindings(ShaderContext *prev) { } continue; } + else if (Texture::is_integer(tex->get_format())) { + // Required to satisfy Intel drivers, which will otherwise sample zero. + sampler.set_minfilter(sampler.uses_mipmaps() ? SamplerState::FT_nearest_mipmap_nearest : SamplerState::FT_nearest); + sampler.set_magfilter(SamplerState::FT_nearest); + } if (tex->get_texture_type() != spec._desired_type) { switch (spec._part) { diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index d1d76d471c..a5658c8146 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -2628,6 +2628,25 @@ is_srgb(Format format) { } } +/** + * Returns true if the indicated format is an integer format, false otherwise. + */ +bool Texture:: +is_integer(Format format) { + switch (format) { + case F_r32i: + case F_r8i: + case F_rg8i: + case F_rgb8i: + case F_rgba8i: + case F_r16i: + return true; + + default: + return false; + } +} + /** * Computes the proper size of the texture, based on the original size, the * filename, and the resizing whims of the config file. diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index 7cb5f305fb..af96f49d1d 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -625,6 +625,7 @@ public: static bool has_alpha(Format format); static bool has_binary_alpha(Format format); static bool is_srgb(Format format); + static bool is_integer(Format format); static bool adjust_size(int &x_size, int &y_size, const std::string &name, bool for_padding, AutoTextureScale auto_texture_scale = ATS_unspecified); From 3479c6eee2988e90e81f46c1115f46d8e97dc4b2 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 12:12:18 +0100 Subject: [PATCH 03/10] tests: Add unit tests for GLSL usampler/isamspler/uimage/iimage --- tests/display/test_glsl_shader.py | 120 +++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/tests/display/test_glsl_shader.py b/tests/display/test_glsl_shader.py index cb7ab165d4..97718ac4b7 100644 --- a/tests/display/test_glsl_shader.py +++ b/tests/display/test_glsl_shader.py @@ -141,15 +141,77 @@ def test_glsl_sampler(gsg): tex2.setup_2d_texture(1, 1, core.Texture.T_float, core.Texture.F_rgba32) tex2.set_clear_color((1.0, 2.0, -3.14, 0.0)) + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_float, core.Texture.F_r32) + tex3.set_clear_color((0.5, 0.0, 0.0, 1.0)) + preamble = """ uniform sampler1D tex1; uniform sampler2D tex2; + uniform sampler3D tex3; """ code = """ assert(texelFetch(tex1, 0, 0) == vec4(0, 2 / 255.0, 1, 1)); assert(texelFetch(tex2, ivec2(0, 0), 0) == vec4(1.0, 2.0, -3.14, 0.0)); + assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == vec4(0.5, 0.0, 0.0, 1.0)); """ - run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}) + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + +def test_glsl_isampler(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('h', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('i', 5)) + + preamble = """ + uniform isampler1D tex1; + uniform isampler2D tex2; + uniform isampler3D tex3; + """ + code = """ + assert(texelFetch(tex1, 0, 0) == ivec4(0, 1, 2, 3)); + assert(texelFetch(tex2, ivec2(0, 0), 0) == ivec4(4, 0, 0, 1)); + assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == ivec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + +def test_glsl_usampler(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('H', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('I', 5)) + + preamble = """ + uniform usampler1D tex1; + uniform usampler2D tex2; + uniform usampler3D tex3; + """ + code = """ + assert(texelFetch(tex1, 0, 0) == uvec4(0, 1, 2, 3)); + assert(texelFetch(tex2, ivec2(0, 0), 0) == uvec4(4, 0, 0, 1)); + assert(texelFetch(tex3, ivec3(0, 0, 0), 0) == uvec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) def test_glsl_image(gsg): @@ -172,6 +234,62 @@ def test_glsl_image(gsg): run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}) +def test_glsl_iimage(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('bbbb', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('h', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('i', 5)) + + preamble = """ + layout(rgba8i) uniform iimage1D tex1; + layout(r16i) uniform iimage2D tex2; + layout(r32i) uniform iimage3D tex3; + """ + code = """ + assert(imageLoad(tex1, 0) == ivec4(0, 1, 2, 3)); + assert(imageLoad(tex2, ivec2(0, 0)) == ivec4(4, 0, 0, 1)); + assert(imageLoad(tex3, ivec3(0, 0, 0)) == ivec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + +def test_glsl_uimage(gsg): + from struct import pack + + tex1 = core.Texture("") + tex1.setup_1d_texture(1, core.Texture.T_unsigned_byte, core.Texture.F_rgba8i) + tex1.set_ram_image(pack('BBBB', 0, 1, 2, 3)) + + tex2 = core.Texture("") + tex2.setup_2d_texture(1, 1, core.Texture.T_unsigned_short, core.Texture.F_r16i) + tex2.set_ram_image(pack('H', 4)) + + tex3 = core.Texture("") + tex3.setup_3d_texture(1, 1, 1, core.Texture.T_unsigned_int, core.Texture.F_r32i) + tex3.set_ram_image(pack('I', 5)) + + preamble = """ + layout(rgba8ui) uniform uimage1D tex1; + layout(r16ui) uniform uimage2D tex2; + layout(r32ui) uniform uimage3D tex3; + """ + code = """ + assert(imageLoad(tex1, 0) == uvec4(0, 1, 2, 3)); + assert(imageLoad(tex2, ivec2(0, 0)) == uvec4(4, 0, 0, 1)); + assert(imageLoad(tex3, ivec3(0, 0, 0)) == uvec4(5, 0, 0, 1)); + """ + run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2, 'tex3': tex3}) + + def test_glsl_ssbo(gsg): from struct import pack num1 = pack(' Date: Sun, 17 Jan 2021 13:11:30 +0100 Subject: [PATCH 04/10] texture: Add missing integer texture formats --- panda/src/gles2gsg/gles2gsg.h | 24 +++ .../glstuff/glGraphicsStateGuardian_src.cxx | 140 ++++++++++++++++-- panda/src/gobj/texture.cxx | 138 +++++++++++++++-- panda/src/gobj/texture.h | 10 +- panda/src/gobj/texturePeeker.cxx | 14 +- 5 files changed, 297 insertions(+), 29 deletions(-) diff --git a/panda/src/gles2gsg/gles2gsg.h b/panda/src/gles2gsg/gles2gsg.h index 729ee6e589..c328c99ac4 100644 --- a/panda/src/gles2gsg/gles2gsg.h +++ b/panda/src/gles2gsg/gles2gsg.h @@ -156,6 +156,18 @@ typedef char GLchar; #define GL_TEXTURE_MAX_LEVEL 0x813D #define GL_NUM_EXTENSIONS 0x821D #define GL_RG_INTEGER 0x8228 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C #define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 #define GL_PROGRAM_BINARY_LENGTH 0x8741 #define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE @@ -196,6 +208,18 @@ typedef char GLchar; #define GL_SRGB8 0x8C41 #define GL_SRGB8_ALPHA8 0x8C43 #define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F #define GL_RED_INTEGER 0x8D94 #define GL_RGB_INTEGER 0x8D98 #define GL_RGBA_INTEGER 0x8D99 diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 38f6ccb24f..2ee90887c7 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -9320,6 +9320,8 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgba16: case Texture::F_rgba32: case Texture::F_rgba8i: + case Texture::F_rgba16i: + case Texture::F_rgba32i: case Texture::F_rgb10_a2: return GL_COMPRESSED_RGBA; @@ -9331,7 +9333,9 @@ get_external_image_format(Texture *tex) const { case Texture::F_rgb12: case Texture::F_rgb332: case Texture::F_rgb16: + case Texture::F_rgb16i: case Texture::F_rgb32: + case Texture::F_rgb32i: return GL_COMPRESSED_RGB; case Texture::F_alpha: @@ -9350,7 +9354,9 @@ get_external_image_format(Texture *tex) const { case Texture::F_rg: case Texture::F_rg8i: case Texture::F_rg16: + case Texture::F_rg16i: case Texture::F_rg32: + case Texture::F_rg32i: return GL_COMPRESSED_RG; case Texture::F_luminance: @@ -9605,10 +9611,16 @@ get_external_image_format(Texture *tex) const { case Texture::F_r32i: return GL_RED_INTEGER; case Texture::F_rg8i: + case Texture::F_rg16i: + case Texture::F_rg32i: return GL_RG_INTEGER; case Texture::F_rgb8i: + case Texture::F_rgb16i: + case Texture::F_rgb32i: return GL_RGB_INTEGER; case Texture::F_rgba8i: + case Texture::F_rgba16i: + case Texture::F_rgba32i: return GL_RGBA_INTEGER; #endif @@ -9660,7 +9672,13 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rgb8i: case Texture::F_rgba8i: case Texture::F_r16i: + case Texture::F_rg16i: + case Texture::F_rgb16i: + case Texture::F_rgba16i: case Texture::F_r32i: + case Texture::F_rg32i: + case Texture::F_rgb32i: + case Texture::F_rgba32i: case Texture::F_r11_g11_b10: case Texture::F_rgb9_e5: // Unsupported; fall through to below. @@ -10211,12 +10229,6 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } else { return GL_R16_SNORM; } - case Texture::F_r16i: - if (Texture::is_unsigned(tex->get_component_type())) { - return GL_R16UI; - } else { - return GL_R16I; - } case Texture::F_rg16: if (tex->get_component_type() == Texture::T_float) { return GL_RG16F; @@ -10225,6 +10237,30 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } else { return GL_RG16_SNORM; } + case Texture::F_r16i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_R16UI; + } else { + return GL_R16I; + } + case Texture::F_rg16i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RG16UI; + } else { + return GL_RG16I; + } + case Texture::F_rgb16i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RGB16UI; + } else { + return GL_RGB16I; + } + case Texture::F_rgba16i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RGBA16UI; + } else { + return GL_RGBA16I; + } #endif #ifndef OPENGLES_1 @@ -10337,9 +10373,31 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return _core_profile ? GL_SRGB8_ALPHA8 : GL_SLUMINANCE8_ALPHA8; #endif -#ifndef OPENGLES +#ifndef OPENGLES_1 case Texture::F_r32i: - return GL_R32I; + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_R32UI; + } else { + return GL_R32I; + } + case Texture::F_rg32i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RG32UI; + } else { + return GL_RG32I; + } + case Texture::F_rgb32i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RGB32UI; + } else { + return GL_RGB32I; + } + case Texture::F_rgba32i: + if (Texture::is_unsigned(tex->get_component_type())) { + return GL_RGBA32UI; + } else { + return GL_RGBA32I; + } #endif #ifndef OPENGLES_1 @@ -13972,7 +14030,9 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { case GL_R3_G3_B2: format = Texture::F_rgb332; break; +#endif +#ifndef OPENGLES_1 case GL_R8I: type = Texture::T_byte; format = Texture::F_r8i; @@ -14011,11 +14071,69 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { type = Texture::T_short; format = Texture::F_r16i; break; + case GL_RG16I: + type = Texture::T_short; + format = Texture::F_rg16i; + break; + case GL_RGB16I: + type = Texture::T_short; + format = Texture::F_rgb16i; + break; + case GL_RGBA16I: + type = Texture::T_short; + format = Texture::F_rgba16i; + break; + case GL_R16UI: type = Texture::T_unsigned_short; format = Texture::F_r16i; break; + case GL_RG16UI: + type = Texture::T_unsigned_short; + format = Texture::F_rg16i; + break; + case GL_RGB16UI: + type = Texture::T_unsigned_short; + format = Texture::F_rgb16i; + break; + case GL_RGBA16UI: + type = Texture::T_unsigned_short; + format = Texture::F_rgba16i; + break; + case GL_R32I: + type = Texture::T_int; + format = Texture::F_r32i; + break; + case GL_RG32I: + type = Texture::T_int; + format = Texture::F_rg32i; + break; + case GL_RGB32I: + type = Texture::T_int; + format = Texture::F_rgb32i; + break; + case GL_RGBA32I: + type = Texture::T_int; + format = Texture::F_rgba32i; + break; + + case GL_R32UI: + type = Texture::T_unsigned_int; + format = Texture::F_r32i; + break; + case GL_RG32UI: + type = Texture::T_unsigned_int; + format = Texture::F_rg32i; + break; + case GL_RGB32UI: + type = Texture::T_unsigned_int; + format = Texture::F_rgb32i; + break; + case GL_RGBA32UI: + type = Texture::T_unsigned_int; + format = Texture::F_rgba32i; + break; #endif #ifndef OPENGLES_1 @@ -14104,12 +14222,6 @@ do_extract_texture_data(CLP(TextureContext) *gtc) { format = Texture::F_red; break; #endif -#ifndef OPENGLES - case GL_R32I: - type = Texture::T_int; - format = Texture::F_r32i; - break; -#endif #ifndef OPENGLES case GL_RED: diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index a5658c8146..8d4756fee4 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -676,7 +676,7 @@ estimate_texture_memory() const { CDReader cdata(_cycler); size_t pixels = cdata->_x_size * cdata->_y_size * cdata->_z_size; - size_t bpp = 4; + size_t bpp = 0; switch (cdata->_format) { case Texture::F_rgb332: bpp = 1; @@ -739,10 +739,8 @@ estimate_texture_memory() const { bpp = 8; break; - case Texture::F_rgba16: - bpp = 8; - break; case Texture::F_rgba32: + case Texture::F_rgba32i: bpp = 16; break; @@ -752,9 +750,13 @@ estimate_texture_memory() const { bpp = 2; break; case Texture::F_rg16: + case Texture::F_rg16i: bpp = 4; break; case Texture::F_rgb16: + case Texture::F_rgb16i: + case Texture::F_rgba16: + case Texture::F_rgba16i: bpp = 8; break; @@ -764,10 +766,12 @@ estimate_texture_memory() const { break; case Texture::F_rg32: + case Texture::F_rg32i: bpp = 8; break; case Texture::F_rgb32: + case Texture::F_rgb32i: bpp = 16; break; @@ -776,11 +780,12 @@ estimate_texture_memory() const { case Texture::F_rgb10_a2: bpp = 4; break; + } - default: + if (bpp == 0) { + bpp = 4; gobj_cat.warning() << "Unhandled format in estimate_texture_memory(): " << cdata->_format << "\n"; - break; } size_t bytes = pixels * bpp; @@ -1789,10 +1794,6 @@ write(ostream &out, int indent_level) const { case F_r16: out << "r16"; break; - case F_r16i: - out << "r16i"; - break; - case F_rg16: out << "rg16"; break; @@ -1852,6 +1853,29 @@ write(ostream &out, int indent_level) const { case F_rg: out << "rg"; break; + + case F_r16i: + out << "r16i"; + break; + case F_rg16i: + out << "rg16i"; + break; + case F_rgb16i: + out << "rgb16i"; + break; + case F_rgba16i: + out << "rgba16i"; + break; + + case F_rg32i: + out << "rg32i"; + break; + case F_rgb32i: + out << "rgb32i"; + break; + case F_rgba32i: + out << "rgba32i"; + break; } if (cdata->_compression != CM_default) { @@ -2217,8 +2241,6 @@ format_format(Format format) { return "rgba32"; case F_r16: return "r16"; - case F_r16i: - return "r16i"; case F_rg16: return "rg16"; case F_rgb16: @@ -2255,6 +2277,20 @@ format_format(Format format) { return "rgb10_a2"; case F_rg: return "rg"; + case F_r16i: + return "r16i"; + case F_rg16i: + return "rg16i"; + case F_rgb16i: + return "rgb16i"; + case F_rgba16i: + return "rgba16i"; + case F_rg32i: + return "rg32i"; + case F_rgb32i: + return "rgb32i"; + case F_rgba32i: + return "rgba32i"; } return "**invalid**"; } @@ -2340,6 +2376,14 @@ string_format(const string &str) { return F_rg32; } else if (cmp_nocase(str, "rgb32") == 0 || cmp_nocase(str, "r32g32b32") == 0) { return F_rgb32; + } else if (cmp_nocase_uh(str, "r8i") == 0) { + return F_r8i; + } else if (cmp_nocase_uh(str, "rg8i") == 0 || cmp_nocase_uh(str, "r8g8i") == 0) { + return F_rg8i; + } else if (cmp_nocase_uh(str, "rgb8i") == 0 || cmp_nocase_uh(str, "r8g8b8i") == 0) { + return F_rgb8i; + } else if (cmp_nocase_uh(str, "rgba8i") == 0 || cmp_nocase_uh(str, "r8g8b8a8i") == 0) { + return F_rgba8i; } else if (cmp_nocase(str, "r11g11b10") == 0) { return F_r11_g11_b10; } else if (cmp_nocase(str, "rgb9_e5") == 0) { @@ -2348,6 +2392,20 @@ string_format(const string &str) { return F_rgb10_a2; } else if (cmp_nocase_uh(str, "rg") == 0) { return F_rg; + } else if (cmp_nocase_uh(str, "r16i") == 0) { + return F_r16i; + } else if (cmp_nocase_uh(str, "rg16i") == 0 || cmp_nocase_uh(str, "r16g16i") == 0) { + return F_rg16i; + } else if (cmp_nocase_uh(str, "rgb16i") == 0 || cmp_nocase_uh(str, "r16g16b16i") == 0) { + return F_rgb16i; + } else if (cmp_nocase_uh(str, "rgba16i") == 0 || cmp_nocase_uh(str, "r16g16b16a16i") == 0) { + return F_rgba16i; + } else if (cmp_nocase_uh(str, "rg32i") == 0 || cmp_nocase_uh(str, "r32g32i") == 0) { + return F_rg32i; + } else if (cmp_nocase_uh(str, "rgb32i") == 0 || cmp_nocase_uh(str, "r32g32b32i") == 0) { + return F_rgb32i; + } else if (cmp_nocase_uh(str, "rgba32i") == 0 || cmp_nocase_uh(str, "r32g32b32a32i") == 0) { + return F_rgba32i; } gobj_cat->error() @@ -2588,6 +2646,8 @@ has_alpha(Format format) { case F_sluminance_alpha: case F_rgba8i: case F_rgb10_a2: + case F_rgba16i: + case F_rgba32i: return true; default: @@ -2640,6 +2700,12 @@ is_integer(Format format) { case F_rgb8i: case F_rgba8i: case F_r16i: + case F_rg16i: + case F_rgb16i: + case F_rgba16i: + case F_rg32i: + case F_rgb32i: + case F_rgba32i: return true; default: @@ -3693,11 +3759,31 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) component_type = T_unsigned_short; func = read_dds_level_abgr16; break; + case 12: // DXGI_FORMAT_R16G16B16A16_UINT + format = F_rgba16i; + component_type = T_unsigned_short; + func = read_dds_level_abgr16; + break; + case 14: // DXGI_FORMAT_R16G16B16A16_SINT + format = F_rgba16i; + component_type = T_short; + func = read_dds_level_abgr16; + break; case 16: // DXGI_FORMAT_R32G32_FLOAT format = F_rg32; component_type = T_float; func = read_dds_level_raw; break; + case 17: // DXGI_FORMAT_R32G32_UINT + format = F_rg32i; + component_type = T_unsigned_int; + func = read_dds_level_raw; + break; + case 18: // DXGI_FORMAT_R32G32_SINT + format = F_rg32i; + component_type = T_int; + func = read_dds_level_raw; + break; case 27: // DXGI_FORMAT_R8G8B8A8_TYPELESS case 28: // DXGI_FORMAT_R8G8B8A8_UNORM format = F_rgba8; @@ -3731,11 +3817,21 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only) component_type = T_unsigned_short; func = read_dds_level_raw; break; + case 36: // DXGI_FORMAT_R16G16_UINT: + format = F_rg16i; + component_type = T_unsigned_short; + func = read_dds_level_raw; + break; case 37: // DXGI_FORMAT_R16G16_SNORM: format = F_rg16; component_type = T_short; func = read_dds_level_raw; break; + case 38: // DXGI_FORMAT_R16G16_SINT: + format = F_rg16i; + component_type = T_short; + func = read_dds_level_raw; + break; case 40: // DXGI_FORMAT_D32_FLOAT format = F_depth_component32; component_type = T_float; @@ -4630,8 +4726,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) break; case KTX_RG16I: case KTX_RG16UI: + format = F_rg16i; + break; case KTX_RG32I: case KTX_RG32UI: + format = F_rg32i; + break; default: gobj_cat.error() << filename << " has unsupported RG integer format " << internal_format << "\n"; @@ -4695,8 +4795,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) break; case KTX_RGB16I: case KTX_RGB16UI: + format = F_rgb16i; + break; case KTX_RGB32I: case KTX_RGB32UI: + format = F_rgb32i; + break; default: gobj_cat.error() << filename << " has unsupported RGB integer format " << internal_format << "\n"; @@ -4758,8 +4862,12 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) break; case KTX_RGBA16I: case KTX_RGBA16UI: + format = F_rgba16i; + break; case KTX_RGBA32I: case KTX_RGBA32UI: + format = F_rgba32i; + break; default: gobj_cat.error() << filename << " has unsupported RGBA integer format " << internal_format << "\n"; @@ -6896,6 +7004,8 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rg32: case F_rg8i: case F_rg: + case F_rg16i: + case F_rg32i: cdata->_num_components = 2; break; @@ -6910,6 +7020,8 @@ do_set_format(CData *cdata, Texture::Format format) { case F_rgb8i: case F_r11_g11_b10: case F_rgb9_e5: + case F_rgb16i: + case F_rgb32i: cdata->_num_components = 3; break; @@ -6924,6 +7036,8 @@ do_set_format(CData *cdata, Texture::Format format) { case F_srgb_alpha: case F_rgba8i: case F_rgb10_a2: + case F_rgba16i: + case F_rgba32i: cdata->_num_components = 4; break; } diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index af96f49d1d..86ca58fe02 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -161,7 +161,15 @@ PUBLISHED: F_rgb10_a2, F_rg, - F_r16i + + F_r16i, + F_rg16i, + F_rgb16i, // not recommended + F_rgba16i, + + F_rg32i, + F_rgb32i, + F_rgba32i, }; // Deprecated. See SamplerState.FilterType. diff --git a/panda/src/gobj/texturePeeker.cxx b/panda/src/gobj/texturePeeker.cxx index ece87f36a5..03d9bff39d 100644 --- a/panda/src/gobj/texturePeeker.cxx +++ b/panda/src/gobj/texturePeeker.cxx @@ -114,6 +114,7 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { case Texture::F_r16: case Texture::F_r32: case Texture::F_r32i: + case Texture::F_r16i: _get_texel = get_texel_r; break; @@ -140,21 +141,27 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { _get_texel = get_texel_la; break; - case Texture::F_rg16: - case Texture::F_rg32: case Texture::F_rg: + case Texture::F_rg8i: + case Texture::F_rg16: + case Texture::F_rg16i: + case Texture::F_rg32: + case Texture::F_rg32i: _get_texel = get_texel_rg; break; case Texture::F_rgb: case Texture::F_rgb5: case Texture::F_rgb8: + case Texture::F_rgb8i: case Texture::F_rgb12: case Texture::F_rgb16: + case Texture::F_rgb16i: case Texture::F_rgb332: case Texture::F_r11_g11_b10: case Texture::F_rgb9_e5: case Texture::F_rgb32: + case Texture::F_rgb32i: _get_texel = get_texel_rgb; break; @@ -163,9 +170,12 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { case Texture::F_rgba4: case Texture::F_rgba5: case Texture::F_rgba8: + case Texture::F_rgba8i: case Texture::F_rgba12: case Texture::F_rgba16: + case Texture::F_rgba16i: case Texture::F_rgba32: + case Texture::F_rgba32i: case Texture::F_rgb10_a2: _get_texel = get_texel_rgba; break; From b060767bd8fb2327e0fd5d17ca5f29a2f0d344b7 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 14:36:14 +0100 Subject: [PATCH 05/10] glgsg: slight refactor of get_internal_image_format() --- .../glstuff/glGraphicsStateGuardian_src.cxx | 82 ++++++++++--------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 2ee90887c7..45eac22e9e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -9648,8 +9648,10 @@ get_internal_image_format(Texture *tex, bool force_sized) const { // no compression for render targets compression = Texture::CM_off; } - bool is_3d = (tex->get_texture_type() == Texture::TT_3d_texture || - tex->get_texture_type() == Texture::TT_2d_texture_array); + Texture::ComponentType component_type = tex->get_component_type(); + Texture::TextureType texture_type = tex->get_texture_type(); + bool is_3d = (texture_type == Texture::TT_3d_texture || + texture_type == Texture::TT_2d_texture_array); if (get_supports_compressed_texture_format(compression)) { switch (compression) { @@ -9789,7 +9791,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } #endif if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) { - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_COMPRESSED_R11_EAC; } else { return GL_COMPRESSED_SIGNED_R11_EAC; @@ -9815,7 +9817,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { } #endif if (get_supports_compressed_texture_format(Texture::CM_eac) && !is_3d) { - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_COMPRESSED_RG11_EAC; } else { return GL_COMPRESSED_SIGNED_RG11_EAC; @@ -9993,7 +9995,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { break; case Texture::CM_eac: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { if (tex->get_num_components() == 1) { return GL_COMPRESSED_R11_EAC; } else { @@ -10026,7 +10028,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_depth_stencil: if (_supports_depth_stencil) { #ifndef OPENGLES - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_DEPTH32F_STENCIL8; } else #endif @@ -10038,7 +10040,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_depth_component: #ifndef OPENGLES - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_DEPTH_COMPONENT32F; } else #endif @@ -10073,7 +10075,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_DEPTH_COMPONENT16_OES; } #else - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_DEPTH_COMPONENT32F; } else { return GL_DEPTH_COMPONENT32; @@ -10083,7 +10085,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rgba: case Texture::F_rgbm: #ifndef OPENGLES_1 - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_RGBA16F; } else #endif @@ -10093,11 +10095,11 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return _supports_bgr ? GL_BGRA : GL_RGBA; } #else - if (tex->get_component_type() == Texture::T_unsigned_short) { + if (component_type == Texture::T_unsigned_short) { return GL_RGBA16; - } else if (tex->get_component_type() == Texture::T_short) { + } else if (component_type == Texture::T_short) { return GL_RGBA16_SNORM; - } else if (tex->get_component_type() == Texture::T_byte) { + } else if (component_type == Texture::T_byte) { return GL_RGBA8_SNORM; } else { return force_sized ? GL_RGBA8 : GL_RGBA; @@ -10114,32 +10116,32 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return _supports_bgr ? GL_BGRA : (force_sized ? GL_RGBA8 : GL_RGBA); #else case Texture::F_rgba8: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGBA8; } else { return GL_RGBA8_SNORM; } case Texture::F_r8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_R8UI; } else { return GL_R8I; } case Texture::F_rg8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RG8UI; } else { return GL_RG8I; } case Texture::F_rgb8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGB8UI; } else { return GL_RGB8I; } case Texture::F_rgba8i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGBA8UI; } else { return GL_RGBA8I; @@ -10149,9 +10151,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #endif // OPENGLES #ifndef OPENGLES case Texture::F_rgba16: - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_RGBA16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { + } else if (Texture::is_unsigned(component_type)) { return GL_RGBA16; } else { return GL_RGBA16_SNORM; @@ -10161,7 +10163,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #endif // OPENGLES case Texture::F_rgb: - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: return GL_RGB16F; #ifndef OPENGLES case Texture::T_unsigned_short: return GL_RGB16; @@ -10191,7 +10193,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_RGB16F; #else case Texture::F_rgb8: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGB8; } else { return GL_RGB8_SNORM; @@ -10199,9 +10201,9 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_rgb12: return GL_RGB12; case Texture::F_rgb16: - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_RGB16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { + } else if (Texture::is_unsigned(component_type)) { return GL_RGB16; } else { return GL_RGB16_SNORM; @@ -10222,41 +10224,41 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return GL_RG16F_EXT; #elif !defined(OPENGLES_1) case Texture::F_r16: - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_R16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { + } else if (Texture::is_unsigned(component_type)) { return GL_R16; } else { return GL_R16_SNORM; } case Texture::F_rg16: - if (tex->get_component_type() == Texture::T_float) { + if (component_type == Texture::T_float) { return GL_RG16F; - } else if (Texture::is_unsigned(tex->get_component_type())) { + } else if (Texture::is_unsigned(component_type)) { return GL_RG16; } else { return GL_RG16_SNORM; } case Texture::F_r16i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_R16UI; } else { return GL_R16I; } case Texture::F_rg16i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RG16UI; } else { return GL_RG16I; } case Texture::F_rgb16i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGB16UI; } else { return GL_RGB16I; } case Texture::F_rgba16i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGBA16UI; } else { return GL_RGBA16I; @@ -10273,7 +10275,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { case Texture::F_green: case Texture::F_blue: #ifndef OPENGLES - if (!Texture::is_unsigned(tex->get_component_type())) { + if (!Texture::is_unsigned(component_type)) { return GL_R8_SNORM; } else #endif @@ -10298,7 +10300,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE; #else if (_supports_luminance_texture) { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_LUMINANCE16F_ARB; @@ -10310,7 +10312,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE; } } else { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_R16F; @@ -10329,7 +10331,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA; #else if (_supports_luminance_texture) { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_LUMINANCE_ALPHA16F_ARB; @@ -10341,7 +10343,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const { return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA; } } else { - switch (tex->get_component_type()) { + switch (component_type) { case Texture::T_float: case Texture::T_half_float: return GL_RG16F; @@ -10375,25 +10377,25 @@ get_internal_image_format(Texture *tex, bool force_sized) const { #ifndef OPENGLES_1 case Texture::F_r32i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_R32UI; } else { return GL_R32I; } case Texture::F_rg32i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RG32UI; } else { return GL_RG32I; } case Texture::F_rgb32i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGB32UI; } else { return GL_RGB32I; } case Texture::F_rgba32i: - if (Texture::is_unsigned(tex->get_component_type())) { + if (Texture::is_unsigned(component_type)) { return GL_RGBA32UI; } else { return GL_RGBA32I; From 4783c2902d0b5da0d993085634a6bfd27949cbef Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 14:39:15 +0100 Subject: [PATCH 06/10] grutil: Add missing switch case --- panda/src/grutil/multitexReducer.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index 2fff484de3..fd94e1d173 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -714,6 +714,7 @@ make_texture_layer(const NodePath &render, case TextureStage::M_height: case TextureStage::M_selector: case TextureStage::M_normal_gloss: + case TextureStage::M_emission: // Don't know what to do with these funny modes. We should probably raise // an exception or something. Fall through for now. From a5a080994956e0a5059ab8f87819d938e57ca2b9 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 15:27:19 +0100 Subject: [PATCH 07/10] gobj: Support integer texture formats in TexturePeeker --- panda/src/gobj/texturePeeker.cxx | 132 +++++++++++++++++++++++++------ tests/gobj/test_texture_peek.py | 64 +++++++++++++++ 2 files changed, 173 insertions(+), 23 deletions(-) diff --git a/panda/src/gobj/texturePeeker.cxx b/panda/src/gobj/texturePeeker.cxx index 03d9bff39d..ee82e4644b 100644 --- a/panda/src/gobj/texturePeeker.cxx +++ b/panda/src/gobj/texturePeeker.cxx @@ -14,6 +14,58 @@ #include "texturePeeker.h" +static double get_unsigned_byte_i(const unsigned char *&p) { + return *p++; +} + +static double get_signed_byte_i(const unsigned char *&p) { + return *(signed char *)p++; +} + +static double get_unsigned_short_i(const unsigned char *&p) { + union { + unsigned short us; + unsigned char uc[2]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + return (double)v.us; +} + +static double get_signed_short_i(const unsigned char *&p) { + union { + signed short ss; + unsigned char uc[2]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + return (double)v.ss; +} + +static double get_unsigned_int_i(const unsigned char *&p) { + union { + unsigned int ui; + unsigned char uc[4]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + v.uc[2] = (*p++); + v.uc[3] = (*p++); + return (double)v.ui; +} + +static double get_signed_int_i(const unsigned char *&p) { + union { + signed int si; + unsigned char uc[4]; + } v; + v.uc[0] = (*p++); + v.uc[1] = (*p++); + v.uc[2] = (*p++); + v.uc[3] = (*p++); + return (double)v.si; +} + /** * Use Texture::peek() to construct a TexturePeeker. * @@ -73,35 +125,69 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) { } _pixel_width = _component_width * _num_components; - switch (_component_type) { - case Texture::T_unsigned_byte: - _get_component = Texture::get_unsigned_byte; - break; + if (Texture::is_integer(_format)) { + switch (_component_type) { + case Texture::T_unsigned_byte: + _get_component = get_unsigned_byte_i; + break; - case Texture::T_unsigned_short: - _get_component = Texture::get_unsigned_short; - break; + case Texture::T_unsigned_short: + _get_component = get_unsigned_short_i; + break; - case Texture::T_unsigned_int: - _get_component = Texture::get_unsigned_int; - break; + case Texture::T_unsigned_int: + _get_component = get_unsigned_int_i; + break; - case Texture::T_float: - _get_component = Texture::get_float; - break; + case Texture::T_byte: + _get_component = get_signed_byte_i; + break; - case Texture::T_half_float: - _get_component = Texture::get_half_float; - break; + case Texture::T_short: + _get_component = get_signed_short_i; + break; - case Texture::T_unsigned_int_24_8: - _get_component = Texture::get_unsigned_int_24; - break; + case Texture::T_int: + _get_component = get_signed_int_i; + break; - default: - // Not supported. - _image.clear(); - return; + default: + // Not supported. + _image.clear(); + return; + } + } + else { + switch (_component_type) { + case Texture::T_unsigned_byte: + _get_component = Texture::get_unsigned_byte; + break; + + case Texture::T_unsigned_short: + _get_component = Texture::get_unsigned_short; + break; + + case Texture::T_unsigned_int: + _get_component = Texture::get_unsigned_int; + break; + + case Texture::T_float: + _get_component = Texture::get_float; + break; + + case Texture::T_half_float: + _get_component = Texture::get_half_float; + break; + + case Texture::T_unsigned_int_24_8: + _get_component = Texture::get_unsigned_int_24; + break; + + default: + // Not supported. + _image.clear(); + return; + } } switch (_format) { diff --git a/tests/gobj/test_texture_peek.py b/tests/gobj/test_texture_peek.py index accd1b02d0..b113312dbb 100644 --- a/tests/gobj/test_texture_peek.py +++ b/tests/gobj/test_texture_peek.py @@ -94,3 +94,67 @@ def test_texture_peek_srgba(): # We allow some imprecision. assert col.almost_equal((0.5, 0.5, 0.5, 188 / 255.0), 1 / 255.0) + + +def test_texture_peek_ubyte_i(): + maxval = 255 + data = array('B', (2, 1, 0, maxval)) + peeker = peeker_from_pixel(Texture.T_unsigned_byte, Texture.F_rgba8i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (0, 1, 2, maxval) + + +def test_texture_peek_byte_i(): + minval = -128 + maxval = 127 + data = array('b', (0, -1, minval, maxval)) + peeker = peeker_from_pixel(Texture.T_byte, Texture.F_rgba8i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (minval, -1, 0, maxval) + + +def test_texture_peek_ushort_i(): + maxval = 65535 + data = array('H', (2, 1, 0, maxval)) + peeker = peeker_from_pixel(Texture.T_unsigned_short, Texture.F_rgba16i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (0, 1, 2, maxval) + + +def test_texture_peek_short_i(): + minval = -32768 + maxval = 32767 + data = array('h', (0, -1, minval, maxval)) + peeker = peeker_from_pixel(Texture.T_short, Texture.F_rgba16i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (minval, -1, 0, maxval) + + +def test_texture_peek_uint_i(): + # Highest integer that fits inside float + maxval = 2147483648 + data = array('I', (2, 1, 0, maxval)) + peeker = peeker_from_pixel(Texture.T_unsigned_int, Texture.F_rgba32i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (0, 1, 2, maxval) + + +def test_texture_peek_int_i(): + minval = -2147483648 + maxval = 2147483647 + data = array('i', (0, -1, minval, maxval)) + peeker = peeker_from_pixel(Texture.T_int, Texture.F_rgba32i, data) + + col = LColor() + peeker.fetch_pixel(col, 0, 0) + assert col == (minval, -1, 0, maxval) From fb6ec557cebf7651f4f4939279dc48e783de2420 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 15:27:42 +0100 Subject: [PATCH 08/10] egl: Add missing init_type() for eglGraphicsBuffer/Pixmap --- panda/src/egldisplay/config_egldisplay.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/panda/src/egldisplay/config_egldisplay.cxx b/panda/src/egldisplay/config_egldisplay.cxx index 2f8e99cc0f..bb5b623a47 100644 --- a/panda/src/egldisplay/config_egldisplay.cxx +++ b/panda/src/egldisplay/config_egldisplay.cxx @@ -12,7 +12,9 @@ */ #include "config_egldisplay.h" +#include "eglGraphicsBuffer.h" #include "eglGraphicsPipe.h" +#include "eglGraphicsPixmap.h" #include "eglGraphicsWindow.h" #include "eglGraphicsStateGuardian.h" #include "graphicsPipeSelection.h" @@ -44,7 +46,9 @@ init_libegldisplay() { } initialized = true; + eglGraphicsBuffer::init_type(); eglGraphicsPipe::init_type(); + eglGraphicsPixmap::init_type(); eglGraphicsWindow::init_type(); eglGraphicsStateGuardian::init_type(); From b3f0768656345e15371cf31ec2a13f1e9ea7362b Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 17 Jan 2021 15:40:47 +0100 Subject: [PATCH 09/10] Revert "directtools: Fix empty scaling node of object handle" This reverts commit b507c88cd9fd5d3a432aae42fdc9165422a527b4. --- direct/src/directtools/DirectManipulation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/direct/src/directtools/DirectManipulation.py b/direct/src/directtools/DirectManipulation.py index 8a07b14702..d7aeb1ee3b 100644 --- a/direct/src/directtools/DirectManipulation.py +++ b/direct/src/directtools/DirectManipulation.py @@ -1066,7 +1066,7 @@ class ObjectHandles(NodePath, DirectObject): # Load up object handles model and assign it to self self.assign(loader.loadModel('models/misc/objectHandles')) self.setName(name) - self.scalingNode = self.getChild(0) + self.scalingNode = NodePath(self) self.scalingNode.setName('ohScalingNode') self.ohScalingFactor = 1.0 self.directScalingFactor = 1.0 From 8924b77da4c01a8b57ceecbf020574422ad7debe Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 19 May 2020 22:33:48 +0200 Subject: [PATCH 10/10] egldisplay: Backport changes for creating headless EGL contexts Backport of fbc49474557fe7b2ec1875ebb1cfb62e96e7f103 and 9f1289b4920074feb7f0b9b203d2a5b6e811c816 See #557 --- makepanda/makepanda.py | 32 ++++- panda/metalibs/pandagl/pandagl.cxx | 19 ++- panda/src/egldisplay/config_egldisplay.cxx | 10 +- panda/src/egldisplay/config_egldisplay.h | 10 +- panda/src/egldisplay/eglGraphicsBuffer.cxx | 8 +- panda/src/egldisplay/eglGraphicsPipe.I | 8 ++ panda/src/egldisplay/eglGraphicsPipe.cxx | 47 ++++++- panda/src/egldisplay/eglGraphicsPipe.h | 30 +++-- panda/src/egldisplay/eglGraphicsPixmap.cxx | 13 +- panda/src/egldisplay/eglGraphicsPixmap.h | 4 + .../egldisplay/eglGraphicsStateGuardian.cxx | 118 +++++++++--------- .../src/egldisplay/eglGraphicsStateGuardian.h | 39 +++--- panda/src/egldisplay/eglGraphicsWindow.cxx | 11 +- panda/src/egldisplay/eglGraphicsWindow.h | 4 + 14 files changed, 240 insertions(+), 113 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 88735bc34a..e8391482ff 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -2695,6 +2695,9 @@ def WriteConfigSettings(): dtool_config["PHAVE_LINUX_INPUT_H"] = 'UNDEF' dtool_config["IS_OSX"] = '1' + if PkgSkip("X11"): + dtool_config["HAVE_GLX"] = 'UNDEF' + if (GetTarget() == "freebsd"): dtool_config["IS_LINUX"] = 'UNDEF' dtool_config["HAVE_VIDEO4LINUX"] = 'UNDEF' @@ -5141,13 +5144,33 @@ if (GetTarget() == 'windows' and PkgSkip("GL")==0 and not RUNTIME): # DIRECTORY: panda/src/egldisplay/ # -if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTIME): +# If we're not compiling with any windowing system at all, but we do have EGL, +# we can use that to create a headless libpandagl instead. +if not PkgSkip("EGL") and not PkgSkip("GL") and PkgSkip("X11") and GetTarget() not in ('windows', 'darwin') and not RUNTIME: + DefSymbol('EGL', 'HAVE_EGL', '') + OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGL', 'GL', 'EGL'] + TargetAdd('pandagl_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx') + OPTS=['DIR:panda/metalibs/pandagl', 'BUILDING:PANDAGL', 'GL', 'EGL'] + TargetAdd('pandagl_pandagl.obj', opts=OPTS, input='pandagl.cxx') + TargetAdd('libpandagl.dll', input='pandagl_pandagl.obj') + TargetAdd('libpandagl.dll', input='p3glgsg_config_glgsg.obj') + TargetAdd('libpandagl.dll', input='p3glgsg_glgsg.obj') + TargetAdd('libpandagl.dll', input='pandagl_egldisplay_composite1.obj') + TargetAdd('libpandagl.dll', input=COMMON_PANDA_LIBS) + TargetAdd('libpandagl.dll', opts=['MODULE', 'GL', 'EGL', 'CGGL']) + +# +# DIRECTORY: panda/src/egldisplay/ +# + +if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and not RUNTIME): DefSymbol('GLES', 'OPENGLES_1', '') OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES', 'GLES', 'EGL'] TargetAdd('pandagles_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx') OPTS=['DIR:panda/metalibs/pandagles', 'BUILDING:PANDAGLES', 'GLES', 'EGL'] TargetAdd('pandagles_pandagles.obj', opts=OPTS, input='pandagles.cxx') - TargetAdd('libpandagles.dll', input='p3x11display_composite1.obj') + if not PkgSkip("X11"): + TargetAdd('libpandagles.dll', input='p3x11display_composite1.obj') TargetAdd('libpandagles.dll', input='pandagles_pandagles.obj') TargetAdd('libpandagles.dll', input='p3glesgsg_config_glesgsg.obj') TargetAdd('libpandagles.dll', input='p3glesgsg_glesgsg.obj') @@ -5159,13 +5182,14 @@ if (PkgSkip("EGL")==0 and PkgSkip("GLES")==0 and PkgSkip("X11")==0 and not RUNTI # DIRECTORY: panda/src/egldisplay/ # -if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and PkgSkip("X11")==0 and not RUNTIME): +if (PkgSkip("EGL")==0 and PkgSkip("GLES2")==0 and not RUNTIME): DefSymbol('GLES2', 'OPENGLES_2', '') OPTS=['DIR:panda/src/egldisplay', 'DIR:panda/src/glstuff', 'BUILDING:PANDAGLES2', 'GLES2', 'EGL'] TargetAdd('pandagles2_egldisplay_composite1.obj', opts=OPTS, input='p3egldisplay_composite1.cxx') OPTS=['DIR:panda/metalibs/pandagles2', 'BUILDING:PANDAGLES2', 'GLES2', 'EGL'] TargetAdd('pandagles2_pandagles2.obj', opts=OPTS, input='pandagles2.cxx') - TargetAdd('libpandagles2.dll', input='p3x11display_composite1.obj') + if not PkgSkip("X11"): + TargetAdd('libpandagles2.dll', input='p3x11display_composite1.obj') TargetAdd('libpandagles2.dll', input='pandagles2_pandagles2.obj') TargetAdd('libpandagles2.dll', input='p3gles2gsg_config_gles2gsg.obj') TargetAdd('libpandagles2.dll', input='p3gles2gsg_gles2gsg.obj') diff --git a/panda/metalibs/pandagl/pandagl.cxx b/panda/metalibs/pandagl/pandagl.cxx index 0e33961c9f..e6f01d9ce2 100644 --- a/panda/metalibs/pandagl/pandagl.cxx +++ b/panda/metalibs/pandagl/pandagl.cxx @@ -26,8 +26,13 @@ #include "glxGraphicsPipe.h" #endif -#if !defined(HAVE_WGL) && !defined(HAVE_COCOA) && !defined(HAVE_CARBON) && !defined(HAVE_GLX) -#error One of HAVE_WGL, HAVE_COCOA, HAVE_CARBON or HAVE_GLX must be defined when compiling pandagl! +#if defined(HAVE_EGL) && !defined(HAVE_X11) +#include "config_egldisplay.h" +#include "eglGraphicsPipe.h" +#endif + +#if !defined(HAVE_WGL) && !defined(HAVE_COCOA) && !defined(HAVE_CARBON) && !defined(HAVE_GLX) && !defined(HAVE_EGL) +#error One of HAVE_WGL, HAVE_COCOA, HAVE_CARBON, HAVE_GLX or HAVE_EGL must be defined when compiling pandagl! #endif /** @@ -50,9 +55,13 @@ init_libpandagl() { init_libosxdisplay(); #endif -#ifdef IS_LINUX +#ifdef HAVE_GLX init_libglxdisplay(); #endif + +#if defined(HAVE_EGL) && !defined(HAVE_X11) + init_libegldisplay(); +#endif } /** @@ -75,5 +84,9 @@ get_pipe_type_pandagl() { return glxGraphicsPipe::get_class_type().get_index(); #endif +#if defined(HAVE_EGL) && !defined(HAVE_X11) + return eglGraphicsPipe::get_class_type().get_index(); +#endif + return 0; } diff --git a/panda/src/egldisplay/config_egldisplay.cxx b/panda/src/egldisplay/config_egldisplay.cxx index bb5b623a47..e80137290d 100644 --- a/panda/src/egldisplay/config_egldisplay.cxx +++ b/panda/src/egldisplay/config_egldisplay.cxx @@ -21,8 +21,8 @@ #include "dconfig.h" #include "pandaSystem.h" -#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDAGLES) && !defined(BUILDING_PANDAGLES2) - #error Buildsystem error: BUILDING_PANDAGLES(2) not defined +#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDAGLES) && !defined(BUILDING_PANDAGLES2) && !defined(BUILDING_PANDAGL) + #error Buildsystem error: BUILDING_PANDAGL(ES(2)) not defined #endif Configure(config_egldisplay); @@ -48,8 +48,10 @@ init_libegldisplay() { eglGraphicsBuffer::init_type(); eglGraphicsPipe::init_type(); +#ifdef HAVE_X11 eglGraphicsPixmap::init_type(); eglGraphicsWindow::init_type(); +#endif eglGraphicsStateGuardian::init_type(); GraphicsPipeSelection *selection = GraphicsPipeSelection::get_global_ptr(); @@ -59,8 +61,10 @@ init_libegldisplay() { PandaSystem *ps = PandaSystem::get_global_ptr(); #ifdef OPENGLES_2 ps->set_system_tag("OpenGL ES 2", "window_system", "EGL"); -#else +#elif defined(OPENGLES_1) ps->set_system_tag("OpenGL ES", "window_system", "EGL"); +#else + ps->set_system_tag("OpenGL", "window_system", "EGL"); #endif } diff --git a/panda/src/egldisplay/config_egldisplay.h b/panda/src/egldisplay/config_egldisplay.h index 40e30893b8..a85df9748e 100644 --- a/panda/src/egldisplay/config_egldisplay.h +++ b/panda/src/egldisplay/config_egldisplay.h @@ -23,20 +23,22 @@ #if defined(OPENGLES_1) && defined(OPENGLES_2) #error OPENGLES_1 and OPENGLES_2 cannot be defined at the same time! #endif -#if !defined(OPENGLES_1) && !defined(OPENGLES_2) - #error Either OPENGLES_1 or OPENGLES_2 must be defined when compiling egldisplay! -#endif #ifdef OPENGLES_2 NotifyCategoryDecl(egldisplay, EXPCL_PANDAGLES2, EXPTP_PANDAGLES2); extern EXPCL_PANDAGLES2 void init_libegldisplay(); extern EXPCL_PANDAGLES2 const std::string get_egl_error_string(int error); -#else +#elif defined(OPENGLES_1) NotifyCategoryDecl(egldisplay, EXPCL_PANDAGLES, EXPTP_PANDAGLES); extern EXPCL_PANDAGLES void init_libegldisplay(); extern EXPCL_PANDAGLES const std::string get_egl_error_string(int error); +#else + NotifyCategoryDecl(egldisplay, EXPCL_PANDAGL, EXPTP_PANDAGL); + + extern EXPCL_PANDAGL void init_libegldisplay(); + extern EXPCL_PANDAGL const std::string get_egl_error_string(int error); #endif #endif diff --git a/panda/src/egldisplay/eglGraphicsBuffer.cxx b/panda/src/egldisplay/eglGraphicsBuffer.cxx index 7319f25430..2cfbff83b4 100644 --- a/panda/src/egldisplay/eglGraphicsBuffer.cxx +++ b/panda/src/egldisplay/eglGraphicsBuffer.cxx @@ -127,7 +127,7 @@ close_buffer() { if (_gsg != nullptr) { eglGraphicsStateGuardian *eglgsg; DCAST_INTO_V(eglgsg, _gsg); - if (!eglMakeCurrent(eglgsg->_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { + if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { egldisplay_cat.error() << "Failed to call eglMakeCurrent: " << get_egl_error_string(eglGetError()) << "\n"; } @@ -159,7 +159,7 @@ open_buffer() { if (_gsg == 0) { // There is no old gsg. Create a new one. eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, true, false); _gsg = eglgsg; } else { // If the old gsg has the wrong pixel format, create a new one that shares @@ -167,7 +167,7 @@ open_buffer() { DCAST_INTO_R(eglgsg, _gsg, false); if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) { eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, true, false); _gsg = eglgsg; } } @@ -178,6 +178,8 @@ open_buffer() { return false; } + _egl_display = eglgsg->_egl_display; + int attrib_list[] = { EGL_WIDTH, _size.get_x(), EGL_HEIGHT, _size.get_y(), diff --git a/panda/src/egldisplay/eglGraphicsPipe.I b/panda/src/egldisplay/eglGraphicsPipe.I index 53d9c311af..216c0ad721 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.I +++ b/panda/src/egldisplay/eglGraphicsPipe.I @@ -10,3 +10,11 @@ * @author rdb * @date 2009-05-21 */ + +/** + * + */ +INLINE EGLDisplay eglGraphicsPipe:: +get_egl_display() const { + return _egl_display; +} diff --git a/panda/src/egldisplay/eglGraphicsPipe.cxx b/panda/src/egldisplay/eglGraphicsPipe.cxx index 17594f799e..18c2317664 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.cxx +++ b/panda/src/egldisplay/eglGraphicsPipe.cxx @@ -25,19 +25,39 @@ TypeHandle eglGraphicsPipe::_type_handle; * */ eglGraphicsPipe:: -eglGraphicsPipe(const std::string &display) : x11GraphicsPipe(display) { +eglGraphicsPipe() { + //NB. if the X11 display failed to open, _display will be 0, which is a valid + // input to eglGetDisplay - it means to open the default display. +#ifdef HAVE_X11 _egl_display = eglGetDisplay((NativeDisplayType) _display); +#else + _egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); +#endif if (!eglInitialize(_egl_display, nullptr, nullptr)) { egldisplay_cat.error() << "Couldn't initialize the EGL display: " << get_egl_error_string(eglGetError()) << "\n"; + _is_valid = false; + return; } +#if defined(OPENGLES_1) || defined(OPENGLES_2) if (!eglBindAPI(EGL_OPENGL_ES_API)) { egldisplay_cat.error() << "Couldn't bind EGL to the OpenGL ES API: " << get_egl_error_string(eglGetError()) << "\n"; +#else + if (!eglBindAPI(EGL_OPENGL_API)) { + egldisplay_cat.error() + << "Couldn't bind EGL to the OpenGL API: " + << get_egl_error_string(eglGetError()) << "\n"; +#endif + _is_valid = false; + return; } + + // Even if we don't have an X11 display, we can still render headless. + _is_valid = true; } /** @@ -61,7 +81,11 @@ eglGraphicsPipe:: */ std::string eglGraphicsPipe:: get_interface_name() const { +#if defined(OPENGLES_1) || defined(OPENGLES_2) return "OpenGL ES"; +#else + return "OpenGL"; +#endif } /** @@ -110,6 +134,10 @@ make_output(const std::string &name, // First thing to try: an eglGraphicsWindow if (retry == 0) { +#ifdef HAVE_X11 + if (!_display) { + return nullptr; + } if (((flags&BF_require_parasite)!=0)|| ((flags&BF_refuse_window)!=0)|| ((flags&BF_resizeable)!=0)|| @@ -121,9 +149,12 @@ make_output(const std::string &name, } return new eglGraphicsWindow(engine, this, name, fb_prop, win_prop, flags, gsg, host); +#else + return nullptr; +#endif } - // Second thing to try: a GLES(2)GraphicsBuffer + // Second thing to try: a GL(ES(2))GraphicsBuffer if (retry == 1) { if ((host==0)|| // (!gl_support_fbo)|| @@ -154,9 +185,12 @@ make_output(const std::string &name, #ifdef OPENGLES_2 return new GLES2GraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host); -#else +#elif defined(OPENGLES_1) return new GLESGraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host); +#else + return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop, + flags, gsg, host); #endif } @@ -184,6 +218,10 @@ make_output(const std::string &name, // Fourth thing to try: an eglGraphicsPixmap. if (retry == 3) { +#ifdef HAVE_X11 + if (!_display) { + return nullptr; + } if (((flags&BF_require_parasite)!=0)|| ((flags&BF_require_window)!=0)|| ((flags&BF_resizeable)!=0)|| @@ -198,6 +236,9 @@ make_output(const std::string &name, return new eglGraphicsPixmap(engine, this, name, fb_prop, win_prop, flags, gsg, host); +#else + return nullptr; +#endif } // Nothing else left to try. diff --git a/panda/src/egldisplay/eglGraphicsPipe.h b/panda/src/egldisplay/eglGraphicsPipe.h index aebd9c70e1..def344a61c 100644 --- a/panda/src/egldisplay/eglGraphicsPipe.h +++ b/panda/src/egldisplay/eglGraphicsPipe.h @@ -15,7 +15,14 @@ #define EGLGRAPHICSPIPE_H #include "pandabase.h" + +#ifdef HAVE_X11 #include "x11GraphicsPipe.h" +typedef x11GraphicsPipe BaseGraphicsPipe; +#else +#include "graphicsPipe.h" +typedef GraphicsPipe BaseGraphicsPipe; +#endif #ifdef OPENGLES_2 #include "gles2gsg.h" @@ -25,11 +32,16 @@ #define NativeDisplayType EGLNativeDisplayType #define NativePixmapType EGLNativePixmapType #define NativeWindowType EGLNativeWindowType -#else +#elif defined(OPENGLES_1) #include "glesgsg.h" #include "pre_x11_include.h" #include #include "post_x11_include.h" +#else + #include "glgsg.h" + #include "pre_x11_include.h" + #include + #include "post_x11_include.h" #endif class FrameBufferProperties; @@ -42,14 +54,16 @@ class eglGraphicsWindow; * This graphics pipe represents the interface for creating OpenGL ES graphics * windows on an X-based (e.g. Unix) client. */ -class eglGraphicsPipe : public x11GraphicsPipe { +class eglGraphicsPipe : public BaseGraphicsPipe { public: - eglGraphicsPipe(const std::string &display = std::string()); + eglGraphicsPipe(); virtual ~eglGraphicsPipe(); virtual std::string get_interface_name() const; static PT(GraphicsPipe) pipe_constructor(); + INLINE EGLDisplay get_egl_display() const; + protected: virtual PT(GraphicsOutput) make_output(const std::string &name, const FrameBufferProperties &fb_prop, @@ -62,16 +76,16 @@ protected: bool &precertify); private: - EGLDisplay _egl_display; + EGLDisplay _egl_display = 0; public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - x11GraphicsPipe::init_type(); + BaseGraphicsPipe::init_type(); register_type(_type_handle, "eglGraphicsPipe", - x11GraphicsPipe::get_class_type()); + BaseGraphicsPipe::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); @@ -80,10 +94,6 @@ public: private: static TypeHandle _type_handle; - - friend class eglGraphicsBuffer; - friend class eglGraphicsPixmap; - friend class eglGraphicsWindow; }; #include "eglGraphicsPipe.I" diff --git a/panda/src/egldisplay/eglGraphicsPixmap.cxx b/panda/src/egldisplay/eglGraphicsPixmap.cxx index 5933416f5c..946499746c 100644 --- a/panda/src/egldisplay/eglGraphicsPixmap.cxx +++ b/panda/src/egldisplay/eglGraphicsPixmap.cxx @@ -12,6 +12,9 @@ */ #include "eglGraphicsPixmap.h" + +#ifdef HAVE_X11 + #include "eglGraphicsWindow.h" #include "eglGraphicsStateGuardian.h" #include "config_egldisplay.h" @@ -37,8 +40,7 @@ eglGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe, { eglGraphicsPipe *egl_pipe; DCAST_INTO_V(egl_pipe, _pipe); - _display = egl_pipe->get_display(); - _egl_display = egl_pipe->_egl_display; + _egl_display = egl_pipe->get_egl_display(); _drawable = None; _x_pixmap = None; _egl_surface = EGL_NO_SURFACE; @@ -167,7 +169,7 @@ open_buffer() { if (_gsg == 0) { // There is no old gsg. Create a new one. eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr); - eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, false, true); _gsg = eglgsg; } else { // If the old gsg has the wrong pixel format, create a new one that shares @@ -175,7 +177,7 @@ open_buffer() { DCAST_INTO_R(eglgsg, _gsg, false); if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) { eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg); - eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, false, false, true); _gsg = eglgsg; } } @@ -194,6 +196,7 @@ open_buffer() { return false; } + _display = egl_pipe->get_display(); _drawable = egl_pipe->get_root(); if (_host != nullptr) { if (_host->is_of_type(eglGraphicsWindow::get_class_type())) { @@ -241,3 +244,5 @@ open_buffer() { _is_valid = true; return true; } + +#endif // HAVE_X11 diff --git a/panda/src/egldisplay/eglGraphicsPixmap.h b/panda/src/egldisplay/eglGraphicsPixmap.h index ed7e7f90e9..95cb7842c0 100644 --- a/panda/src/egldisplay/eglGraphicsPixmap.h +++ b/panda/src/egldisplay/eglGraphicsPixmap.h @@ -16,6 +16,8 @@ #include "pandabase.h" +#ifdef HAVE_X11 + #include "eglGraphicsPipe.h" #include "graphicsBuffer.h" @@ -67,4 +69,6 @@ private: static TypeHandle _type_handle; }; +#endif // HAVE_X11 + #endif diff --git a/panda/src/egldisplay/eglGraphicsStateGuardian.cxx b/panda/src/egldisplay/eglGraphicsStateGuardian.cxx index ae3867feec..26f55f3b74 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.cxx +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.cxx @@ -25,19 +25,11 @@ TypeHandle eglGraphicsStateGuardian::_type_handle; eglGraphicsStateGuardian:: eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, eglGraphicsStateGuardian *share_with) : -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian(engine, pipe) -#else - GLESGraphicsStateGuardian(engine, pipe) -#endif + BaseGraphicsStateGuardian(engine, pipe) { _share_context=0; _context=0; - _display=0; _egl_display=0; - _screen=0; - _visual=0; - _visuals=0; _fbconfig=0; if (share_with != nullptr) { @@ -51,9 +43,6 @@ eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, */ eglGraphicsStateGuardian:: ~eglGraphicsStateGuardian() { - if (_visuals != nullptr) { - XFree(_visuals); - } if (_context != (EGLContext)nullptr) { if (!eglDestroyContext(_egl_display, _context)) { egldisplay_cat.error() << "Failed to destroy EGL context: " @@ -108,11 +97,6 @@ get_properties(FrameBufferProperties &properties, slow = true; } - if ((surface_type & EGL_WINDOW_BIT)==0) { - // We insist on having a context that will support an onscreen window. - return; - } - properties.set_back_buffers(1); properties.set_rgb_color(1); properties.set_rgba_bits(red_size, green_size, blue_size, alpha_size); @@ -131,26 +115,23 @@ get_properties(FrameBufferProperties &properties, */ void eglGraphicsStateGuardian:: choose_pixel_format(const FrameBufferProperties &properties, - X11_Display *display, - int screen, bool need_pbuffer, bool need_pixmap) { + eglGraphicsPipe *egl_pipe, bool need_window, + bool need_pbuffer, bool need_pixmap) { - _display = display; - _egl_display = eglGetDisplay((NativeDisplayType) display); - _screen = screen; + _egl_display = egl_pipe->get_egl_display(); _context = 0; _fbconfig = 0; - _visual = 0; - _visuals = 0; _fbprops.clear(); int attrib_list[] = { -#ifdef OPENGLES_1 +#if defined(OPENGLES_1) EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, -#endif -#ifdef OPENGLES_2 +#elif defined(OPENGLES_2) EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, #endif - EGL_SURFACE_TYPE, EGL_DONT_CARE, + EGL_SURFACE_TYPE, need_window ? EGL_WINDOW_BIT : EGL_DONT_CARE, EGL_NONE }; @@ -206,23 +187,56 @@ choose_pixel_format(const FrameBufferProperties &properties, best_props = fbprops; } } - int depth = DefaultDepth(_display, _screen); - _visual = new XVisualInfo; - XMatchVisualInfo(_display, _screen, depth, TrueColor, _visual); +#ifdef HAVE_X11 + X11_Display *display = egl_pipe->get_display(); + if (display) { + int screen = egl_pipe->get_screen(); + int depth = DefaultDepth(display, screen); + _visual = new XVisualInfo; + XMatchVisualInfo(display, screen, depth, TrueColor, _visual); + } +#endif if (best_quality > 0) { egldisplay_cat.debug() << "Chosen config " << best_result << ": " << best_props << "\n"; _fbconfig = configs[best_result]; + + EGLint attribs[32]; + int n = 0; + #ifdef OPENGLES_2 - EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - _context = eglCreateContext(_egl_display, _fbconfig, _share_context, context_attribs); -#else - _context = eglCreateContext(_egl_display, _fbconfig, _share_context, nullptr); + attribs[n++] = EGL_CONTEXT_CLIENT_VERSION; + attribs[n++] = 2; +#elif defined(OPENGLES_1) +#else // Regular OpenGL + if (gl_version.get_num_words() > 0) { + attribs[n++] = EGL_CONTEXT_MAJOR_VERSION; + attribs[n++] = gl_version[0]; + if (gl_version.get_num_words() > 1) { + attribs[n++] = EGL_CONTEXT_MINOR_VERSION; + attribs[n++] = gl_version[1]; + } + } + if (gl_debug) { + attribs[n++] = EGL_CONTEXT_OPENGL_DEBUG; + attribs[n++] = EGL_TRUE; + } + if (gl_forward_compatible) { + attribs[n++] = EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE; + attribs[n++] = EGL_TRUE; + } #endif + attribs[n] = EGL_NONE; + + _context = eglCreateContext(_egl_display, _fbconfig, _share_context, (n > 0) ? attribs : nullptr); + int err = eglGetError(); if (_context && err == EGL_SUCCESS) { - if (_visual) { +#ifdef HAVE_X11 + if (!display || _visual) +#endif + { // This is set during window creation, but for now we have to pretend // that we can honor the request, if we support the extension. if (properties.get_srgb_color()) { @@ -248,8 +262,9 @@ choose_pixel_format(const FrameBufferProperties &properties, << get_egl_error_string(err) << "\n"; _fbconfig = 0; _context = 0; +#ifdef HAVE_X11 _visual = 0; - _visuals = 0; +#endif } egldisplay_cat.error() << @@ -263,11 +278,7 @@ choose_pixel_format(const FrameBufferProperties &properties, */ void eglGraphicsStateGuardian:: reset() { -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::reset(); -#else - GLESGraphicsStateGuardian::reset(); -#endif + BaseGraphicsStateGuardian::reset(); if (_gl_renderer == "Software Rasterizer") { _fbprops.set_force_software(1); @@ -295,13 +306,11 @@ egl_is_at_least_version(int major_version, int minor_version) const { */ void eglGraphicsStateGuardian:: gl_flush() const { +#ifdef HAVE_X11 // This call requires synchronization with X. LightReMutexHolder holder(eglGraphicsPipe::_x_mutex); -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::gl_flush(); -#else - GLESGraphicsStateGuardian::gl_flush(); #endif + BaseGraphicsStateGuardian::gl_flush(); } /** @@ -309,13 +318,11 @@ gl_flush() const { */ GLenum eglGraphicsStateGuardian:: gl_get_error() const { +#ifdef HAVE_X11 // This call requires synchronization with X. LightReMutexHolder holder(eglGraphicsPipe::_x_mutex); -#ifdef OPENGLES_2 - return GLES2GraphicsStateGuardian::gl_get_error(); -#else - return GLESGraphicsStateGuardian::gl_get_error(); #endif + return BaseGraphicsStateGuardian::gl_get_error(); } /** @@ -323,11 +330,7 @@ gl_get_error() const { */ void eglGraphicsStateGuardian:: query_gl_version() { -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::query_gl_version(); -#else - GLESGraphicsStateGuardian::query_gl_version(); -#endif + BaseGraphicsStateGuardian::query_gl_version(); // Calling eglInitialize on an already-initialized display will just provide // us the version numbers. @@ -342,9 +345,12 @@ query_gl_version() { #ifdef OPENGLES_2 if (gles2gsg_cat.is_debug()) { gles2gsg_cat.debug() -#else +#elif defined(OPENGLES_1) if (glesgsg_cat.is_debug()) { glesgsg_cat.debug() +#else + if (glgsg_cat.is_debug()) { + glgsg_cat.debug() #endif << "EGL_VERSION = " << _egl_version_major << "." << _egl_version_minor << "\n"; diff --git a/panda/src/egldisplay/eglGraphicsStateGuardian.h b/panda/src/egldisplay/eglGraphicsStateGuardian.h index ab47d7adf1..608e9aa080 100644 --- a/panda/src/egldisplay/eglGraphicsStateGuardian.h +++ b/panda/src/egldisplay/eglGraphicsStateGuardian.h @@ -16,26 +16,32 @@ #include "pandabase.h" #include "eglGraphicsPipe.h" + +#ifdef HAVE_X11 #include "get_x11.h" +#endif + +#ifdef OPENGLES_2 +typedef GLES2GraphicsStateGuardian BaseGraphicsStateGuardian; +#elif defined(OPENGLES_1) +typedef GLESGraphicsStateGuardian BaseGraphicsStateGuardian; +#else +typedef GLGraphicsStateGuardian BaseGraphicsStateGuardian; +#endif /** * A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific * information. */ -#ifdef OPENGLES_2 -class eglGraphicsStateGuardian : public GLES2GraphicsStateGuardian { -#else -class eglGraphicsStateGuardian : public GLESGraphicsStateGuardian { -#endif +class eglGraphicsStateGuardian : public BaseGraphicsStateGuardian { public: INLINE const FrameBufferProperties &get_fb_properties() const; void get_properties(FrameBufferProperties &properties, bool &pbuffer_supported, bool &pixmap_supported, bool &slow, EGLConfig config); void choose_pixel_format(const FrameBufferProperties &properties, - X11_Display *_display, - int _screen, - bool need_pbuffer, bool need_pixmap); + eglGraphicsPipe *egl_pipe, bool need_window, + bool need_pbuffer, bool need_pixmap); eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe, eglGraphicsStateGuardian *share_with); @@ -49,10 +55,9 @@ public: EGLContext _share_context; EGLContext _context; EGLDisplay _egl_display; - X11_Display *_display; - int _screen; - XVisualInfo *_visual; - XVisualInfo *_visuals; +#ifdef HAVE_X11 + XVisualInfo *_visual = nullptr; +#endif EGLConfig _fbconfig; FrameBufferProperties _fbprops; @@ -72,15 +77,9 @@ public: return _type_handle; } static void init_type() { -#ifdef OPENGLES_2 - GLES2GraphicsStateGuardian::init_type(); + BaseGraphicsStateGuardian::init_type(); register_type(_type_handle, "eglGraphicsStateGuardian", - GLES2GraphicsStateGuardian::get_class_type()); -#else - GLESGraphicsStateGuardian::init_type(); - register_type(_type_handle, "eglGraphicsStateGuardian", - GLESGraphicsStateGuardian::get_class_type()); -#endif + BaseGraphicsStateGuardian::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/egldisplay/eglGraphicsWindow.cxx b/panda/src/egldisplay/eglGraphicsWindow.cxx index 8827325ce0..c85ff9d8df 100644 --- a/panda/src/egldisplay/eglGraphicsWindow.cxx +++ b/panda/src/egldisplay/eglGraphicsWindow.cxx @@ -12,6 +12,9 @@ */ #include "eglGraphicsWindow.h" + +#ifdef HAVE_X11 + #include "eglGraphicsStateGuardian.h" #include "config_egldisplay.h" #include "eglGraphicsPipe.h" @@ -52,7 +55,7 @@ eglGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, { eglGraphicsPipe *egl_pipe; DCAST_INTO_V(egl_pipe, _pipe); - _egl_display = egl_pipe->_egl_display; + _egl_display = egl_pipe->get_egl_display(); _egl_surface = 0; } @@ -214,7 +217,7 @@ open_window() { if (_gsg == 0) { // There is no old gsg. Create a new one. eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, true, false, false); _gsg = eglgsg; } else { // If the old gsg has the wrong pixel format, create a new one that shares @@ -222,7 +225,7 @@ open_window() { DCAST_INTO_R(eglgsg, _gsg, false); if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) { eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg); - eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false); + eglgsg->choose_pixel_format(_fb_properties, egl_pipe, true, false, false); _gsg = eglgsg; } } @@ -275,3 +278,5 @@ open_window() { return true; } + +#endif // HAVE_X11 diff --git a/panda/src/egldisplay/eglGraphicsWindow.h b/panda/src/egldisplay/eglGraphicsWindow.h index 3d4ef62e44..1c359aa666 100644 --- a/panda/src/egldisplay/eglGraphicsWindow.h +++ b/panda/src/egldisplay/eglGraphicsWindow.h @@ -16,6 +16,8 @@ #include "pandabase.h" +#ifdef HAVE_X11 + #include "eglGraphicsPipe.h" #include "x11GraphicsWindow.h" @@ -65,4 +67,6 @@ private: #include "eglGraphicsWindow.I" +#endif // HAVE_X11 + #endif