#include "Display.h" #include "DrawContext.h" #include "FrameBuffer.h" #include "Image.h" #include "SpriteAssetLoader.h" #include "SdlPhotoSensor.h" #include #include #include #include #include namespace { class CaptureDisplay : public Platform::IDisplay { public: const Core::FrameBuffer* framebuffer; CaptureDisplay() : framebuffer(nullptr) { } bool init(int, int) override { return true; } void present(const Core::FrameBuffer* fb) override { framebuffer = fb; } void poll_events(bool&) override {} void shutdown() override {} }; const Core::FramePixel* PresentPixels(Core::DrawContext& ctx, CaptureDisplay& display) { ctx.present(&display); assert(display.framebuffer != nullptr); return static_cast(display.framebuffer->get_buffer()); } void TestFramePixelIsRgb565() { static_assert(sizeof(Core::FramePixel) == sizeof(uint16_t), "FramePixel must stay RGB565"); assert(RenderData::rgba5551_to_rgb565(0xF801u) == 0xF800u); assert(RenderData::rgba5551_to_rgb565(0x07C1u) == 0x07E0u); assert(RenderData::rgba5551_to_rgb565(0x003Fu) == 0x001Fu); } void TestFrameBufferStoresRgb565() { Core::FrameBuffer framebuffer(2, 1); framebuffer.clear(RenderData::Color(255, 0, 0, 255)); const Core::FramePixel* pixels = static_cast(framebuffer.get_buffer()); assert(pixels[0] == 0xF800u); assert(pixels[1] == 0xF800u); } void TestImageDefaultsToRgba5551AndReturnsRawPixels() { const uint16_t default_pixels[] = { 0xF801u, 0x0000u }; RenderData::Image default_image(default_pixels, 1, 1); assert(default_image.format == RenderData::PixelFormat::RGBA5551); const uint16_t explicit_pixels[] = { 0x07C1u }; RenderData::Image explicit_image( explicit_pixels, 1, 1, RenderData::PixelFormat::RGBA5551); assert(explicit_image.get_pixel(0, 0) == 0x07C1u); } void TestDrawSpriteUsesOneBitAlpha() { const uint16_t sprite_pixels[] = { 0xF800u, 0x07C1u }; Core::DrawContext ctx(2, 1); ctx.clear_color(RenderData::Color(0, 0, 255, 255)); RenderData::Image image( sprite_pixels, 2, 1, RenderData::PixelFormat::RGBA5551); RenderData::Sprite sprite(&image, 0, 0, image.width, image.height); ctx.draw_sprite(0, 0, sprite); CaptureDisplay display; ctx.present(&display); assert(display.framebuffer != nullptr); const Core::FramePixel* pixels = static_cast(display.framebuffer->get_buffer()); assert(pixels[0] == 0x001Fu); assert(pixels[1] == 0x07E0u); } void TestDrawSpriteUsesAtlasSubrect() { const uint16_t atlas_pixels[] = { 0xF801u, 0x07C1u }; RenderData::Image atlas( atlas_pixels, 2, 1, RenderData::PixelFormat::RGBA5551); RenderData::Sprite sprite(&atlas, 1, 0, 1, 1); Core::DrawContext ctx(1, 1); ctx.clear_color(RenderData::Color::Blue()); ctx.draw_sprite(0, 0, sprite); CaptureDisplay display; const Core::FramePixel* pixels = PresentPixels(ctx, display); assert(pixels[0] == 0x07E0u); } void TestSpriteAssetLoaderRoundTripsRgba5551() { const std::string path = "render_pipeline_test.sprite"; const uint16_t original_pixels[] = { 0x0000u, 0xF801u, 0x07C1u, 0x003Fu }; RenderData::Image original( original_pixels, 2, 2, RenderData::PixelFormat::RGBA5551); assert(Asset::SpriteAssetLoader::Save(path, original)); std::vector loaded_pixels; RenderData::Image loaded; const bool loaded_ok = Asset::SpriteAssetLoader::Load(path, loaded_pixels, loaded); std::remove(path.c_str()); assert(loaded_ok); assert(loaded.format == RenderData::PixelFormat::RGBA5551); assert(loaded.width == 2); assert(loaded.height == 2); assert(loaded_pixels.size() == 4u); for (size_t i = 0; i < loaded_pixels.size(); ++i) { assert(loaded_pixels[i] == original_pixels[i]); } } void TestDrawTextUsesBitMaskAndColor() { const uint8_t glyph_mask[] = { 0x90u }; RenderData::BitmapFont font; font.mask_bits = glyph_mask; font.atlas_width = 2; font.atlas_height = 2; font.char_w = 2; font.char_h = 2; font.columns = 1; font.first_char = 'A'; Core::DrawContext ctx(2, 2); ctx.clear_color(RenderData::Color::Black()); ctx.draw_text(font, 0, 0, RenderData::Color::Red(), "A"); CaptureDisplay display; const Core::FramePixel* pixels = PresentPixels(ctx, display); assert(pixels[0] == 0xF800u); assert(pixels[1] == 0x0000u); assert(pixels[2] == 0x0000u); assert(pixels[3] == 0xF800u); } void TestDrawTextColorChangesPerCallAndBackgroundFill() { const uint8_t glyph_mask[] = { 0x90u }; RenderData::BitmapFont font; font.mask_bits = glyph_mask; font.atlas_width = 2; font.atlas_height = 2; font.char_w = 2; font.char_h = 2; font.columns = 1; font.first_char = 'A'; Core::DrawContext ctx(4, 2); ctx.clear_color(RenderData::Color::Black()); ctx.draw_text(font, 0, 0, RenderData::Color::White(), RenderData::Color::Blue(), "A"); ctx.draw_text(font, 2, 0, RenderData::Color::Green(), "A"); CaptureDisplay display; const Core::FramePixel* pixels = PresentPixels(ctx, display); assert(pixels[0] == 0xFFFFu); assert(pixels[1] == 0x001Fu); assert(pixels[2] == 0x07E0u); assert(pixels[3] == 0x0000u); assert(pixels[4] == 0x001Fu); assert(pixels[5] == 0xFFFFu); assert(pixels[6] == 0x0000u); assert(pixels[7] == 0x07E0u); } void TestDrawTextClipsBitMaskToScreen() { const uint8_t glyph_mask[] = { 0x90u }; RenderData::BitmapFont font; font.mask_bits = glyph_mask; font.atlas_width = 2; font.atlas_height = 2; font.char_w = 2; font.char_h = 2; font.columns = 1; font.first_char = 'A'; Core::DrawContext ctx(2, 2); ctx.clear_color(RenderData::Color::Black()); ctx.draw_text(font, -1, -1, RenderData::Color::Green(), "A"); ctx.draw_text(font, 3, 3, RenderData::Color::Red(), "A"); CaptureDisplay display; const Core::FramePixel* pixels = PresentPixels(ctx, display); assert(pixels[0] == 0x07E0u); assert(pixels[1] == 0x0000u); assert(pixels[2] == 0x0000u); assert(pixels[3] == 0x0000u); } void TestSdlPhotoSensorClampAndRange() { Platform::SdlPhotoSensor sensor; assert(sensor.init()); sensor.set_range(100, 3000); assert(sensor.read_level() >= 100); assert(sensor.read_level() <= 3000); sensor.set_level(50); assert(sensor.read_level() == 100); sensor.set_level(5000); assert(sensor.read_level() == 3000); sensor.set_level(1500); assert(sensor.read_level() == 1500); sensor.set_step(100); assert(sensor.is_open()); sensor.shutdown(); assert(!sensor.is_open()); assert(sensor.read_level() == 2048); } } int main() { TestFramePixelIsRgb565(); TestFrameBufferStoresRgb565(); TestImageDefaultsToRgba5551AndReturnsRawPixels(); TestDrawSpriteUsesOneBitAlpha(); TestDrawSpriteUsesAtlasSubrect(); TestSpriteAssetLoaderRoundTripsRgba5551(); TestDrawTextUsesBitMaskAndColor(); TestDrawTextColorChangesPerCallAndBackgroundFill(); TestDrawTextClipsBitMaskToScreen(); TestSdlPhotoSensorClampAndRange(); std::cout << "render_pipeline_tests: PASS\n"; return 0; }