sdl_effect: Implement linear blur effects

Now Gpx and NIGHTDLL are fully migrated to sdl_effect.
This commit is contained in:
kichikuou
2022-01-17 17:41:13 +09:00
parent d945dfe77d
commit d35a24f142
11 changed files with 164 additions and 553 deletions
-1
View File
@@ -79,7 +79,6 @@ add_library(modules STATIC
lib/graph_draw_amap.c
lib/graph_stretch.c
lib/graph_cg.c
lib/graph_buller.c
lib/gre_blend_useamap.c
lib/gre_blend.c
lib/gre_blend_screen.c
+18 -139
View File
@@ -5,43 +5,12 @@
#include "portab.h"
#include "system.h"
#include "surface.h"
// #include "gleffectcopy.h"
#include "sdl_core.h"
#include "ags.h"
#include "input.h"
#include "graph.h"
#include "ngraph.h"
/* saved parameter */
struct ecopyparam {
surface_t *src;
int sx;
int sy;
surface_t *dst;
int dx;
int dy;
int w;
int h;
surface_t *write;
int wx;
int wy;
int time;
boolean cancel;
int spCol;
int extp[10];
// for ec11
surface_t *ss[8];
surface_t *sd[8];
};
typedef struct ecopyparam ecopyparam_t;
static ecopyparam_t ecp;
static void ec11_cb(int step);
static void ec11_prepare(void);
void gpx_effect(int no,
int wx, int wy,
surface_t *dst, int dx, int dy,
@@ -55,118 +24,28 @@ void gpx_effect(int no,
*endtype = 0;
enum sdl_effect_type sdl_effect = from_sact_effect(no);
if (sdl_effect != EFFECT_INVALID) {
SDL_Rect rect = { wx, wy, width, height };
struct sdl_effect *eff = sdl_effect_init(&rect, dst, dx, dy, src, sx, sy, sdl_effect);
if (!time)
time = (no == SACT_EFFECT_CROSSFADE_DOWN || SACT_EFFECT_CROSSFADE_UP) ? 1150 : 2700;
ags_fade2(time, FALSE, (ags_fade2_callback)sdl_effect_step, eff);
sdl_effect_finish(eff);
switch (no) {
case SACT_EFFECT_FADEOUT:
gr_fill(write, wx, wy, width, height, 0, 0, 0);
break;
case SACT_EFFECT_WHITEOUT:
gr_fill(write, wx, wy, width, height, 255, 255, 255);
break;
default:
gr_copy(write, wx, wy, src, sx, sy, width, height);
break;
}
ags_updateArea(wx, wy, width, height);
return;
enum sdl_effect_type type = from_sact_effect(no);
if (type == EFFECT_INVALID) {
WARNING("Unimplemented effect %d\n", no);
type = EFFECT_CROSSFADE;
}
SDL_Rect rect = { wx, wy, width, height };
struct sdl_effect *eff = sdl_effect_init(&rect, dst, dx, dy, src, sx, sy, type);
if (!time)
time = (no == SACT_EFFECT_CROSSFADE_DOWN || SACT_EFFECT_CROSSFADE_UP) ? 1150 : 2700;
ags_fade2(time, FALSE, (ags_fade2_callback)sdl_effect_step, eff);
sdl_effect_finish(eff);
ecp.write = write;
ecp.wx = wx;
ecp.wy = wy;
ecp.dst = dst;
ecp.dx = dx;
ecp.dy = dy;
ecp.src = src;
ecp.sx = sx;
ecp.sy = sy;
ecp.w = width;
ecp.h = height;
ecp.time = time;
ags_faderinfo_t i;
switch(no) {
case 11:
ec11_prepare();
i.step_max = 6;
i.effect_time = time == 0 ? 2700 : time;
i.cancel = FALSE;
i.callback = ec11_cb;
ags_fader(&i);
switch (no) {
case SACT_EFFECT_FADEOUT:
gr_fill(write, wx, wy, width, height, 0, 0, 0);
break;
case SACT_EFFECT_WHITEOUT:
gr_fill(write, wx, wy, width, height, 255, 255, 255);
break;
default:
gr_copy(write, wx, wy, src, sx, sy, width, height);
ags_updateArea(wx, wy, width, height);
break;
}
ags_updateArea(wx, wy, width, height);
}
static void ec11_prepare() {
int i;
ecp.ss[0] = sf_create_surface(ecp.w, ecp.h, ecp.write->depth);
ecp.sd[0] = sf_create_surface(ecp.w, ecp.h, ecp.write->depth);
gr_buller(ecp.ss[0], 0, 0, ecp.src, ecp.sx, ecp.sy, ecp.w, ecp.h, 1 << 2);
gr_buller(ecp.sd[0], 0, 0, ecp.dst, ecp.dx, ecp.dy, ecp.w, ecp.h, 1 << 2);
for (i = 1; i < 6; i++) {
ecp.ss[i] = sf_create_surface(ecp.w, ecp.h, ecp.write->depth);
ecp.sd[i] = sf_create_surface(ecp.w, ecp.h, ecp.write->depth);
gr_buller(ecp.ss[i], 0, 0, ecp.ss[i-1], 0, 0, ecp.w, ecp.h, 1 << (i+2));
gr_buller(ecp.sd[i], 0, 0, ecp.sd[i-1], 0, 0, ecp.w, ecp.h, 1 << (i+2));
}
}
static void ec11_cb(int step) {
int i;
if (step == 6) {
for (i = 0; i < 6; i++) {
sf_free(ecp.ss[i]);
sf_free(ecp.sd[i]);
}
gr_copy(ecp.write, ecp.wx, ecp.wy, ecp.src, ecp.sx, ecp.sy, ecp.w, ecp.h);
ags_updateArea(ecp.wx, ecp.wy, ecp.w, ecp.h);
return;
}
gre_Blend(ecp.write, ecp.wx, ecp.wy, ecp.sd[step], 0, 0, ecp.ss[5-step], 0, 0, ecp.w, ecp.h, ((step+1)*256)/7);
ags_updateArea(ecp.wx, ecp.wy, ecp.w, ecp.h);
}
#if 0
static void ec11_cb(int step) {
static surface_t *ss;
static surface_t *sd;
if (step == 0) {
ss = sf_create_surface(ecp.w, ecp.h, ecp.write->depth);
sd = sf_create_surface(ecp.w, ecp.h, ecp.write->depth);
gr_copy(ss, 0, 0, ecp.src, ecp.sx, ecp.sy, ecp.w, ecp.h);
gr_copy(sd, 0, 0, ecp.dst, ecp.dx, ecp.dy, ecp.w, ecp.h);
return;
}
if (step == 6) {
sf_free(ss);
sf_free(sd);
gr_copy(ecp.write, ecp.wx, ecp.wy, ecp.src, ecp.sx, ecp.sy, ecp.w, ecp.h);
ags_updateArea(ecp.wx, ecp.wy, ecp.w, ecp.h);
return;
}
gr_buller(ss, 0, 0, ecp.src, ecp.sx, ecp.sy, ecp.w, ecp.h, 1 << (7-step));
gr_buller(sd, 0, 0, ecp.dst, ecp.dx, ecp.dy, ecp.w, ecp.h, 1 << (step+1));
gre_Blend(ecp.write, ecp.wx, ecp.wy, sd, 0, 0, ss, 0, 0, ecp.w, ecp.h, (step*256)/6);
ags_updateArea(ecp.wx, ecp.wy, ecp.w, ecp.h);
}
#endif
+23 -89
View File
@@ -38,106 +38,40 @@
#include "sactcg.h"
#include "sdl_core.h"
static void ec6_cb(surface_t *, surface_t *);
static void ec11_cb(surface_t *, surface_t *);
static void ec_dummy_cb(surface_t *, surface_t *);
struct ecopyparam {
int sttime;
int curtime;
int edtime;
int curstep;
int oldstep;
};
typedef struct ecopyparam ecopyparam_t;
static ecopyparam_t ecp;
// #include "sprite_eupdate_perspect.c"
// #include "sprite_eupdate_mosaic.c"
// #include "sprite_eupdate_uneune.c"
#include "sprite_eupdate_buller.c"
// #include "sprite_eupdate_zmbbul.c"
typedef void entrypoint (surface_t *, surface_t *);
static void ec_dummy_cb(surface_t *sfsrc, surface_t *sfdst) {
WARNING("NOT IMPLEMENTED\n");
}
/*
効果つき画面更新
@param type: 効果の種類
@param no: 効果の種類
@param time: 実行時間(msec)
@param cancel: キー抜け(0:なし, 1:あり)
*/
int nt_sp_eupdate(int type, int time, int cancel) {
surface_t *sfsrc, *sfdst;
int key;
entrypoint *cb;
int nt_sp_eupdate(int no, int time, int cancel) {
if (no == 1013) {
nt_sp_update_all(TRUE);
return OK;
}
// 現在の sf0 をセーブ
sfsrc = sf_dup(sf0);
nt_sp_update_all(FALSE);
sfdst = sf_dup(sf0);
enum sdl_effect_type sdl_effect = from_sact_effect(type - 100);
struct sdl_effect *eff = NULL;
if (sdl_effect != EFFECT_INVALID) {
SDL_Rect rect = { 0, 0, sfsrc->width, sfsrc->height };
eff = sdl_effect_init(&rect, NULL, 0, 0, sdl_getDIB(), 0, 0, sdl_effect);
} else {
sf_copyall(sf0, sfsrc); // 全部の効果タイプにこの処理は要らないんだけど
enum sdl_effect_type type = from_sact_effect(no - 100);
if (type == EFFECT_INVALID) {
WARNING("Unimplemented effect %d\n", no);
type = EFFECT_CROSSFADE;
}
SDL_Rect rect = { 0, 0, sf0->width, sf0->height };
struct sdl_effect *eff = sdl_effect_init(&rect, NULL, 0, 0, sdl_getDIB(), 0, 0, type);
ecp.sttime = ecp.curtime = sdl_getTicks();
ecp.edtime = ecp.curtime + time;
ecp.oldstep = 0;
switch(type) {
case 10:
cb = ec_dummy_cb;
break;
case 111: // 線形ぼかし
ec11_prepare(sfsrc, sfdst);
cb = ec11_cb;
break;
case 1011:
cb = ec_dummy_cb;
break;
case 1013:
nt_sp_update_all(TRUE); return OK;
// cb = ec_dummy_cb;
break;
default:
cb = ec_dummy_cb;
break;
int sttime, curtime;
sttime = curtime = sdl_getTicks();
int edtime = curtime + time;
while ((curtime = sdl_getTicks()) < edtime) {
sdl_effect_step(eff, (double)(curtime - sttime) / (edtime - sttime));
int rest = 16 - (sdl_getTicks() - curtime);
int key = sys_keywait(rest, cancel ? KEYWAIT_CANCELABLE : KEYWAIT_NONCANCELABLE);
if (cancel && key)
break;
}
while ((ecp.curtime = sdl_getTicks()) < ecp.edtime) {
if (eff) {
sdl_effect_step(eff, (double)(ecp.curtime - ecp.sttime) / (ecp.edtime - ecp.sttime));
} else {
cb(sfsrc, sfdst);
}
int rest = 15 - (sdl_getTicks() - ecp.curtime);
key = sys_keywait(rest, cancel ? KEYWAIT_CANCELABLE : KEYWAIT_NONCANCELABLE);
if (cancel && key) break;
}
sf_copyall(sf0, sfdst);
sdl_effect_finish(eff);
ags_updateFull();
sf_free(sfsrc);
sf_free(sfdst);
if (type == 111) {
ec11_drain(sfsrc, sfdst);
}
if (eff)
sdl_effect_finish(eff);
return OK;
}
-66
View File
@@ -1,66 +0,0 @@
// 11 と 19 で共有
static surface_t *ec11_ss[6];
static surface_t *ec11_sd[6];
// 線形ブラー
static void ec11_cb(surface_t *sfsrc, surface_t *sfdst) {
int curstep, maxstep = 6;
curstep = maxstep * (ecp.curtime - ecp.sttime)/ (ecp.edtime - ecp.sttime);
if (curstep < 6) {
gre_Blend(sf0, 0, 0, ec11_ss[curstep], 0, 0, ec11_sd[5-curstep], 0, 0, sfsrc->width, sfsrc->height, (curstep+1)*256/7);
ags_updateFull();
}
}
static void ec11_prepare(surface_t *src, surface_t *dst) {
int i;
ec11_ss[0] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[0] = sf_create_surface(src->width, src->height, src->depth);
gr_buller(ec11_ss[0], 0, 0, src, 0, 0, src->width, src->height, 1 << 2);
gr_buller(ec11_sd[0], 0, 0, dst, 0, 0, dst->width, dst->height, 1 << 2);
for (i = 1; i < 6; i++) {
ec11_ss[i] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[i] = sf_create_surface(dst->width, dst->height, dst->depth);
gr_buller(ec11_ss[i], 0, 0, ec11_ss[i-1], 0, 0, src->width, src->height, 1 << (i+2));
gr_buller(ec11_sd[i], 0, 0, ec11_sd[i-1], 0, 0, dst->width, dst->height, 1 << (i+2));
}
}
static void ec11_drain(surface_t *src, surface_t *dst) {
int i;
for (i = 0; i < 6; i++) {
sf_free(ec11_ss[i]);
sf_free(ec11_sd[i]);
}
}
// 縦線形ブラー
static void ec19_cb(surface_t *sfsrc, surface_t *sfdst) {
ec11_cb(sfsrc, sfdst);
}
static void ec19_prepare(surface_t *src, surface_t *dst) {
int i;
ec11_ss[0] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[0] = sf_create_surface(src->width, src->height, src->depth);
gr_buller_v(ec11_ss[0], 0, 0, src, 0, 0, src->width, src->height, 1 << 2);
gr_buller_v(ec11_sd[0], 0, 0, dst, 0, 0, dst->width, dst->height, 1 << 2);
for (i = 1; i < 6; i++) {
ec11_ss[i] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[i] = sf_create_surface(dst->width, dst->height, dst->depth);
gr_buller_v(ec11_ss[i], 0, 0, ec11_ss[i-1], 0, 0, src->width, src->height, 1 << (i+2));
gr_buller_v(ec11_sd[i], 0, 0, ec11_sd[i-1], 0, 0, dst->width, dst->height, 1 << (i+2));
}
}
static void ec19_drain(surface_t *src, surface_t *dst) {
int i;
for (i = 0; i < 6; i++) {
sf_free(ec11_ss[i]);
sf_free(ec11_sd[i]);
}
}
+2 -16
View File
@@ -41,7 +41,6 @@
static void ec6_cb(surface_t *, surface_t *);
static void ec11_cb(surface_t *, surface_t *);
static void sdl_effect_cb(surface_t *, surface_t *);
static void ec_dummy_cb(surface_t *, surface_t *);
@@ -59,7 +58,6 @@ static ecopyparam_t ecp;
#include "sprite_eupdate_perspect.c"
#include "sprite_eupdate_mosaic.c"
#include "sprite_eupdate_uneune.c"
#include "sprite_eupdate_buller.c"
#include "sprite_eupdate_zmbbul.c"
typedef void entrypoint (surface_t *, surface_t *);
@@ -75,7 +73,7 @@ static entrypoint *cb[39] = {
sdl_effect_cb,
sdl_effect_cb,
ec10_cb,
ec11_cb,
sdl_effect_cb,
sdl_effect_cb,
sdl_effect_cb,
sdl_effect_cb,
@@ -83,7 +81,7 @@ static entrypoint *cb[39] = {
sdl_effect_cb,
sdl_effect_cb,
ec_dummy_cb, // 欠番
ec19_cb,
sdl_effect_cb,
sdl_effect_cb,
sdl_effect_cb,
sdl_effect_cb,
@@ -192,12 +190,6 @@ int sp_eupdate(int type, int time, int cancel) {
if (type == 10) {
ec10_prepare(sfsrc, sfdst);
}
if (type == 11) {
ec11_prepare(sfsrc, sfdst);
}
if (type == 19) {
ec19_prepare(sfsrc, sfdst);
}
ecp.sttime = ecp.curtime = sdl_getTicks();
ecp.edtime = ecp.curtime + time*10;
@@ -221,12 +213,6 @@ int sp_eupdate(int type, int time, int cancel) {
if (type == 10) {
ec10_drain(sfsrc, sfdst);
}
if (type == 11) {
ec11_drain(sfsrc, sfdst);
}
if (type == 19) {
ec19_drain(sfsrc, sfdst);
}
if (ecp.eff) {
sdl_effect_finish(ecp.eff);
ecp.eff = NULL;
-66
View File
@@ -1,66 +0,0 @@
// 11 と 19 で共有
static surface_t *ec11_ss[6];
static surface_t *ec11_sd[6];
// 線形ブラー
static void ec11_cb(surface_t *sfsrc, surface_t *sfdst) {
int curstep, maxstep = 6;
curstep = maxstep * (ecp.curtime - ecp.sttime)/ (ecp.edtime - ecp.sttime);
if (curstep < 6) {
gre_Blend(sf0, 0, 0, ec11_ss[curstep], 0, 0, ec11_sd[5-curstep], 0, 0, sfsrc->width, sfsrc->height, (curstep+1)*256/7);
ags_updateFull();
}
}
static void ec11_prepare(surface_t *src, surface_t *dst) {
int i;
ec11_ss[0] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[0] = sf_create_surface(src->width, src->height, src->depth);
gr_buller(ec11_ss[0], 0, 0, src, 0, 0, src->width, src->height, 1 << 2);
gr_buller(ec11_sd[0], 0, 0, dst, 0, 0, dst->width, dst->height, 1 << 2);
for (i = 1; i < 6; i++) {
ec11_ss[i] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[i] = sf_create_surface(dst->width, dst->height, dst->depth);
gr_buller(ec11_ss[i], 0, 0, ec11_ss[i-1], 0, 0, src->width, src->height, 1 << (i+2));
gr_buller(ec11_sd[i], 0, 0, ec11_sd[i-1], 0, 0, dst->width, dst->height, 1 << (i+2));
}
}
static void ec11_drain(surface_t *src, surface_t *dst) {
int i;
for (i = 0; i < 6; i++) {
sf_free(ec11_ss[i]);
sf_free(ec11_sd[i]);
}
}
// 縦線形ブラー
static void ec19_cb(surface_t *sfsrc, surface_t *sfdst) {
ec11_cb(sfsrc, sfdst);
}
static void ec19_prepare(surface_t *src, surface_t *dst) {
int i;
ec11_ss[0] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[0] = sf_create_surface(src->width, src->height, src->depth);
gr_buller_v(ec11_ss[0], 0, 0, src, 0, 0, src->width, src->height, 1 << 2);
gr_buller_v(ec11_sd[0], 0, 0, dst, 0, 0, dst->width, dst->height, 1 << 2);
for (i = 1; i < 6; i++) {
ec11_ss[i] = sf_create_surface(src->width, src->height, src->depth);
ec11_sd[i] = sf_create_surface(dst->width, dst->height, dst->depth);
gr_buller_v(ec11_ss[i], 0, 0, ec11_ss[i-1], 0, 0, src->width, src->height, 1 << (i+2));
gr_buller_v(ec11_sd[i], 0, 0, ec11_sd[i-1], 0, 0, dst->width, dst->height, 1 << (i+2));
}
}
static void ec19_drain(surface_t *src, surface_t *dst) {
int i;
for (i = 0; i < 6; i++) {
sf_free(ec11_ss[i]);
sf_free(ec11_sd[i]);
}
}
-171
View File
@@ -1,171 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "portab.h"
#include "surface.h"
#include "ngraph.h"
#include "ags.h"
int gr_buller(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int step) {
BYTE *dp, *sp;
int x, y;
int r1, g1, b1;
int r2, g2, b2;
int r3, g3, b3;
if (src == NULL || dst == NULL) return NG;
if (!gr_clip(src, &sx, &sy, &width, &height, dst, &dx, &dy)) return NG;
sp = GETOFFSET_PIXEL(src, sx, sy);
dp = GETOFFSET_PIXEL(dst, dx, dy);
switch(dst->depth) {
case 16:
{
WORD *yld, *yls;
for (y = 0; y < height; y++) {
yls = (WORD *)(sp + y * src->bytes_per_line);
yld = (WORD *)(dp + y * dst->bytes_per_line);
for (x = 0; x < step; x++) {
*yld = *(yls+step);
yls++; yld++;
}
for (; x < (width - step*2); x++) {
r1 = PIXR16((*(yls+step)));
g1 = PIXG16((*(yls+step)));
b1 = PIXB16((*(yls+step)));
r2 = PIXR16((*(yls-step)));
g2 = PIXG16((*(yls-step)));
b2 = PIXB16((*(yls-step)));
r3 = min(255, (r1+r2) >> 1);
g3 = min(255, (g1+g2) >> 1);
b3 = min(255, (b1+b2) >> 1);
*yld = PIX16(r3, g3, b3);
yld++; yls++;
}
for (; x < width; x++) {
*yld = *(yls-step);
yls++; yld++;
}
}
break;
}
case 24:
case 32:
{
DWORD *yld, *yls;
for (y = 0; y < height; y++) {
yls = (DWORD *)(sp + y * src->bytes_per_line);
yld = (DWORD *)(dp + y * dst->bytes_per_line);
for (x = 0; x < step; x++) {
*yld = *(yls+step);
yls++; yld++;
}
for (; x < (width - step*2); x++) {
r1 = PIXR24((*(yls+step)));
g1 = PIXG24((*(yls+step)));
b1 = PIXB24((*(yls+step)));
r2 = PIXR24((*(yls-step)));
g2 = PIXG24((*(yls-step)));
b2 = PIXB24((*(yls-step)));
r3 = min(255, (r1+r2) >> 1);
g3 = min(255, (g1+g2) >> 1);
b3 = min(255, (b1+b2) >> 1);
*yld = PIX24(r3, g3, b3);
yld++; yls++;
}
for (; x < width; x++) {
*yld = *(yls-step);
yls++; yld++;
}
}
break;
}}
return OK;
}
// 縦方向ブラー
int gr_buller_v(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int step) {
BYTE *dp, *sp;
int x, y;
int r1, g1, b1;
int r2, g2, b2;
int r3, g3, b3;
if (src == NULL || dst == NULL) return NG;
if (!gr_clip(src, &sx, &sy, &width, &height, dst, &dx, &dy)) return NG;
sp = GETOFFSET_PIXEL(src, sx, sy);
dp = GETOFFSET_PIXEL(dst, dx, dy);
switch(dst->depth) {
case 16:
{
WORD *yld, *yls;
for (x = 0; x < width; x++) {
yls = (WORD *)(sp + x * src->bytes_per_pixel);
yld = (WORD *)(dp + x * dst->bytes_per_pixel);
for (y = 0; y < step; y++) {
*(yld+y*dst->width) = *(yls+(y+step)*src->width);
}
for (; y < (height - step*2); y++) {
r1 = PIXR16((*(yls+(y+step)*src->width)));
g1 = PIXG16((*(yls+(y+step)*src->width)));
b1 = PIXB16((*(yls+(y+step)*src->width)));
r2 = PIXR16((*(yls+(y-step)*src->width)));
g2 = PIXG16((*(yls+(y-step)*src->width)));
b2 = PIXB16((*(yls+(y-step)*src->width)));
r3 = min(255, (r1+r2) >> 1);
g3 = min(255, (g1+g2) >> 1);
b3 = min(255, (b1+b2) >> 1);
*(yld+y*dst->width) = PIX16(r3, g3, b3);
}
for (; y < height; y++) {
*(yld+y*dst->width) = *(yls+(y-step)*src->width);
}
}
break;
}
case 24:
case 32:
{
DWORD *yld, *yls;
for (x = 0; x < width; x++) {
yls = (DWORD *)(sp + x * src->bytes_per_pixel);
yld = (DWORD *)(dp + x * dst->bytes_per_pixel);
for (y = 0; y < step; y++) {
*(yld+y*dst->width) = *(yls+(y+step)*src->width);
}
for (; y < (height - step*2); y++) {
r1 = PIXR24((*(yls+(y+step)*src->width)));
g1 = PIXG24((*(yls+(y+step)*src->width)));
b1 = PIXB24((*(yls+(y+step)*src->width)));
r2 = PIXR24((*(yls+(y-step)*src->width)));
g2 = PIXG24((*(yls+(y-step)*src->width)));
b2 = PIXB24((*(yls+(y-step)*src->width)));
r3 = min(255, (r1+r2) >> 1);
g3 = min(255, (g1+g2) >> 1);
b3 = min(255, (b1+b2) >> 1);
*(yld+y*dst->width) = PIX24(r3, g3, b3);
}
for (; y < height; y++) {
*(yld+y*dst->width) = *(yls+(y-step)*src->width);
}
}
break;
}}
return OK;
}
-4
View File
@@ -64,10 +64,6 @@ extern int gre_Blend(surface_t *write, int wx, int wy, surface_t *dst, int dx, i
/* in gre_blend_screen.c */
extern int gre_BlendScreen(surface_t *write, int wx, int wy, surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height);
/* in graph_buller */
extern int gr_buller(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int step);
extern int gr_buller_v(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int step);
/* in graph_stretch.c */
extern void gr_copy_stretch(surface_t *dst, int dx, int dy, int dw, int dh, surface_t *src, int sx, int sy, int sw, int sh);
+2 -1
View File
@@ -885,6 +885,8 @@ static int duration(enum nact_effect effect, int opt, SDL_Rect *rect) {
case NACT_EFFECT_WINDMILL_180:
case NACT_EFFECT_WINDMILL_360:
return opt ? opt : 1000;
case NACT_EFFECT_LINEAR_BLUR:
return opt ? opt : 1700;
}
return 1000;
}
@@ -954,7 +956,6 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
case 19:
case 20:
case 21:
case 53:
case 54:
if (spCol == -1) {
ags_copyArea(sx, sy, w, h, dx, dy);
+5
View File
@@ -43,6 +43,7 @@ enum nact_effect {
NACT_EFFECT_WINDMILL = 50,
NACT_EFFECT_WINDMILL_180 = 51,
NACT_EFFECT_WINDMILL_360 = 52,
NACT_EFFECT_LINEAR_BLUR = 53,
};
// Effect types of SCAT.DrawEffect and Gpx.EffectCopy.
@@ -55,12 +56,14 @@ enum sact_effect {
SACT_EFFECT_BLIND_DOWN = 7,
SACT_EFFECT_BLIND_LR = 8,
SACT_EFFECT_BLIND_DOWN_LR = 9,
SACT_EFFECT_LINEAR_BLUR = 11,
SACT_EFFECT_CROSSFADE_DOWN = 12,
SACT_EFFECT_CROSSFADE_UP = 13,
SACT_EFFECT_PENTAGRAM_IN_OUT = 14,
SACT_EFFECT_PENTAGRAM_OUT_IN = 15,
SACT_EFFECT_HEXAGRAM_IN_OUT = 16,
SACT_EFFECT_HEXAGRAM_OUT_IN = 17,
SACT_EFFECT_LINEAR_BLUR_VERT = 19,
SACT_EFFECT_ROTATE_OUT = 20,
SACT_EFFECT_ROTATE_IN = 21,
SACT_EFFECT_ROTATE_OUT_CW = 22,
@@ -87,6 +90,8 @@ enum sdl_effect_type {
EFFECT_CROSSFADE_UP,
EFFECT_CROSSFADE_LR,
EFFECT_CROSSFADE_RL,
EFFECT_LINEAR_BLUR,
EFFECT_LINEAR_BLUR_VERT,
EFFECT_PENTAGRAM_IN_OUT,
EFFECT_PENTAGRAM_OUT_IN,
EFFECT_HEXAGRAM_IN_OUT,
+114
View File
@@ -52,6 +52,7 @@ enum sdl_effect_type from_nact_effect(enum nact_effect effect) {
case NACT_EFFECT_WINDMILL: return EFFECT_WINDMILL;
case NACT_EFFECT_WINDMILL_180: return EFFECT_WINDMILL_180;
case NACT_EFFECT_WINDMILL_360: return EFFECT_WINDMILL_360;
case NACT_EFFECT_LINEAR_BLUR: return EFFECT_LINEAR_BLUR;
default: return EFFECT_INVALID;
}
}
@@ -66,12 +67,14 @@ enum sdl_effect_type from_sact_effect(enum sact_effect effect) {
case SACT_EFFECT_BLIND_DOWN: return EFFECT_BLIND_DOWN;
case SACT_EFFECT_BLIND_LR: return EFFECT_BLIND_LR;
case SACT_EFFECT_BLIND_DOWN_LR: return EFFECT_BLIND_DOWN_LR;
case SACT_EFFECT_LINEAR_BLUR: return EFFECT_LINEAR_BLUR;
case SACT_EFFECT_CROSSFADE_DOWN: return EFFECT_CROSSFADE_DOWN;
case SACT_EFFECT_CROSSFADE_UP: return EFFECT_CROSSFADE_UP;
case SACT_EFFECT_PENTAGRAM_IN_OUT: return EFFECT_PENTAGRAM_IN_OUT;
case SACT_EFFECT_PENTAGRAM_OUT_IN: return EFFECT_PENTAGRAM_OUT_IN;
case SACT_EFFECT_HEXAGRAM_IN_OUT: return EFFECT_HEXAGRAM_IN_OUT;
case SACT_EFFECT_HEXAGRAM_OUT_IN: return EFFECT_HEXAGRAM_OUT_IN;
case SACT_EFFECT_LINEAR_BLUR_VERT: return EFFECT_LINEAR_BLUR_VERT;
case SACT_EFFECT_ROTATE_OUT: return EFFECT_ROTATE_OUT;
case SACT_EFFECT_ROTATE_IN: return EFFECT_ROTATE_IN;
case SACT_EFFECT_ROTATE_OUT_CW: return EFFECT_ROTATE_OUT_CW;
@@ -474,6 +477,114 @@ static void blind_free(struct sdl_effect *eff) {
free(eff);
}
// EFFECT_LINEAR_BLUR, EFFECT_LINEAR_BLUR_VERT
#define LINEAR_BLUR_STEPS 10
struct linear_blur_effect {
struct sdl_effect eff;
SDL_Texture *blurred_old[LINEAR_BLUR_STEPS];
SDL_Texture *blurred_new[LINEAR_BLUR_STEPS];
};
static void linear_blur_step(struct sdl_effect *eff, double progress);
static void linear_blur_free(struct sdl_effect *eff);
static struct sdl_effect *linear_blur_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
if (!SDL_RenderTargetSupported(sdl_renderer)) {
WARNING("Effect %d is not supported in this system. Falling back to crossfade.\n", type);
return crossfade_new(rect, old, new);
}
struct linear_blur_effect *lbe = calloc(1, sizeof(struct linear_blur_effect));
if (!lbe)
NOMEMERR();
effect_init(&lbe->eff, rect, old, new, type);
lbe->eff.step = linear_blur_step;
lbe->eff.finish = linear_blur_free;
return &lbe->eff;
}
static SDL_Texture *blur(struct linear_blur_effect *this, SDL_Texture *src, int stride) {
bool vertical = this->eff.type == EFFECT_LINEAR_BLUR_VERT;
int w = this->eff.dst_rect.w;
int h = this->eff.dst_rect.h;
SDL_Texture *dst = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, w, h);
SDL_SetRenderTarget(sdl_renderer, dst);
SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255);
SDL_RenderClear(sdl_renderer);
SDL_SetTextureBlendMode(src, SDL_BLENDMODE_ADD);
SDL_SetTextureAlphaMod(src, 127);
SDL_Rect dr = {0, 0, w, h};
*(vertical ? &dr. y : &dr.x) = -stride / 2;
SDL_RenderCopy(sdl_renderer, src, NULL, &dr);
*(vertical ? &dr. y : &dr.x) = max(1, stride / 2);
SDL_RenderCopy(sdl_renderer, src, NULL, &dr);
// Copy the edge pixels to emulate texture clamping.
SDL_Rect sr = {0, 0, vertical ? w : 1, vertical ? 1 : h};
*(vertical ? &dr.h : &dr.w) = max(1, stride / 2);
*(vertical ? &dr.y : &dr.x) = 0;
SDL_RenderCopy(sdl_renderer, src, &sr, &dr);
if (stride > 1) {
if (vertical) {
sr.y = h - 1;
dr.y = h - stride / 2;
} else {
sr.x = w - 1;
dr.x = w - stride / 2;
}
SDL_RenderCopy(sdl_renderer, src, &sr, &dr);
}
SDL_SetTextureAlphaMod(src, 255);
SDL_SetTextureBlendMode(src, SDL_BLENDMODE_NONE);
SDL_SetRenderTarget(sdl_renderer, NULL);
return dst;
}
static void linear_blur_step(struct sdl_effect *eff, double progress) {
struct linear_blur_effect *this = (struct linear_blur_effect *)eff;
int step = progress * LINEAR_BLUR_STEPS * 2;
if (step == LINEAR_BLUR_STEPS * 2) {
SDL_RenderCopy(sdl_renderer, eff->tx_new, NULL, NULL);
SDL_RenderPresent(sdl_renderer);
return;
}
for (int i = 0; i <= step && i < LINEAR_BLUR_STEPS; i++) {
if (this->blurred_old[i])
continue;
this->blurred_old[i] = blur(this, i ? this->blurred_old[i - 1] : eff->tx_old, 1 << i);
this->blurred_new[i] = blur(this, i ? this->blurred_new[i - 1] : eff->tx_new, 1 << i);
}
int i = step < LINEAR_BLUR_STEPS ? step : LINEAR_BLUR_STEPS * 2 - 1 - step;
SDL_Texture *old = this->blurred_old[i];
SDL_Texture *new = this->blurred_new[i];
SDL_RenderCopy(sdl_renderer, old, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(new, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(new, 255 * progress);
SDL_RenderCopy(sdl_renderer, new, NULL, &eff->dst_rect);
SDL_RenderPresent(sdl_renderer);
}
static void linear_blur_free(struct sdl_effect *eff) {
struct linear_blur_effect *this = (struct linear_blur_effect *)eff;
for (int i = 0; i < LINEAR_BLUR_STEPS; i++) {
if (this->blurred_old[i])
SDL_DestroyTexture(this->blurred_old[i]);
if (this->blurred_new[i])
SDL_DestroyTexture(this->blurred_new[i]);
}
effect_finish(&this->eff, true);
free(this);
}
// EFFECT_PENTAGRAM_*, EFFECT_HEXAGRAM_*, EFFECT_WINDMILL*
struct polygon_mask_effect {
@@ -835,6 +946,9 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
case EFFECT_BLIND_UP_DOWN:
case EFFECT_BLIND_DOWN_LR:
return blind_new(rect, sf_old, sf_new, type);
case EFFECT_LINEAR_BLUR:
case EFFECT_LINEAR_BLUR_VERT:
return linear_blur_new(rect, sf_old, sf_new, type);
case EFFECT_PENTAGRAM_IN_OUT:
case EFFECT_PENTAGRAM_OUT_IN:
case EFFECT_HEXAGRAM_IN_OUT: