From 4e1ddaa964f5f818e9a022991a48567ecced519d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Jan 2023 11:33:47 +0900 Subject: [PATCH] [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. --- include/QF/GL/qf_draw.h | 1 + include/QF/GLSL/qf_draw.h | 1 + include/QF/Vulkan/qf_draw.h | 2 + include/QF/draw.h | 9 ++++ include/QF/plugin/vid_render.h | 1 + include/QF/ui/canvas.h | 1 + libs/console/client.c | 22 ++++++---- libs/ui/canvas.c | 28 ++++++++++++- libs/video/renderer/gl/gl_draw.c | 20 +++++++++ libs/video/renderer/glsl/glsl_draw.c | 7 ++++ libs/video/renderer/sw/draw.c | 52 ++++++++++++++++++++++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 ++++ libs/video/renderer/vulkan/vulkan_draw.c | 6 +++ 16 files changed, 150 insertions(+), 10 deletions(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index f9f9eb004..9674594ba 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -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); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index bc5def658..3a8ea0276 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -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); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 4182fe5d9..8b65e114c 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -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, diff --git a/include/QF/draw.h b/include/QF/draw.h index 780063064..82d0eee8a 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -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 diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index cb9a96304..b4a1e441f 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -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); diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index 0033ff739..2c832120f 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -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, diff --git a/libs/console/client.c b/libs/console/client.c index b05cb13b9..23371e14a 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -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 diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 6d7e621bf..c4506fc00 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -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, diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 7ed383cf6..61ea1d9a7 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -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) { diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 428e9db9c..73a9b661e 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -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) { diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 778a96002..7c19bc473 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -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) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 6c13ad913..51229897d 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -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, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 26375d469..3070b963a 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -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, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 3ef972ae6..703eee190 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -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, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 093e042ae..95403632d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -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, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 39982f5f0..b73816d33 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -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) {