SACT2: only render when scene changes

Track dirty status of scene. This cuts the CPU usage roughly in half at
idle. Could be improved further with damage tracking.
This commit is contained in:
Nunuhara Cabbage
2020-09-06 11:06:43 -07:00
parent 678a9a96f0
commit 2bda2b0ea8
4 changed files with 85 additions and 45 deletions
+10
View File
@@ -47,8 +47,18 @@ struct sact_sprite {
int cg_no;
};
extern bool sact_dirty;
static inline void sprite_dirty(struct sact_sprite *sp)
{
if (sp && sp->show)
sact_dirty = true;
}
struct sact_sprite *sact_get_sprite(int sp);
struct sact_sprite *sact_get_sprite_dirty(int sp);
struct texture *sact_get_texture(int sp_no);
struct texture *sact_get_texture_dirty(int sp_no);
void sact_render_scene(void);
+26 -25
View File
@@ -19,101 +19,102 @@
#include "gfx/types.h"
#include "system4/string.h"
#define TEX(sp_no) sact_get_texture(sp_no)
#define STEX(sp_no) sact_get_texture(sp_no)
#define DTEX(sp_no) sact_get_texture_dirty(sp_no)
static void DrawGraph_Copy(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_copy(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_copy(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static void DrawGraph_CopyBright(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int rate)
{
gfx_copy_bright(TEX(dst), dx, dy, TEX(src), sx, sy, w, h, rate);
gfx_copy_bright(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h, rate);
}
static void DrawGraph_CopyAMap(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_copy_amap(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_copy_amap(STEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static void DrawGraph_CopySprite(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int r, int g, int b)
{
gfx_copy_sprite(TEX(dst), dx, dy, TEX(src), sx, sy, w, h, COLOR(r, g, b, 0));
gfx_copy_sprite(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h, COLOR(r, g, b, 0));
}
static void DrawGraph_CopyUseAMapUnder(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int alpha)
{
gfx_copy_use_amap_under(TEX(dst), dx, dy, TEX(src), sx, sy, w, h, alpha);
gfx_copy_use_amap_under(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h, alpha);
}
static void DrawGraph_CopyUseAMapBorder(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int alpha)
{
gfx_copy_use_amap_border(TEX(dst), dx, dy, TEX(src), sx, sy, w, h, alpha);
gfx_copy_use_amap_border(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h, alpha);
}
static void DrawGraph_CopyAMapMax(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_copy_amap_max(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_copy_amap_max(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static void DrawGraph_CopyAMapMin(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_copy_amap_min(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_copy_amap_min(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static void DrawGraph_Blend(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int alpha)
{
gfx_blend(TEX(dst), dx, dy, TEX(src), sx, sy, w, h, alpha);
gfx_blend(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h, alpha);
}
static void DrawGraph_BlendAMap(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_blend_amap(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_blend_amap(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static void DrawGraph_BlendAMapAlpha(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int alpha)
{
gfx_blend_amap_alpha(TEX(dst), dx, dy, TEX(src), sx, sy, w, h, alpha);
gfx_blend_amap_alpha(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h, alpha);
}
static void DrawGraph_Fill(int dst, int x, int y, int w, int h, int r, int g, int b)
{
gfx_fill(TEX(dst), x, y, w, h, r, g, b);
gfx_fill(DTEX(dst), x, y, w, h, r, g, b);
}
static void DrawGraph_FillAlphaColor(int dst, int x, int y, int w, int h, int r, int g, int b, int rate)
{
gfx_fill_alpha_color(TEX(dst), x, y, w, h, r, g, b, rate);
gfx_fill_alpha_color(DTEX(dst), x, y, w, h, r, g, b, rate);
}
static void DrawGraph_FillAMap(int dst, int x, int y, int w, int h, int alpha)
{
gfx_fill_amap(TEX(dst), x, y, w, h, alpha);
gfx_fill_amap(DTEX(dst), x, y, w, h, alpha);
}
static void DrawGraph_AddDA_DAxSA(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_add_da_daxsa(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_add_da_daxsa(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static void DrawGraph_CopyStretch(int dst, int dx, int dy, int dw, int dh, int src, int sx, int sy, int sw, int sh)
{
gfx_copy_stretch(TEX(dst), dx, dy, dw, dh, TEX(src), sx, sy, sw, sh);
gfx_copy_stretch(DTEX(dst), dx, dy, dw, dh, STEX(src), sx, sy, sw, sh);
}
static void DrawGraph_CopyStretchAMap(int dst, int dx, int dy, int dw, int dh, int src, int sx, int sy, int sw, int sh)
{
gfx_copy_stretch_amap(TEX(dst), dx, dy, dw, dh, TEX(src), sx, sy, sw, sh);
gfx_copy_stretch_amap(DTEX(dst), dx, dy, dw, dh, STEX(src), sx, sy, sw, sh);
}
static void DrawGraph_DrawTextToPMap(int dst, int x, int y, struct string *s)
{
gfx_draw_text_to_pmap(TEX(dst), x, y, s->text);
gfx_draw_text_to_pmap(DTEX(dst), x, y, s->text);
}
static void DrawGraph_DrawTextToAMap(int dst, int x, int y, struct string *s)
{
gfx_draw_text_to_amap(TEX(dst), x, y, s->text);
gfx_draw_text_to_amap(DTEX(dst), x, y, s->text);
}
static void DrawGraph_SetFontColor(int r, int g, int b)
@@ -131,27 +132,27 @@ static void DrawGraph_GetFontColor(int *r, int *g, int *b)
static void DrawGraph_CopyRotZoom(int dst, int src, int sx, int sy, int w, int h, float rotate, float mag)
{
gfx_copy_rot_zoom(TEX(dst), TEX(src), sx, sy, w, h, rotate, mag);
gfx_copy_rot_zoom(DTEX(dst), STEX(src), sx, sy, w, h, rotate, mag);
}
static void DrawGraph_CopyRotZoomAMap(int dst, int src, int sx, int sy, int w, int h, float rotate, float mag)
{
gfx_copy_rot_zoom_amap(TEX(dst), TEX(src), sx, sy, w, h, rotate, mag);
gfx_copy_rot_zoom_amap(DTEX(dst), STEX(src), sx, sy, w, h, rotate, mag);
}
static void DrawGraph_CopyRotZoomUseAMap(int dst, int src, int sx, int sy, int w, int h, float rotate, float mag)
{
gfx_copy_rot_zoom_use_amap(TEX(dst), TEX(src), sx, sy, w, h, rotate, mag);
gfx_copy_rot_zoom_use_amap(DTEX(dst), STEX(src), sx, sy, w, h, rotate, mag);
}
static void DrawGraph_CopyReverseLR(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_copy_reverse_LR(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_copy_reverse_LR(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static void DrawGraph_CopyReverseAMapLR(int dst, int dx, int dy, int src, int sx, int sy, int w, int h)
{
gfx_copy_reverse_amap_LR(TEX(dst), dx, dy, TEX(src), sx, sy, w, h);
gfx_copy_reverse_amap_LR(DTEX(dst), dx, dy, STEX(src), sx, sy, w, h);
}
static bool DrawGraph_GetAlphaColor(int surface, int x, int y, int *a)
+1 -1
View File
@@ -236,7 +236,7 @@ static void sact_System_GetTime(int *hour, int *min, int *sec, int *ms)
static void sact_CG_BlendAMapBin(int dst, int dx, int dy, int src, int sx, int sy, int w, int h, int border)
{
gfx_copy_use_amap_border(sact_get_texture(dst), dx, dy, sact_get_texture(src), sx, sy, w, h, border);
gfx_copy_use_amap_border(sact_get_texture_dirty(dst), dx, dy, sact_get_texture(src), sx, sy, w, h, border);
}
//int SACT2_Error(struct string *err);
+48 -19
View File
@@ -32,6 +32,8 @@
static struct sact_sprite *create_sprite(int sp_no, int width, int height, int r, int g, int b, int a);
bool sact_dirty = true;
static struct sact_sprite **sprites = NULL;
static int nr_sprites = 0;
@@ -65,6 +67,14 @@ struct sact_sprite *sact_get_sprite(int sp)
return sprites[sp];
}
struct sact_sprite *sact_get_sprite_dirty(int sp)
{
if (sp < -1 || sp >= nr_sprites)
return NULL;
sprite_dirty(sprites[sp]);
return sprites[sp];
}
struct texture *sact_get_texture(int sp_no)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
@@ -76,10 +86,23 @@ struct texture *sact_get_texture(int sp_no)
return &sp->texture;
}
struct texture *sact_get_texture_dirty(int sp_no)
{
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp)
return NULL;
if (!sp->texture.handle) {
gfx_init_texture_with_color(&sp->texture, sp->rect.w, sp->rect.h, sp->color);
}
return &sp->texture;
}
static struct sact_sprite *alloc_sprite(int sp)
{
sprites[sp] = xcalloc(1, sizeof(struct sact_sprite));
sprites[sp]->no = sp;
sprite_dirty(sprites[sp]);
return sprites[sp];
}
@@ -152,6 +175,7 @@ int sact_SetWP(int cg_no)
gfx_delete_texture(&wp.texture);
gfx_init_texture_with_cg(&wp.texture, cg);
cg_free(cg);
sact_dirty = true;
return 1;
}
@@ -198,8 +222,11 @@ void sact_render_scene(void)
int sact_Update(void)
{
handle_events();
sact_render_scene();
gfx_swap();
if (sact_dirty) {
sact_render_scene();
gfx_swap();
sact_dirty = false;
}
return 1;
}
@@ -246,7 +273,7 @@ int sact_SP_GetMaxZ(void)
int sact_SP_SetCG(int sp_no, int cg_no)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp)
sact_SP_Create(sp_no, 1, 1, 0, 0, 0, 255);
if (!(sp = sact_get_sprite(sp_no))) {
@@ -272,7 +299,7 @@ static struct sact_sprite *create_sprite(int sp_no, int width, int height, int r
if (sp_no >= nr_sprites) {
realloc_sprite_table(sp_no+256);
}
if (!(sp = sact_get_sprite(sp_no)))
if (!(sp = sact_get_sprite_dirty(sp_no)))
sp = alloc_sprite(sp_no);
sp->color = (SDL_Color) { .r = r, .g = g, .b = b, .a = (a >= 0 ? a : 255) };
sp->rect.w = width;
@@ -302,12 +329,13 @@ int sact_SP_Delete(int sp_no)
struct sact_sprite *sp = sact_get_sprite(sp_no);
if (!sp) return 0;
free_sprite(sp);
sact_dirty = true;
return 1;
}
int sact_SP_SetPos(int sp_no, int x, int y)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 1;
sp->rect.x = x;
sp->rect.y = y;
@@ -316,7 +344,7 @@ int sact_SP_SetPos(int sp_no, int x, int y)
int sact_SP_SetX(int sp_no, int x)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
sp->rect.x = x;
return 1;
@@ -324,7 +352,7 @@ int sact_SP_SetX(int sp_no, int x)
int sact_SP_SetY(int sp_no, int y)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
sp->rect.y = y;
return 1;
@@ -332,7 +360,7 @@ int sact_SP_SetY(int sp_no, int y)
int sact_SP_SetZ(int sp_no, int z)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
sp->z = z;
if (sp->show) {
@@ -351,7 +379,7 @@ int sact_SP_GetBlendRate(int sp_no)
int sact_SP_SetBlendRate(int sp_no, int rate)
{
struct texture *t = sact_get_texture(sp_no);
struct texture *t = sact_get_texture_dirty(sp_no);
if (!t) return 0;
t->alpha_mod = max(0, min(255, rate));
return 1;
@@ -364,6 +392,7 @@ int sact_SP_SetShow(int sp_no, bool show)
if (show == sp->show)
return 1;
sp->show = show;
sprite_dirty(sp);
if (show)
sprite_register(sp);
else
@@ -373,7 +402,7 @@ int sact_SP_SetShow(int sp_no, bool show)
int sact_SP_SetDrawMethod(int sp_no, int method)
{
struct texture *t = sact_get_texture(sp_no);
struct texture *t = sact_get_texture_dirty(sp_no);
if (!t) return 0;
if (method < 0 || method >= NR_DRAW_METHODS) {
WARNING("unknown draw method: %d", method);
@@ -446,7 +475,7 @@ int sact_SP_GetShow(int sp_no)
int sact_SP_SetTextHome(int sp_no, int x, int y)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
sp->text.home = (Point) { .x = x, .y = y };
return 1;
@@ -454,7 +483,7 @@ int sact_SP_SetTextHome(int sp_no, int x, int y)
int sact_SP_SetTextLineSpace(int sp_no, int px)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 1;
sp->text.line_space = px;
return 1;
@@ -462,7 +491,7 @@ int sact_SP_SetTextLineSpace(int sp_no, int px)
int sact_SP_SetTextCharSpace(int sp_no, int px)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 1;
sp->text.char_space = px;
return 1;
@@ -470,7 +499,7 @@ int sact_SP_SetTextCharSpace(int sp_no, int px)
int sact_SP_SetTextPos(int sp_no, int x, int y)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
sp->text.pos = (Point) { .x = x, .y = y };
return 1;
@@ -503,7 +532,7 @@ static void init_text_metrics(struct text_metrics *tm, union vm_value *_tm)
int _sact_SP_TextDraw(int sp_no, struct string *text, struct text_metrics *tm)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
if (!sp->text.texture.handle) {
@@ -536,7 +565,7 @@ static void clear_text(struct sact_sprite *sp)
int sact_SP_TextClear(int sp_no)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
clear_text(sp);
return 1;
@@ -544,7 +573,7 @@ int sact_SP_TextClear(int sp_no)
int sact_SP_TextHome(int sp_no, possibly_unused int size)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
// FIXME: do something with nTextSize
sp->text.pos = sp->text.home;
@@ -553,7 +582,7 @@ int sact_SP_TextHome(int sp_no, possibly_unused int size)
int sact_SP_TextNewLine(int sp_no, int size)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp = sact_get_sprite_dirty(sp_no);
if (!sp) return 0;
sp->text.pos = POINT(sp->text.home.x, sp->text.pos.y + size + sp->text.line_space);
return 1;
@@ -561,7 +590,7 @@ int sact_SP_TextNewLine(int sp_no, int size)
int sact_SP_TextCopy(int dno, int sno)
{
struct sact_sprite *dsp = sact_get_sprite(dno);
struct sact_sprite *dsp = sact_get_sprite_dirty(dno);
struct sact_sprite *ssp = sact_get_sprite(sno);
if (!ssp)
return 0;