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:
parent
b2fc0db544
commit
c966807cd7
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__ } \
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
|
@ -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,
|
|
@ -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)
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue