mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
[renderer] Add a cell-based character buffer
This is intended for the built-in 8x8 bitmap characters and quake's "conchars", but could potentially be used for any simple (non-composed characters) mono-spaced font. Currently, the buffers can be created, destroyed, cleared, scrolled vertically in either direction, and rendered to the screen in a single blast. One of the reasons for creating the buffer is to make it so scaling can be supported in the sw renderer.
This commit is contained in:
parent
62ccafca8c
commit
25a14eb232
17 changed files with 311 additions and 1 deletions
|
@ -30,9 +30,11 @@
|
|||
|
||||
struct qpic_s;
|
||||
struct rfont_s;
|
||||
struct draw_charbuffer_s;
|
||||
|
||||
void gl_Draw_Init (void);
|
||||
void gl_Draw_Shutdown (void);
|
||||
void gl_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer);
|
||||
void gl_Draw_Character (int x, int y, unsigned ch);
|
||||
void gl_Draw_String (int x, int y, const char *str);
|
||||
void gl_Draw_nString (int x, int y, const char *str, int count);
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
|
||||
struct qpic_s;
|
||||
struct rfont_s;
|
||||
struct draw_charbuffer_s;
|
||||
|
||||
void glsl_Draw_Init (void);
|
||||
void glsl_Draw_Shutdown (void);
|
||||
void glsl_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer);
|
||||
void glsl_Draw_Character (int x, int y, unsigned ch);
|
||||
void glsl_Draw_String (int x, int y, const char *str);
|
||||
void glsl_Draw_nString (int x, int y, const char *str, int count);
|
||||
|
|
|
@ -32,7 +32,10 @@ struct vulkan_ctx_s;
|
|||
struct qfv_renderframe_s;
|
||||
struct qpic_s;
|
||||
struct rfont_s;
|
||||
struct draw_charbuffer_s;
|
||||
|
||||
void Vulkan_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Draw_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Draw_Character (int x, int y, unsigned ch,
|
||||
|
|
|
@ -41,6 +41,23 @@
|
|||
|
||||
#include "QF/wad.h"
|
||||
|
||||
/** Buffer for drawing text using quake conchars or the default 8x8 font.
|
||||
|
||||
Characters are stored with the first character in the upper left, scanning
|
||||
horizontally to the right.
|
||||
*/
|
||||
typedef struct draw_charbuffer_s {
|
||||
int width; ///< width in character cells
|
||||
int height; ///< height in character cells
|
||||
char *chars; ///< width * height characters
|
||||
} draw_charbuffer_t;
|
||||
|
||||
draw_charbuffer_t *Draw_CreateBuffer (int width, int height);
|
||||
void Draw_DestroyBuffer (draw_charbuffer_t *buffer);
|
||||
void Draw_ClearBuffer (draw_charbuffer_t *buffer);
|
||||
void Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines);
|
||||
void Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer);
|
||||
|
||||
extern byte *draw_chars;
|
||||
|
||||
/** Initialize the draw stuff.
|
||||
|
|
|
@ -79,10 +79,13 @@ typedef struct vid_model_funcs_s {
|
|||
|
||||
struct tex_s;
|
||||
struct rfont_s;
|
||||
struct draw_charbuffer_s;
|
||||
|
||||
typedef void (*capfunc_t) (struct tex_s *screencap, void *data);
|
||||
|
||||
typedef struct vid_render_funcs_s {
|
||||
void (*init) (void);
|
||||
void (*Draw_CharBuffer) (int x, int y, struct draw_charbuffer_s *buffer);
|
||||
void (*Draw_Character) (int x, int y, unsigned ch);
|
||||
void (*Draw_String) (int x, int y, const char *str);
|
||||
void (*Draw_nString) (int x, int y, const char *str, int count);
|
||||
|
|
|
@ -226,4 +226,7 @@ extern float r_skytime;
|
|||
|
||||
extern int c_surf;
|
||||
|
||||
struct draw_charbuffer_s;
|
||||
void sw_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer);
|
||||
|
||||
#endif // _D_IFACE_H
|
||||
|
|
|
@ -50,6 +50,7 @@ libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs)
|
|||
libs_video_renderer_libQFrenderer_la_SOURCES=\
|
||||
libs/video/renderer/r_bsp.c \
|
||||
libs/video/renderer/r_cvar.c \
|
||||
libs/video/renderer/r_draw.c \
|
||||
libs/video/renderer/r_efrag.c \
|
||||
libs/video/renderer/r_fog.c \
|
||||
libs/video/renderer/r_font.c \
|
||||
|
|
|
@ -486,6 +486,21 @@ tVA_increment (void)
|
|||
flush_text ();
|
||||
}
|
||||
|
||||
void
|
||||
gl_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer)
|
||||
{
|
||||
const byte *line = (byte *) buffer->chars;
|
||||
int width = buffer->width;
|
||||
int height = buffer->height;
|
||||
while (height-- > 0) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
gl_Draw_Character (x + i * 8, y, line[i]);
|
||||
}
|
||||
line += width;
|
||||
y += 8;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Draw_Character
|
||||
|
||||
|
|
|
@ -485,6 +485,21 @@ flush_2d (void)
|
|||
line_queue->size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
glsl_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer)
|
||||
{
|
||||
const byte *line = (byte *) buffer->chars;
|
||||
int width = buffer->width;
|
||||
int height = buffer->height;
|
||||
while (height-- > 0) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
glsl_Draw_Character (x + i * 8, y, line[i]);
|
||||
}
|
||||
line += width;
|
||||
y += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glsl_Draw_Character (int x, int y, unsigned int chr)
|
||||
{
|
||||
|
|
88
libs/video/renderer/r_draw.c
Normal file
88
libs/video/renderer/r_draw.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
r_draw.c
|
||||
|
||||
Renderer general draw support
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/draw.h"
|
||||
#include "QF/render.h"
|
||||
|
||||
#include "QF/plugin/vid_render.h"
|
||||
|
||||
VISIBLE draw_charbuffer_t *
|
||||
Draw_CreateBuffer (int width, int height)
|
||||
{
|
||||
size_t size = width * height;
|
||||
draw_charbuffer_t *buffer = malloc (sizeof (draw_charbuffer_t) + size);
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
buffer->chars = (char *) (buffer + 1);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Draw_DestroyBuffer (draw_charbuffer_t *buffer)
|
||||
{
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Draw_ClearBuffer (draw_charbuffer_t *buffer)
|
||||
{
|
||||
memset (buffer->chars, ' ', buffer->height * buffer->width);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines)
|
||||
{
|
||||
int down = 0;
|
||||
if (lines < 0) {
|
||||
lines = -lines;
|
||||
down = 1;
|
||||
}
|
||||
if (lines > buffer->height) {
|
||||
lines = buffer->height;
|
||||
}
|
||||
if (down) {
|
||||
memmove (buffer->chars + lines * buffer->width, buffer->chars,
|
||||
(buffer->height - lines) * buffer->width);
|
||||
memset (buffer->chars, ' ', lines * buffer->width);
|
||||
} else {
|
||||
memmove (buffer->chars, buffer->chars + lines * buffer->width,
|
||||
(buffer->height - lines) * buffer->width);
|
||||
memset (buffer->chars + (buffer->height - lines) * buffer->width, ' ',
|
||||
lines * buffer->width);
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer)
|
||||
{
|
||||
r_funcs->Draw_CharBuffer (x, y, buffer);
|
||||
}
|
|
@ -63,10 +63,17 @@ typedef struct qpic_res_s {
|
|||
char *name;
|
||||
} qpic_res_t;
|
||||
|
||||
typedef struct bi_charbuff_s {
|
||||
struct bi_charbuff_s *next;
|
||||
draw_charbuffer_t *buffer;
|
||||
} bi_charbuff_t;
|
||||
|
||||
typedef struct {
|
||||
PR_RESMAP (qpic_res_t) qpic_map;
|
||||
PR_RESMAP (bi_charbuff_t) charbuff_map;
|
||||
qpic_res_t *qpics;
|
||||
hashtab_t *pic_hash;
|
||||
bi_charbuff_t *charbuffs;
|
||||
} draw_resources_t;
|
||||
|
||||
static qpic_res_t *
|
||||
|
@ -121,6 +128,47 @@ get_qpic (progs_t *pr, draw_resources_t *res, const char *name, int qpic_handle)
|
|||
return qp;
|
||||
}
|
||||
|
||||
static bi_charbuff_t *
|
||||
charbuff_new (draw_resources_t *res)
|
||||
{
|
||||
return PR_RESNEW (res->charbuff_map);
|
||||
}
|
||||
|
||||
static void
|
||||
charbuff_free (draw_resources_t *res, bi_charbuff_t *cbuff)
|
||||
{
|
||||
Draw_DestroyBuffer (cbuff->buffer);
|
||||
PR_RESFREE (res->charbuff_map, cbuff);
|
||||
}
|
||||
|
||||
static void
|
||||
charbuff_reset (draw_resources_t *res)
|
||||
{
|
||||
PR_RESRESET (res->charbuff_map);
|
||||
}
|
||||
|
||||
static inline bi_charbuff_t *
|
||||
charbuff_get (draw_resources_t *res, int index)
|
||||
{
|
||||
return PR_RESGET (res->charbuff_map, index);
|
||||
}
|
||||
|
||||
static inline int __attribute__((pure))
|
||||
charbuff_index (draw_resources_t *res, bi_charbuff_t *qp)
|
||||
{
|
||||
return PR_RESINDEX (res->charbuff_map, qp);
|
||||
}
|
||||
|
||||
static bi_charbuff_t * __attribute__((pure))
|
||||
get_charbuff (progs_t *pr, draw_resources_t *res, const char *name, int charbuff_handle)
|
||||
{
|
||||
bi_charbuff_t *cbuff = charbuff_get (res, charbuff_handle);
|
||||
|
||||
if (!cbuff)
|
||||
PR_RunError (pr, "invalid charbuff handle passed to %s", name + 3);
|
||||
return cbuff;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Draw_FreePic (progs_t *pr, void *_res)
|
||||
{
|
||||
|
@ -354,6 +402,66 @@ bi_Font_String (progs_t *pr, void *_res)
|
|||
r_funcs->Draw_FontString (x, y, str);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Draw_CreateBuffer (progs_t *pr, void *_res)
|
||||
{
|
||||
draw_resources_t *res = _res;
|
||||
int width = P_INT (pr, 0);
|
||||
int height = P_INT (pr, 1);
|
||||
draw_charbuffer_t *buffer;
|
||||
bi_charbuff_t *cbuff;
|
||||
|
||||
buffer = Draw_CreateBuffer (width, height);
|
||||
cbuff = charbuff_new (res);
|
||||
cbuff->next = res->charbuffs;
|
||||
res->charbuffs = cbuff;
|
||||
cbuff->buffer = buffer;
|
||||
R_INT (pr) = charbuff_index (res, cbuff);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Draw_DestroyBuffer (progs_t *pr, void *_res)
|
||||
{
|
||||
draw_resources_t *res = _res;
|
||||
pr_ptr_t cbuff_handle = P_POINTER (pr, 0);
|
||||
bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle);
|
||||
|
||||
charbuff_free (res, cbuff);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Draw_ClearBuffer (progs_t *pr, void *_res)
|
||||
{
|
||||
draw_resources_t *res = _res;
|
||||
pr_ptr_t cbuff_handle = P_POINTER (pr, 0);
|
||||
bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle);
|
||||
|
||||
Draw_ClearBuffer (cbuff->buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Draw_ScrollBuffer (progs_t *pr, void *_res)
|
||||
{
|
||||
draw_resources_t *res = _res;
|
||||
pr_ptr_t cbuff_handle = P_POINTER (pr, 0);
|
||||
bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle);
|
||||
int lines = P_INT (pr, 1);
|
||||
|
||||
Draw_ScrollBuffer (cbuff->buffer, lines);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Draw_CharBuffer (progs_t *pr, void *_res)
|
||||
{
|
||||
draw_resources_t *res = _res;
|
||||
int x = P_INT (pr, 0);
|
||||
int y = P_INT (pr, 1);
|
||||
pr_ptr_t cbuff_handle = P_POINTER (pr, 2);
|
||||
bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle);
|
||||
|
||||
Draw_CharBuffer (x, y, cbuff->buffer);
|
||||
}
|
||||
|
||||
static const char *
|
||||
bi_draw_get_key (const void *p, void *unused)
|
||||
{
|
||||
|
@ -365,13 +473,20 @@ bi_draw_clear (progs_t *pr, void *_res)
|
|||
{
|
||||
draw_resources_t *res = (draw_resources_t *) _res;
|
||||
qpic_res_t *qp;
|
||||
bi_charbuff_t *cbuff;
|
||||
|
||||
for (qp = res->qpics; qp; qp = qp->next) {
|
||||
bi_draw_free_qpic (qp);
|
||||
}
|
||||
res->qpics = 0;
|
||||
|
||||
for (cbuff = res->charbuffs; cbuff; cbuff = cbuff->next) {
|
||||
Draw_DestroyBuffer (cbuff->buffer);
|
||||
}
|
||||
res->charbuffs = 0;
|
||||
|
||||
qpic_reset (res);
|
||||
charbuff_reset (res);
|
||||
Hash_FlushTable (res->pic_hash);
|
||||
}
|
||||
|
||||
|
@ -406,6 +521,12 @@ static builtin_t builtins[] = {
|
|||
|
||||
bi(Font_Load, 2, p(string), p(int)),
|
||||
bi(Font_String, 3, p(int), p(int), p(string)),
|
||||
|
||||
bi(Draw_CreateBuffer, 2, p(int), p(int)),
|
||||
bi(Draw_DestroyBuffer, 1, p(ptr)),
|
||||
bi(Draw_ClearBuffer, 1, p(ptr)),
|
||||
bi(Draw_ScrollBuffer, 2, p(ptr), p(int)),
|
||||
bi(Draw_CharBuffer, 3, p(int), p(int), p(ptr)),
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -245,7 +245,6 @@ Draw_Init (void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Draw_Character
|
||||
|
||||
|
@ -306,6 +305,21 @@ Draw_Character (int x, int y, unsigned int chr)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
sw_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer)
|
||||
{
|
||||
const byte *line = (byte *) buffer->chars;
|
||||
int width = buffer->width;
|
||||
int height = buffer->height;
|
||||
while (height-- > 0) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
Draw_Character (x + i * 8, y, line[i]);
|
||||
}
|
||||
line += width;
|
||||
y += 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Draw_String (int x, int y, const char *str)
|
||||
|
|
|
@ -486,6 +486,7 @@ gl_capture_screen (capfunc_t callback, void *data)
|
|||
|
||||
vid_render_funcs_t gl_vid_render_funcs = {
|
||||
gl_vid_render_init,
|
||||
gl_Draw_CharBuffer,
|
||||
gl_Draw_Character,
|
||||
gl_Draw_String,
|
||||
gl_Draw_nString,
|
||||
|
|
|
@ -430,6 +430,7 @@ glsl_capture_screen (capfunc_t callback, void *data)
|
|||
|
||||
vid_render_funcs_t glsl_vid_render_funcs = {
|
||||
glsl_vid_render_init,
|
||||
glsl_Draw_CharBuffer,
|
||||
glsl_Draw_Character,
|
||||
glsl_Draw_String,
|
||||
glsl_Draw_nString,
|
||||
|
|
|
@ -450,6 +450,7 @@ sw_capture_screen (capfunc_t callback, void *data)
|
|||
|
||||
vid_render_funcs_t sw_vid_render_funcs = {
|
||||
sw_vid_render_init,
|
||||
sw_Draw_CharBuffer,
|
||||
Draw_Character,
|
||||
Draw_String,
|
||||
Draw_nString,
|
||||
|
|
|
@ -135,6 +135,12 @@ vulkan_R_LineGraph (int x, int y, int *h_vals, int count, int height)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer)
|
||||
{
|
||||
Vulkan_Draw_CharBuffer (x, y, buffer, vulkan_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_Draw_Character (int x, int y, unsigned ch)
|
||||
{
|
||||
|
@ -740,6 +746,7 @@ vulkan_vid_render_shutdown (void)
|
|||
|
||||
vid_render_funcs_t vulkan_vid_render_funcs = {
|
||||
vulkan_vid_render_init,
|
||||
vulkan_Draw_CharBuffer,
|
||||
vulkan_Draw_Character,
|
||||
vulkan_Draw_String,
|
||||
vulkan_Draw_nString,
|
||||
|
|
|
@ -571,6 +571,22 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx)
|
|||
&frame->quad_verts);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer,
|
||||
vulkan_ctx_t *ctx)
|
||||
{
|
||||
const byte *line = (byte *) buffer->chars;
|
||||
int width = buffer->width;
|
||||
int height = buffer->height;
|
||||
while (height-- > 0) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
Vulkan_Draw_Character (x + i * 8, y, line[i], ctx);
|
||||
}
|
||||
line += width;
|
||||
y += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue