feat: Implement screenshot capture functionality in ImGuiTestHarnessService

This commit is contained in:
scawful
2025-10-02 20:22:47 -04:00
parent ef631d263a
commit 5baa1b144d
5 changed files with 134 additions and 29 deletions

View File

@@ -2,9 +2,12 @@
#ifdef YAZE_WITH_GRPC
#include <SDL.h>
#include <algorithm>
#include <chrono>
#include <deque>
#include <fstream>
#include <iostream>
#include <limits>
#include <thread>
@@ -1184,15 +1187,82 @@ absl::Status ImGuiTestHarnessServiceImpl::Assert(const AssertRequest* request,
return finalize(absl::OkStatus());
}
// Helper struct matching imgui_impl_sdlrenderer2.cpp backend data
struct ImGui_ImplSDLRenderer2_Data {
SDL_Renderer* Renderer;
};
absl::Status ImGuiTestHarnessServiceImpl::Screenshot(
const ScreenshotRequest* request, ScreenshotResponse* response) {
// TODO: Implement actual screenshot capture
response->set_success(false);
response->set_message("Screenshot not yet implemented");
response->set_file_path("");
response->set_file_size_bytes(0);
// Get the SDL renderer from ImGui backend
ImGuiIO& io = ImGui::GetIO();
auto* backend_data = static_cast<ImGui_ImplSDLRenderer2_Data*>(io.BackendRendererUserData);
if (!backend_data || !backend_data->Renderer) {
response->set_success(false);
response->set_message("SDL renderer not available");
return absl::FailedPreconditionError("No SDL renderer available");
}
SDL_Renderer* renderer = backend_data->Renderer;
// Get renderer output size
int width, height;
if (SDL_GetRendererOutputSize(renderer, &width, &height) != 0) {
response->set_success(false);
response->set_message(absl::StrFormat("Failed to get renderer size: %s", SDL_GetError()));
return absl::InternalError("Failed to get renderer output size");
}
// Create surface to hold screenshot
SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32,
0x00FF0000, 0x0000FF00,
0x000000FF, 0xFF000000);
if (!surface) {
response->set_success(false);
response->set_message(absl::StrFormat("Failed to create surface: %s", SDL_GetError()));
return absl::InternalError("Failed to create SDL surface");
}
// Read pixels from renderer
if (SDL_RenderReadPixels(renderer, nullptr, SDL_PIXELFORMAT_ARGB8888,
surface->pixels, surface->pitch) != 0) {
SDL_FreeSurface(surface);
response->set_success(false);
response->set_message(absl::StrFormat("Failed to read pixels: %s", SDL_GetError()));
return absl::InternalError("Failed to read renderer pixels");
}
// Determine output path
std::string output_path = request->output_path();
if (output_path.empty()) {
// Default: /tmp/yaze_screenshot_<timestamp>.bmp
output_path = absl::StrFormat("/tmp/yaze_screenshot_%lld.bmp",
absl::ToUnixMillis(absl::Now()));
}
// Save to BMP file (SDL built-in, no external deps needed)
if (SDL_SaveBMP(surface, output_path.c_str()) != 0) {
SDL_FreeSurface(surface);
response->set_success(false);
response->set_message(absl::StrFormat("Failed to save BMP: %s", SDL_GetError()));
return absl::InternalError("Failed to save screenshot");
}
// Get file size
std::ifstream file(output_path, std::ios::binary | std::ios::ate);
int64_t file_size = file.tellg();
file.close();
// Clean up and return success
SDL_FreeSurface(surface);
response->set_success(true);
response->set_message(absl::StrFormat("Screenshot saved to %s (%dx%d)",
output_path, width, height));
response->set_file_path(output_path);
response->set_file_size_bytes(file_size);
return absl::OkStatus();
}