VxKernel 0.6.0-12 : Fix image rendering + fix shader crash

@update
<> include/display/image/render
  | update dimage_* prototype to force return the display ID
  | update dimage_* prototype to change the arguments order
  | isolate "render" part of the API and the "shader" part
  | prepare shadow shader primitives
<> include/display/shader
  | change routine prototype (remove routine status)
  | update macros, to generate directly usable dshader_call_t pointer
  | add shader primitives to add shader on some display action
<> src/modules/display/stack
  | update shader allocation sizeof for more visibility
  | isolate shader adding
<> src/modules/display/image
  | isolate each render primitive in "render/" sub-folder
  | isolate each shader primitive in "shader/" sub-folder
  | prepare shadow shader code (WIP)
  | enable image rendering for image with no alpha channel

@fix
<> src/modules/display/stack
  | remove memset() which removed shader table allocation
This commit is contained in:
Yann MAGNIN 2022-06-21 18:43:11 +02:00
parent b2fc0db544
commit c966807cd7
9 changed files with 302 additions and 146 deletions

View File

@ -3,6 +3,12 @@
#include <vhex/display/image/types.h>
//---
// User-level API
//---
/* render part */
/* Alignment settings for dimage*(). Combining a vertical and a horizontal
alignment option specifies where a given point (x,y) should be relative to
the rendered image. */
@ -17,25 +23,60 @@ enum {
DIMAGE_BOTTOM = 0x40,
};
/* dimage(): Render a full image
This function blits an image on the VRAM using vhex's special format. It is
a special case of dsubimage() where the full image is drawn with clipping.
/* dimage(): Render a full image */
extern did_t dimage(image_t const *image, int x, int y, int mode);
@x @y Coordinates of the top-left corner of the image
@image Pointer to image encoded with fxconv for bopti */
extern void dimage(image_t const *image, int x, int y, int mode);
/* dsubimage(): Render a section of an image
This function blits a subrectangle [left, top, width, height] of an image.
@x @y Coordinates on screen of the rendered subrectangle
@image Pointer to image encoded with fxconv for bopti
@left @top Top-left coordinates of the subrectangle within the image
@width @height Subrectangle dimensions
@flags OR-combination of DIMAGE_* flags */
extern void dsubimage(
int x, int y,
/* dsubimage(): Render a section of an image */
extern did_t dsubimage(
image_t const *image,
int x, int y,
int left, int top, int width, int height
);
/* shader part */
/* dimage_shader_shadow() : add shadows in any image rendered */
extern int dimage_shader_shadow(did_t did, int xoff, int yoff);
//---
// Kernel-level API
//---
/* dsubimage_render() : draw a subimage in the surface */
extern void dsubimage_render(
dsurface_t *surface,
image_t const *image,
int x, int y,
int left, int top, int width, int height
);
/* dimage_render(): Render a full image */
extern void dimage_render(dsurface_t *s, image_t const *img, int x, int y);
/* help part */
struct imgbox {
struct {
struct {
int start;
int end;
} y;
struct {
int start;
int end;
} x;
} img;
struct {
uint16_t *vram;
int voff;
} surface;
};
/* dsubimage_render_box() : generate box information */
extern void dsubimage_render_box(
struct imgbox *imgbox,
image_t const *image,
int x, int y,
int left, int top, int width, int height
);

View File

@ -3,6 +3,7 @@
#include <vhex/defs/attributes.h>
#include <vhex/defs/types.h>
#include <vhex/display/types.h>
/* Image formats. Note that transparency really only indicates the default
rendering method, as a transparent background can always be added or removed

View File

@ -5,7 +5,7 @@
/* dshader - display shader definition */
struct dshader_call {
int (*routine)(
void (*routine)(
dsurface_t *surface,
uint32_t *draw_args,
uint32_t *shader_args
@ -14,11 +14,8 @@ struct dshader_call {
};
typedef struct dshader_call dshader_call_t;
/* DSHADER_LIST - helper to create a list of shader "on-the-fly" */
#define DSHADER_LIST(shader_list) (dshader_call_t*)&{ shader_list }
/* DSHADER - helper to create a shader object */
#define DSHADER(fct, ...) (dshader_call_t){ \
#define DSHADER(fct, ...) (dshader_call_t*)&(dshader_call_t){ \
.routine = fct, \
.args = { __VA_ARGS__ } \
}

View File

@ -44,8 +44,8 @@ extern did_t dstack_add_action(
void (*quit)(uint32_t *args)
);
/* dstack_get_action() : get display stack action using its ID */
extern struct dstack_action *dstack_get_action(did_t did);
/* dstack_add_shader() : add shader on particular action */
extern int dstack_add_shader(did_t did, dshader_call_t *call);
/* dstack_render(): render a frame */
extern void dstack_render(void);

View File

@ -46,7 +46,7 @@ int dstack_init(void)
for (int i = 0; i < dstack_info.pool.slots; ++i) {
dstack_info.pool.action[i].shader.table = calloc(
4,
sizeof(*dstack_info.pool.action[i].shader.table)
sizeof(dshader_call_t)
);
dstack_info.pool.action[i].shader.number = 4;
dstack_info.pool.action[i].shader.idx = -1;
@ -76,10 +76,32 @@ int dstack_quit(void)
}
//
//---
// Internal API
//
//---
/* dstack_action_add_shader() : add a shader in action */
static void dstack_action_add_shader(
struct dstack_action *action,
dshader_call_t *shader
) {
action->shader.idx += 1;
if (action->shader.idx >= action->shader.number) {
action->shader.number += action->shader.number;
action->shader.table = reallocarray(
action->shader.table,
action->shader.number,
sizeof(dshader_call_t)
);
}
memcpy(
&action->shader.table[action->shader.idx],
shader,
sizeof(dshader_call_t)
);
}
/* dstack_action_alloc() : allocate a new dstack action with shader */
static did_t dstack_action_alloc(
dstack_call_t *call,
dshader_call_t *shader,
@ -98,31 +120,25 @@ static did_t dstack_action_alloc(
);
}
action = &dstack_info.pool.action[dstack_info.pool.idx];
memset(action, 0x00, sizeof(struct dstack_action));
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) {
action->shader.number += action->shader.number;
action->shader.table = reallocarray(
action->shader.table,
action->shader.number,
sizeof(*action->shader.table)
);
}
memcpy(
&action->shader.table[i],
&shader[i],
sizeof(dshader_call_t)
);
dstack_action_add_shader(action, &shader[i]);
}
action->shader.idx = i;
}
action->quit = quit;
return dstack_info.pool.idx;
}
/* dstack_action_get() : return the display action using its dislay ID */
struct dstack_action *dstack_action_get(did_t did)
{
if (did > dstack_info.pool.idx)
return NULL;
return &dstack_info.pool.action[did];
}
//---
// Public API
//---
@ -133,7 +149,23 @@ did_t dstack_add_action(
dshader_call_t *shader,
void (*quit)(uint32_t *arg)
) {
return (dstack_action_alloc(call, shader, quit));
return dstack_action_alloc(call, shader, quit);
}
/* dstack_add_shader() : add shader on particular action */
int dstack_add_shader(did_t did, dshader_call_t *call)
{
struct dstack_action *action;
if (call == NULL)
return -1;
action = dstack_action_get(did);
if (action == NULL)
return -1;
dstack_action_add_shader(action, call);
return 0;
}
/* dstack_render(): render a frame */

