enable write buffering on VRAM, optimize some UI drawing algorithms

This commit is contained in:
Wolfvak 2019-05-24 18:09:50 -03:00 committed by d0k3
parent bb5182cae3
commit 6823e15584
4 changed files with 62 additions and 65 deletions

View File

@ -25,19 +25,21 @@ static u32 font_height = 0;
static u32 line_height = 0; static u32 line_height = 0;
static u8 font_bin[FONT_MAX_HEIGHT * 256]; static u8 font_bin[FONT_MAX_HEIGHT * 256];
#define PIXEL_OFFSET(x, y) (((x) * SCREEN_HEIGHT) + (SCREEN_HEIGHT - (y) - 1))
u8* GetFontFromPbm(const void* pbm, const u32 pbm_size, u32* w, u32* h) { u8* GetFontFromPbm(const void* pbm, const u32 pbm_size, u32* w, u32* h) {
char* hdr = (char*) pbm; char* hdr = (char*) pbm;
u32 hdr_max_size = min(512, pbm_size); u32 hdr_max_size = min(512, pbm_size);
u32 pbm_w = 0; u32 pbm_w = 0;
u32 pbm_h = 0; u32 pbm_h = 0;
// minimum size // minimum size
if (hdr_max_size < 7) return NULL; if (hdr_max_size < 7) return NULL;
// check header magic, then skip over // check header magic, then skip over
if (strncmp(hdr, "P4\n", 3) != 0) return NULL; if (strncmp(hdr, "P4\n", 3) != 0) return NULL;
// skip any comments // skip any comments
u32 p = 3; u32 p = 3;
while (hdr[p] == '#') { while (hdr[p] == '#') {
@ -45,29 +47,29 @@ u8* GetFontFromPbm(const void* pbm, const u32 pbm_size, u32* w, u32* h) {
if (p >= hdr_max_size) return NULL; if (p >= hdr_max_size) return NULL;
} }
} }
// parse width // parse width
while ((hdr[p] >= '0') && (hdr[p] <= '9')) { while ((hdr[p] >= '0') && (hdr[p] <= '9')) {
if (p >= hdr_max_size) return NULL; if (p >= hdr_max_size) return NULL;
pbm_w *= 10; pbm_w *= 10;
pbm_w += hdr[p++] - '0'; pbm_w += hdr[p++] - '0';
} }
// whitespace // whitespace
if ((hdr[p++] != ' ') || (p >= hdr_max_size)) if ((hdr[p++] != ' ') || (p >= hdr_max_size))
return NULL; return NULL;
// parse height // parse height
while ((hdr[p] >= '0') && (hdr[p] <= '9')) { while ((hdr[p] >= '0') && (hdr[p] <= '9')) {
if (p >= hdr_max_size) return NULL; if (p >= hdr_max_size) return NULL;
pbm_h *= 10; pbm_h *= 10;
pbm_h += hdr[p++] - '0'; pbm_h += hdr[p++] - '0';
} }
// line break // line break
if ((hdr[p++] != '\n') || (p >= hdr_max_size)) if ((hdr[p++] != '\n') || (p >= hdr_max_size))
return NULL; return NULL;
// check sizes // check sizes
if (pbm_w <= 8) { // 1x256 format if (pbm_w <= 8) { // 1x256 format
if ((pbm_w > FONT_MAX_WIDTH) || (pbm_h % 256) || if ((pbm_w > FONT_MAX_WIDTH) || (pbm_h % 256) ||
@ -81,7 +83,7 @@ u8* GetFontFromPbm(const void* pbm, const u32 pbm_size, u32* w, u32* h) {
((pbm_h * pbm_w / 8) != (pbm_size - p))) ((pbm_h * pbm_w / 8) != (pbm_size - p)))
return NULL; return NULL;
} }
// all good // all good
if (w) *w = pbm_w; if (w) *w = pbm_w;
if (h) *h = pbm_h; if (h) *h = pbm_h;
@ -93,23 +95,23 @@ u8* GetFontFromPbm(const void* pbm, const u32 pbm_size, u32* w, u32* h) {
bool SetFontFromPbm(const void* pbm, u32 pbm_size) { bool SetFontFromPbm(const void* pbm, u32 pbm_size) {
u32 w, h; u32 w, h;
u8* ptr = NULL; u8* ptr = NULL;
if (!pbm) { if (!pbm) {
u64 pbm_size64 = 0; u64 pbm_size64 = 0;
pbm = FindVTarFileInfo(VRAM0_FONT_PBM, &pbm_size64); pbm = FindVTarFileInfo(VRAM0_FONT_PBM, &pbm_size64);
pbm_size = (u32) pbm_size64; pbm_size = (u32) pbm_size64;
} }
if (pbm) if (pbm)
ptr = GetFontFromPbm(pbm, pbm_size, &w, &h); ptr = GetFontFromPbm(pbm, pbm_size, &w, &h);
if (!ptr) { if (!ptr) {
return false; return false;
} else if (w > 8) { } else if (w > 8) {
font_width = w / 16; font_width = w / 16;
font_height = h / 16; font_height = h / 16;
memset(font_bin, 0x00, w * h / 8); memset(font_bin, 0x00, w * h / 8);
for (u32 cy = 0; cy < 16; cy++) { for (u32 cy = 0; cy < 16; cy++) {
for (u32 row = 0; row < font_height; row++) { for (u32 row = 0; row < font_height; row++) {
for (u32 cx = 0; cx < 16; cx++) { for (u32 cx = 0; cx < 16; cx++) {
@ -126,7 +128,7 @@ bool SetFontFromPbm(const void* pbm, u32 pbm_size) {
font_height = h / 256; font_height = h / 256;
memcpy(font_bin, ptr, h); memcpy(font_bin, ptr, h);
} }
line_height = min(10, font_height + 2); line_height = min(10, font_height + 2);
return true; return true;
} }
@ -151,50 +153,41 @@ void ClearScreenF(bool clear_main, bool clear_alt, u32 color)
u16 GetColor(u16 *screen, int x, int y) u16 GetColor(u16 *screen, int x, int y)
{ {
int xDisplacement = x * SCREEN_HEIGHT; return screen[PIXEL_OFFSET(x, y)];
int yDisplacement = SCREEN_HEIGHT - y - 1;
return screen[xDisplacement + yDisplacement];
} }
void DrawPixel(u16 *screen, int x, int y, int color) void DrawPixel(u16 *screen, int x, int y, u32 color)
{ {
int xDisplacement = x * SCREEN_HEIGHT; screen[PIXEL_OFFSET(x, y)] = color;
int yDisplacement = SCREEN_HEIGHT - y - 1;
screen[xDisplacement + yDisplacement] = color;
} }
void DrawRectangle(u16 *screen, int x, int y, int width, int height, int color) void DrawRectangle(u16 *screen, int x, int y, u32 width, u32 height, u32 color)
{ {
for (int yy = 0; yy < height; yy++) { screen += PIXEL_OFFSET(x, y) - height;
int xDisplacement = x * SCREEN_HEIGHT; while(width--) {
int yDisplacement = (SCREEN_HEIGHT - (y + yy) - 1); for (u32 h = 0; h < height; h++)
u16* screenPos = screen + xDisplacement + yDisplacement; screen[h] = color;
for (int xx = width - 1; xx >= 0; xx--) { screen += SCREEN_HEIGHT;
*screenPos = color;
screenPos += SCREEN_HEIGHT;
}
} }
} }
void DrawBitmap(u16 *screen, int x, int y, int w, int h, const u8* bitmap) void DrawBitmap(u16 *screen, int x, int y, u32 w, u32 h, const u8* bitmap)
{ {
// on negative values: center the bitmap // on negative values: center the bitmap
if (x < 0) x = (SCREEN_WIDTH(screen) - w) >> 1; if (x < 0) x = (SCREEN_WIDTH(screen) - w) >> 1;
if (y < 0) y = (SCREEN_HEIGHT - h) >> 1; if (y < 0) y = (SCREEN_HEIGHT - h) >> 1;
// bug out on too big bitmaps / too large dimensions // bug out on too big bitmaps / too large dimensions
if ((x < 0) || (y < 0) || (w > SCREEN_WIDTH(screen)) || (h > SCREEN_HEIGHT)) if ((x < 0) || (y < 0) || (w > SCREEN_WIDTH(screen)) || (h > SCREEN_HEIGHT))
return; return;
for (int yy = 0; yy < h; yy++) { screen += PIXEL_OFFSET(x, y);
int xDisplacement = x * SCREEN_HEIGHT; while(h--) {
int yDisplacement = SCREEN_HEIGHT - (y + yy) - 1; for (u32 i = 0; i < w; i++) {
u16 *screenPos = screen + xDisplacement + yDisplacement; screen[i * SCREEN_HEIGHT] = RGB(bitmap[2], bitmap[1], bitmap[0]);
for (int xx = 0; xx < w; xx++) {
*(screenPos) = RGB(bitmap[2], bitmap[1], bitmap[0]);
bitmap += 3; bitmap += 3;
screenPos += SCREEN_HEIGHT;
} }
screen--;
} }
} }
@ -203,19 +196,19 @@ void DrawQrCode(u16 *screen, const u8* qrcode)
const u32 size_qr = qrcodegen_getSize(qrcode); const u32 size_qr = qrcodegen_getSize(qrcode);
u32 size_qr_s = size_qr; u32 size_qr_s = size_qr;
u32 size_canvas = size_qr + 8; u32 size_canvas = size_qr + 8;
// handle scaling // handle scaling
u32 scale = 1; u32 scale = 1;
for (; size_canvas * (scale+1) < SCREEN_HEIGHT; scale++); for (; size_canvas * (scale+1) < SCREEN_HEIGHT; scale++);
size_qr_s *= scale; size_qr_s *= scale;
size_canvas *= scale; size_canvas *= scale;
// clear screen, draw the canvas // clear screen, draw the canvas
u32 x_canvas = (SCREEN_WIDTH(screen) - size_canvas) / 2; u32 x_canvas = (SCREEN_WIDTH(screen) - size_canvas) / 2;
u32 y_canvas = (SCREEN_HEIGHT - size_canvas) / 2; u32 y_canvas = (SCREEN_HEIGHT - size_canvas) / 2;
ClearScreen(screen, COLOR_STD_BG); ClearScreen(screen, COLOR_STD_BG);
DrawRectangle(screen, x_canvas, y_canvas, size_canvas, size_canvas, COLOR_WHITE); DrawRectangle(screen, x_canvas, y_canvas, size_canvas, size_canvas, COLOR_WHITE);
// draw the QR code // draw the QR code
u32 x_qr = (SCREEN_WIDTH(screen) - size_qr_s) / 2; u32 x_qr = (SCREEN_WIDTH(screen) - size_qr_s) / 2;
u32 y_qr = (SCREEN_HEIGHT - size_qr_s) / 2; u32 y_qr = (SCREEN_HEIGHT - size_qr_s) / 2;
@ -231,7 +224,7 @@ void DrawQrCode(u16 *screen, const u8* qrcode)
} }
} }
void DrawCharacter(u16 *screen, int character, int x, int y, int color, int bgcolor) void DrawCharacter(u16 *screen, int character, int x, int y, u32 color, u32 bgcolor)
{ {
for (int yy = 0; yy < (int) font_height; yy++) { for (int yy = 0; yy < (int) font_height; yy++) {
int xDisplacement = x * SCREEN_HEIGHT; int xDisplacement = x * SCREEN_HEIGHT;
@ -250,17 +243,18 @@ void DrawCharacter(u16 *screen, int character, int x, int y, int color, int bgco
} }
} }
void DrawString(u16 *screen, const char *str, int x, int y, int color, int bgcolor, bool fix_utf8) void DrawString(u16 *screen, const char *str, int x, int y, u32 color, u32 bgcolor, bool fix_utf8)
{ {
size_t max_len = (((screen == TOP_SCREEN) ? SCREEN_WIDTH_TOP : SCREEN_WIDTH_BOT) - x) / font_width; size_t max_len = (((screen == TOP_SCREEN) ? SCREEN_WIDTH_TOP : SCREEN_WIDTH_BOT) - x) / font_width;
size_t len = (strlen(str) > max_len) ? max_len : strlen(str); size_t len = (strlen(str) > max_len) ? max_len : strlen(str);
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
char c = (char) (fix_utf8 && str[i] >= 0x80) ? '?' : str[i]; char c = (char) (fix_utf8 && str[i] >= 0x80) ? '?' : str[i];
DrawCharacter(screen, c, x + i * font_width, y, color, bgcolor); DrawCharacter(screen, c, x + i * font_width, y, color, bgcolor);
} }
} }
void DrawStringF(u16 *screen, int x, int y, int color, int bgcolor, const char *format, ...) void DrawStringF(u16 *screen, int x, int y, u32 color, u32 bgcolor, const char *format, ...)
{ {
char str[STRBUF_SIZE] = { 0 }; char str[STRBUF_SIZE] = { 0 };
va_list va; va_list va;
@ -272,19 +266,19 @@ void DrawStringF(u16 *screen, int x, int y, int color, int bgcolor, const char *
DrawString(screen, text, x, y, color, bgcolor, true); DrawString(screen, text, x, y, color, bgcolor, true);
} }
void DrawStringCenter(u16 *screen, int color, int bgcolor, const char *format, ...) void DrawStringCenter(u16 *screen, u32 color, u32 bgcolor, const char *format, ...)
{ {
char str[STRBUF_SIZE] = { 0 }; char str[STRBUF_SIZE] = { 0 };
va_list va; va_list va;
va_start(va, format); va_start(va, format);
vsnprintf(str, STRBUF_SIZE, format, va); vsnprintf(str, STRBUF_SIZE, format, va);
va_end(va); va_end(va);
u32 w = GetDrawStringWidth(str); u32 w = GetDrawStringWidth(str);
u32 h = GetDrawStringHeight(str); u32 h = GetDrawStringHeight(str);
int x = (w >= SCREEN_WIDTH(screen)) ? 0 : (SCREEN_WIDTH(screen) - w) >> 1; int x = (w >= SCREEN_WIDTH(screen)) ? 0 : (SCREEN_WIDTH(screen) - w) >> 1;
int y = (h >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - h) >> 1; int y = (h >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - h) >> 1;
DrawStringF(screen, x, y, color, bgcolor, "%s", str); DrawStringF(screen, x, y, color, bgcolor, "%s", str);
} }
@ -890,16 +884,16 @@ u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...) {
char inputstr[16 + 1] = { 0 }; char inputstr[16 + 1] = { 0 };
u64 ret = 0; u64 ret = 0;
va_list va; va_list va;
if (n_digits > 16) n_digits = 16; if (n_digits > 16) n_digits = 16;
snprintf(inputstr, 16 + 1, "%0*llX", (int) n_digits, start_val); snprintf(inputstr, 16 + 1, "%0*llX", (int) n_digits, start_val);
va_start(va, format); va_start(va, format);
if (ShowInputPrompt(inputstr, n_digits + 1, 0, alphabet, format, va)) { if (ShowInputPrompt(inputstr, n_digits + 1, 0, alphabet, format, va)) {
sscanf(inputstr, "%llX", &ret); sscanf(inputstr, "%llX", &ret);
} else ret = (u64) -1; } else ret = (u64) -1;
va_end(va); va_end(va);
return ret; return ret;
} }

View File

@ -52,15 +52,15 @@ u16 GetColor(u16 *screen, int x, int y);
void ClearScreen(u16 *screen, u32 color); void ClearScreen(u16 *screen, u32 color);
void ClearScreenF(bool clear_main, bool clear_alt, u32 color); void ClearScreenF(bool clear_main, bool clear_alt, u32 color);
void DrawPixel(u16 *screen, int x, int y, int color); void DrawPixel(u16 *screen, int x, int y, u32 color);
void DrawRectangle(u16 *screen, int x, int y, int width, int height, int color); void DrawRectangle(u16 *screen, int x, int y, u32 width, u32 height, u32 color);
void DrawBitmap(u16 *screen, int x, int y, int w, int h, const u8* bitmap); void DrawBitmap(u16 *screen, int x, int y, u32 w, u32 h, const u8* bitmap);
void DrawQrCode(u16 *screen, const u8* qrcode); void DrawQrCode(u16 *screen, const u8* qrcode);
void DrawCharacter(u16 *screen, int character, int x, int y, int color, int bgcolor); void DrawCharacter(u16 *screen, int character, int x, int y, u32 color, u32 bgcolor);
void DrawString(u16 *screen, const char *str, int x, int y, int color, int bgcolor, bool fix_utf8); void DrawString(u16 *screen, const char *str, int x, int y, u32 color, u32 bgcolor, bool fix_utf8);
void DrawStringF(u16 *screen, int x, int y, int color, int bgcolor, const char *format, ...); void DrawStringF(u16 *screen, int x, int y, u32 color, u32 bgcolor, const char *format, ...);
void DrawStringCenter(u16 *screen, int color, int bgcolor, const char *format, ...); void DrawStringCenter(u16 *screen, u32 color, u32 bgcolor, const char *format, ...);
u32 GetDrawStringHeight(const char* str); u32 GetDrawStringHeight(const char* str);
u32 GetDrawStringWidth(const char* str); u32 GetDrawStringWidth(const char* str);

View File

@ -2049,7 +2049,7 @@ u32 GodMode(int entrypoint) {
InitNandCrypto(true); // (entrypoint != ENTRY_B9S); InitNandCrypto(true); // (entrypoint != ENTRY_B9S);
InitExtFS(); InitExtFS();
CalibrateTouchFromFlash(); // !!! this may need some further checking CalibrateTouchFromFlash(); // !!! this may need some further checking
// custom font handling // custom font handling
if (CheckSupportFile("font.pbm")) { if (CheckSupportFile("font.pbm")) {
u8* pbm = (u8*) malloc(0x10000); // arbitrary, should be enough by far u8* pbm = (u8*) malloc(0x10000); // arbitrary, should be enough by far

View File

@ -46,9 +46,8 @@ _start:
mcr p15, 0, r0, c5, c0, 3 @ write instruction access mcr p15, 0, r0, c5, c0, 3 @ write instruction access
@ Set MPU regions and cache settings @ Set MPU regions and cache settings
ldr lr, =__mpu_regions ldr r0, =__mpu_regions
ldmia lr, {r0-r7} ldmia r0, {r0-r7}
mov lr, #0b00101000
mcr p15, 0, r0, c6, c0, 0 mcr p15, 0, r0, c6, c0, 0
mcr p15, 0, r1, c6, c1, 0 mcr p15, 0, r1, c6, c1, 0
mcr p15, 0, r2, c6, c2, 0 mcr p15, 0, r2, c6, c2, 0
@ -57,9 +56,13 @@ _start:
mcr p15, 0, r5, c6, c5, 0 mcr p15, 0, r5, c6, c5, 0
mcr p15, 0, r6, c6, c6, 0 mcr p15, 0, r6, c6, c6, 0
mcr p15, 0, r7, c6, c7, 0 mcr p15, 0, r7, c6, c7, 0
mcr p15, 0, lr, c3, c0, 0 @ Write bufferable
mcr p15, 0, lr, c2, c0, 0 @ Data cacheable mov r0, #0b10101000 @ enable write buffer for VRAM
mcr p15, 0, lr, c2, c0, 1 @ Inst cacheable mcr p15, 0, r0, c3, c0, 0 @ Write bufferable
mov r0, #0b00101000
mcr p15, 0, r0, c2, c0, 0 @ Data cacheable
mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable
@ Enable DTCM @ Enable DTCM
ldr r0, =0x3000800A ldr r0, =0x3000800A