VxKernel 0.6.0-3 : Fix dstack crash + pixel API + support assets generation

@add
<> include/vhex/display/draw/pixel :
   | add pixel drawing API
<> modules/display/draw/dpixel
   | add pixel drawing API code

@update
<> board/fxcg50/board :
   | remove old DWIDTH/DHEIGHT display API dependencies (use the new driver
   | interface instead).
<> include/vhex/display/font :
   | update the font structure information
<> include/vhex/display/shader :
   | switch x/y to unsigned int to signed int to avoid many cast in render
   | primitives
<> make/Makefile
   | support header modification detection (header dependencies)
   | support assets generation
<> modules/display/text/font
<> modules/display/text/text
   | prepare drawing algorithm (WIP)

@fix
<> kernel/drivers/screen/r61524/r61524
   | proper handle geometry of each drawing area
   | fix clear loop boundary
   | fix render loop boundary
<> modules/display/dstack
   | fix shader index
   | remove useless extern keyword
This commit is contained in:
Yann MAGNIN 2022-06-02 10:16:25 +02:00
parent 510c4f1f86
commit eb9b0078c2
15 changed files with 336 additions and 121 deletions

View File

@ -7,5 +7,5 @@ mpu=sh7305
[toolchain]
prefix=sh-elf-vhex-
cflags=-DFXCG50,-m4-nofpu,-mb,-DWIDTH=396,-DHEIGHT=224
cflags=-DFXCG50,-m4-nofpu,-mb
libs=-lgcc

View File

@ -100,17 +100,6 @@ SECTIONS
/* dynamic BSS information (move me ?) */
*(.dynbss)
/* Video RAM symbols
The video RAM contains a full pixel sized frame for the
screen. Its size is 396x224 and each pixel depth is 16its,
so (3996 * 224) * 2 = 177408
*/
_vhex_vram = ALIGN(4);
/* create the VRAM gap */
. = _vhex_vram + 177408;
} > userram
/* Vhex VBR management geometry

View File

@ -0,0 +1,24 @@
#ifndef __VHEX_DISPLAY_DRAW_PIXEL__
# define __VHEX_DISPLAY_DRAW_PIXEL__
#include <vhex/display/types.h>
#include <vhex/display/shader.h>
//---
// User-level API
//---
/* dpixel() : draw a pixel in screen */
extern did_t dpixel(int x, int y, int color);
//---
// Kernel-level API
//---
/* dpixel_render_dstack() : dstack-API compatible render */
extern void dpixel_render_dstack(struct dshader_surface *surface, uint32_t *arg);
/* dpixel_render() : drawing algorithm */
extern void dpixel_render(struct dshader_surface *surface, int x, int y, int c);
#endif /* __VHEX_DISPLAY_DRAW_PIXEL__ */

View File

@ -20,45 +20,41 @@ typedef struct font {
uint8_t prop :1;
);
/* Line height */
uint8_t line_height;
/* Storage height */
uint8_t data_height;
/* Number of Unicode blocks */
uint8_t block_count;
/* Number of total glyphs */
uint32_t glyph_count;
/* Character spacing (usually 1) */
uint8_t char_spacing;
/* glyph information */
struct {
/* Unicode point of first character in block */
uint32_t start :20;
/* Length of block */
uint32_t length :12;
} *blocks;
uint8_t height;
uint8_t line_height;
uint32_t *data;
uint32_t count;
/* Raw glyph data */
uint32_t *data;
union {
/* For monospaced fonts */
struct {
uint8_t width;
uint16_t storage_size;
} mono;
/* For proportional fonts */
struct __workaround {
uint8_t width;
uint16_t index;
uint8_t shift;
} *prop;
};
} glyph;
union {
/* For monospaced fonts */
/* unicode blocks */
struct {
struct {
/* Width of glyphs */
uint16_t width;
/* Storage size, in longwords, of each glyph */
uint16_t storage_size;
};
/* For proportional fonts */
struct {
/* Storage index to find glyphs quickly */
uint16_t *glyph_index;
/* Width of each individual glyph */
uint8_t *glyph_width;
};
};
/* Unicode point of first character in block */
uint32_t start :20;
/* Length of block */
uint32_t length :12;
} *blocks;
uint8_t block_count;
} unicode;
} VPACKED(4) font_t;