View File

@ -52,7 +52,7 @@ int image_get_pixel(image_t const *img, int x, int y)
return (data_u16[x]);
}
else if(IMAGE_IS_P8(img->format)) {
return ((int8_t)data_u8[x]);
return (data_u8[x]);
}
else if(IMAGE_IS_P4(img->format)) {
if(x & 1) {

View File

@ -0,0 +1,46 @@
#include <vhex/display/image.h>
#include <vhex/display/stack.h>
//---
// Kernel-level API
//---
/* dimage_render(): Render a full image */
void dimage_render(dsurface_t *surface, image_t const *img, int x, int y)
{
dsubimage_render(surface, img, x, y, 0, 0, img->width, img->height);
}
//---
// Dstack API (internal)
//---
/* dimage_dstack(): dstack wrapper primitive */
static void dimage_dstack(dsurface_t *surface, uint32_t *args)
{
dimage_render(
surface,
(image_t*)(uintptr_t)args[0],
(int)args[1],
(int)args[2]
);
}
//---
// User-level API
//---
/* dimage(): Render a full image */
did_t dimage(image_t const *image, int x, int y, int mode)
{
if (mode & DIMAGE_CENTER) { x -= image->width >> 1; }
if (mode & DIMAGE_RIGHT) { x -= image->width; }
if (mode & DIMAGE_MIDDLE) { y -= image->height >> 1; }
if (mode & DIMAGE_BOTTOM) { y -= image->height; }
return dstack_add_action(
&DSTACK_CALL(&dimage_dstack, (uintptr_t)image, x, y),
NULL,
NULL
);
}

View File

@ -6,49 +6,30 @@
// Internal functions
//---
struct imgbox {
struct {
struct {
int start;
int end;
} y;
struct {
int start;
int end;
} x;
} img;
struct {
uint16_t *vram;
int voff;
} surface;
};
/* dsubimage_default_render() : raw-format image render */
static void dsubimage_default_render(image_t const *image, struct imgbox *box)
{
(void)image;
(void)box;
#if 0
uint16_t *vram;
uint16_t *vidxs;
uint16_t *vidx;
uint16_t *data;
int voff;
int c;
vram = surface->draw;
voff = box->surface.idx.offset;
vidxs = &vram[box->surface.idx.start];
voff = box->surface.voff;
vram = box->surface.vram;
for (int iy = box->img.y.start; iy < box->img.y.end; ++iy) {
vidx = vidxs;
data = vram;
c = 0;
for (int ix = box->img.x.start; ix < box->img.x.end; ++ix) {
*(vidx++) = image_decode_pixel(
data[c] = image_decode_pixel(
image,
image_get_pixel(image, ix, iy)
);
c += 1;
}
vidxs = &vidxs[voff];
vram = &vram[voff];
}
#endif
}
/* dsubimage_alpha_render() : alpha-format image render */
@ -83,10 +64,11 @@ static void dsubimage_alpha_render(image_t const *image, struct imgbox *box)
// Kernel-level API
//---
/* dsubimage_render() : draw a subimage in the surface */
void dsubimage_render(
dsurface_t *surface,
int x, int y,
image_t const *image,
int x, int y,
int left, int top, int width, int height
) {
uint16_t *vram;
@ -128,7 +110,7 @@ void dsubimage_render(
if (vys < 0) {
vys = 0;
top += (surface->y1 - y);
height -= (surface->y1 + y);
height -= (surface->y1 - y);
}
if ((size_t)(vxs + width) > surface->width)
width = surface->width - vxs;
@ -136,7 +118,6 @@ void dsubimage_render(
height = surface->height - vys;
vram = surface->vram;
/* prepare box request */
struct imgbox imgbox = {
.img = {
@ -156,41 +137,44 @@ void dsubimage_render(
};
#if 0
dclear(C_WHITE);
dprint(0, 0, C_BLACK,
"surface.x1 = %d\n"
"surface.x2 = %d\n"
"surface.y1 = %d\n"
"surface.y2 = %d\n"
"surface.width = %d\n"
"surface.height = %d\n"
"\n"
"img.y.start = %d\n"
"img.y.end = %d\n"
"img.x.start = %d\n"
"img.x.end = %d\n"
"\n"
"image.x = %d\n"
"image.y = %d\n"
"image.width = %d\n"
"image.heigt = %d\n",
surface->x1,
surface->x2,
surface->y1,
surface->y2,
surface->width,
surface->height,
imgbox.img.y.start,
imgbox.img.y.end,
imgbox.img.x.start,
imgbox.img.x.end,
x,
y,
width,
height
);
dupdate();
while(1) { __asm__ volatile ("sleep"); }
static int test = 0;
if (++test >= 12) {
dclear(C_WHITE);
dprint(0, 0, C_BLACK,
"surface.x1 = %d\n"
"surface.x2 = %d\n"
"surface.y1 = %d\n"
"surface.y2 = %d\n"
"surface.width = %d\n"
"surface.height = %d\n"
"\n"
"img.y.start = %d\n"
"img.y.end = %d\n"
"img.x.start = %d\n"
"img.x.end = %d\n"
"\n"
"image.x = %d\n"
"image.y = %d\n"
"image.width = %d\n"
"image.heigt = %d\n",
surface->x1,
surface->x2,
surface->y1,
surface->y2,
surface->width,
surface->height,
imgbox.img.y.start,
imgbox.img.y.end,
imgbox.img.x.start,
imgbox.img.x.end,
x,
y,
width,
height
);
dupdate();
while(1) { __asm__ volatile ("sleep"); }
}
#endif
/* send drawing request in the approriate optimized function */
@ -201,11 +185,6 @@ void dsubimage_render(
dsubimage_default_render(image, &imgbox);
}
/* dimage_render(): Render a full image */
void dimage_render(dsurface_t *surface, int x, int y, image_t const *img)
{
dsubimage_render(surface, x, y, img, 0, 0, img->width, img->height);
}
@ -213,25 +192,14 @@ void dimage_render(dsurface_t *surface, int x, int y, image_t const *img)
// Dstack API
//---
/* dimage_dstack(): dstack wrapper primitive */
void dimage_dstack(dsurface_t *surface, uint32_t *args)
{
dimage_render(
surface,
(int)args[0],
(int)args[1],
(image_t*)(uintptr_t)args[2]
);
}
/* dsubimage_dstack(): dstack wrapper primitive */
void dsubimage_dstack(dsurface_t *surface, uint32_t *args)
{
dsubimage_render(
surface,
(int)args[0],
(image_t*)(uintptr_t)args[0],
(int)args[1],
(image_t*)(uintptr_t)args[2],
(int)args[2],
(int)args[3],
(int)args[4],
(int)args[5],
@ -245,31 +213,17 @@ void dsubimage_dstack(dsurface_t *surface, uint32_t *args)
// User-level API
//---
/* dimage(): Render a full image */
void dimage(image_t const *image, int x, int y, int mode)
{
if (mode & DIMAGE_CENTER) { x -= image->width >> 1; }
if (mode & DIMAGE_RIGHT) { x -= image->width; }
if (mode & DIMAGE_MIDDLE) { y -= image->height >> 1; }
if (mode & DIMAGE_BOTTOM) { y -= image->height; }
dstack_add_action(
&DSTACK_CALL(&dimage_dstack, x, y, (uintptr_t)image),
NULL,
NULL
);
}
/* dsubimage(): Render a section of an image */
void dsubimage(
int x, int y,
did_t dsubimage(
image_t const *image,
int x, int y,
int left, int top, int width, int height
) {
dstack_add_action(
return dstack_add_action(
&DSTACK_CALL(
&dsubimage_dstack,
x, y,
(uintptr_t)image,
x, y,
left, top, width, height
),
NULL,

View File

@ -0,0 +1,85 @@
#include <vhex/display/image.h>
#include <vhex/display/types.h>
#include <vhex/display/stack.h>
#include <vhex/display/shader.h>
//---
// Internal functions
//---
/* dimg_shadow_default_render() : add shadow on image with no alpha */
static void dimg_shadow_default_render(
dsurface_t *surface,
image_t *img,
uint32_t *draw,
uint32_t *shader
) {
(void)surface;
(void)img;
(void)draw;
(void)shader;
}
/* dimg_shadow_alpha_render() : add shadow on image with no alpha */
static void dimg_shadow_alpha_render(
dsurface_t *surface,
image_t *img,
uint32_t *draw,
uint32_t *shader
) {
(void)img;
(void)surface;
(void)draw;
(void)shader;
#if 0
struct imgbox imgbox;
dsubimage_render_box(
&imgbox,
image,
(int)draw[1] + xoff,
(int)draw[2] + yoff,
(int)draw[3],
(int)draw[4],
(int)draw[5],
(int)draw[6]
);
#endif
}
//---
// Dstack-level API
//---
/* dimage_shader_shadow() : add shadows in any image rendered */
static void dimage_shader_shadow_dstack(
dsurface_t *surface,
uint32_t *draw,
uint32_t *shader
) {
image_t *image;
image = (image_t*)(uintptr_t)draw[0];
/* send drawing request in the approriate optimized function */
if (IMAGE_IS_ALPHA(image->format)) {
dimg_shadow_alpha_render(surface, image, draw, shader);
return;
}
dimg_shadow_default_render(surface, image, draw, shader);
}
//---
// User-level API
//---
/* dimage_shader_shadow() : add shadows in any image rendered */
int dimage_shader_shadow(did_t did, int xoff, int yoff)
{
return dstack_add_shader(
did,
DSHADER(&dimage_shader_shadow_dstack, xoff, yoff)
);
}