diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 87cd010..5ea9fbc 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -130,8 +130,9 @@ Known local toolchain state: upload-type mapping used by legacy `Texture2D` and `RTT` creation. It also validates image channel-count to OpenGL texture format mapping, including invalid channel counts rejected by `Texture2D::create(Image)`, RGBA8/RGBA32F - readback formats and byte-count math used by `RTT` and `PBO` readbacks, and - framebuffer status naming used by `RTT` diagnostics. It also owns and + readback formats, byte-count math, and PBO pixel-buffer target/usage/access + mapping used by `RTT` and `PBO` readbacks, and framebuffer status naming + used by `RTT` diagnostics. It also owns and validates framebuffer blit color mask and linear/nearest filters used by `RTT::resize` and `RTT::copy`, plus the default linear clamp-to-edge render-target texture parameters used by `RTT::create`. It also validates diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 7d8fade..64a24b1 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -390,11 +390,12 @@ OpenGL capability detection for framebuffer fetch, map-buffer alignment, and float texture support. It also owns the OpenGL texture upload-type mapping used by legacy `Texture2D` and `RTT` creation, plus image channel-count to texture format mapping for `Texture2D` image uploads and framebuffer status naming for -`RTT` diagnostics. RGBA8/RGBA32F readback formats and byte-count math used by -`RTT` and `PBO` readbacks now live in `pp_renderer_gl`. The framebuffer blit -color mask and linear/nearest filter tokens used by `RTT::resize` and -`RTT::copy`, plus the default render-target texture parameters used by -`RTT::create`, also live in `pp_renderer_gl`. +`RTT` diagnostics. RGBA8/RGBA32F readback formats, byte-count math, and PBO +pixel-buffer target/usage/access tokens used by `RTT` and `PBO` readbacks now +live in `pp_renderer_gl`. The framebuffer blit color mask and linear/nearest +filter tokens used by `RTT::resize` and `RTT::copy`, plus the default +render-target texture parameters used by `RTT::create`, also live in +`pp_renderer_gl`. Mesh index-type and primitive-mode decisions used by legacy `Shape` drawing and the PanoPainter cube-face to OpenGL texture-target mapping used by `TextureCube` also live in @@ -648,9 +649,9 @@ Results: alignment, desktop GL core float support, GLES float/half-float extensions, WebGL exclusion behavior, upload types for RGBA8/RGBA16F/RGBA32F internal formats, image channel-count format mapping including invalid counts, and - RGBA8/RGBA32F readback format and byte-count mapping, framebuffer status - names, framebuffer blit color mask and linear/nearest filters, plus Shape - index-type and fill/stroke primitive mode mapping, + RGBA8/RGBA32F readback format and byte-count mapping, PBO pixel-buffer + target/usage/access mapping, framebuffer status names, framebuffer blit color + mask and linear/nearest filters, plus Shape index-type and fill/stroke primitive mode mapping, PanoPainter cube-face texture-target order, and the linear clamp-to-edge render-target texture parameter set used by `RTT::create`. Sampler parameter validation covers wrap S/T/R plus min/mag filter ordering diff --git a/src/renderer_gl/opengl_capabilities.cpp b/src/renderer_gl/opengl_capabilities.cpp index 89756f5..7b82678 100644 --- a/src/renderer_gl/opengl_capabilities.cpp +++ b/src/renderer_gl/opengl_capabilities.cpp @@ -48,6 +48,10 @@ constexpr std::uint32_t gl_texture_wrap_t = 0x2803U; constexpr std::uint32_t gl_texture_wrap_r = 0x8072U; constexpr std::uint32_t gl_texture_border_color = 0x1004U; constexpr std::uint32_t gl_clamp_to_edge = 0x812FU; +constexpr std::uint32_t gl_pixel_pack_buffer = 0x88EBU; +constexpr std::uint32_t gl_pixel_unpack_buffer = 0x88ECU; +constexpr std::uint32_t gl_stream_read = 0x88E1U; +constexpr std::uint32_t gl_map_read_bit = 0x0001U; [[nodiscard]] bool contains(std::string_view text, std::string_view needle) noexcept { @@ -149,6 +153,26 @@ std::uint64_t readback_byte_count( return static_cast(width) * height * format.bytes_per_pixel; } +std::uint32_t pixel_pack_buffer_target() noexcept +{ + return gl_pixel_pack_buffer; +} + +std::uint32_t pixel_unpack_buffer_target() noexcept +{ + return gl_pixel_unpack_buffer; +} + +std::uint32_t pixel_buffer_stream_read_usage() noexcept +{ + return gl_stream_read; +} + +std::uint32_t pixel_buffer_map_read_access() noexcept +{ + return gl_map_read_bit; +} + const char* framebuffer_status_name(std::uint32_t status) noexcept { switch (status) { diff --git a/src/renderer_gl/opengl_capabilities.h b/src/renderer_gl/opengl_capabilities.h index be4cc65..084c60e 100644 --- a/src/renderer_gl/opengl_capabilities.h +++ b/src/renderer_gl/opengl_capabilities.h @@ -50,6 +50,10 @@ struct OpenGlReadbackFormat { OpenGlReadbackFormat format, std::uint32_t width, std::uint32_t height) noexcept; +[[nodiscard]] std::uint32_t pixel_pack_buffer_target() noexcept; +[[nodiscard]] std::uint32_t pixel_unpack_buffer_target() noexcept; +[[nodiscard]] std::uint32_t pixel_buffer_stream_read_usage() noexcept; +[[nodiscard]] std::uint32_t pixel_buffer_map_read_access() noexcept; [[nodiscard]] const char* framebuffer_status_name(std::uint32_t status) noexcept; [[nodiscard]] std::uint32_t framebuffer_color_buffer_mask() noexcept; [[nodiscard]] std::uint32_t framebuffer_blit_filter(bool linear) noexcept; diff --git a/src/rtt.cpp b/src/rtt.cpp index 874a025..ae69e3f 100644 --- a/src/rtt.cpp +++ b/src/rtt.cpp @@ -493,17 +493,18 @@ bool PBO::create(RTT& rtt) noexcept width = rtt.getWidth(); height = rtt.getHeight(); const auto readback = pp::renderer::gl::rgba8_readback_format(); + const auto buffer_target = static_cast(pp::renderer::gl::pixel_pack_buffer_target()); rtt.bindFramebuffer(); glGenBuffers(1, &buffer_id); - glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id); + glBindBuffer(buffer_target, buffer_id); glBufferData( - GL_PIXEL_PACK_BUFFER, + buffer_target, static_cast(pp::renderer::gl::readback_byte_count( readback, static_cast(width), static_cast(height))), 0, - GL_STREAM_READ); + static_cast(pp::renderer::gl::pixel_buffer_stream_read_usage())); glReadPixels( 0, 0, @@ -512,7 +513,7 @@ bool PBO::create(RTT& rtt) noexcept static_cast(readback.pixel_format), static_cast(readback.component_type), 0); - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + glBindBuffer(buffer_target, 0); rtt.unbindFramebuffer(); }); return true; @@ -537,8 +538,9 @@ void PBO::destroy() noexcept void PBO::bind_read() noexcept { App::I->render_task([this] { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer_id); - bound_slot = GL_PIXEL_UNPACK_BUFFER; + const auto buffer_target = static_cast(pp::renderer::gl::pixel_unpack_buffer_target()); + glBindBuffer(buffer_target, buffer_id); + bound_slot = buffer_target; }); } @@ -554,14 +556,15 @@ glm::uint8_t* PBO::map() noexcept { App::I->render_task([this] { const auto readback = pp::renderer::gl::rgba8_readback_format(); - glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id); - mapped_ptr = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, + const auto buffer_target = static_cast(pp::renderer::gl::pixel_pack_buffer_target()); + glBindBuffer(buffer_target, buffer_id); + mapped_ptr = (GLubyte*)glMapBufferRange(buffer_target, 0, static_cast(pp::renderer::gl::readback_byte_count( readback, static_cast(width), static_cast(height))), - GL_MAP_READ_BIT); - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + static_cast(pp::renderer::gl::pixel_buffer_map_read_access())); + glBindBuffer(buffer_target, 0); }); return mapped_ptr; } @@ -569,8 +572,9 @@ glm::uint8_t* PBO::map() noexcept void PBO::unmap() noexcept { App::I->render_task([this] { - glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer_id); - glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + const auto buffer_target = static_cast(pp::renderer::gl::pixel_pack_buffer_target()); + glBindBuffer(buffer_target, buffer_id); + glUnmapBuffer(buffer_target); + glBindBuffer(buffer_target, 0); }); } diff --git a/tests/renderer_gl/capabilities_tests.cpp b/tests/renderer_gl/capabilities_tests.cpp index 99f0ceb..c550300 100644 --- a/tests/renderer_gl/capabilities_tests.cpp +++ b/tests/renderer_gl/capabilities_tests.cpp @@ -132,6 +132,14 @@ void maps_readback_formats(pp::tests::Harness& h) PP_EXPECT(h, pp::renderer::gl::readback_byte_count(rgba32f, 3U, 5U) == 240U); } +void maps_pixel_buffer_parameters(pp::tests::Harness& h) +{ + PP_EXPECT(h, pp::renderer::gl::pixel_pack_buffer_target() == 0x88EBU); + PP_EXPECT(h, pp::renderer::gl::pixel_unpack_buffer_target() == 0x88ECU); + PP_EXPECT(h, pp::renderer::gl::pixel_buffer_stream_read_usage() == 0x88E1U); + PP_EXPECT(h, pp::renderer::gl::pixel_buffer_map_read_access() == 0x0001U); +} + void names_framebuffer_status_codes(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CD5U) == std::string_view("GL_FRAMEBUFFER_COMPLETE")); @@ -339,6 +347,7 @@ int main() harness.run("selects_texture_upload_type_from_internal_format", selects_texture_upload_type_from_internal_format); harness.run("maps_image_channel_count_to_texture_format", maps_image_channel_count_to_texture_format); harness.run("maps_readback_formats", maps_readback_formats); + harness.run("maps_pixel_buffer_parameters", maps_pixel_buffer_parameters); harness.run("names_framebuffer_status_codes", names_framebuffer_status_codes); harness.run("maps_framebuffer_blit_parameters", maps_framebuffer_blit_parameters); harness.run("maps_shape_index_and_primitive_modes", maps_shape_index_and_primitive_modes);