[renderer] Add fitted pic rendering

The pic is scaled to fill the specified rect (then clipped to the
screen (effectively)). Done just for the console background for now, but
it will be used for slice-pics as well.

Not implemented for vulkan yet as I'm still thinking about the
descriptor management needed for the instanced rendering.

Making the conback rendering conditional gave an approximately 3% speed
boost to glsl with the GL stub (~12200fps to ~12550fps), for either
conback render method.
This commit is contained in:
Bill Currie 2023-01-17 11:33:47 +09:00
parent 96c82106f9
commit 4e1ddaa964
16 changed files with 150 additions and 10 deletions

View File

@ -55,6 +55,7 @@ struct qpic_s *gl_Draw_MakePic (int width, int height, const byte *data);
void gl_Draw_DestroyPic (struct qpic_s *pic);
struct qpic_s *gl_Draw_PicFromWad (const char *name);
void gl_Draw_Pic (int x, int y, struct qpic_s *pic);
void gl_Draw_FitPic (int x, int y, int width, int height, struct qpic_s *pic);
void gl_Draw_Picf (float x, float y, struct qpic_s *pic);
void gl_Draw_SubPic(int x, int y, struct qpic_s *pic,
int srcx, int srcy, int width, int height);

View File

@ -56,6 +56,7 @@ struct qpic_s *glsl_Draw_MakePic (int width, int height, const byte *data);
void glsl_Draw_DestroyPic (struct qpic_s *pic);
struct qpic_s *glsl_Draw_PicFromWad (const char *name);
void glsl_Draw_Pic (int x, int y, struct qpic_s *pic);
void glsl_Draw_FitPic (int x, int y, int width, int height, struct qpic_s *pic);
void glsl_Draw_Picf (float x, float y, struct qpic_s *pic);
void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic,
int srcx, int srcy, int width, int height);

View File

