Skip to content

Commit

Permalink
fix review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
shadow578 authored Apr 29, 2024
1 parent 6c57b3d commit 53a1022
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 95 deletions.
29 changes: 13 additions & 16 deletions Marlin/src/lcd/e3v2/common/dwin_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,51 +188,48 @@ void dwinFrameClear(const uint16_t color) {
const uint16_t map_columns,
const uint16_t map_rows,
const uint8_t *map_data) {
// how many bytes can we write to the send buffer?
// one byte is used for F_HONE, so we can write up to len(dwinSendBuf) - 1 bytes.
constexpr size_t send_buffer_size = (COUNT(dwinSendBuf) - 1);
// at how many bytes should we flush the send buffer?
// one byte is used (hidden) for F_HONE, and we need 4 bytes when appending a point.
// so we should flush the send buffer when we have less than 5 bytes left.
// At how many bytes should we flush the send buffer?
// One byte is used (hidden) for F_HONE, and we need 4 bytes when appending a point.
// So we should flush the send buffer when we have less than 5 bytes left.
constexpr size_t flush_send_buffer_at = (COUNT(dwinSendBuf) - 1 - 4);

// how long is the header of each draw command?
// How long is the header of each draw command?
// 1B CMD, 2B COLOR, 1B WIDTH, 1B HEIGHT
constexpr size_t command_header_size = 5;

// draw the point map
// Draw the point map
size_t i = 0;
for (uint16_t row = 0; row < map_rows; row++) {
for (uint16_t col = 0; col < map_columns; col++) {
const uint8_t map_byte = map_data[(row * map_columns) + col];
for (uint8_t bit = 0; bit < 8; bit++) {
// draw the bit of the byte if it's set
// Draw the bit of the byte if it's set
if (TEST(map_byte, bit)) {
// flush the send buffer and prepare next draw if either
// a) the buffer reached the 'should flush' state, or
// b) this is the first point to draw
// Flush the send buffer and prepare next draw if either
// a) The buffer reached the 'should flush' state, or
// b) This is the first point to draw
if (i >= flush_send_buffer_at || i == 0)
{
// dispatch the current draw command
// Dispatch the current draw command
if (i > command_header_size) dwinSend(i);

// prepare the next draw command
// Prepare the next draw command
i = 0;
dwinByte(i, 0x02); // cmd: draw point(s)
dwinWord(i, color);
dwinByte(i, point_width);
dwinByte(i, point_height);
}

// append point coordinates to draw command
// Append point coordinates to draw command
dwinWord(i, x + (point_width * ((8 * col) + (7 - bit)))); // x
dwinWord(i, y + (point_height * (row))); // y
}
}
}
}

// dispatch final draw command if the buffer contains any points
// Dispatch final draw command if the buffer contains any points
if (i > command_header_size) dwinSend(i);
}
#endif
Expand Down
86 changes: 43 additions & 43 deletions Marlin/src/lcd/e3v2/marlinui/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,68 @@

#if IS_DWIN_MARLINUI && HAS_GAMES

#define PERFORMANCE_COUNTERS 1
// Show performance counters on the screen (frame timing and draw call count)
#define PERFORMANCE_COUNTERS 0

// Compound calls are calls that are made up of multiple subcalls (e.g. draw_hline, which is made up of a draw_box call)
#define INCLUDE_COMPOUNT_CALLS 0

#include "../../menu/game/types.h" // includes e3v2/marlinui/game.h
#include "../../lcdprint.h"
#include "lcdprint_dwin.h"
#include "marlinui_dwin.h"

#if PERFORMANCE_COUNTERS == 1
static uint32_t draw_call_cnt = 0; // total number of draw calls in the current frame
static millis_t frame_draw_millis = 0, // time spent drawing the frame
frame_wait_millis = 0; // time spent waiting for the next frame
#if ENABLED(PERFORMANCE_COUNTERS)
static uint32_t draw_call_cnt = 0; // Total number of draw calls in the current frame
static millis_t frame_draw_millis = 0, // Time spent drawing the frame
frame_wait_millis = 0; // Time spent waiting for the next frame

#define DRAW_CALL_INC(subcall_cnt) draw_call_cnt++
#define COUNT_DRAW_CALL(compound_call_count) TERN(INCLUDE_COMPOUNT_CALLS, draw_call_cnt++, draw_call_cnt = draw_call_cnt + 1 - compound_call_count)
#else
#define DRAW_CALL_INC(subcall_cnt)
#define COUNT_DRAW_CALL(compound_call_count)
#endif

