This commit is contained in:
HP
2026-06-07 14:37:58 +08:00
13 changed files with 445 additions and 43 deletions
+45 -34
View File
@@ -6,10 +6,10 @@
#include <cstdio>
#include <iostream>
#include <thread>
#include "BitmapFont.h"
#include <chrono>
#include "Color.h"
#include "Display.h"
#include <cstdlib>
#include "Timer.h"
#include "DrawContext.h"
#include "Image.h"
#include "TimeSource.h"
@@ -23,10 +23,15 @@
#include "SDLDisplay.h"
#endif
namespace
const int32_t width = 1024;
const int32_t height = 600;
static void PrintUsage(const char *program_name)
{
const int32_t DemoWidth = 800;
const int32_t DemoHeight = 600;
std::cout
<< "Usage: " << program_name << " [--fps 30|45|60]\n"
<< " " << program_name << " [--fps=30|45|60]\n";
}
struct ProgramOptions
{
@@ -141,39 +146,46 @@ int main(int argc, char* argv[])
font.columns = font_columns;
font.first_char = font_first_char;
RenderData::Image sprite(test_sprite_pixels, test_sprite_width, test_sprite_height, 0x00000000u);
RenderData::Image sprite_img(test_sprite_pixels, test_sprite_width, test_sprite_height, 0x00000000);
RenderData::SpriteRegion sprite_region(&sprite_img, 0, 0, sprite_img.width, sprite_img.height);
const std::array<uint16_t, 8 * 4> tileIds = {
0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile,
RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0,
0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile,
RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0, RenderData::Tilemap::EmptyTile, 0};
RenderData::Tilemap testTilemap(tileIds.data(), 8, 4, &sprite_img, sprite_img.width, sprite_img.height, 1);
const RenderData::Color clearColor(18, 18, 24, 255);
const RenderData::Color fpsColor(0, 255, 80, 255);
const RenderData::Color fpsBg(0, 0, 0, 200);
int32_t fps = 0;
int32_t frame_count = 0;
uint32_t last_fps_time = 0;
uint32_t animation_time_ms = 0;
char fps_text[32];
char perf_text[64];
uint32_t last_frame_ms = 0;
uint32_t last_present_ms = 0;
std::cout << "Demo started. Target FPS: " << timer.target_fps() << std::endl;
bool is_running = true;
while (is_running)
bool isRunning = true;
while (isRunning)
{
timer.begin_frame(time_source.get_time_ms());
animation_time_ms += timer.fixed_delta_ms();
const uint32_t frame_start_ms = time_source.get_time_ms();
timer.begin_frame(frame_start_ms);
bool should_quit = false;
display->poll_events(should_quit);
if (should_quit)
{
is_running = false;
}
display->poll_events(isRunning);
ctx.clear(RenderData::Color(18, 18, 24, 255));
ctx.fill_rect(48, 72, 704, 360, RenderData::Color(42, 48, 60, 255));
ctx.fill_rect(64, 88, 672, 328, RenderData::Color(24, 28, 36, 255));
ctx.clear_color(clearColor);
const int32_t travel = std::max(1, DemoWidth - sprite.width - 128);
const int32_t sprite_x = 64 + static_cast<int32_t>((animation_time_ms / 8u) % static_cast<uint32_t>(travel));
const int32_t sprite_y = 220;
ctx.draw_sprite(sprite_x, sprite_y, sprite);
ctx.draw_text(font, 64, 96, RenderData::Color(240, 240, 240, 255), "GFX DEMO");
// sprite 测试
ctx.draw_sprite(10, 10, sprite_img);
ctx.draw_sprite_region_ex(30, 10, sprite_region, 2, false, false);
ctx.draw_sprite_region_ex(10, 30, sprite_region, 3, true, false);
ctx.draw_tilemap(testTilemap, 650, 500, 96, 48, static_cast<int32_t>(frame_start_ms / 20u) % 32, 0);
// FPS 计数
++frame_count;
const uint32_t now = time_source.get_time_ms();
if (now - last_fps_time >= 1000u)
@@ -184,15 +196,14 @@ int main(int argc, char* argv[])
}
std::snprintf(fps_text, sizeof(fps_text), "FPS: %d", fps);
ctx.draw_text(
font,
4,
4,
RenderData::Color(0, 255, 80, 255),
RenderData::Color(0, 0, 0, 200),
fps_text);
ctx.draw_text(font, 4, 4, fpsColor, fpsBg, fps_text);
std::snprintf(perf_text, sizeof(perf_text), "Frame:%ums Present:%ums", last_frame_ms, last_present_ms);
ctx.draw_text(font, 4, 4 + font.char_h, fpsColor, fpsBg, perf_text);
const uint32_t present_start_ms = time_source.get_time_ms();
ctx.present(display);
last_present_ms = time_source.get_time_ms() - present_start_ms;
last_frame_ms = time_source.get_time_ms() - frame_start_ms;
SleepRemainingFrameTime(timer, time_source);
}
+1
View File
@@ -3,6 +3,7 @@
#include <vector>
#include "Vector2.h"
#include <cmath>
#include <cstddef>
namespace Core
{
+1 -1
View File
@@ -18,6 +18,6 @@ namespace Core
}
// Row-major layout with y = 0 on the first row, matching a top-left screen origin.
size_t index = static_cast<size_t>(y) * width + x;
buffer.at(index) = color;
buffer[index] = color;
}
}
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once
#include "Color.h"
#include "Vector2.h"
#include <cstddef>
#include <cstdint>
#include <vector>
@@ -43,4 +44,4 @@ namespace Core
void set_pixel(const int32_t x, const int32_t y, const uint32_t color);
};
}
}
+5
View File
@@ -40,6 +40,11 @@ namespace Core
depthBuffer->clear();
}
void DrawContext::clear_color(const RenderData::Color& color)
{
frameBuffer->clear(color);
}
void DrawContext::clear_depth()
{
depthBuffer->clear();
+1
View File
@@ -46,6 +46,7 @@ namespace Core
int32_t get_height() const;
void clear(const RenderData::Color& color);
void clear_color(const RenderData::Color& color);
void clear_depth();
void draw_line(const Math::Vector2Int& from, const Math::Vector2Int& to, const RenderData::Color& color);
+1
View File
@@ -1,4 +1,5 @@
#pragma once
#include <cstddef>
#include <cmath>
#include "Vector3.h"
#include "Vector4.h"
+70 -4
View File
@@ -13,6 +13,22 @@
namespace Platform
{
namespace
{
inline uint16_t rgba_to_rgb565(uint32_t rgba)
{
const uint32_t r = (rgba >> 24) & 0xFFu;
const uint32_t g = (rgba >> 16) & 0xFFu;
const uint32_t b = (rgba >> 8) & 0xFFu;
return static_cast<uint16_t>(((r & 0xF8u) << 8) | ((g & 0xFCu) << 3) | (b >> 3));
}
inline uint32_t rgba_to_argb8888(uint32_t rgba)
{
return ((rgba >> 8) & 0x00FFFFFFu) | ((rgba & 0xFFu) << 24);
}
}
bool FBDisplay::init(int w, int h)
{
width = w;
@@ -81,15 +97,65 @@ namespace Platform
return;
const uint32_t* src = static_cast<const uint32_t*>(framebuffer->get_buffer());
int dst_width = std::min(width, static_cast<int>(vinfo.xres));
int dst_height = std::min(height, static_cast<int>(vinfo.yres));
int bytes_per_pixel = vinfo.bits_per_pixel / 8;
const int src_width = framebuffer->get_width();
const int dst_width = std::min(src_width, static_cast<int>(vinfo.xres));
const int dst_height = std::min(framebuffer->get_height(), static_cast<int>(vinfo.yres));
const int bytes_per_pixel = vinfo.bits_per_pixel / 8;
const bool is_rgb565 =
vinfo.bits_per_pixel == 16 &&
vinfo.red.offset == 11 && vinfo.red.length == 5 &&
vinfo.green.offset == 5 && vinfo.green.length == 6 &&
vinfo.blue.offset == 0 && vinfo.blue.length == 5;
const bool is_argb8888 =
vinfo.bits_per_pixel == 32 &&
vinfo.red.offset == 16 && vinfo.red.length == 8 &&
vinfo.green.offset == 8 && vinfo.green.length == 8 &&
vinfo.blue.offset == 0 && vinfo.blue.length == 8;
const bool is_rgba8888 =
vinfo.bits_per_pixel == 32 &&
vinfo.red.offset == 24 && vinfo.red.length == 8 &&
vinfo.green.offset == 16 && vinfo.green.length == 8 &&
vinfo.blue.offset == 8 && vinfo.blue.length == 8;
if (is_rgb565)
{
for (int y = 0; y < dst_height; ++y)
{
const uint32_t* src_row = src + y * src_width;
uint16_t* dst_row = reinterpret_cast<uint16_t*>(fb_mem + y * finfo.line_length);
for (int x = 0; x < dst_width; ++x)
{
dst_row[x] = rgba_to_rgb565(src_row[x]);
}
}
return;
}
if (is_argb8888)
{
for (int y = 0; y < dst_height; ++y)
{
const uint32_t* src_row = src + y * src_width;
uint32_t* dst_row = reinterpret_cast<uint32_t*>(fb_mem + y * finfo.line_length);
for (int x = 0; x < dst_width; ++x)
{
dst_row[x] = rgba_to_argb8888(src_row[x]);
}
}
return;
}
if (is_rgba8888 && dst_width == src_width && static_cast<int>(finfo.line_length) == dst_width * 4)
{
std::memcpy(fb_mem, src, static_cast<size_t>(dst_height) * static_cast<size_t>(dst_width) * sizeof(uint32_t));
return;
}
for (int y = 0; y < dst_height; ++y)
{
for (int x = 0; x < dst_width; ++x)
{
uint32_t pixel = convert_pixel(src[y * width + x]);
uint32_t pixel = convert_pixel(src[y * src_width + x]);
uint8_t* dst = fb_mem + y * finfo.line_length + x * bytes_per_pixel;
if (vinfo.bits_per_pixel == 32)
{