VxKernel 0.6.0-11 : Update text/font architecture

@update
<> board/fxcg50.ld
  | add on-chip IL memory information
  | add ".vhex.ilram" section
<> board/initialize
  | relocalize IL memory code
<> include/vhex/display && src/modules/display
  | update color information
  | use only "dsurface_t" type
  | isolate the dsurface_t types
  | isolate interface structure information
  | isolate shader structure information
  | remove dstack configuration structure
  | remove draw/frag information and use only one VRAM information
<> include/vhex/display/font
  | isolate structure-oriented information in <vhex/display/font/types.h>
  | isolate render API information in <vhex/display/font/render.h>
  | isolate information API in <vhex/display/font/information.h>
<> include/vhex/display/text
  | isolate render API information in <vhex/display/text/render.h>
  | isolate information API in <vhex/display/text/information.h>
<> make/Makefile
  | enable DSP instructions
<> src/drivers/screen/r61524
  | try to use the DSP instruction for the sending loop, but seems to be a bit
    too slow instead of the "full-CPU" version generated by GCC
This commit is contained in:
Yann MAGNIN 2022-06-20 16:29:28 +02:00
parent 1ebab24090
commit b2fc0db544
29 changed files with 483 additions and 418 deletions

View File

@ -13,6 +13,8 @@ MEMORY
{
/* virtual memory, read-write segment */
userram (WX) : o = 0x00000000, l = 1M
/* On-chip IL memory */
ilram (rwx): o = 0xe5200000, l = 4k
}
SECTIONS
@ -153,6 +155,21 @@ SECTIONS
} > userram
/* On-chip memory sections: IL and Y (X is reserved) */
. = ORIGIN(ilram);
.ilram ALIGN(4) : ALIGN(4) {
_lilram = LOADADDR(.ilram);
_rilram = . ;
*(.vhex.ilram)
. = ALIGN(16);
} > ilram AT> userram
_silram = SIZEOF(.ilram);
/* unwanted section */
/DISCARD/ : {
*(.rela.debug*)

View File

@ -16,6 +16,9 @@
extern void (*bctors)(void), (*ectors)(void);
extern void (*bdtors)(void), (*edtors)(void);
/* on-chip RAM information */
extern uint32_t lilram, silram, rilram; /* IL memory section */
/* User-provided main() function */
extern int main(void);
@ -30,6 +33,22 @@ static void callarray(void (**f)(void), void (**l)(void))
while(f < l) (*(*f++))();
}
/* regcpy(): Copy a memory region using symbol information
@l Source pointer (load address)
@s Size of area (should be a multiple of 16)
@r Destination pointer (relocation address) */
static void regcpy(uint32_t * __restrict l, int32_t s, uint32_t * __restrict r)
{
while(s > 0)
{
*r++ = *l++;
*r++ = *l++;
*r++ = *l++;
*r++ = *l++;
s -= 16;
}
}
/* initialize() : Where it all starts
We are currently in a RAM location at a non-constant address due to the
@ -93,6 +112,10 @@ void initialize(void)
tell us if we are running in an emulator or on a real device. */
hw_detect();
/* move special on-chip RAM section */
regcpy(&lilram, (uintptr_t)&silram, &rilram);
/* Install Vhex, switch VBR, initialize drivers and modules */
kinit();

View File

@ -43,6 +43,6 @@ VINLINE size_t dheight(void)
//---
/* dclear_render() : internal pipeline drawing */
extern void dclear_render(struct dshader_surface *surface, uint32_t color);
extern void dclear_render(dsurface_t *surface, uint32_t color);
#endif /*__VHEX_DISPLAY__*/

View File

@ -4,16 +4,16 @@
//FIXME: this is plateform-specific :/
enum {
C_WHITE = 0xffff,
C_LIGHT = 0xad55,
C_DARK = 0x528a,
C_BLACK = 0x0000,
C_WHITE = 0xffff,
C_LIGHT = 0xad55,
C_DARK = 0x528a,
C_BLACK = 0x0000,
C_RED = 0xf800,
C_GREEN = 0x07e0,
C_BLUE = 0x001f,
C_RED = 0xf800,
C_GREEN = 0x07e0,
C_BLUE = 0x001f,
C_NONE = -1,
C_NONE = -1,
C_INVERT = -2,
};

View File

@ -1,91 +1,2 @@
#ifndef __VHEX_DISPLAY_FONT__
# define __VHEX_DISPLAY_FONT__
#include <vhex/defs/types.h>
#include <vhex/defs/attributes.h>
#include <vhex/display/shader.h>
/* font_t: Font data encoded for dfont*() functions */
typedef struct font {
/* Font name (NUL-terminated), NULL if no title */
char const *name;
/* Font shape flags */
byte_union(shape,
uint8_t bold :1;
uint8_t italic :1;
uint8_t serif :1;
uint8_t mono :1;
uint8_t :3;
uint8_t prop :1;
);
/* Character spacing (usually 1) */
uint8_t char_spacing;
/* glyph information */
struct {
uint8_t height;
uint8_t line_height;
uint32_t *data;
uint32_t count;
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;
/* unicode blocks */
struct {
struct {
/* 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;
/* dfont_get() : get the current font */
extern font_t *dfont_get(void);
/* dfont_text_geometry() : get the char geometry */
extern int dfont_text_geometry(
font_t *font,
char const * const str_char,
int *size,
size_t *w,
size_t *h
);
//---
// Kernel-level API
//---
/* dfont_char_render() : character render */
extern void dfont_char_render(
struct dshader_surface *surface,
int glyph_idx,
uint32_t *arg
);
/* dfont_glyph_index(): Obtain the glyph index of a Unicode code point */
extern int dfont_glyph_index(font_t const *f, uint32_t code_point);
/* dfont_render() : draw caracter in surface */
extern void dfont_text_render(struct dshader_surface *surface, uint32_t *arg);
#endif /* __VHEX_DISPLAY_FONT__ */
#include <vhex/display/font/information.h>
#include <vhex/display/font/render.h>

View File

@ -0,0 +1,24 @@
#ifndef __VHEX_DISPLAY_FONT_INFORMATION__
# define __VHEX_DISPLAY_FONT_INFORMATION__
#include <vhex/display/font/types.h>
/* dfont_get() : get the current font */
extern font_t *dfont_get(void);
/* dfont_glyph_index(): Obtain the glyph index of a Unicode code point */
extern int dfont_glyph_index(font_t const *f, uint32_t code_point);
/* dfont_utf8_next(): Read the next UTF-8 code point of a string */
extern uint32_t dfont_utf8_next(uint8_t const **str_pointer);
/* dfont_text_geometry() : get the rendered text geometry with a given font */
extern int dfont_text_geometry(
font_t *font,
char const * const str_char,
int *size,
size_t *w,
size_t *h
);
#endif /* __VHEX_DISPLAY_FONT_INFORMATION__ */

View File

@ -0,0 +1,23 @@
#ifndef __VHEX_DISPLAY_FONT_RENDER__
# define __VHEX_DISPLAY_FONT_RENDER__
#include <vhex/display/types.h>
//---
// User-level API
//---
/* dfont_cjar() : display one char */
extern void dfont_char(uint32_t n, int x, int y, int fg, int bg);
//---
// kernel-level API
//---
extern void dfont_char_render(
dsurface_t *surface,
int glyph_idx,
uint32_t *arg
);
#endif /* __VHEX_DISPLAY_FONT_RENDER__ */

View File

@ -0,0 +1,60 @@
#ifndef __VHEX_DISPLAY_FONT_TYPES__
# define __VHEX_DISPLAY_FONT_TYPES__
#include <vhex/defs/types.h>
#include <vhex/defs/attributes.h>
/* font_t: Font data encoded for dfont*() functions */
typedef struct font {
/* Font name (NUL-terminated), NULL if no title */
char const *name;
/* Font shape flags */
byte_union(shape,
uint8_t bold :1;
uint8_t italic :1;
uint8_t serif :1;
uint8_t mono :1;
uint8_t :3;
uint8_t prop :1;
);
/* Character spacing (usually 1) */
uint8_t char_spacing;
/* glyph information */
struct {
uint8_t height;
uint8_t line_height;
uint32_t *data;
uint32_t count;
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;
/* unicode blocks */
struct {
struct {
/* 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;
#endif /* __VHEX_DISPLAY_FONT_TYPES__ */

View File

@ -0,0 +1,16 @@
#ifndef __VHEX_DISPLAY_INTERFACE__
# define __VHEX_DISPLAY_INTERFACE__
#include <vhex/display/types.h>
/* dstack_drv_interface - driver interface */
struct dstack_drv_interface {
int (*frame_start)(dsurface_t *);
int (*frame_frag_next)(dsurface_t *);
int (*frame_frag_send)(dsurface_t *);
int (*frame_end)(dsurface_t *);
size_t display_width;
size_t display_height;
};
#endif /* __VHEX_DISPLAY_INTERFACE__ */

View File

@ -1,33 +1,18 @@
#ifndef __VHEX_DISPLAY_SHADER__
# define __VHEX_DISPLAY_SHADER__
#include <vhex/defs/attributes.h>
#include <vhex/defs/types.h>
/* dshader_surface - Describe the surface */
struct dshader_surface {
void *draw;
void *frag;
size_t width;
size_t height;
int x1;
int y1;
int x2;
int y2;
};
typedef struct dshader_surface dsurface_t;
#include <vhex/display/types.h>
/* dshader - display shader definition */
struct dshader_call {
int (*routine)(
struct dshader_surface *surface,
dsurface_t *surface,
uint32_t *draw_args,
uint32_t *shader_args
);
uint32_t args[8];
};
typedef struct dshader_call dshader_call_t;
typedef struct dshader_call dshader_t;
/* DSHADER_LIST - helper to create a list of shader "on-the-fly" */
#define DSHADER_LIST(shader_list) (dshader_call_t*)&{ shader_list }

View File

@ -4,12 +4,10 @@
#include <vhex/display/shader.h>
#include <vhex/display/types.h>
/* dstack_call - dstack indirect call (same as dshader) */
struct dstack_call {
void (*routine)(
struct dshader_surface *surface,
uint32_t *draw_args
);
void (*routine)(dsurface_t *surface, uint32_t *draw_args);
uint32_t args[12];
};
typedef struct dstack_call dstack_call_t;
@ -32,41 +30,12 @@ struct dstack_action {
}
/* dstack_config - dstack configuration structure */
struct dstack_config {
int default_icall_pool_slot;
int default_icall_args_nb;
int default_shader_per_action;
};
#ifndef DSTACK_DEFAULT_ICALL_SLOT
# define DSTACK_DEFAULT_ICALL_SLOT 32
#endif
#ifndef DSTACK_DEFAULT_ICALL_ARGS
# define DSTACK_DEFAULT_ICALL_ARGS 12
#endif
#ifndef DSTACK_DEFAULT_SHADER_PER_ACTION
# define DSTACK_DEFAULT_SHADER_PER_ACTION 4
#endif
/* dstack_drv_interface - driver interface */
struct dstack_drv_interface {
int (*frame_start)(struct dshader_surface *);
int (*frame_frag_next)(struct dshader_surface *);
int (*frame_frag_send)(struct dshader_surface *);
int (*frame_end)(struct dshader_surface *);
size_t display_width;
size_t display_height;
};
//---
// Display stack API
//---
/* dstack_init() : Initialise the draw stack (should not be involved) */
extern int dstack_init(struct dstack_config *config);
extern int dstack_init(void);
/* dstack_add_action() : add a new action in the draw stack */
extern did_t dstack_add_action(

View File

@ -1,46 +1,2 @@
#ifndef __VHEX_DISPLAY_TEXT__
# define __VHEX_DISPLAY_TEXT__
#include <vhex/defs/types.h>
#include <vhex/display/types.h>
/* Alignment settings for dtext_opt() and dprint_opt(). Combining a vertical
and a horizontal alignment option specifies where a given point (x,y) should
be relative to the rendered string. */
enum {
/* Horizontal settings: default in dtext() is DTEXT_LEFT */
DTEXT_LEFT = 0,
DTEXT_CENTER = 1,
DTEXT_RIGHT = 2,
/* Vertical settings: default in dtext() is DTEXT_TOP */
DTEXT_TOP = 0,
DTEXT_MIDDLE = 1,
DTEXT_BOTTOM = 2,
};
/* dtext_opt(): Display a string of text */
extern did_t dtext_opt(
int x, int y,
int fg, int bg,
int halign, int valign,
char const * const str, int size
);
/* dtext() : display raw text */
extern did_t dtext(int x, int y, int fg, char const * const text);
/* dprint_opt(): Display a formated string */
extern did_t dprint_opt(
int x, int y,
int fg, int bg,
int halign, int valign,
char const * const str, ...
);
/* dprint() : display formated text */
extern did_t dprint(int x, int y, int fg, char const * const text, ...);
/* dnsize(): Get the width and height of rendered text for the n first char */
extern int dtext_geometry(char const * const str, int *n, size_t *w, size_t *h);
#endif /* __VHEX_DISPLAY_TEXT__ */
#include <vhex/display/text/information.h>
#include <vhex/display/text/render.h>

View File

@ -0,0 +1,9 @@
#ifndef __VHEX_DISPLAY_TEXT_INFORMATION__
# define __VHEX_DISPLAY_TEXT_INFORMATION__
#include <vhex/defs/types.h>
/* dtext_geometry() : get the rendered text geometry with the current font */
extern int dtext_geometry(char const * const str, int *n, size_t *w, size_t *h);
#endif /* __VHEX_DISPLAY_TEXT_INFORMATION__ */

View File

@ -0,0 +1,43 @@
#ifndef __VHEX_DISPLAY_TEXT_RENDER__
# define __VHEX_DISPLAY_TEXT_RENDER__
#include <vhex/defs/types.h>
#include <vhex/display/types.h>
/* Alignment settings for dtext_opt() and dprint_opt(). Combining a vertical
and a horizontal alignment option specifies where a given point (x,y) should
be relative to the rendered string. */
enum {
/* Horizontal settings: default in dtext() is DTEXT_LEFT */
DTEXT_LEFT = 0,
DTEXT_CENTER = 1,
DTEXT_RIGHT = 2,
/* Vertical settings: default in dtext() is DTEXT_TOP */
DTEXT_TOP = 0,
DTEXT_MIDDLE = 1,
DTEXT_BOTTOM = 2,
};
/* dtext_opt(): Display a string of text */
extern did_t dtext_opt(
int x, int y,
int fg, int bg,
int halign, int valign,
char const * const str, int size
);
/* dtext() : display raw text */
extern did_t dtext(int x, int y, int fg, char const * const text);
/* dprint_opt(): Display a formated string */
extern did_t dprint_opt(
int x, int y,
int fg, int bg,
int halign, int valign,
char const * const str, ...
);
/* dprint() : display formated text */
extern did_t dprint(int x, int y, int fg, char const * const text, ...);
#endif /* __VHEX_DISPLAY_TEXT_RENDER__ */

View File

@ -1,7 +1,21 @@
#ifndef __VHEX_DISPLAY_TYPES__
# define __VHEX_DISPLAY_TYPES__
#include <vhex/defs/types.h>
/* draw ID */
typedef int did_t;
/* dsurface - Describe the surface */
struct dsurface {
void *vram;
size_t width;
size_t height;
int x1;
int y1;
int x2;
int y2;
};
typedef struct dsurface dsurface_t;
#endif /* __VHEX_DISPLAY_TYPES__ */

View File

@ -156,6 +156,7 @@ t-$1-$2-gcc := $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc
t-$1-$2-ldflags := $$(CONFIG.$1.TOOLCHAIN.LDFLAGS)
t-$1-$2-cflags := $$(CONFIG.$1.TOOLCHAIN.CFLAGS)
t-$1-$2-cflags += -fpic -ffreestanding -nostdlib -fstrict-volatile-bitfields -O1
t-$1-$2-cflags += -Wa,--dsp
# generate compiler information (used to find some library like libgcc.a)
t-$1-$2-gcc-base := $$(shell $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc --print-search-dirs | grep install | sed 's/install: //')

View File

@ -3,11 +3,42 @@
.global _r61524_frame_frag_send
.align 4
.balign 4
! r61524_frame_frag_send() : send fragment in screen
_r61524_frame_frag_send:
! prepare loop information
mov #0xb4, r3 ! EX (1)
mov.l @(8, r4), r0 ! LS
shll8 r3 ! EX (2)
mov.l @(0, r4), r2 ! LS
shll16 r3 ! EX (3)
mov.w long_frag, r1 ! LS
cmp/eq #4, r0 ! EX (4)
bf 1f ! BR (?)
mov.w short_frag, r1 ! LS
nop ! MT
! prepare loop
1: ldrs 2f
ldre 3f
nop
ldrc r1
2: mov.w @r2+, r0
3: mov.w r0, @r3
rts
nop
long_frag:
.word 3960
short_frag:
.word 1584
#endif
#if 0
! check number of word to be send
mov.l @(20, r4), r0 ! LS
cmp/eq #220, r0 ! EX (1)

View File

@ -1,25 +1,14 @@
#include <vhex/defs/types.h>
#include <vhex/driver.h>
#include <vhex/driver/screen/r61524.h>
#include <vhex/display/stack.h>
#include <vhex/display/interface.h>
//---
// R61524 driver API
//---
/* r61524_clear_surface() - optimal way to clear the draw and render surface */
VINLINE void r61524_clear_surface(struct dshader_surface *surface)
{
uint32_t *xram = surface->draw;
int size = (surface->y1 == 220) ? 792 : 1980;
for (int i = 0; i < size; ++i) {
xram[i] = 0x00010001;
}
}
/* r61524_frame_start() - prepar the screen and reset surfaces */
int r61524_frame_start(struct dshader_surface *surface)
int r61524_frame_start(dsurface_t *surface)
{
/* Set the windows size */
r61524_select(horizontal_ram_start);
@ -41,21 +30,17 @@ int r61524_frame_start(struct dshader_surface *surface)
r61524_select(write_data);
/* initialize surface information */
surface->draw = (void*)0xe5007000;
surface->frag = (void*)0xe5017000;
surface->vram = (void*)0xe5017000;
surface->width = 396;
surface->height = 10;
surface->x1 = 0;
surface->y1 = 0;
surface->x2 = 395;
surface->y2 = 9;
/* reset the two surfaces */
r61524_clear_surface(surface);
return (0);
}
int r61524_frame_frag_next(struct dshader_surface *surface)
int r61524_frame_frag_next(dsurface_t *surface)
{
surface->y1 += 10;
if (surface->y1 >= 224) {
@ -69,9 +54,9 @@ int r61524_frame_frag_next(struct dshader_surface *surface)
return (0);
}
VWEAK int r61524_frame_frag_send(struct dshader_surface *surface)
VWEAK int r61524_frame_frag_send(dsurface_t *surface)
{
uint16_t * restrict yram = surface->frag;
uint16_t * restrict yram = surface->vram;
int size = (surface->y1 == 220) ? 1584 : 3960;
for (int i = 0; i < size; ++i) {
@ -80,7 +65,7 @@ VWEAK int r61524_frame_frag_send(struct dshader_surface *surface)
return (0);
}
int r61524_frame_end(struct dshader_surface *surface)
int r61524_frame_end(dsurface_t *surface)
{
(void)surface;
return (0);

View File

@ -7,12 +7,12 @@
//---
/* dclear_draw() : real drawing algorithm */
void dclear_render(struct dshader_surface *surface, uint32_t color)
void dclear_render(dsurface_t *surface, uint32_t color)
{
uint32_t *vram;
int size = (surface->y1 == 220) ? 792 : 1980;
vram = surface->frag;
vram = surface->vram;
for (int i = 0; i < size; ++i)
vram[i] = color;
}
@ -22,7 +22,7 @@ void dclear_render(struct dshader_surface *surface, uint32_t color)
//---
/* dclear_dstack() : dstack rwrapper primitive */
void dclear_dstack(struct dshader_surface *surface, uint32_t *arg)
void dclear_dstack(dsurface_t *surface, uint32_t *arg)
{
dclear_render(surface, arg[0]);
}

View File

@ -6,12 +6,7 @@
/* __display_init() : initialize the display */
static void __display_init(void)
{
struct dstack_config conf = {
.default_icall_pool_slot = DSTACK_DEFAULT_ICALL_SLOT,
.default_icall_args_nb = DSTACK_DEFAULT_ICALL_ARGS,
.default_shader_per_action = DSTACK_DEFAULT_SHADER_PER_ACTION
};
dstack_init(&conf);
dstack_init();
}
/* __display_quit() : uninit the display */

View File

@ -76,7 +76,7 @@ void dhline_render(dsurface_t *surface, int y, int x1, int x2, int color)
/* Use longwords to do the copy, but first paint the endpoints to heed
for odd x1 and x2. Checking the parity may be a waste of time. */
uint16_t *vram = surface->frag;
uint16_t *vram = surface->vram;
if (color != C_INVERT) {
vram[offset + x1] = color;
vram[offset + x2] = color;
@ -117,7 +117,7 @@ void dvline_render(dsurface_t *surface, int x, int y1, int y2, int color)
y1 -= surface->y1;
y2 -= surface->y1;
uint16_t *vram = surface->frag;
uint16_t *vram = surface->vram;
uint16_t *v = &vram[(surface->width * y1) + x];
int height = y2 - y1;

View File

@ -26,17 +26,20 @@ void dpixel_render(dsurface_t *surface, int x, int y, int color)
int draw_idx = real_y + real_x;
/* handle special color */
//uint16_t *draw = surface->draw;
uint16_t *frag = surface->frag;
uint16_t *vram = surface->vram;
if (color == C_INVERT)
color = frag[draw_idx] ^ 0xffff;
color = vram[draw_idx] ^ 0xffff;
/* set the pixel */
frag[draw_idx] = color;
vram[draw_idx] = color;
}
//---
// Dstack-level API
//---
/* dpixel_render_dstack() : dstack-API compatible render */
void dpixel_dstack(struct dshader_surface *surface, uint32_t *arg)
void dpixel_dstack(dsurface_t *surface, uint32_t *arg)
{
dpixel_render(surface, arg[0], arg[1], arg[2]);
}

View File

@ -1,5 +1,6 @@
#include <vhex/display/stack.h>
#include <vhex/display/shader.h>
#include <vhex/display/interface.h>
#include <vhex/driver.h>
#include <stdlib.h>
@ -33,21 +34,21 @@ static struct {
//---
/* dstack_init() : Initialise the draw stack (should not be involved) */
int dstack_init(struct dstack_config *config)
int dstack_init(void)
{
dstack_info.pool.action = calloc(
config->default_icall_pool_slot,
16,
sizeof(struct dstack_action)
);
dstack_info.pool.idx = -1;
dstack_info.pool.slots = config->default_icall_pool_slot;
dstack_info.pool.slots = 16;
for (int i = 0; i < dstack_info.pool.slots; ++i) {
dstack_info.pool.action[i].shader.table = calloc(
config->default_shader_per_action,
4,
sizeof(*dstack_info.pool.action[i].shader.table)
);
dstack_info.pool.action[i].shader.number =
config->default_shader_per_action;
dstack_info.pool.action[i].shader.number = 4;
dstack_info.pool.action[i].shader.idx = -1;
}
@ -138,7 +139,7 @@ did_t dstack_add_action(
/* dstack_render(): render a frame */
void dstack_render(void)
{
struct dshader_surface surface;
dsurface_t surface;
struct dstack_action *action;
action = dstack_info.pool.action;

View File

@ -1,13 +1,7 @@
#include <vhex/display/font.h>
#include <vhex/display/draw/pixel.h>
#include <vhex/display/color.h>
//---
// Internal
//---
/* dfont_utf8_next(): Read the next UTF-8 code point of a string */
static uint32_t dfont_utf8_next(uint8_t const **str_pointer)
uint32_t dfont_utf8_next(uint8_t const **str_pointer)
{
uint8_t const *str = *str_pointer;
uint8_t lead = *str++;
@ -76,128 +70,6 @@ int dfont_glyph_index(font_t const *f, uint32_t code_point)
return code_point;
}
/* dfont_char_render() : */
void dfont_char_render(
struct dshader_surface *surface,
int glyph_idx,
uint32_t *arg
) {
uint32_t glyph_bitmap;
uint32_t glyph_shift;
int glyph_width;
int glyph_size;
font_t *font;
int counter;
int sx;
int x;
int y;
x = arg[0];
y = arg[1];
/* 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;
glyph_bitmap = font->glyph.data[glyph_idx];
for (int i = 0; i < glyph_size; ++i)
{
if (glyph_bitmap & glyph_shift) {
dpixel_render(surface, x, y, arg[4]);
} else {
dpixel_render(surface, x, y, arg[5]);
}
/* update font bitmap index / shift */
glyph_shift >>= 1;
if (glyph_shift == 0x00000000) {
glyph_shift = 0x80000000;
glyph_bitmap = font->glyph.data[++glyph_idx];
}
/* update bitmap position */
x += 1;
counter += 1;
if (counter >= glyph_width) {
counter = 0;
x = sx;
y += 1;
}
}
}
//---
// Kernel-level API
//---
/* dfont_render() : draw caracter in surface */
void dfont_text_render(struct dshader_surface *surface, uint32_t *arg)
{
uint32_t code_point;
uint8_t const * str;
font_t *font;
int glyph_idx;
int glyph_width;
int counter;
int sx;
int sy;
/* check culling */
if (((int)arg[3] < surface->y1 && (int)arg[1] > surface->y2)
|| ((int)arg[2] < surface->x1 && (int)arg[0] > surface->x2)) {
return;
}
/* draw algo (update me) */
sx = arg[0];
sy = arg[1];
counter = -1;
font = dfont_get();
str = (void*)(uintptr_t)arg[6];
while (++counter < (int)arg[7])
{
code_point = dfont_utf8_next(&str);
if (code_point == '\n') {
arg[1] += font->glyph.height;
arg[0] = sx;
continue;
}
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;
dfont_char_render(surface, glyph_idx, arg);
arg[0] += glyph_width + font->char_spacing;
}
arg[1] = sy;
arg[0] = sx;
}
//---
// Public API
//---
/* dfont_get() : get the current font */
font_t *dfont_get(void)
{
@ -205,7 +77,7 @@ font_t *dfont_get(void)
return &font8x9;
}
/* dfont_geometry() : get the char geometry */
/* dfont_text_geometry() : get the rendered text geometry with a given font */
int dfont_text_geometry(
font_t *font,
char const * const str_char,

View File

@ -0,0 +1,108 @@
#include <vhex/display/font.h>
#include <vhex/display/draw/pixel.h>
#include <vhex/display/color.h>
#include <vhex/display/stack.h>
//---
// Kernel-level render API
//---
/* dfont_char_render() : */
void dfont_char_render(
dsurface_t *surface,
int glyph_idx,
uint32_t *arg
) {
uint32_t glyph_bitmap;
uint32_t glyph_shift;
int glyph_width;
int glyph_size;
font_t *font;
int counter;
int sx;
int x;
int y;
x = arg[0];
y = arg[1];
/* 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;
glyph_bitmap = font->glyph.data[glyph_idx];
for (int i = 0; i < glyph_size; ++i)
{
if (glyph_bitmap & glyph_shift) {
dpixel_render(surface, x, y, arg[4]);
} else {
dpixel_render(surface, x, y, arg[5]);
}
/* update font bitmap index / shift */
glyph_shift >>= 1;
if (glyph_shift == 0x00000000) {
glyph_shift = 0x80000000;
glyph_bitmap = font->glyph.data[++glyph_idx];
}
/* update bitmap position */
x += 1;
counter += 1;
if (counter >= glyph_width) {
counter = 0;
x = sx;
y += 1;
}
}
}
//---
// Dstack API
//---
/* dfont_char_dstack() : dstack wrapper */
void dfont_char_dstack(dsurface_t *surface, uint32_t *arg)
{
font_t *font = dfont_get();
uint32_t buff[6] = {
arg[1], arg[2], 0, 0, arg[3], arg[4]
};
dfont_char_render(surface, dfont_glyph_index(font, arg[0]), buff);
}
//---
// User-level API
//---
/* dfont_char() : display one char */
void dfont_char(uint32_t n, int x, int y, int fg, int bg)
{
dstack_add_action(
&DSTACK_CALL(
&dfont_char_dstack,
n,
x, y,
fg, bg
),
NULL,
NULL
);
}

View File

@ -134,7 +134,7 @@ void dsubimage_render(
width = surface->width - vxs;
if ((size_t)(vys + height) > surface->height)
height = surface->height - vys;
vram = surface->frag;
vram = surface->vram;
/* prepare box request */

View File

@ -1,37 +0,0 @@
#include <vhex/display.h>
#include <vhex/defs/types.h>
#include <vhex/display/font.h>
//---
// Kernel-level API
//---
void dascii_dstack_render(struct dshader_surface *surface, uint32_t *arg)
{
font_t *font = dfont_get();
uint32_t buff[6] = {
arg[1], arg[2], 0, 0, arg[3], arg[4]
};
dfont_char_render(surface, dfont_glyph_index(font, arg[0]), buff);
}
//---
// User-level API
//---
/* dascii() : display one char */
void dascii(char n, int x, int y, int fg, int bg)
{
dstack_add_action(
&DSTACK_CALL(
&dascii_dstack_render,
n,
x, y,
fg, bg
),
NULL,
NULL
);
}

View File

@ -0,0 +1,8 @@
#include <vhex/display/types.h>
#include <vhex/display/font/information.h>
/* dtext_geometry() : get the rendered text geometry with the current font */
int dtext_geometry(char const * const str_char, int *s, size_t *w, size_t *h)
{
return dfont_text_geometry(NULL, str_char, s, w, h);
}

View File

@ -1,9 +1,7 @@
#include <vhex/defs/types.h>
#include <vhex/display/text.h>
#include <vhex/display/shader.h>
#include <vhex/display/types.h>
#include <vhex/display/stack.h>
#include <vhex/display/color.h>
#include <vhex/display/font.h>
#include <vhex/display/text.h>
#include <vhex/display.h>
#include <stdarg.h>
@ -97,9 +95,59 @@ static char *dtext_info_register(char const * const str)
}
//---
// Public API
// Dstack API
//---
/* dfont_render() : draw caracter in surface */
void dtext_dstack(dsurface_t *surface, uint32_t *arg)
{
uint32_t code_point;
uint8_t const * str;
font_t *font;
int glyph_idx;
int glyph_width;
int counter;
int sx;
int sy;
/* check culling */
if (((int)arg[3] < surface->y1 && (int)arg[1] > surface->y2)
|| ((int)arg[2] < surface->x1 && (int)arg[0] > surface->x2)) {
return;
}
/* draw algo (update me) */
sx = arg[0];
sy = arg[1];
counter = -1;
font = dfont_get();
str = (void*)(uintptr_t)arg[6];
while (++counter < (int)arg[7])
{
code_point = dfont_utf8_next(&str);
if (code_point == '\n') {
arg[1] += font->glyph.height;
arg[0] = sx;
continue;
}
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;
dfont_char_render(surface, glyph_idx, arg);
arg[0] += glyph_width + font->char_spacing;
}
arg[1] = sy;
arg[0] = sx;
}
//---
// Public API
//---
/* dtext_opt(): Display a string of text */
did_t dtext_opt(
@ -113,7 +161,7 @@ did_t dtext_opt(
void *real_str;
/* get text geometry and handle obvious culling */
if (dfont_text_geometry(NULL, str, &size, &width, &height) != 0)
if (dtext_geometry(str, &size, &width, &height) != 0)
return (-1);
if (x >= (int)dwidth()
|| y >= (int)dheight()
@ -134,7 +182,7 @@ did_t dtext_opt(
/* request draw call */
return dstack_add_action(
&DSTACK_CALL(
&dfont_text_render,
&dtext_dstack,
x, y, x + width, y + height,
fg, bg,
(uint32_t)(uintptr_t)real_str, size,