RetroQUEST/gdlibretro/src/Video.cpp

100 lines
3.5 KiB
C++

#include "RetroHost.hpp"
#include "godot_cpp/classes/image.hpp"
#include "godot_cpp/variant/utility_functions.hpp"
void RetroHost::core_video_init(const struct retro_game_geometry *geometry)
{
godot::UtilityFunctions::print("[RetroHost] Video init ", geometry->base_width, " x ",
geometry->base_height);
this->frame_buffer = godot::Image::create(geometry->base_width, geometry->base_height, false,
this->pixel_format);
}
void RetroHost::core_video_refresh(const void *data, unsigned width, unsigned height,
size_t pitch)
{
if (!data || frame_buffer.is_null() || !frame_buffer.is_valid())
{
return;
}
if ((unsigned)frame_buffer->get_width() != width ||
(unsigned)frame_buffer->get_height() != height)
{
godot::UtilityFunctions::print("[RetroHost] Resizing frame buffer to ", width, "x",
height);
auto created_frame_buffer =
godot::Image::create(width, height, false, frame_buffer->get_format());
if (created_frame_buffer.is_null() || !created_frame_buffer.is_valid())
{
godot::UtilityFunctions::printerr("[RetroHost] Failed to recreate frame buffer");
return;
}
frame_buffer = created_frame_buffer;
}
unsigned buffer_size;
switch (frame_buffer->get_format())
{
case godot::Image::FORMAT_RGB565:
buffer_size = width * height * 2;
break;
case godot::Image::FORMAT_RGBA8:
{
buffer_size = width * height * 4;
#if defined(_MSC_VER) // MSVC compiler
#pragma warning(push)
#pragma warning(disable : 4244)
#endif
uint32_t *data32 = (uint32_t *)data;
for (unsigned i = 0; i < width * height; i++)
{
uint32_t pixel = data32[i];
uint8_t alpha = (pixel & 0xFF000000) >> 24;
uint8_t red = (pixel & 0x00FF0000) >> 16;
uint8_t green = (pixel & 0x0000FF00) >> 8;
uint8_t blue = (pixel & 0x000000FF);
data32[i] = (alpha << 24) | (blue << 16) | (green << 8) | red;
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
}
break;
default:
godot::UtilityFunctions::printerr("[RetroHost] Unhandled pixel format: ",
frame_buffer->get_format());
return;
}
godot::PackedByteArray intermediary_buffer;
intermediary_buffer.resize(buffer_size);
memcpy((void *)intermediary_buffer.ptr(), data, buffer_size);
frame_buffer->set_data(width, height, false, frame_buffer->get_format(), intermediary_buffer);
}
bool RetroHost::core_video_set_pixel_format(unsigned format)
{
switch (format)
{
case RETRO_PIXEL_FORMAT_0RGB1555:
godot::UtilityFunctions::print("[RetroHost] Pixel format: 0RGB1555");
this->pixel_format = godot::Image::Format::FORMAT_RGB565;
return true;
case RETRO_PIXEL_FORMAT_XRGB8888:
godot::UtilityFunctions::print("[RetroHost] Pixel format: XRGB8888");
this->pixel_format = godot::Image::Format::FORMAT_RGBA8;
return true;
case RETRO_PIXEL_FORMAT_RGB565:
godot::UtilityFunctions::print("[RetroHost] Pixel format: RGB565");
this->pixel_format = godot::Image::Format::FORMAT_RGB565;
return true;
default:
return false;
}
}