mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-05 21:37:59 +03:00
Refactor graphics code
Sprites are now rendered directly, rather than being blitted to a master surface which is then copied to a texture. Every sprite now carries an SDL_Texture in addition to an SDL_Surface (we need both, since SDL_Texture doesn't give read-access to the pixel data). All of the image-manipulation code is now in sdl_draw.c, and the DrawGraph_* functions are now wrappers. Some games (Daibanchou at least) use an API other than SACT2/DrawGraph, so these operations should be generic to avoid duplication.
This commit is contained in:
@@ -39,7 +39,6 @@ static enum cg_type check_cgformat(uint8_t *data)
|
||||
if (qnt_checkfmt(data)) {
|
||||
return ALCG_QNT;
|
||||
}
|
||||
WARNING("Unknown CG type");
|
||||
return ALCG_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -55,6 +54,7 @@ bool cg_get_metrics(int no, struct cg_metrics *dst)
|
||||
qnt_get_metrics(dfile->data, dst);
|
||||
break;
|
||||
default:
|
||||
WARNING("Unknown CG type (CG %d)", no);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -89,7 +89,7 @@ void cg_free(struct cg *cg)
|
||||
bool cg_load(struct cg *cg, int no)
|
||||
{
|
||||
struct archive_data *dfile;
|
||||
int type, possibly_unused size = 0;
|
||||
int type;
|
||||
|
||||
if (!(dfile = ald_get(ald[ALDFILE_CG], no))) {
|
||||
WARNING("Failed to load CG %d", no);
|
||||
@@ -100,32 +100,32 @@ bool cg_load(struct cg *cg, int no)
|
||||
type = check_cgformat(dfile->data);
|
||||
|
||||
// extract cg
|
||||
// size is only pixel data size
|
||||
switch(type) {
|
||||
case ALCG_QNT:
|
||||
cg->type = ALCG_QNT;
|
||||
cg->s = qnt_extract(dfile->data);
|
||||
cg->pixel_alloc = true;
|
||||
qnt_extract(dfile->data, cg);
|
||||
break;
|
||||
case ALCG_AJP:
|
||||
// TODO
|
||||
WARNING("Unimplemented CG type: AJP");
|
||||
break;
|
||||
case ALCG_PNG:
|
||||
// TODO
|
||||
WARNING("Unimplemented CG type: PNG");
|
||||
break;
|
||||
default:
|
||||
WARNING("Unknown CG type (CG %d)", no);
|
||||
break;
|
||||
}
|
||||
|
||||
// ok to free
|
||||
ald_free_data(dfile);
|
||||
|
||||
return true;
|
||||
return !!cg->s;
|
||||
}
|
||||
|
||||
void _cg_init(struct cg *cg)
|
||||
{
|
||||
cg->type = ALCG_UNKNOWN;
|
||||
cg->pixel_alloc = false;
|
||||
cg->has_alpha = false;
|
||||
cg->s = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ enum cg_type {
|
||||
struct cg {
|
||||
enum cg_type type; // cg format type
|
||||
bool pixel_alloc;
|
||||
bool has_alpha;
|
||||
SDL_Surface *s;
|
||||
SDL_Texture *t;
|
||||
};
|
||||
|
||||
struct cg_metrics {
|
||||
|
||||
+7
-18
@@ -22,30 +22,19 @@
|
||||
#include <stdint.h>
|
||||
#include <SDL.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t red[256];
|
||||
uint8_t green[256];
|
||||
uint8_t blue[256];
|
||||
} Pallet256;
|
||||
|
||||
typedef struct {
|
||||
uint8_t r,g,b;
|
||||
uint32_t pixel;
|
||||
} Pallet;
|
||||
|
||||
typedef SDL_Point Point;
|
||||
|
||||
#define POINT(_x, _y) ((Point){.x=_x, .y=_y})
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int w;
|
||||
int h;
|
||||
} Dimension;
|
||||
|
||||
#define DIM(_w, _h) ((Dimension){.w=_w, .h=_h})
|
||||
|
||||
typedef SDL_Rect Rectangle;
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
} DispInfo;
|
||||
#define RECT(_x, _y, _w, _h) ((Rectangle){.x=_x, .y=_y, .w=_w, .h=_h})
|
||||
|
||||
#endif /* SYSTEM4_GRAPHICS_H */
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "cg.h"
|
||||
#include "qnt.h"
|
||||
#include "system4.h"
|
||||
#include "sdl_private.h"
|
||||
#include "sdl_core.h"
|
||||
|
||||
/*
|
||||
zlib の展開バッファで、幅×高さ×3に、さらにどれくらい余裕をとるか
|
||||
@@ -249,17 +251,27 @@ bool qnt_get_metrics(uint8_t *data, struct cg_metrics *dst)
|
||||
*
|
||||
* return: extracted image data and information
|
||||
*/
|
||||
SDL_Surface *qnt_extract(uint8_t *data)
|
||||
void qnt_extract(uint8_t *data, struct cg *cg)
|
||||
{
|
||||
struct qnt_header qnt;
|
||||
extract_header(data, &qnt);
|
||||
uint8_t *pixels = malloc(sizeof(uint8_t) * ((qnt.width+10) * (qnt.height+10) * 3));
|
||||
extract_pixel(&qnt, pixels, data + qnt.hdr_size);
|
||||
|
||||
if (!qnt.alpha_size)
|
||||
return SDL_CreateRGBSurfaceWithFormatFrom(pixels, qnt.width, qnt.height, 24,
|
||||
qnt.width * 3, SDL_PIXELFORMAT_RGB24);
|
||||
cg->type = ALCG_QNT;
|
||||
cg->has_alpha = qnt.alpha_size > 0;
|
||||
|
||||
if (!qnt.alpha_size) {
|
||||
// convert RGB -> ARGB
|
||||
SDL_Surface *tmp = SDL_CreateRGBSurfaceWithFormatFrom(pixels, qnt.width, qnt.height, 24,
|
||||
qnt.width * 3, SDL_PIXELFORMAT_RGB24);
|
||||
cg->s = SDL_ConvertSurface(tmp, sdl.format, 0);
|
||||
cg->t = sdl_surface_to_texture(cg->s);
|
||||
cg->pixel_alloc = false;
|
||||
SDL_FreeSurface(tmp);
|
||||
free(pixels);
|
||||
return;
|
||||
}
|
||||
// combine color/alpha data
|
||||
uint8_t *alpha = malloc(sizeof(uint8_t) * ((qnt.width+10) * (qnt.height+10)));
|
||||
uint8_t *tmp = malloc((qnt.width+10) * (qnt.height+10) * 4);
|
||||
@@ -274,6 +286,8 @@ SDL_Surface *qnt_extract(uint8_t *data)
|
||||
free(pixels);
|
||||
pixels = tmp;
|
||||
|
||||
return SDL_CreateRGBSurfaceWithFormatFrom(pixels, qnt.width, qnt.height, 32,
|
||||
qnt.width * 4, SDL_PIXELFORMAT_ARGB32);
|
||||
cg->s = SDL_CreateRGBSurfaceWithFormatFrom(pixels, qnt.width, qnt.height, 32,
|
||||
qnt.width * 4, SDL_PIXELFORMAT_ARGB32);
|
||||
cg->t = sdl_surface_to_texture(cg->s);
|
||||
cg->pixel_alloc = true;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,6 @@ struct qnt_header {
|
||||
|
||||
bool qnt_checkfmt(uint8_t *data);
|
||||
bool qnt_get_metrics(uint8_t *data, struct cg_metrics *dst);
|
||||
SDL_Surface *qnt_extract(uint8_t *data);
|
||||
void qnt_extract(uint8_t *data, struct cg *cg);
|
||||
|
||||
#endif /* __QNT_H__ */
|
||||
|
||||
@@ -34,6 +34,7 @@ struct sact_sprite {
|
||||
struct {
|
||||
struct string *str;
|
||||
SDL_Surface *surf;
|
||||
SDL_Texture *t;
|
||||
Point home;
|
||||
Point pos;
|
||||
int char_space;
|
||||
|
||||
+51
-255
@@ -70,17 +70,21 @@ int sact_Init(void)
|
||||
int sact_Update(void)
|
||||
{
|
||||
handle_events();
|
||||
|
||||
sdl_render_clear();
|
||||
struct sact_sprite *p;
|
||||
TAILQ_FOREACH(p, &sprite_list, entry) {
|
||||
if (!p->show)
|
||||
continue;
|
||||
if (!p->cg->s)
|
||||
p->cg->s = sdl_make_rectangle(p->rect.w, p->rect.h, &p->color);
|
||||
sdl_draw_surface(p->cg->s, &p->rect);
|
||||
if (p->text.surf)
|
||||
sdl_draw_surface(p->text.surf, &p->rect);
|
||||
if (!p->cg->s) {
|
||||
p->cg->s = sdl_create_surface(p->rect.w, p->rect.h, &p->color);
|
||||
p->cg->t = sdl_surface_to_texture(p->cg->s);
|
||||
}
|
||||
sdl_render_texture(p->cg->t, &p->rect);
|
||||
if (p->text.t)
|
||||
sdl_render_texture(p->text.t, &p->rect);
|
||||
}
|
||||
sdl_update_screen();
|
||||
sdl_render_present();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -253,7 +257,7 @@ static struct sact_sprite *create_sprite(int sp_no, int width, int height, int r
|
||||
VM_ERROR("Invalid sprite number: %d", sp_no);
|
||||
if (!(sp = sact_get_sprite(sp_no)))
|
||||
sp = alloc_sprite(sp_no);
|
||||
sp->color = (SDL_Color) { .r = r, .g = g, .b = b, .a = a };
|
||||
sp->color = (SDL_Color) { .r = r, .g = g, .b = b, .a = (a >= 0 ? a : 255) };
|
||||
sp->rect.w = width;
|
||||
sp->rect.h = height;
|
||||
if (sp->cg) {
|
||||
@@ -262,6 +266,7 @@ static struct sact_sprite *create_sprite(int sp_no, int width, int height, int r
|
||||
sp->cg = cg_init();
|
||||
sprite_register(sp);
|
||||
}
|
||||
sp->cg->has_alpha = a >= 0;
|
||||
return sp;
|
||||
}
|
||||
|
||||
@@ -273,7 +278,7 @@ int sact_SP_Create(int sp_no, int width, int height, int r, int g, int b, int a)
|
||||
|
||||
int sact_SP_CreatePixelOnly(int sp_no, int width, int height)
|
||||
{
|
||||
create_sprite(sp_no, width, height, 0, 0, 0, 255);
|
||||
create_sprite(sp_no, width, height, 0, 0, 0, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -303,46 +308,31 @@ int sact_SP_ExistsAlpha(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
if (!sp) return 0;
|
||||
if (!sp->cg->s) return 1;
|
||||
return !!sp->cg->s->format->Amask;
|
||||
return sp->cg->has_alpha;
|
||||
}
|
||||
|
||||
#define tm_ColorR(tm) (tm[0].i)
|
||||
#define tm_ColorG(tm) (tm[1].i)
|
||||
#define tm_ColorB(tm) (tm[2].i)
|
||||
#define tm_Size(tm) (tm[3].i)
|
||||
#define tm_Weight(tm) (tm[4].i)
|
||||
#define tm_Face(tm) (tm[5].i)
|
||||
#define tm_ShadowPixelL(tm) (tm[6].i)
|
||||
#define tm_ShadowPixelU(tm) (tm[7].i)
|
||||
#define tm_ShadowPixelR(tm) (tm[8].i)
|
||||
#define tm_ShadowPixelD(tm) (tm[9].i)
|
||||
#define tm_ShadowColorR(tm) (tm[10].i)
|
||||
#define tm_ShadowColorG(tm) (tm[11].i)
|
||||
#define tm_ShadowColorB(tm) (tm[12].i)
|
||||
|
||||
static void init_text_metrics(struct text_metrics *tm, union vm_value *_tm)
|
||||
{
|
||||
*tm = (struct text_metrics) {
|
||||
.color = {
|
||||
.r = tm_ColorR(_tm),
|
||||
.g = tm_ColorG(_tm),
|
||||
.b = tm_ColorB(_tm),
|
||||
.r = _tm[0].i,
|
||||
.g = _tm[1].i,
|
||||
.b = _tm[2].i,
|
||||
.a = 255
|
||||
},
|
||||
.outline_color = {
|
||||
.r = tm_ShadowColorR(_tm),
|
||||
.g = tm_ShadowColorG(_tm),
|
||||
.b = tm_ShadowColorB(_tm),
|
||||
.r = _tm[10].i,
|
||||
.g = _tm[11].i,
|
||||
.b = _tm[12].i,
|
||||
.a = 255
|
||||
},
|
||||
.size = tm_Size(_tm),
|
||||
.weight = tm_Weight(_tm),
|
||||
.face = tm_Face(_tm),
|
||||
.outline_left = tm_ShadowPixelL(_tm),
|
||||
.outline_up = tm_ShadowPixelU(_tm),
|
||||
.outline_right = tm_ShadowPixelR(_tm),
|
||||
.outline_down = tm_ShadowPixelD(_tm),
|
||||
.size = _tm[3].i,
|
||||
.weight = _tm[4].i,
|
||||
.face = _tm[5].i,
|
||||
.outline_left = _tm[6].i,
|
||||
.outline_up = _tm[7].i,
|
||||
.outline_right = _tm[8].i,
|
||||
.outline_down = _tm[9].i,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -354,11 +344,13 @@ int sact_SP_TextDraw(int sp_no, struct string *text, union vm_value *_tm)
|
||||
|
||||
if (!sp->text.surf) {
|
||||
SDL_Color c = { 0, 0, 0, 0 };
|
||||
sp->text.surf = sdl_make_rectangle(sp->rect.w, sp->rect.h, &c);
|
||||
sp->text.surf = sdl_create_surface(sp->rect.w, sp->rect.h, &c);
|
||||
sp->text.t = sdl_create_texture(sp->rect.w, sp->rect.h);
|
||||
}
|
||||
|
||||
init_text_metrics(&tm, _tm);
|
||||
sp->text.pos.x += sdl_render_text(sp->text.surf, sp->text.pos, text->text, &tm) + sp->text.char_space;
|
||||
sdl_update_texture(sp->text.t, sp->text.surf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -366,7 +358,9 @@ static void clear_text(struct sact_sprite *sp)
|
||||
{
|
||||
if (sp->text.surf) {
|
||||
SDL_FreeSurface(sp->text.surf);
|
||||
SDL_DestroyTexture(sp->text.t);
|
||||
sp->text.surf = NULL;
|
||||
sp->text.t = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,9 +389,11 @@ int sact_SP_TextCopy(int dno, int sno)
|
||||
clear_text(dsp);
|
||||
if (ssp->text.surf) {
|
||||
SDL_Color c = { 0, 0, 0, 0 };
|
||||
Rectangle rect = { .x = 0, .y = 0, .w = dsp->rect.w, .h = dsp->rect.h };
|
||||
dsp->text.surf = sdl_make_rectangle(dsp->rect.w, dsp->rect.h, &c);
|
||||
Rectangle rect = RECT(0, 0, dsp->rect.w, dsp->rect.h);
|
||||
dsp->text.surf = sdl_create_surface(dsp->rect.w, dsp->rect.h, &c);
|
||||
dsp->text.t = sdl_create_texture(dsp->rect.w, dsp->rect.h);
|
||||
SDL_BlitSurface(ssp->text.surf, NULL, dsp->text.surf, &rect);
|
||||
sdl_update_texture(dsp->text.t, dsp->text.surf);
|
||||
}
|
||||
dsp->text.home = ssp->text.home;
|
||||
dsp->text.pos = ssp->text.pos;
|
||||
@@ -425,269 +421,69 @@ int sact_CG_GetMetrics(int cg_no, union vm_value *cgm)
|
||||
// --- DrawGraph.dll ---
|
||||
//
|
||||
|
||||
struct sact_sprite *DrawGraph_get_sprite(int no)
|
||||
struct sact_sprite *get_surface(int no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(no);
|
||||
if (!sp)
|
||||
ERROR("Invalid sprite number: %d", no);
|
||||
if (!sp->cg->s)
|
||||
sp->cg->s = sdl_make_rectangle(sp->rect.w, sp->rect.h, &sp->color);
|
||||
sp->cg->s = sdl_create_surface(sp->rect.w, sp->rect.h, &sp->color);
|
||||
if (!sp->cg->t)
|
||||
sp->cg->t = sdl_surface_to_texture(sp->cg->s);
|
||||
return sp;
|
||||
}
|
||||
|
||||
static void DrawGraph_Blit(SDL_Surface *ds, int dx, int dy, SDL_Surface *ss, int sx, int sy, int w, int h)
|
||||
{
|
||||
Rectangle src_rect = { .x = sx, .y = sy, .w = w, .h = h };
|
||||
Rectangle dst_rect = { .x = dx, .y = dy, .w = w, .h = h };
|
||||
SDL_BlitSurface(ss, &src_rect, ds, &dst_rect);
|
||||
}
|
||||
|
||||
void DrawGraph_Copy(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h)
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
SDL_GetSurfaceBlendMode(ss, &mode);
|
||||
SDL_SetSurfaceBlendMode(ss, SDL_BLENDMODE_NONE);
|
||||
|
||||
DrawGraph_Blit(ds, dx, dy, ss, sx, sy, w, h);
|
||||
|
||||
SDL_SetSurfaceBlendMode(ss, mode);
|
||||
sdl_copy(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h);
|
||||
}
|
||||
|
||||
void DrawGraph_CopyBright(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h, int rate)
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
SDL_GetSurfaceBlendMode(ss, &mode);
|
||||
SDL_SetSurfaceBlendMode(ss, SDL_BLENDMODE_NONE);
|
||||
SDL_SetSurfaceColorMod(ss, rate, rate, rate);
|
||||
|
||||
DrawGraph_Blit(ds, dx, dy, ss, sx, sy, w, h);
|
||||
|
||||
SDL_SetSurfaceColorMod(ss, 255, 255, 255);
|
||||
SDL_SetSurfaceBlendMode(ss, mode);
|
||||
sdl_copy_bright(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h, rate);
|
||||
}
|
||||
|
||||
// Clip src/dst rectangles in preparation for a copy.
|
||||
static void clip_rects(SDL_Surface *ds, int *dx, int *dy, SDL_Surface *ss, int *sx, int *sy, int *w, int *h)
|
||||
{
|
||||
if (*sx < 0) {
|
||||
*dx -= *sx;
|
||||
*w += *sx;
|
||||
*sx = 0;
|
||||
}
|
||||
if (*sy < 0) {
|
||||
*dy -= *sy;
|
||||
*h += *sy;
|
||||
*sy = 0;
|
||||
}
|
||||
if (*dx < 0) {
|
||||
*sx -= *dx;
|
||||
*w += *dx;
|
||||
*dx = 0;
|
||||
}
|
||||
if (*dy < 0) {
|
||||
*sy -= *dy;
|
||||
*w += *dy;
|
||||
*dy = 0;
|
||||
}
|
||||
*w = min(*w, min(ds->w - *dx, ss->w - *sx));
|
||||
*h = min(*h, min(ds->h - *dy, ss->h - *sy));
|
||||
}
|
||||
|
||||
static inline uint32_t *get_pixel(SDL_Surface *s, int x, int y)
|
||||
{
|
||||
return (uint32_t*)(((uint8_t*)s->pixels) + s->pitch*y + s->format->BytesPerPixel*x);
|
||||
}
|
||||
|
||||
static inline void next_pixel(SDL_Surface *s, uint32_t **p)
|
||||
{
|
||||
*p = (uint32_t*)((uint8_t*)*p + s->format->BytesPerPixel);
|
||||
}
|
||||
|
||||
// iterator for copy operations
|
||||
#define copy_for_each_pixel(ds, dx, dy, ss, sx, sy, w, h, dp, sp, expr) \
|
||||
do { \
|
||||
clip_rects(ds, &dx, &dy, ss, &sx, &sy, &w, &h); \
|
||||
SDL_LockSurface(ds); \
|
||||
SDL_LockSurface(ss); \
|
||||
for (int _row = 0; _row < h; _row++) { \
|
||||
uint32_t *dp = get_pixel(ds, dx, _row+dy); \
|
||||
uint32_t *sp = get_pixel(ss, sx, _row+sy); \
|
||||
for (int _col = 0; _col < w; _col++, next_pixel(ds, &dp), next_pixel(ss, &sp)) \
|
||||
expr; \
|
||||
} \
|
||||
SDL_UnlockSurface(ss); \
|
||||
SDL_UnlockSurface(ds); \
|
||||
} while (0)
|
||||
|
||||
#define fill_for_each_pixel(s, x, y, w, h, p, expr) \
|
||||
do { \
|
||||
SDL_LockSurface(s); \
|
||||
for (int _row = 0; _row < h; _row++) { \
|
||||
uint32_t *p = get_pixel(s, x, _row+y); \
|
||||
for (int _col = 0; _col < w; _col++, next_pixel(s, &p)) \
|
||||
expr; \
|
||||
} \
|
||||
SDL_UnlockSurface(s); \
|
||||
} while(0);
|
||||
|
||||
void DrawGraph_CopyAMap(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h)
|
||||
{
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
if (!ds->format->Amask || !ss->format->Amask)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(ds, dx, dy, ss, sx, sy, w, h, dp, sp, {
|
||||
uint32_t a = (*sp & ss->format->Amask) >> ss->format->Ashift;
|
||||
*dp &= ~ds->format->Amask;
|
||||
*dp |= (a << ds->format->Ashift);
|
||||
});
|
||||
sdl_copy_amap(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h);
|
||||
}
|
||||
|
||||
void DrawGraph_CopySprite(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h, int r, int g, int b)
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
SDL_GetSurfaceBlendMode(ss, &mode);
|
||||
SDL_SetSurfaceBlendMode(ss, SDL_BLENDMODE_NONE);
|
||||
SDL_SetColorKey(ss, SDL_TRUE, SDL_MapRGB(ss->format, r, g, b));
|
||||
|
||||
DrawGraph_Blit(ds, dx, dy, ss, sx, sy, w, h);
|
||||
|
||||
SDL_SetColorKey(ss, SDL_FALSE, 0);
|
||||
SDL_SetSurfaceBlendMode(ss, mode);
|
||||
sdl_copy_sprite(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h, r, g, b);
|
||||
}
|
||||
|
||||
void DrawGraph_CopyUseAMapUnder(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h, int a_threshold)
|
||||
{
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
if (!ss->format->Amask)
|
||||
return;
|
||||
|
||||
uint8_t r, g, b, a;
|
||||
copy_for_each_pixel(ds, dx, dy, ss, sx, sy, w, h, dp, sp, {
|
||||
SDL_GetRGBA(*sp, ss->format, &r, &g, &b, &a);
|
||||
if (a <= a_threshold) {
|
||||
*dp &= ~(ds->format->Rmask | ds->format->Gmask | ds->format->Bmask);
|
||||
*dp |= (uint32_t)r << ds->format->Rshift;
|
||||
*dp |= (uint32_t)g << ds->format->Gshift;
|
||||
*dp |= (uint32_t)b << ds->format->Bshift;
|
||||
}
|
||||
});
|
||||
sdl_copy_use_amap_under(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h, a_threshold);
|
||||
}
|
||||
|
||||
void DrawGraph_CopyUseAMapBorder(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h, int a_threshold)
|
||||
{
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
if (!ss->format->Amask)
|
||||
return;
|
||||
|
||||
uint8_t r, g, b, a;
|
||||
copy_for_each_pixel(ds, dx, dy, ss, sx, sy, w, h, dp, sp, {
|
||||
SDL_GetRGBA(*sp, ss->format, &r, &g, &b, &a);
|
||||
if (a >= a_threshold) {
|
||||
*dp &= ~(ds->format->Rmask | ds->format->Gmask | ds->format->Bmask);
|
||||
*dp |= (uint32_t)r << ds->format->Rshift;
|
||||
*dp |= (uint32_t)g << ds->format->Gshift;
|
||||
*dp |= (uint32_t)b << ds->format->Bshift;
|
||||
}
|
||||
});
|
||||
sdl_copy_use_amap_border(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h, a_threshold);
|
||||
}
|
||||
|
||||
void DrawGraph_CopyAMapMax(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h)
|
||||
{
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
if (!ss->format->Amask || !ds->format->Amask)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(ds, dx, dy, ss, sx, sy, w, h, dp, sp, {
|
||||
uint32_t d_a = (*dp & ds->format->Amask) >> ds->format->Ashift;
|
||||
uint32_t s_a = (*sp & ss->format->Amask) >> ss->format->Ashift;
|
||||
if (s_a > d_a) {
|
||||
*dp &= ~ds->format->Amask;
|
||||
*dp |= s_a << ds->format->Ashift;
|
||||
}
|
||||
});
|
||||
sdl_copy_amap_max(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h);
|
||||
}
|
||||
|
||||
void DrawGraph_CopyAMapMin(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h)
|
||||
{
|
||||
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
|
||||
SDL_Surface *ss = DrawGraph_get_sprite(sno)->cg->s;
|
||||
|
||||
if (!ss->format->Amask || !ds->format->Amask)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(ds, dx, dy, ss, sx, sy, w, h, dp, sp, {
|
||||
uint32_t d_a = (*dp & ds->format->Amask) >> ds->format->Ashift;
|
||||
uint32_t s_a = (*sp & ss->format->Amask) >> ss->format->Ashift;
|
||||
if (s_a < d_a) {
|
||||
*dp &= ~ds->format->Amask;
|
||||
*dp |= s_a << ds->format->Ashift;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void blend_pixels(SDL_Color *dst, SDL_Color src)
|
||||
{
|
||||
uint32_t alpha = src.a + 1;
|
||||
uint32_t inv_alpha = 256 - src.a;
|
||||
dst->r = (uint8_t)((alpha * src.r + inv_alpha * dst->r) >> 8);
|
||||
dst->g = (uint8_t)((alpha * src.g + inv_alpha * dst->g) >> 8);
|
||||
dst->b = (uint8_t)((alpha * src.b + inv_alpha * dst->b) >> 8);
|
||||
sdl_copy_amap_min(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h);
|
||||
}
|
||||
|
||||
void DrawGraph_Fill(int sp_no, int x, int y, int w, int h, int r, int g, int b)
|
||||
{
|
||||
SDL_Surface *s = DrawGraph_get_sprite(sp_no)->cg->s;
|
||||
|
||||
fill_for_each_pixel(s, x, y, w, h, p, {
|
||||
*p &= ~(s->format->Rmask | s->format->Gmask | s->format->Bmask);
|
||||
*p |= (uint32_t)r << s->format->Rshift;
|
||||
*p |= (uint32_t)g << s->format->Gshift;
|
||||
*p |= (uint32_t)b << s->format->Bshift;
|
||||
});
|
||||
sdl_fill(get_surface(sp_no)->cg, x, y, w, h, r, g, b);
|
||||
}
|
||||
|
||||
// XXX: Despite being called a fill operation, this function actually performs blending.
|
||||
void DrawGraph_FillAlphaColor(int sp_no, int x, int y, int w, int h, int r, int g, int b, int a)
|
||||
{
|
||||
SDL_Surface *s = DrawGraph_get_sprite(sp_no)->cg->s;
|
||||
|
||||
SDL_Color dst;
|
||||
SDL_Color src = { .r = r, .g = g, .b = b, .a = a };
|
||||
fill_for_each_pixel(s, x, y, w, h, p, {
|
||||
SDL_GetRGBA(*p, s->format, &dst.r, &dst.g, &dst.b, &dst.a);
|
||||
blend_pixels(&dst, src);
|
||||
*p &= ~(s->format->Rmask | s->format->Gmask | s->format->Bmask | s->format->Amask);
|
||||
*p |= (uint32_t)dst.r << s->format->Rshift;
|
||||
*p |= (uint32_t)dst.g << s->format->Gshift;
|
||||
*p |= (uint32_t)dst.b << s->format->Bshift;
|
||||
*p |= (uint32_t)dst.a << s->format->Ashift;
|
||||
});
|
||||
sdl_fill_alpha_color(get_surface(sp_no)->cg, x, y, w, h, r, g, b, a);
|
||||
}
|
||||
|
||||
void DrawGraph_FillAMap(int sp_no, int x, int y, int w, int h, int a)
|
||||
{
|
||||
SDL_Surface *s = DrawGraph_get_sprite(sp_no)->cg->s;
|
||||
|
||||
fill_for_each_pixel(s, x, y, w, h, p, {
|
||||
*p &= ~s->format->Amask;
|
||||
*p |= (uint32_t)a << s->format->Ashift;
|
||||
});
|
||||
sdl_fill_amap(get_surface(sp_no)->cg, x, y, w, h, a);
|
||||
}
|
||||
|
||||
+24
-4
@@ -28,12 +28,32 @@ struct cg;
|
||||
int sdl_initialize(void);
|
||||
void sdl_remove(void);
|
||||
|
||||
void sdl_set_window_size(int x, int y, int w, int h);
|
||||
void sdl_set_window_size(int w, int h);
|
||||
void sdl_fullscreen(bool on);
|
||||
|
||||
void sdl_update_screen(void);
|
||||
void sdl_draw_surface(SDL_Surface *s, Rectangle *dst);
|
||||
SDL_Surface *sdl_make_rectangle(int w, int h, SDL_Color *color);
|
||||
// surface/texture creation
|
||||
SDL_Texture *sdl_create_texture(int w, int h);
|
||||
void sdl_update_texture(SDL_Texture *t, SDL_Surface *s);
|
||||
SDL_Texture *sdl_surface_to_texture(SDL_Surface *s);
|
||||
SDL_Surface *sdl_create_surface(int w, int h, SDL_Color *color);
|
||||
|
||||
// rendering
|
||||
void sdl_render_clear(void);
|
||||
void sdl_render_present(void);
|
||||
void sdl_render_texture(SDL_Texture *t, Rectangle *r);
|
||||
|
||||
// drawing
|
||||
void sdl_copy(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h);
|
||||
void sdl_copy_bright(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int rate);
|
||||
void sdl_copy_amap(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h);
|
||||
void sdl_copy_sprite(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int r, int g, int b);
|
||||
void sdl_copy_use_amap_under(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int a_threshold);
|
||||
void sdl_copy_use_amap_border(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int a_threshold);
|
||||
void sdl_copy_amap_max(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h);
|
||||
void sdl_copy_amap_min(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h);
|
||||
void sdl_fill(struct cg *dst, int x, int y, int w, int h, int r, int g, int b);
|
||||
void sdl_fill_alpha_color(struct cg *dst, int x, int y, int w, int h, int r, int g, int b, int a);
|
||||
void sdl_fill_amap(struct cg *dst, int x, int y, int w, int h, int a);
|
||||
|
||||
enum font_weight {
|
||||
FW_NORMAL = 400,
|
||||
|
||||
+261
-41
@@ -1,5 +1,4 @@
|
||||
/* Copyright (C) 2000- Fumihiko Murata <fmurata@p1.tcnet.ne.jp>
|
||||
* 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
/* 2019 Nunuhara Cabbage <nunuhara@haniwa.technology>
|
||||
*
|
||||
* 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
|
||||
@@ -23,55 +22,276 @@
|
||||
#include "sdl_private.h"
|
||||
#include "cg.h"
|
||||
|
||||
bool sdl_dirty = false;
|
||||
// FIXME: these can be constants (but depend on endianness)
|
||||
#define R_MASK (sdl.format->Rmask)
|
||||
#define G_MASK (sdl.format->Gmask)
|
||||
#define B_MASK (sdl.format->Bmask)
|
||||
#define A_MASK (sdl.format->Amask)
|
||||
|
||||
void sdl_update_screen(void)
|
||||
#define R_SHIFT (sdl.format->Rshift)
|
||||
#define G_SHIFT (sdl.format->Gshift)
|
||||
#define B_SHIFT (sdl.format->Bshift)
|
||||
#define A_SHIFT (sdl.format->Ashift)
|
||||
|
||||
#define PIXEL_R(p) ((p & R_MASK) >> R_SHIFT)
|
||||
#define PIXEL_G(p) ((p & G_MASK) >> G_SHIFT)
|
||||
#define PIXEL_B(p) ((p & B_MASK) >> B_SHIFT)
|
||||
#define PIXEL_A(p) ((p & A_MASK) >> A_SHIFT)
|
||||
|
||||
static inline void PIXEL_SET_R(uint32_t *p, uint8_t r)
|
||||
{
|
||||
if (!sdl.dirty)
|
||||
*p = (*p & ~R_MASK) | (r << R_SHIFT);
|
||||
}
|
||||
|
||||
static inline void PIXEL_SET_G(uint32_t *p, uint8_t g)
|
||||
{
|
||||
*p = (*p & ~G_MASK) | (g << G_SHIFT);
|
||||
}
|
||||
|
||||
static inline void PIXEL_SET_B(uint32_t *p, uint8_t b)
|
||||
{
|
||||
*p = (*p & ~B_MASK) | (b << B_SHIFT);
|
||||
}
|
||||
|
||||
static inline void PIXEL_SET_A(uint32_t *p, uint8_t a)
|
||||
{
|
||||
*p = (*p & ~A_MASK) | (a << A_SHIFT);
|
||||
}
|
||||
|
||||
static inline void PIXEL_SET_RGB(uint32_t *p, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
*p = (*p & A_MASK) | (r << R_SHIFT) | (g << G_SHIFT) | (b << B_SHIFT);
|
||||
}
|
||||
|
||||
static inline void PIXEL_SET_RGBA(uint32_t *p, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
*p = (r << R_SHIFT) | (g << G_SHIFT) | (b << B_SHIFT) | (a << A_SHIFT);
|
||||
}
|
||||
|
||||
// Clip src/dst rectangles in preparation for a copy.
|
||||
static void copy_clip_rects(int dw, int dh, int *dx, int *dy, int sw, int sh, int *sx, int *sy, int *w, int *h)
|
||||
{
|
||||
if (*sx < 0) {
|
||||
*dx -= *sx;
|
||||
*w += *sx;
|
||||
*sx = 0;
|
||||
}
|
||||
if (*sy < 0) {
|
||||
*dy -= *sy;
|
||||
*h += *sy;
|
||||
*sy = 0;
|
||||
}
|
||||
if (*dx < 0) {
|
||||
*sx -= *dx;
|
||||
*w += *dx;
|
||||
*dx = 0;
|
||||
}
|
||||
if (*dy < 0) {
|
||||
*sy -= *dy;
|
||||
*w += *dy;
|
||||
*dy = 0;
|
||||
}
|
||||
*w = min(*w, min(dw - *dx, sw - *sx));
|
||||
*h = min(*h, min(dh - *dy, sh - *sy));
|
||||
}
|
||||
|
||||
static void fill_clip_rect(int *dx, int *dy, int dw, int dh, int *w, int *h)
|
||||
{
|
||||
if (*dx > dw || *dy > dh) {
|
||||
*dx = *dy = *w = *h = 0;
|
||||
return;
|
||||
SDL_UpdateTexture(sdl.texture, NULL, sdl.display->pixels, sdl.display->pitch);
|
||||
SDL_RenderClear(sdl.renderer);
|
||||
SDL_RenderCopy(sdl.renderer, sdl.texture, NULL, NULL);
|
||||
SDL_RenderPresent(sdl.renderer);
|
||||
sdl.dirty = false;
|
||||
}
|
||||
|
||||
if (*dx < 0) {
|
||||
*w += *dx;
|
||||
*dx = 0;
|
||||
}
|
||||
if (*dy < 0) {
|
||||
*h += *dy;
|
||||
*dy = 0;
|
||||
}
|
||||
*w = min(*w, dw - *dx);
|
||||
*h = min(*h, dh - *dy);
|
||||
}
|
||||
|
||||
SDL_Surface *sdl_make_rectangle(int w, int h, SDL_Color *color)
|
||||
static inline uint32_t *get_pixel(SDL_Surface *s, int x, int y)
|
||||
{
|
||||
Rectangle rect = { .x = 0, .y = 0, .w = w, .h = w };
|
||||
SDL_Surface *s = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_ARGB32);
|
||||
uint32_t c = SDL_MapRGBA(s->format, color->r, color->g, color->b, color->a);
|
||||
SDL_FillRect(s, &rect, c);
|
||||
return s;
|
||||
return (uint32_t*)(((uint8_t*)s->pixels) + s->pitch*y + s->format->BytesPerPixel*x);
|
||||
}
|
||||
|
||||
void sdl_draw_rectangle(Rectangle *_rect, int pixels, uint8_t r, uint8_t g, uint8_t b)
|
||||
// iterator for copy operations
|
||||
// FIXME: texture should be marked as dirty and updated later to avoid unnecessary copying
|
||||
#define copy_for_each_pixel(dcg, dx, dy, scg, sx, sy, w, h, dp, sp, expr) \
|
||||
do { \
|
||||
copy_clip_rects(dcg->s->w, dcg->s->h, &dx, &dy, scg->s->w, scg->s->h, &sx, &sy, &w, &h); \
|
||||
SDL_LockSurface(dcg->s); \
|
||||
SDL_LockSurface(scg->s); \
|
||||
for (int _row = 0; _row < h; _row++) { \
|
||||
uint32_t *dp = get_pixel(dcg->s, dx, _row+dy); \
|
||||
uint32_t *sp = get_pixel(scg->s, sx, _row+sy); \
|
||||
for (int _col = 0; _col < w; _col++, dp++, sp++) \
|
||||
expr; \
|
||||
} \
|
||||
SDL_UpdateTexture(dcg->t, NULL, dcg->s->pixels, dcg->s->pitch); \
|
||||
SDL_UnlockSurface(scg->s); \
|
||||
SDL_UnlockSurface(dcg->s); \
|
||||
} while (0)
|
||||
|
||||
// iterator for fill operations
|
||||
#define fill_for_each_pixel(cg, x, y, w, h, p, expr) \
|
||||
do { \
|
||||
fill_clip_rect(&x, &y, cg->s->w, cg->s->h, &w, &h); \
|
||||
SDL_LockSurface(cg->s); \
|
||||
for (int _row = 0; _row < h; _row++) { \
|
||||
uint32_t *p = get_pixel(cg->s, x, _row+y); \
|
||||
for (int _col = 0; _col < w; _col++, p++) \
|
||||
expr; \
|
||||
} \
|
||||
SDL_UpdateTexture(cg->t, NULL, cg->s->pixels, cg->s->pitch); \
|
||||
SDL_UnlockSurface(cg->s); \
|
||||
} while(0);
|
||||
|
||||
static void sdl_blit(SDL_Surface *ds, int dx, int dy, SDL_Surface *ss, int sx, int sy, int w, int h)
|
||||
{
|
||||
SDL_Rect rect[4];
|
||||
|
||||
// top
|
||||
rect[0] = *_rect;
|
||||
rect[0].h = pixels;
|
||||
// bot
|
||||
rect[1] = *_rect;
|
||||
rect[1].y += _rect->h - pixels;
|
||||
rect[1].h = pixels;
|
||||
// left
|
||||
rect[2] = *_rect;
|
||||
rect[2].w = pixels;
|
||||
// right
|
||||
rect[3] = *_rect;
|
||||
rect[3].x += _rect->w - pixels;
|
||||
rect[3].w = pixels;
|
||||
|
||||
uint32_t c = SDL_MapRGB(sdl.display->format, r, g, b);
|
||||
SDL_FillRects(sdl.display, rect, 4, c);
|
||||
sdl.dirty = true;
|
||||
Rectangle src_rect = RECT(sx, sy, w, h);
|
||||
Rectangle dst_rect = RECT(dx, dy, w, h);
|
||||
SDL_BlitSurface(ss, &src_rect, ds, &dst_rect);
|
||||
}
|
||||
|
||||
void sdl_draw_surface(SDL_Surface *s, Rectangle *dst)
|
||||
void sdl_copy(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h)
|
||||
{
|
||||
Rectangle src = { .x = 0, .y = 0, .w = s->w, .h = s->h };
|
||||
SDL_BlitSurface(s, &src, sdl.display, dst);
|
||||
sdl.dirty = true;
|
||||
SDL_BlendMode mode;
|
||||
SDL_GetSurfaceBlendMode(src->s, &mode);
|
||||
SDL_SetSurfaceBlendMode(src->s, SDL_BLENDMODE_NONE);
|
||||
sdl_blit(dst->s, dx, dy, src->s, sx, sy, w, h);
|
||||
|
||||
SDL_SetSurfaceBlendMode(src->s, mode);
|
||||
}
|
||||
|
||||
void sdl_copy_bright(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int rate)
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
SDL_GetSurfaceBlendMode(src->s, &mode);
|
||||
SDL_SetSurfaceBlendMode(src->s, SDL_BLENDMODE_NONE);
|
||||
SDL_SetSurfaceColorMod(src->s, rate, rate, rate);
|
||||
|
||||
sdl_blit(dst->s, dx, dy, src->s, sx, sy, w, h);
|
||||
|
||||
SDL_SetSurfaceColorMod(src->s, 255, 255, 255);
|
||||
SDL_SetSurfaceBlendMode(src->s, mode);
|
||||
}
|
||||
|
||||
void sdl_copy_amap(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h)
|
||||
{
|
||||
if (!dst->has_alpha || !src->has_alpha)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
PIXEL_SET_A(dp, PIXEL_A(*sp));
|
||||
});
|
||||
}
|
||||
|
||||
void sdl_copy_sprite(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int r, int g, int b)
|
||||
{
|
||||
SDL_BlendMode mode;
|
||||
|
||||
SDL_GetSurfaceBlendMode(src->s, &mode);
|
||||
SDL_SetSurfaceBlendMode(src->s, SDL_BLENDMODE_NONE);
|
||||
SDL_SetColorKey(src->s, SDL_TRUE, SDL_MapRGB(sdl.format, r, g, b));
|
||||
|
||||
sdl_blit(dst->s, dx, dy, src->s, sx, sy, w, h);
|
||||
|
||||
SDL_SetColorKey(src->s, SDL_FALSE, 0);
|
||||
SDL_SetSurfaceBlendMode(src->s, mode);
|
||||
}
|
||||
|
||||
void sdl_copy_use_amap_under(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int a_threshold)
|
||||
{
|
||||
if (!src->has_alpha)
|
||||
return;
|
||||
|
||||
uint8_t r, g, b, a;
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
SDL_GetRGBA(*sp, sdl.format, &r, &g, &b, &a);
|
||||
if (a <= a_threshold) {
|
||||
PIXEL_SET_RGB(dp, r, g, b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void sdl_copy_use_amap_border(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int a_threshold)
|
||||
{
|
||||
if (!src->has_alpha)
|
||||
return;
|
||||
|
||||
uint8_t r, g, b, a;
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
SDL_GetRGBA(*sp, sdl.format, &r, &g, &b, &a);
|
||||
if (a >= a_threshold) {
|
||||
PIXEL_SET_RGB(dp, r, g, b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void sdl_copy_amap_max(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h)
|
||||
{
|
||||
if (!src->has_alpha || !dst->has_alpha)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
uint32_t d_a = (*dp & sdl.format->Amask) >> sdl.format->Ashift;
|
||||
uint32_t s_a = (*sp & sdl.format->Amask) >> sdl.format->Ashift;
|
||||
if (s_a > d_a) {
|
||||
PIXEL_SET_A(dp, s_a);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void sdl_copy_amap_min(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h)
|
||||
{
|
||||
if (!src->has_alpha || !dst->has_alpha)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
uint32_t d_a = (*dp & A_MASK) >> A_SHIFT;
|
||||
uint32_t s_a = (*sp & A_MASK) >> A_SHIFT;
|
||||
if (s_a < d_a) {
|
||||
PIXEL_SET_A(dp, s_a);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void blend_pixels(SDL_Color *dst, SDL_Color src)
|
||||
{
|
||||
uint32_t alpha = src.a + 1;
|
||||
uint32_t inv_alpha = 256 - src.a;
|
||||
dst->r = (uint8_t)((alpha * src.r + inv_alpha * dst->r) >> 8);
|
||||
dst->g = (uint8_t)((alpha * src.g + inv_alpha * dst->g) >> 8);
|
||||
dst->b = (uint8_t)((alpha * src.b + inv_alpha * dst->b) >> 8);
|
||||
}
|
||||
|
||||
void sdl_fill(struct cg *dst, int x, int y, int w, int h, int r, int g, int b)
|
||||
{
|
||||
fill_for_each_pixel(dst, x, y, w, h, p, {
|
||||
PIXEL_SET_RGBA(p, r, g, b, PIXEL_A(*p));
|
||||
});
|
||||
}
|
||||
|
||||
// XXX: Despite being called a fill operation, this function actually performs blending.
|
||||
void sdl_fill_alpha_color(struct cg *cg, int x, int y, int w, int h, int r, int g, int b, int a)
|
||||
{
|
||||
SDL_Color dst;
|
||||
SDL_Color src = { .r = r, .g = g, .b = b, .a = a };
|
||||
fill_for_each_pixel(cg, x, y, w, h, p, {
|
||||
SDL_GetRGBA(*p, sdl.format, &dst.r, &dst.g, &dst.b, &dst.a);
|
||||
blend_pixels(&dst, src);
|
||||
PIXEL_SET_RGBA(p, dst.r, dst.g, dst.b, dst.a);
|
||||
});
|
||||
}
|
||||
|
||||
void sdl_fill_amap(struct cg *dst, int x, int y, int w, int h, int a)
|
||||
{
|
||||
fill_for_each_pixel(dst, x, y, w, h, p, {
|
||||
PIXEL_SET_A(p, a);
|
||||
});
|
||||
}
|
||||
|
||||
+2
-9
@@ -29,19 +29,12 @@
|
||||
struct sdl_private_data {
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
SDL_Surface *display; /* toplevel surface */
|
||||
SDL_Surface *dib; /* offscreen surface */
|
||||
SDL_Color col[256]; /* color pallet */
|
||||
unsigned long white; /* white pixel */
|
||||
//agsurface_t *cimg;
|
||||
SDL_Rect view;
|
||||
SDL_PixelFormat *format;
|
||||
int w, h;
|
||||
//FONT *font;
|
||||
bool dirty;
|
||||
bool ms_active; /* mouse is active */
|
||||
bool fs_on;
|
||||
int winoffset_x; /* draw offset in Window x */
|
||||
int winoffset_y; /* y */
|
||||
};
|
||||
|
||||
struct sdl_private_data sdl;
|
||||
|
||||
+59
-28
@@ -21,31 +21,24 @@
|
||||
#include "sdl_core.h"
|
||||
#include "sdl_private.h"
|
||||
|
||||
#define PIXEL_FORMAT SDL_PIXELFORMAT_ARGB32
|
||||
|
||||
int sdl_initialize(void)
|
||||
{
|
||||
memset(&sdl, 0, sizeof(struct sdl_private_data));
|
||||
|
||||
// make toplevel window
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
sdl.format = SDL_AllocFormat(PIXEL_FORMAT);
|
||||
sdl.window = SDL_CreateWindow("XSystem4",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
config.view_width,
|
||||
config.view_height,
|
||||
SDL_WINDOW_RESIZABLE);
|
||||
|
||||
sdl.renderer = SDL_CreateRenderer(sdl.window, -1, 0);
|
||||
|
||||
// offscreen pixmap
|
||||
//makeDIB(config.view_width, config.view_height, SYS4_DEFAULT_DEPTH);
|
||||
|
||||
// init cursor
|
||||
//sdl_cursor_init();
|
||||
|
||||
sdl_set_window_size(0, 0, config.view_width, config.view_height);
|
||||
|
||||
//sdl_shadow_init();
|
||||
|
||||
//joy_open();
|
||||
sdl_set_window_size(config.view_width, config.view_height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -54,9 +47,7 @@ void sdl_remove(void)
|
||||
if (!sdl.window)
|
||||
return;
|
||||
|
||||
//SDL_FreeSurface(sdl.dib);
|
||||
SDL_DestroyRenderer(sdl.renderer);
|
||||
//joy_close();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
@@ -71,24 +62,64 @@ void sdl_fullscreen(bool on)
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_set_window_size(int x, int y, int w, int h)
|
||||
void sdl_set_window_size(int w, int h)
|
||||
{
|
||||
sdl.view.x = x;
|
||||
sdl.view.y = y;
|
||||
|
||||
if (w == sdl.view.w && h == sdl.view.h)
|
||||
if (w == sdl.w && h == sdl.h)
|
||||
return;
|
||||
|
||||
sdl.view.w = w;
|
||||
sdl.view.h = h;
|
||||
sdl.w = w;
|
||||
sdl.h = h;
|
||||
|
||||
SDL_SetWindowSize(sdl.window, w, h);
|
||||
SDL_RenderSetLogicalSize(sdl.renderer, w, h);
|
||||
if (sdl.display)
|
||||
SDL_FreeSurface(sdl.display);
|
||||
if (sdl.texture)
|
||||
SDL_DestroyTexture(sdl.texture);
|
||||
sdl.display = SDL_CreateRGBSurface(0, w, h, 32, 0xFF00, 0xFF0000, 0xFF000000, 0xFF);
|
||||
sdl.texture = SDL_CreateTexture(sdl.renderer, sdl.display->format->format,
|
||||
SDL_TEXTUREACCESS_STATIC, w, h);
|
||||
}
|
||||
|
||||
SDL_Texture *sdl_create_texture(int w, int h)
|
||||
{
|
||||
SDL_Texture *t = SDL_CreateTexture(sdl.renderer, PIXEL_FORMAT, SDL_TEXTUREACCESS_STATIC, w, h);
|
||||
SDL_SetTextureBlendMode(t, SDL_BLENDMODE_BLEND);
|
||||
return t;
|
||||
}
|
||||
|
||||
SDL_Surface *sdl_create_surface(int w, int h, SDL_Color *color)
|
||||
{
|
||||
Rectangle rect = { .x = 0, .y = 0, .w = w, .h = w };
|
||||
SDL_Surface *s = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_ARGB32);
|
||||
if (color) {
|
||||
uint32_t c = SDL_MapRGBA(s->format, color->r, color->g, color->b, color->a);
|
||||
SDL_FillRect(s, &rect, c);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void sdl_update_texture(SDL_Texture *t, SDL_Surface *s)
|
||||
{
|
||||
if (SDL_MUSTLOCK(s))
|
||||
SDL_LockSurface(s);
|
||||
SDL_UpdateTexture(t, NULL, s->pixels, s->pitch);
|
||||
if (SDL_MUSTLOCK(s))
|
||||
SDL_UnlockSurface(s);
|
||||
}
|
||||
|
||||
SDL_Texture *sdl_surface_to_texture(SDL_Surface *s)
|
||||
{
|
||||
SDL_Texture *t = SDL_CreateTexture(sdl.renderer, PIXEL_FORMAT, SDL_TEXTUREACCESS_STATIC, s->w, s->h);
|
||||
SDL_SetTextureBlendMode(t, SDL_BLENDMODE_BLEND);
|
||||
SDL_UpdateTexture(t, NULL, s->pixels, s->pitch);
|
||||
return t;
|
||||
}
|
||||
|
||||
void sdl_render_clear(void)
|
||||
{
|
||||
SDL_RenderClear(sdl.renderer);
|
||||
}
|
||||
|
||||
void sdl_render_present(void)
|
||||
{
|
||||
SDL_RenderPresent(sdl.renderer);
|
||||
}
|
||||
|
||||
void sdl_render_texture(SDL_Texture *t, Rectangle *r)
|
||||
{
|
||||
SDL_RenderCopy(sdl.renderer, t, NULL, r);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user