@ -76,6 +76,8 @@ struct qpic_s *Vulkan_Draw_PicFromWad (const char *name,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_Pic (int x, int y, struct qpic_s *pic,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_FitPic (int x, int y, int width, int height,
struct qpic_s *pic, struct vulkan_ctx_s *ctx);
void Vulkan_Draw_Picf (float x, float y, struct qpic_s *pic,
struct vulkan_ctx_s *ctx);
void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic,

View File

@ -245,6 +245,15 @@ qpic_t *Draw_PicFromWad (const char *name);
*/
void Draw_Pic (int x, int y, qpic_t *pic);
/** Draw a qpic to the screen, scaled to fit the given width and height
\param x horizontal location of the upper left corner of the qpic
\param y vertical location of the upper left corner of the qpic
\param width horizontal size of the output pic
\param height vertical size of the output pic
\param pic qpic to draw
*/
void Draw_FitPic (int x, int y, int width, int height, qpic_t *pic);
/** Draw a qpic to the screen
\param x horizontal location of the upper left corner of the qpic
\param y vertical location of the upper left corner of the qpic

View File

@ -108,6 +108,7 @@ typedef struct vid_render_funcs_s {
void (*Draw_DestroyPic) (qpic_t *pic);
qpic_t *(*Draw_PicFromWad) (const char *name);
void (*Draw_Pic) (int x, int y, qpic_t *pic);
void (*Draw_FitPic) (int x, int y, int width, int height, qpic_t *pic);
void (*Draw_Picf) (float x, float y, qpic_t *pic);
void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
int (*Draw_AddFont) (struct font_s *font);

View File

@ -38,6 +38,7 @@ enum {
canvas_updateonce,
canvas_tile,
canvas_pic,
canvas_fitpic, // pic is scaled to fit the view
canvas_subpic,
canvas_cachepic,
canvas_fill,

View File

@ -667,17 +667,21 @@ static void
draw_console (view_t view)
{
byte alpha;
view_pos_t len = View_GetLen (screen_view);
if (con_state == con_fullscreen) {
alpha = 255;
} else {
view_pos_t len = View_GetLen (screen_view);
float y = len.y * con_size;
alpha = 255 * con_alpha * len.y / y;
alpha = min (alpha, 255);
if (con_data.lines > 0) {
// draw the background
if (con_state == con_fullscreen) {
alpha = 255;
} else {
float y = len.y * con_size;
alpha = 255 * con_alpha * len.y / y;
alpha = min (alpha, 255);
}
//r_funcs->Draw_ConsoleBackground (con_data.lines, alpha);
qpic_t *pic = r_funcs->Draw_CachePic ("gfx/conback.lmp", false);
r_funcs->Draw_FitPic (0, con_data.lines - len.y, len.x, len.y, pic);
}
// draw the background
r_funcs->Draw_ConsoleBackground (con_data.lines, alpha);
update_notify ();
// draw everything else

View File

@ -49,6 +49,7 @@ canvas_rangeid(update)
canvas_rangeid(updateonce)
canvas_rangeid(tile)
canvas_rangeid(pic)
canvas_rangeid(fitpic)
canvas_rangeid(subpic)
canvas_rangeid(cachepic)
canvas_rangeid(fill)
@ -75,7 +76,7 @@ const component_t canvas_components[canvas_comp_count] = {
},
[canvas_tile] = {
.size = sizeof (byte),
.name = "pic",
.name = "tile",
.rangeid = canvas_tile_rangeid,
},
[canvas_pic] = {
@ -83,6 +84,11 @@ const component_t canvas_components[canvas_comp_count] = {
.name = "pic",
.rangeid = canvas_pic_rangeid,
},
[canvas_fitpic] = {
.size = sizeof (qpic_t *),
.name = "fitpic",
.rangeid = canvas_fitpic_rangeid,
},
[canvas_subpic] = {
.size = sizeof (canvas_subpic_t),
.name = "subpic",
@ -177,6 +183,25 @@ draw_pic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
}
}
static void
draw_fitpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
ecs_range_t range)
{
ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base };
uint32_t count = range.end - range.start;
uint32_t *ent = pool->dense;
__auto_type pic = (qpic_t **) pool->data + range.start;
while (count-- > 0) {
view_t view = View_FromEntity (viewsys, *ent++);
if (View_GetVisible (view)) {
view_pos_t pos = View_GetAbs (view);
view_pos_t len = View_GetLen (view);
r_funcs->Draw_FitPic (pos.x, pos.y, len.x, len.y, *pic);
}
pic++;
}
}
static void
draw_subpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool,
ecs_range_t range)
@ -303,6 +328,7 @@ Canvas_Draw (canvas_system_t canvas_sys)
[canvas_updateonce] = draw_updateonce,
[canvas_tile] = draw_tile_views,
[canvas_pic] = draw_pic_views,
[canvas_fitpic] = draw_fitpic_views,
[canvas_subpic] = draw_subpic_views,
[canvas_cachepic] = draw_cachepic_views,
[canvas_fill] = draw_fill_views,

View File

@ -761,6 +761,26 @@ gl_Draw_Pic (int x, int y, qpic_t *pic)
qfglEnd ();
}
void
gl_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic)
{
glpic_t *gl;
gl = (glpic_t *) pic->data;
qfglBindTexture (GL_TEXTURE_2D, gl->texnum);
qfglBegin (GL_QUADS);
qfglTexCoord2f (0, 0);
qfglVertex2f (x, y);
qfglTexCoord2f (1, 0);
qfglVertex2f (x + width, y);
qfglTexCoord2f (1, 1);
qfglVertex2f (x + width, y + height);
qfglTexCoord2f (0, 1);
qfglVertex2f (x, y + height);
qfglEnd ();
}
void
gl_Draw_Picf (float x, float y, qpic_t *pic)
{

View File

@ -661,6 +661,13 @@ glsl_Draw_Pic (int x, int y, qpic_t *pic)
0, 0, pic->width, pic->height, color);
}
void
glsl_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic)
{
static quat_t color = { 1, 1, 1, 1};
draw_pic (x, y, width, height, pic, 0, 0, pic->width, pic->height, color);
}
void
glsl_Draw_Picf (float x, float y, qpic_t *pic)
{

View File

@ -536,6 +536,58 @@ Draw_Pic (int x, int y, qpic_t *pic)
}
}
void
Draw_FitPic (int x, int y, int width, int height, qpic_t *pic)
{
int v_width = vid.width;
int v_height = vid.height;
if (x > v_width || y > v_width || x + width <= 0 || y + height <= 0) {
return;
}
if (width == pic->width && height == pic->height) {
Draw_Pic (x, y, pic);
return;
}
int sstep = pic->width * 0x10000 / width;
int tstep = pic->height * 0x10000 / height;
int sx = 0, ex = width;
int sy = 0, ey = height;
if (x < 0) {
sx -= x;
ex += x;
}
if (y < 0) {
sy -= y;
ey += y;
}
if (x + width > v_width) {
ex -= x + width - v_width;
}
if (y + height > v_height) {
ey -= y + height - v_height;
}
x += sx;
y += sy;
byte *src, *dst;
// draw the pic
dst = d_viewbuffer + y * d_rowbytes + x;
for (int y = sy; y < sy + ey; y++, dst += d_rowbytes) {
src = pic->data + ((y * tstep) >> 16) * pic->width;
if (width == pic->width)
memcpy (dst, src, width);
else {
int f = sx * sstep;
for (int x = 0; x < ex; x++, f += sstep) {
dst[x] = src[f >> 16];
}
}
}
}
void
Draw_Picf (float x, float y, qpic_t *pic)
{

View File

@ -522,6 +522,7 @@ vid_render_funcs_t gl_vid_render_funcs = {
.Draw_DestroyPic = gl_Draw_DestroyPic,
.Draw_PicFromWad = gl_Draw_PicFromWad,
.Draw_Pic = gl_Draw_Pic,
.Draw_FitPic = gl_Draw_FitPic,
.Draw_Picf = gl_Draw_Picf,
.Draw_SubPic = gl_Draw_SubPic,
.Draw_AddFont = gl_Draw_AddFont,

View File

@ -466,6 +466,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
.Draw_DestroyPic = glsl_Draw_DestroyPic,
.Draw_PicFromWad = glsl_Draw_PicFromWad,
.Draw_Pic = glsl_Draw_Pic,
.Draw_FitPic = glsl_Draw_FitPic,
.Draw_Picf = glsl_Draw_Picf,
.Draw_SubPic = glsl_Draw_SubPic,
.Draw_AddFont = glsl_Draw_AddFont,

View File

@ -479,6 +479,7 @@ vid_render_funcs_t sw_vid_render_funcs = {
.Draw_DestroyPic = Draw_DestroyPic,
.Draw_PicFromWad = Draw_PicFromWad,
.Draw_Pic = Draw_Pic,
.Draw_FitPic = Draw_FitPic,
.Draw_Picf = Draw_Picf,
.Draw_SubPic = Draw_SubPic,
.Draw_AddFont = Draw_AddFont,

View File

@ -272,6 +272,12 @@ vulkan_Draw_Pic (int x, int y, qpic_t *pic)
Vulkan_Draw_Pic (x, y, pic, vulkan_ctx);
}
static void
vulkan_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic)
{
Vulkan_Draw_FitPic (x, y, width, height, pic, vulkan_ctx);
}
static void
vulkan_Draw_Picf (float x, float y, qpic_t *pic)
{
@ -789,6 +795,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
.Draw_DestroyPic = vulkan_Draw_DestroyPic,
.Draw_PicFromWad = vulkan_Draw_PicFromWad,
.Draw_Pic = vulkan_Draw_Pic,
.Draw_FitPic = vulkan_Draw_FitPic,
.Draw_Picf = vulkan_Draw_Picf,
.Draw_SubPic = vulkan_Draw_SubPic,
.Draw_AddFont = vulkan_Draw_AddFont,

View File

@ -1185,6 +1185,12 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx)
draw_quad (x, y, pd->descid, pd->vert_index, color, frame);
}
void
Vulkan_Draw_FitPic (int x, int y, int widht, int height, qpic_t *pic,
vulkan_ctx_t *ctx)
{
}
void
Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx)
{