View File

@ -10,8 +10,8 @@ struct dshader_surface {
void *frag;
size_t width;
size_t height;
unsigned int x;
unsigned int y;
int x;
int y;
};
/* dshader - display shader definition */

View File

@ -1,13 +1,11 @@
#!/usr/bin/make -f
# ---
# Project: vxKernek - Vhex project kernel
# Author: yann.magnin@epitech.eu
# Author: yann.magnin@protonmail.com
#
# TODO:
# <> support header modification detection
# <> remove "target" folder on any directory
# <> installation rule
# <> uninstall rule
# <> proper clean rule
# <> support asset generation
# ---
@ -100,7 +98,8 @@ nocolor := \033[1;0m
# *3 - source file path
# *4 - build root directory path
# *5 - object file compilation rule list
# *6 - unique id (used to generate unique variable name (workaround))
# *6 - dependencies file compilation rule list
# *7 - unique id (used to generate unique variable name (workaround))
define generate-compile-file-rule
# generate the object file path
@ -110,7 +109,7 @@ define generate-compile-file-rule
# 1) ../board/path/file.c -> ../board/path/file
# 2) .._board_path_file -> board_path_file
# 3) board_path_file.o -> {build path}/board_path_file.o
tname := $(strip $6)
tname := $(strip $7)
obj-$(tname)-name := $$(basename $3)
obj-$(tname)-name := $$(subst /,_,$$(obj-$(tname)-name))
obj-$(tname)-name := $$(patsubst .._%,$4/%.o,$$(obj-$(tname)-name))
@ -121,14 +120,15 @@ $$(obj-$(tname)-name): $3
@ mkdir -p $$(dir $$@)
ifeq ($(CONFIG.VERBOSE),false)
@ printf "$(green)>$(nocolor) $(white)$$@$(nocolor)\n"
@ $1 $2 -o $$@ -c $$<
@ $1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP
else
$1 $2 -o $$@ -c $$<
$1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP
endif
# register the buildinf rule
# register the build rules and dependencies file name
$5 += $$(obj-$(tname)-name)
$6 += $$(obj-$(tname)-name).d
endef
@ -190,6 +190,7 @@ endif
# list variable, this will be used by the `main` rule
t-$1-$2-obj :=
t-$1-$2-dep :=
$$(foreach source,$$(t-$1-$2-src),$$(eval \
$$(call generate-compile-file-rule,\
$$(t-$1-$2-gcc),\
@ -197,15 +198,33 @@ $$(foreach source,$$(t-$1-$2-src),$$(eval \
$$(source),\
$$(t-$1-$2-build),\
t-$1-$2-obj,\
t-$1-$2-dep,\
$1-$2\
))\
)
# asset generation
t-$1-$2-asset := $(patsubst \
$(VXSDK_ASSETS_SRC)/%,\
$(VXSDK_ASSETS_BUILD)/$1/$2/%.o,\
$(wildcard $(VXSDK_ASSETS_SRC)/*.c) \
)
$(VXSDK_ASSETS_BUILD)/$1/$2/%.o: $(VXSDK_ASSETS_SRC)/%
ifeq ($(CONFIG.VERBOSE),true)
@ mkdir -p $$(dir $$@)
sh-elf-vhex-gcc $$(t-$1-$2-cflags) -o $$@ -c $$<
else
@ mkdir -p $$(dir $$@)
@ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n"
@ sh-elf-vhex-gcc $$(t-$1-$2-cflags) -o $$@ -c $$<
endif
# generate the "main" rule for this lib
$$(t-$1-$2-exec): $$(t-$1-$2-obj)
$$(t-$1-$2-exec): $$(t-$1-$2-obj) $$(t-$1-$2-asset)
@ mkdir -p $$(dir $$@)
@ echo "dep : $$(t-$1-$2-dep)"
@ printf "$(blue)Create the library $(red)$$@$(nocolor)\n"
ifeq ($2,dynamic)
$$(t-$1-$2-gcc) -shared $$(t-$1-$2-cflags) $$(t-$1-$2-gcc-libs) -o $$@ $$^
@ -217,6 +236,12 @@ endif
$3 += $$(t-$1-$2-exec)
# import dependencies rules
-include $$(t-$1-$2-dep)
$$(t-$1-$2-dep): ;
.PRECIOUS: $$(t-$1-$2-dep)
endef

View File

@ -17,7 +17,7 @@ VINLINE void r61524_clear_surface(struct dshader_surface *surface)
// > restrict / non-restrict
uint32_t * restrict xram = surface->draw;
uint32_t * restrict yram = surface->frag;
for (int i = 0; i < 2048; ++i) {
for (int i = 0; i < 1980; ++i) {
xram[i] = 0x00010001;
yram[i] = 0x00000000;
}
@ -60,6 +60,7 @@ int r61524_frame_start(struct dshader_surface *surface)
int r61524_frame_frag_next(struct dshader_surface *surface)
{
//TODO: perf if culling at the end (220)
surface->y += 10;
if (surface->y >= 224) {
surface->y -= 10;
@ -71,6 +72,8 @@ int r61524_frame_frag_next(struct dshader_surface *surface)
int r61524_frame_frag_send(struct dshader_surface *surface)
{
//static int counter = 0;
//TODO: assembly
//TODO: check cache behaviour:
// > full xram then yram
@ -80,7 +83,7 @@ int r61524_frame_frag_send(struct dshader_surface *surface)
uint16_t pixel;
uint16_t * restrict xram = surface->draw;
uint16_t * restrict yram = surface->frag;
for (int i = 0; i < 4096; ++i) {
for (int i = 0; i < 3960; ++i) {
pixel = xram[i];
if (pixel & 0x0001) {
r61524_write(yram[i]);

View File

@ -52,6 +52,5 @@ void vhex_kernel_exch_panic(void)
dtext(6, 121, C_BLACK, "calculator.");
dupdate();
#endif
while (1) { __asm__ volatile ("sleep"); }
}

View File

@ -1,3 +1,4 @@
#if 0
#include <vhex/display.h>
#include <vhex/defs/utils.h>
#include <vhex/defs/types.h>
@ -48,4 +49,4 @@ void dvline(int y1, int y2, int x, int color)
while(height-- > 0) *v = color, v += 396;
}
#endif

View File

@ -1,3 +1,4 @@
#if 0
#include <vhex/display.h>
#include <vhex/defs/utils.h>
@ -59,3 +60,4 @@ void dline(int x1, int y1, int x2, int y2, int color)
dpixel(x2, y2, color);
}
#endif

View File

@ -2,19 +2,56 @@
#include <vhex/defs/attributes.h>
#include <vhex/defs/types.h>
//---
// Kernel-level API
//---
VWEAK void dpixel(int x, int y, int color)
/* dpixel_render() : drawing algorithm */
void dpixel_render(struct dshader_surface *surface, int x, int y, int color)
{
extern uint16_t vhex_vram[];
if (color == C_NONE)
return;
if ((unsigned int)x < 396 && (unsigned int)y < 224) {
if (color == C_INVERT) {
vhex_vram[(y * 396) + x] ^= 0xffff;
return;
}
vhex_vram[(y * 396) + x] = color;
/* check point culling */
if (y < surface->y
|| x < surface->x
|| y >= (int)(surface->y + surface->height)
|| x >= (int)(surface->x + surface->width)) {
return;
}
/* calculate the draw index */
int real_y = (y - surface->y) * surface->width;
int real_x = (x - surface->x);
int draw_idx = real_y + real_x;
/* handle special color */
//uint16_t *draw = surface->draw;
uint16_t *frag = surface->frag;
if (color == C_INVERT)
color = frag[draw_idx] ^ 0xffff;
/* set the pixel */
frag[draw_idx] = color;
}
/* dpixel_render_dstack() : dstack-API compatible render */
void dpixel_render_dstack(struct dshader_surface *surface, uint32_t *arg)
{
dpixel_render(surface, arg[0], arg[1], arg[2]);
}
//---
// User-level API
//---
/* dpixel() : draw a pixel in screen */
did_t dpixel(int x, int y, int color)
{
return dstack_add_action(
&DSTACK_CALL(&dpixel_render_dstack, x, y, color),
NULL,
NULL
);
}

View File

@ -1,3 +1,4 @@
#if 0
#include <vhex/display.h>
#include <vhex/defs/utils.h>
#include <vhex/defs/types.h>
@ -51,3 +52,4 @@ void drect(int x1, int y1, int x2, int y2, int color)
base += 396;
}
}
#endif

View File

@ -97,6 +97,7 @@ static did_t dstack_action_alloc(
}
action = &dstack_info.pool.action[dstack_info.pool.idx];
memcpy(&action->call, call, sizeof(dstack_call_t));
action->shader.idx = -1;
if (shader != NULL) {
for (i = 0; shader[i].routine != NULL; ++i) {
if (i >= action->shader.number) {
@ -113,8 +114,8 @@ static did_t dstack_action_alloc(
);
action->quit = quit;
}
action->shader.idx = i;
}
action->shader.idx = i;
return dstack_info.pool.idx;
}
@ -143,7 +144,7 @@ void dstack_render(void)
do {
for (int i = 0; i <= dstack_info.pool.idx; ++i) {
action[i].call.routine(&surface, action[i].call.args);
for (int j = 0; j < action[i].shader.idx; j++) {
for (int j = 0; j <= action[i].shader.idx; j++) {
action[i].shader.table[j].routine(
&surface,
action[i].call.args,
@ -164,13 +165,13 @@ void dstack_render(void)
/* dstack_display_width() : return the display width */
extern size_t dstack_display_width(void)
size_t dstack_display_width(void)
{
return dstack_info.driver.display_width;
}
/* dstack_display_height() : return the display height */
extern size_t dstack_display_height(void)
size_t dstack_display_height(void)
{
return dstack_info.driver.display_height;
}

View File

@ -45,6 +45,7 @@ static uint32_t dfont_utf8_next(uint8_t const **str_pointer)
return 0x20;
}
#if 0
/* dfont_glyph_index(): Obtain the glyph index of a Unicode code point */
int dfont_glyph_index(font_t const *f, uint32_t code_point)
{
@ -61,7 +62,152 @@ int dfont_glyph_index(font_t const *f, uint32_t code_point)
return -1;
}
#endif
/* dfont_glyph_index(): Obtain the glyph index of a Unicode code point */
//TODO: suport unicode block
static int dfont_glyph_index(font_t const *f, uint32_t code_point)
{
code_point -= ' ';
if ((int)code_point < 0 || code_point >= f->glyph.count)
return (-1);
return code_point;
}
/* dfont_char_render() : */
static void dfont_char_render(
struct dshader_surface *surface,
int glyph_idx,
int x,
int y
) {
int glyph_shift;
int glyph_width;
int glyph_size;
// int surfa_idx;
// int surfa_shift;
font_t *font;
int counter;
int sx;
(void)surface;
/* generate font index / shift information */
font = dfont_get();
if (font->shape.prop == 1) {
glyph_width = font->glyph.prop[glyph_idx].width;
glyph_shift = font->glyph.prop[glyph_idx].shift;
glyph_idx = font->glyph.prop[glyph_idx].index;
glyph_size = glyph_width * font->glyph.height;
} else {
glyph_width = font->glyph.mono.width;
glyph_size = font->glyph.mono.storage_size;
glyph_shift = glyph_size * glyph_idx;
glyph_idx = glyph_shift >> 8;
glyph_shift = glyph_shift & 0xff;
}
/* drawing algo */
//TODO: cache surface data (limit read/write)
sx = x;
counter = 0;
glyph_shift = 0x80000000 >> glyph_shift;
for (int i = 0; i < glyph_size; ++i)
{
#if 0
if (x >= surface->x
&& x <= surfa_mx
&& y >= surface->y
&& y <= surfa_my) {
tmp0 = (y - surface->y) * 396;
tmp1 = (x - surface->x);
surfa_idx = (tmp0 + tmp1) >> 2;
surfa_shift = (tmp0 + tmp1) & 0xff;
if (font->glyph.data[glyph_idx] & glyph_shift) {
surface->frag[surfa_idx] = (uint16_t)arg[4];
} else {
surface->frag[surfa_idx] = (uint16_t)arg[5];
}
}
#endif
/* update font bitmap index / shift */
glyph_shift >>= 1;
if (glyph_shift == 0x00000000) {
glyph_shift = 0x80000000;
glyph_idx += 1;
}
/* update bitmap position */
x += 1;
counter += 1;
if (counter >= glyph_width) {
counter = 0;
x = sx;
y += 1;
}
}
}
//---
// Kernel API
//---
/* dfont_render() : draw caracter in surface */
void dfont_text_render(struct dshader_surface *surface, uint32_t *arg)
{
int x;
int y;
int mx;
int my;
/* check culling */
x = arg[0];
y = arg[1];
mx = arg[2];
my = arg[3];
if (my < surface->y
|| mx < surface->x
|| y > (int)(surface->y + surface->height)
|| x > (int)(surface->x + surface->width)) {
return;
}
uint8_t const *str = (void*)(uintptr_t)arg[6];
int nb_char = arg[7];
int counter = -1;
uint32_t code_point;
font_t *font = dfont_get();
int glyph_idx;
int glyph_width;
/* draw algo (update me) */
while (++counter < nb_char)
{
/* get glyph geometry information */
code_point = dfont_utf8_next(&str);
glyph_idx = dfont_glyph_index(font, code_point);
glyph_width = font->glyph.mono.width;
if (font->shape.prop == 1)
glyph_width = font->glyph.prop[glyph_idx].width;
/* check char culling */
if (x >= surface->x
&& y >= surface->y
&& y < (int)(surface->y + surface->height)
&& x < (int)(surface->x + surface->width)) {
dfont_char_render(surface, glyph_idx, x, y);
}
/* line discipline */
x += glyph_width + font->char_spacing;
if (code_point == '\n') {
y += font->glyph.height;
x = arg[0];
}
}
}
//---
// Public API
@ -91,8 +237,8 @@ int dfont_text_geometry(
size_t mx = 0;
size_t x = 0;
size_t y = 0;
int glyphidx;
int limit;
int glyph;
/* handle special behaviour */
if (font == NULL)
@ -107,18 +253,18 @@ int dfont_text_geometry(
if (code_point == 0 || (limit > 0 && str0 - str1 >= limit))
break;
char_width = font->width;
char_width = font->glyph.mono.width;
if (font->shape.prop == 1) {
glyph = dfont_glyph_index(font, code_point);
if (glyph < 0)
glyphidx = dfont_glyph_index(font, code_point);
if (glyphidx < 0)
return (-1);
char_width = font->glyph_width[glyph];
char_width = font->glyph.prop[glyphidx].width;
}
/* line discipline */
x += char_width;
x += char_width + font->char_spacing;
if (code_point == '\n') {
y += font->data_height;
y += font->glyph.height;
x = 0;
}
if (x > mx) mx = x;
@ -127,7 +273,7 @@ int dfont_text_geometry(
}
/* set geometry information */
if (w != NULL) *w = mx;
if (w != NULL) *w = mx - font->char_spacing;
if (h != NULL) *h = y;
if (size != NULL) *size = length;
return (0);

View File

@ -9,27 +9,21 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct dtext_geometry {
struct {
char *raw;
size_t raw_size;
int size;
} text;
int x;
int y;
};
static struct {
struct {
struct dtext_geometry *geometry;
struct {
char *raw;
size_t size;
} *text;
int number;
int idx;
} pool;
} dtext_info = {
.pool = {
.geometry = NULL,
.text = NULL,
.number = 0,
.idx = 0
}
@ -43,22 +37,21 @@ VCONSTRUCTOR static void __dtext_constructor(void)
{
dtext_info.pool.number = 16;
dtext_info.pool.idx = -1;
dtext_info.pool.geometry = calloc(
dtext_info.pool.text = calloc(
dtext_info.pool.number,
sizeof(struct dtext_geometry)
sizeof (*dtext_info.pool.text)
);
for (int i = 0; i < dtext_info.pool.number; ++i) {
dtext_info.pool.geometry[i].text.raw = malloc(32);
dtext_info.pool.geometry[i].text.raw_size = 32;
dtext_info.pool.geometry[i].text.size = 0;
dtext_info.pool.text[i].raw = malloc(32);
dtext_info.pool.text[i].size = 32;
}
}
VDESTRUCTOR void __dtext_destructor(void)
{
for (int i = 0; i < dtext_info.pool.number; ++i)
free(dtext_info.pool.geometry[i].text.raw);
free(dtext_info.pool.geometry);
free(dtext_info.pool.text[i].raw);
free(dtext_info.pool.text);
}
static void __dtext_quit(void)
@ -67,29 +60,22 @@ static void __dtext_quit(void)
}
//---
// Drawing functions
// Private functions
//---
#if 0
static void dtext_opt_draw(struct dshader_surface *surface, uint32_t *arg)
static char *dtext_info_register(char const * const str)
{
uint32_t buff[5];
char *str;
buff[0] = (uintptr_t)dfont_get();
buff[1] = arg[0]; // x
buff[2] = arg[1]; // y
buff[3] = arg[2]; // fg
buff[4] = arg[3]; // bg
str = (void*)(uintptr_t)arg[4];
for (int i = 0; i < (int)arg[5]; ++i) {
buff[5] = str[i];
dfont_render(surface, buff);
dtext_info.pool.idx += 1;
if (dtext_info.pool.idx >= dtext_info.pool.number) {
dtext_info.pool.number += dtext_info.pool.number;
dtext_info.pool.text = realloc(
dtext_info.pool.text,
dtext_info.pool.number
);
}
strcpy(dtext_info.pool.text[dtext_info.pool.idx].raw, str);
return dtext_info.pool.text[dtext_info.pool.idx].raw;
}
#endif
//---
// Public API
@ -104,6 +90,7 @@ did_t dtext_opt(
) {
size_t width;
size_t height;
void *real_str;
/* get text geometry and handle obvious culling */
if (dfont_text_geometry(NULL, str, &size, &width, &height) != 0)
@ -121,13 +108,16 @@ did_t dtext_opt(
if (valign == DTEXT_CENTER) y = y - (height / 2);
if (valign == DTEXT_BOTTOM) y = y - (height);
/* register the string */
real_str = dtext_info_register(str);
/* request draw call */
return dstack_add_action(
&DSTACK_CALL(
&dfont_text_render,
x, y,
x, y, x + width, y + height,
fg, bg,
(uint32_t)(uintptr_t)str, size
(uint32_t)(uintptr_t)real_str, size,
),
(dtext_info.pool.idx == 0) ? (void*)&__dtext_quit : NULL,
NULL