void MarlinGame::frame_start() {
// clear the screen before each frame
// Clear the screen before each frame
//dwinFrameClear(CLEAR_COLOR);

// filling the play area should be faster than clearing the whole screen
// Filling the play area is faster than clearing the whole screen
const uint16_t fg = dwin_font.fg;
dwin_font.fg = COLOR_BG_BLACK;
draw_box(0, 0, GAME_WIDTH, GAME_HEIGHT);
dwin_font.fg = fg;

// Ensure the correct font is selected
dwin_font.index = DWIN_FONT_MENU;

// reset performance counters
#if PERFORMANCE_COUNTERS == 1
// Reset the performance counters
#if ENABLED(PERFORMANCE_COUNTERS)
draw_call_cnt = 0;
frame_draw_millis = millis();
frame_wait_millis = frame_draw_millis - frame_wait_millis;
frame_wait_millis = frame_draw_millis - frame_wait_millis;
#endif
}

void MarlinGame::frame_end() {
#if PERFORMANCE_COUNTERS == 1
#if ENABLED(PERFORMANCE_COUNTERS)
const millis_t frame_wait = frame_wait_millis;
frame_wait_millis = millis();
frame_draw_millis = frame_wait_millis - frame_draw_millis;

// calculate frames per deci-seconds (100 milliseconds)
const uint32_t fpds = 100 / (frame_draw_millis + frame_wait);

// format the performance counters as a string
// Format the performance counters as a string
char perf_str[64];
sprintf_P(
perf_str,
PSTR("d%04lu w%04lu c%04lu f%02lu "),
PSTR("d%04lu w%04lu c%04lu "),
frame_draw_millis,
frame_wait,
draw_call_cnt,
fpds
draw_call_cnt
);

// draw the performance counters at the (physical) origin of the screen
// Draw the performance counters at the (physical) origin of the screen
const uint16_t fg = dwin_font.fg;
const bool solid = dwin_font.solid;
dwin_font.fg = RGB(0x1F, 0x3F, 0x00);
set_color(color::YELLOW);
dwin_font.solid = true;

lcd_moveto_xy(0, 0);
Expand Down Expand Up @@ -107,17 +108,17 @@ void MarlinGame::set_color(const color color) {
}

void MarlinGame::draw_hline(const game_dim_t x, const game_dim_t y, const game_dim_t w) {
// draw lines as boxes, since DWIN lines are always 1px wide but we want to scale them
// Draw lines as boxes, since DWIN lines are always 1px wide but we want to scale them
draw_box(x, y, w, 1);

DRAW_CALL_INC(1);
COUNT_DRAW_CALL(1);
}

void MarlinGame::draw_vline(const game_dim_t x, const game_dim_t y, const game_dim_t h) {
// draw lines as boxes, since DWIN lines are always 1px wide but we want to scale them
// Draw lines as boxes, since DWIN lines are always 1px wide but we want to scale them
draw_box(x, y, 1, h);

DRAW_CALL_INC(1);
COUNT_DRAW_CALL(1);
}

void MarlinGame::draw_frame(const game_dim_t x, const game_dim_t y, const game_dim_t w, const game_dim_t h) {
Expand All @@ -130,7 +131,7 @@ void MarlinGame::draw_frame(const game_dim_t x, const game_dim_t y, const game_d
dwin_game::game_to_screen(h)
);

DRAW_CALL_INC(0);
COUNT_DRAW_CALL(0);
}

void MarlinGame::draw_box(const game_dim_t x, const game_dim_t y, const game_dim_t w, const game_dim_t h) {
Expand All @@ -143,17 +144,17 @@ void MarlinGame::draw_box(const game_dim_t x, const game_dim_t y, const game_dim
dwin_game::game_to_screen(h)
);

DRAW_CALL_INC(0);
COUNT_DRAW_CALL(0);
}

void MarlinGame::draw_pixel(const game_dim_t x, const game_dim_t y) {
// draw pixels using boxes.
// while DWIN protocol supports drawing points with different sizes, the
// 0x02 'draw point' command is way slower per pixel than 0x05 'fill rectangle'
// Draw pixels using boxes.
// While DWIN protocol supports drawing points with different sizes, the
// 0x02 'draw point' command is slower per pixel than 0x05 'fill rectangle'
// (0.4 us vs 0.14 us per pixel)
draw_box(x, y, 1, 1);

DRAW_CALL_INC(1);
COUNT_DRAW_CALL(1);
}

void MarlinGame::draw_bitmap(const game_dim_t x, const game_dim_t y, const game_dim_t bytes_per_row, const game_dim_t rows, const pgm_bitmap_t bitmap) {
Expand All @@ -163,20 +164,19 @@ void MarlinGame::draw_bitmap(const game_dim_t x, const game_dim_t y, const game_

#if DISABLED(TJC_DISPLAY)
// DWIN T5UI actually supports drawing multiple points in one go using the 0x02 'draw point' command, ever since kernel 1.2.
// So we use that to draw the bitmap as a series of points, which should be faster than drawing rectangles using draw_pixel.
// This will be somewhat slow, but way faster than drawing rectangles one by one.
// So we use that to draw the bitmap as a series of points, which is faster than drawing rectangles using draw_pixel.
dwinDrawPointMap(
dwin_font.fg, // color
dwin_game::game_to_screen(1), // point size
dwin_font.fg,
dwin_game::game_to_screen(1),
dwin_game::game_to_screen(1),
dwin_game::game_to_screen(x) + dwin_game::x_offset, // x / y
dwin_game::game_to_screen(x) + dwin_game::x_offset,
dwin_game::game_to_screen(y) + dwin_game::y_offset,
bytes_per_row, // bitmap dimensions
bytes_per_row,
rows,
bitmap // U8G bitmap format is compatible to DrawPointMap format
bitmap
);

DRAW_CALL_INC(0);
COUNT_DRAW_CALL(0);
#else
// TJC displays don't seem to support the 0x02 'draw point' command, so instead we have to draw the bitmap
// as a series of rectangles using draw_pixel.
Expand All @@ -185,10 +185,10 @@ void MarlinGame::draw_bitmap(const game_dim_t x, const game_dim_t y, const game_
for (game_dim_t col = 0; col < bytes_per_row; col++) {
const uint8_t byte = bitmap[(row * bytes_per_row) + col];
for (uint8_t bit = 0; bit < 8; bit++) {
// assume that the screen area is cleared before drawing
// Assuming that the drawing area was cleared before drawing
if (byte & (1 << bit)) {
draw_pixel(x + (col * 8) + (7 - bit + 1), y + row);
DRAW_CALL_INC(1);
COUNT_DRAW_CALL(1);
}
}
}
Expand All @@ -197,7 +197,7 @@ void MarlinGame::draw_bitmap(const game_dim_t x, const game_dim_t y, const game_
}

int MarlinGame::draw_string(const game_dim_t x, const game_dim_t y, const char* str) {
DRAW_CALL_INC(0);
COUNT_DRAW_CALL(0);

lcd_moveto_xy(
dwin_game::game_to_screen(x) + dwin_game::x_offset,
Expand Down
10 changes: 5 additions & 5 deletions Marlin/src/lcd/e3v2/marlinui/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ namespace dwin_game {

constexpr int calculate_scale()
{
// use whichever is smaller: the width or height scaling factor
// Use whichever is smaller: the width or height scaling factor
float scaling_factor = _MIN(
static_cast<float>(DWIN_WIDTH) / static_cast<float>(TARGET_WIDTH),
static_cast<float>(DWIN_HEIGHT) / static_cast<float>(TARGET_HEIGHT)
);

// round DOWN to closest integer
// Round DOWN to closest integer
return static_cast<int>(scaling_factor);
}

Expand All @@ -31,14 +31,14 @@ namespace dwin_game {
constexpr int scale = calculate_scale();

/**
* @brief scale a game dimension to screen dimensions
* @brief Scale a game dimension to screen dimensions
*/
constexpr game_dim_t screen_to_game(const screen_dim_t x) {
return x / scale;
}

/**
* @brief scale a screen dimension to game dimensions
* @brief Scale a screen dimension to game dimensions
*/
constexpr screen_dim_t game_to_screen(const game_dim_t x) {
return x * scale;
Expand All @@ -59,7 +59,7 @@ constexpr game_dim_t GAME_HEIGHT = dwin_game::screen_to_game(DWIN_HEIGHT - (dwin
constexpr game_dim_t GAME_FONT_WIDTH = dwin_game::screen_to_game(MENU_FONT_WIDTH);
constexpr game_dim_t GAME_FONT_ASCENT = dwin_game::screen_to_game(MENU_FONT_ASCENT);

// not needed on DWIN
// DWIN screens don't page, so these macros are always true
#define PAGE_OVER(ya) true
#define PAGE_UNDER(yb) true
#define PAGE_CONTAINS(ya, yb) true
12 changes: 4 additions & 8 deletions Marlin/src/lcd/menu/game/brickout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,25 +144,21 @@ void BrickoutGame::game_screen() {
const uint8_t yy = y * BRICK_H + BRICK_TOP;
if (PAGE_CONTAINS(yy, yy + BRICK_H - 1)) {
for (uint8_t x = 0; x < BRICK_COLS; ++x) {
// cycle through colors, even if the brick is gone
// otherwise, bricks would change color if their neighbor is hit
// Cycle through colors, even if the brick is gone.
// Otherwise, bricks would change color if their neighbor is hit
set_color(brick_colors[color_index++ % COUNT(brick_colors)]);

// draw brick if it's still there
// Draw brick if it's still there
if (TEST(bdat.bricks[y], x)) {
const uint8_t xx = x * BRICK_W;
draw_box(xx, yy, BRICK_W - 1, BRICK_H - 1);

//for (uint8_t v = 0; v < BRICK_H - 1; ++v)
// if (PAGE_CONTAINS(yy + v, yy + v))
// draw_hline(xx, yy + v, BRICK_W - 1);
}
}
}
}
}

// everything else is white
// Everything else is white
set_color(color::WHITE);

// Draw paddle
Expand Down
22 changes: 10 additions & 12 deletions Marlin/src/lcd/menu/game/invaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@

#define INVADER_COLOR { MarlinGame::color::GREEN, MarlinGame::color::CYAN, MarlinGame::color::YELLOW }
#define CANNON_COLOR MarlinGame::color::WHITE
#define LASER_COLOR MarlinGame::color::WHITE // shot by player
#define BULLET_COLOR LASER_COLOR // shot by invader
#define LASER_COLOR MarlinGame::color::WHITE // Shot by player
#define BULLET_COLOR LASER_COLOR // Shot by invader
#define LIFE_COLOR CANNON_COLOR
#define UFO_COLOR MarlinGame::color::MAGENTA
#define EXPLOSION_COLOR MarlinGame::color::RED
Expand Down Expand Up @@ -386,8 +386,8 @@ void InvadersGame::game_screen() {
int8_t xx = idat.pos.x;
for (uint8_t x = 0; x < INVADER_COLS; ++x) {
if (TEST(idat.bugs[y], x)) {
constexpr color type_color[] = INVADER_COLOR;
set_color(type_color[type]);
constexpr color invader_color[] = INVADER_COLOR;
set_color(invader_color[type]);
draw_bitmap(xx, yy, 2, INVADER_H, invader[type][idat.game_blink]);
}
xx += INVADER_COL_W;
Expand Down Expand Up @@ -433,22 +433,20 @@ void InvadersGame::game_screen() {
set_color(color::WHITE);

// Blink GAME OVER when game is over
if (!game_state) {
draw_game_over();
}
if (!game_state) draw_game_over();

if (PAGE_UNDER(GAME_FONT_ASCENT - 1)) {
// Draw Score
//const uint8_t sx = (GAME_WIDTH - (score >= 10 ? score >= 100 ? score >= 1000 ? 4 : 3 : 2 : 1) * GAME_FONT_WIDTH) / 2;
constexpr uint8_t sx = 0;
draw_int(sx, GAME_FONT_ASCENT - 1, score);

// Draw lives
if (idat.cannons_left)
for (uint8_t i = 1; i <= idat.cannons_left; ++i) {
set_color(LIFE_COLOR);
draw_bitmap(GAME_WIDTH - i * (LIFE_W), 6 - (LIFE_H), 1, LIFE_H, life);
}

// Draw Score
//const uint8_t sx = (GAME_WIDTH - (score >= 10 ? score >= 100 ? score >= 1000 ? 4 : 3 : 2 : 1) * GAME_FONT_WIDTH) / 2;
constexpr uint8_t sx = 0;
draw_int(sx, GAME_FONT_ASCENT - 1, score);
}

frame_end();
Expand Down
Loading

0 comments on commit 53a1022

Please sign in to comment.