Make Renderer more self-contained.

The Renderer should configure the context and flip the image when
in classic mode and not rely on the Window to do so.

PiperOrigin-RevId: 878480986
Change-Id: I1af899107647469659662abd85527cdf66f507f4
This commit is contained in:
Haroon Qureshi
2026-03-04 07:25:51 -08:00
committed by Copybara-Service
parent 15d8fc13b9
commit c70b05e037
2 changed files with 25 additions and 15 deletions
+24 -2
View File
@@ -17,6 +17,7 @@
#include <chrono>
#include <cstddef>
#include <span>
#include <utility>
#include <mujoco/mujoco.h>
@@ -31,11 +32,24 @@
namespace mujoco::platform {
static void FlipImage(unsigned char* pixels, int width, int height, int bpp) {
const int row_size = width * bpp;
for (int i = 0; i < height / 2; ++i) {
unsigned char* top_row = pixels + i * row_size;
unsigned char* bottom_row = pixels + (height - 1 - i) * row_size;
for (int j = 0; j < row_size; ++j) {
std::swap(top_row[j], bottom_row[j]);
}
}
}
Renderer::Renderer(void* native_window, GraphicsMode gfx)
: native_window_(native_window), gfx_(gfx) {
if (IsClassic(gfx_)) {
if (native_window == nullptr) {
// graphics_api_context_ = CreateEglContext();
#ifndef __EMSCRIPTEN__
graphics_api_context_ = CreateEglContext();
#endif // __EMSCRIPTEN__
}
if (ImGui::GetCurrentContext()) {
ImGui_ImplOpenGL3_Init();
@@ -165,6 +179,9 @@ void Renderer::Render(const mjModel* model, mjData* data,
if (render_to_texture) {
unsigned char* ptr = reinterpret_cast<unsigned char*>(pixels.data());
read_pixels_(ptr, viewport);
if (IsClassic(gfx_)) {
FlipImage(ptr, width, height, 3);
}
}
UpdateFps();
@@ -182,7 +199,12 @@ void Renderer::RenderToTexture(const mjModel* model, mjData* data,
set_buffer_(mjFB_OFFSCREEN);
render_(viewport, &scene_);
read_pixels_((unsigned char*)output, viewport);
unsigned char* ptr = reinterpret_cast<unsigned char*>(output);
read_pixels_(ptr, viewport);
if (IsClassic(gfx_)) {
FlipImage(ptr, width, height, 3);
}
}
int Renderer::UploadImage(int texture_id, const std::byte* pixels, int width,
+1 -13
View File
@@ -140,8 +140,7 @@ Window::Window(std::string_view title, int width, int height, Config config)
// Filament (except WebGL) manages its own swap chain including when to swap.
// In all other cases, we'll use SDL to manage the swap chain.
if (config_.gfx_mode == GraphicsMode::FilamentWebGl ||
config_.gfx_mode == GraphicsMode::ClassicOpenGl ||
config_.gfx_mode == GraphicsMode::ClassicOpenGlHeadless) {
config_.gfx_mode == GraphicsMode::ClassicOpenGl) {
SDL_GLContext gl_context = SDL_GL_CreateContext(sdl_window_);
SDL_GL_MakeCurrent(sdl_window_, gl_context);
}
@@ -260,17 +259,6 @@ void Window::Present(std::span<const std::byte> pixels) {
}
}
// Flip the image vertically because the classic renderer uses a bottom-left
// coordinate system while SDL assumes a top-left coordinate system.
if (config_.gfx_mode == GraphicsMode::ClassicOpenGlHeadless) {
dst = static_cast<unsigned char*>(surface->pixels);
for (int r = 0; r < height_ / 2; ++r) {
unsigned char* top_row = &dst[4 * width_ * r];
unsigned char* bottom_row = &dst[4 * width_ * (height_ - 1 - r)];
std::swap_ranges(top_row, top_row + 4 * width_, bottom_row);
}
}
SDL_RenderPresent(sdl_renderer_);
} else if (config_.gfx_mode != GraphicsMode::FilamentVulkan
&& config_.gfx_mode != GraphicsMode::FilamentOpenGl) {