Remove intermediate screen buffer

Pixels are now copied directly from sdl_dib to sdl_texture.
This commit is contained in:
kichikuou
2025-02-11 08:37:47 +09:00
parent 42faf38a47
commit c621a5dddb
7 changed files with 258 additions and 204 deletions
+1 -1
View File
@@ -329,7 +329,7 @@ void ags_eCopyArea(int sx, int sy, int w, int h, int dx, int dy, int sw, int opt
enum sdl_effect_type sdl_effect = from_nact_effect(sw);
if (sdl_effect != EFFECT_INVALID) {
SDL_Rect rect = { dx - nact->ags.view_area.x, dy - nact->ags.view_area.y, w, h };
// Note that we specify NULL (which means sdl_display) for the old
// Note that we specify NULL (which means sdl_texture) for the old
// surface rather than sdl_getDIB(). This is to use the current display
// contents, not reflecting uncommitted palette changes.
struct sdl_effect *eff = sdl_effect_init(&rect, NULL, rect.x, rect.y, sdl_getDIB(), sx, sy, sdl_effect);
+1 -1
View File
@@ -82,7 +82,7 @@ extern void sdl_putRegion(void *src, int x, int y);
extern void sdl_restoreRegion(void *src, int x, int y);
extern void* sdl_saveRegion(int x, int y, int w, int h);
extern void sdl_delRegion(void *src);
extern SDL_Surface *com2surface(agsurface_t *s);
extern SDL_Surface *com2surface(agsurface_t *s, int x, int y, int w, int h);
/* Effects */
struct sdl_effect;
+23 -14
View File
@@ -59,7 +59,6 @@ static Uint32 palette_color(uint8_t c) {
void sdl_updateScreen(void) {
if (!sdl_dirty)
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);
@@ -104,21 +103,31 @@ void sdl_wait_vsync() {
}
/* off-screen の指定領域を Main Window へ転送 */
void sdl_updateArea(MyRectangle *src, MyPoint *dst) {
SDL_Rect rect_d = {dst->x, dst->y, src->w, src->h};
SDL_BlitSurface(sdl_dib, src, sdl_display, &rect_d);
void sdl_updateArea(MyRectangle *rect, MyPoint *dst) {
SDL_Rect rs = {0, 0, sdl_dib->w, sdl_dib->h};
if (!SDL_IntersectRect(rect, &rs, &rs))
return;
int dx = dst->x + (rs.x - rect->x);
int dy = dst->y + (rs.y - rect->y);
SDL_Rect rd = {dx, dy, rs.w, rs.h};
if (!SDL_IntersectRect(&rd, &(SDL_Rect){0, 0, view_w, view_h}, &rd))
return;
rs.x += rd.x - dx;
rs.y += rd.y - dy;
rs.w = rd.w;
rs.h = rd.h;
SDL_Surface *sf;
SDL_LockTextureToSurface(sdl_texture, &rd, &sf);
SDL_BlitSurface(sdl_dib, &rs, sf, NULL);
SDL_UnlockTexture(sdl_texture);
sdl_dirty = true;
}
/* 全画面更新 */
void sdl_updateAll(MyRectangle *view_rect) {
SDL_Rect rect = {0, 0, view_w, view_h};
SDL_BlitSurface(sdl_dib, view_rect, sdl_display, &rect);
sdl_dirty = true;
sdl_updateArea(view_rect, &(MyPoint){0, 0});
}
/* Color の複数個指定 */
@@ -297,9 +306,9 @@ SDL_Rect sdl_floodFill(int x, int y, int c) {
}
}
SDL_Surface *com2surface(agsurface_t *s) {
return SDL_CreateRGBSurfaceFrom(
s->pixel, s->width, s->height, s->depth, s->bytes_per_line, 0, 0, 0, 0);
SDL_Surface *com2surface(agsurface_t *s, int x, int y, int w, int h) {
uint8_t *pixels = s->pixel + y * s->bytes_per_line + x * s->bytes_per_pixel;
return SDL_CreateRGBSurfaceFrom(pixels, w, h, s->depth, s->bytes_per_line, 0, 0, 0, 0);
}
int sdl_nearest_color(int r, int g, int b) {
+225 -176
View File
@@ -126,28 +126,78 @@ enum sdl_effect_type from_sact_effect(enum sact_effect effect) {
}
}
typedef struct {
SDL_Texture *tx;
SDL_Rect rect;
} EffectTexture;
static SDL_Surface *create_surface_view(SDL_Surface *sf, int x, int y, int w, int h) {
uint8_t *pixels = sf->pixels;
pixels += y * sf->pitch + x * sf->format->BytesPerPixel;
SDL_Surface *view = SDL_CreateRGBSurfaceWithFormatFrom(
pixels, w, h, sf->format->BitsPerPixel, sf->pitch, sf->format->format);
return view;
}
static EffectTexture *create_effect_texture(agsurface_t *as, int x, int y, int w, int h) {
EffectTexture *t = calloc(1, sizeof(EffectTexture));
if (!as) {
t->tx = sdl_texture;
t->rect = (SDL_Rect){ x, y, w, h };
} else {
SDL_Surface *sf = (as == sdl_dibinfo)
? create_surface_view(sdl_dib, x, y, w, h)
: com2surface(as, x, y, w, h);
t->tx = SDL_CreateTextureFromSurface(sdl_renderer, sf);
SDL_FreeSurface(sf);
t->rect = (SDL_Rect){ 0, 0, w, h };
}
return t;
}
static EffectTexture *create_effect_texture_from_surface(SDL_Surface *sf) {
EffectTexture *t = calloc(1, sizeof(EffectTexture));
t->tx = SDL_CreateTextureFromSurface(sdl_renderer, sf);
t->rect = (SDL_Rect){ 0, 0, sf->w, sf->h };
return t;
}
static void destroy_effect_texture(EffectTexture *t) {
if (!t)
return;
if (t->tx && t->tx != sdl_texture)
SDL_DestroyTexture(t->tx);
free(t);
}
static int render_effect_texture(EffectTexture *t, const SDL_Rect* srcrect, const SDL_Rect* dstrect) {
SDL_Rect real_srcrect;
if (!srcrect) {
real_srcrect = t->rect;
} else {
real_srcrect = *srcrect;
real_srcrect.x += t->rect.x;
real_srcrect.y += t->rect.y;
}
return SDL_RenderCopy(sdl_renderer, t->tx, &real_srcrect, dstrect);
}
struct sdl_effect {
void (*step)(struct sdl_effect *this, float progress);
void (*finish)(struct sdl_effect *this);
enum sdl_effect_type type;
SDL_Rect dst_rect;
bool is_fullscreen;
SDL_Texture *tx_old, *tx_new;
EffectTexture *tx_old, *tx_new;
};
static void effect_init(struct sdl_effect *eff, SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static void effect_init(struct sdl_effect *eff, SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
eff->type = type;
eff->dst_rect = *rect;
eff->is_fullscreen = rect->x == 0 && rect->y == 0
&& rect->w == sdl_display->w && rect->h == sdl_display->h;
if (old) {
eff->tx_old = SDL_CreateTextureFromSurface(sdl_renderer, old);
SDL_FreeSurface(old);
}
if (new) {
eff->tx_new = SDL_CreateTextureFromSurface(sdl_renderer, new);
SDL_FreeSurface(new);
}
&& rect->w == view_w && rect->h == view_h;
eff->tx_old = old;
eff->tx_new = new;
if (!eff->is_fullscreen)
sdl_updateScreen(); // Flush pending display changes.
@@ -158,13 +208,11 @@ static void effect_finish(struct sdl_effect *eff, bool present) {
SDL_RenderClear(sdl_renderer);
if (!eff->is_fullscreen)
SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL);
SDL_RenderCopy(sdl_renderer, eff->tx_new, NULL, &eff->dst_rect);
render_effect_texture(eff->tx_new, NULL, &eff->dst_rect);
SDL_RenderPresent(sdl_renderer);
}
if (eff->tx_old)
SDL_DestroyTexture(eff->tx_old);
if (eff->tx_new)
SDL_DestroyTexture(eff->tx_new);
destroy_effect_texture(eff->tx_old);
destroy_effect_texture(eff->tx_new);
}
static inline void flip_rect_h(SDL_Rect *r, int w) {
@@ -194,7 +242,7 @@ static inline void move_rect(SDL_Rect *r, int off_x, int off_y) {
static void crossfade_step(struct sdl_effect *eff, float progress);
static void crossfade_free(struct sdl_effect *eff);
static struct sdl_effect *crossfade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new) {
static struct sdl_effect *crossfade_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -205,11 +253,12 @@ static struct sdl_effect *crossfade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Su
}
static void crossfade_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(eff->tx_new, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(eff->tx_new, progress * 255);
SDL_RenderCopy(sdl_renderer, eff->tx_new, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(eff->tx_new, SDL_BLENDMODE_NONE);
render_effect_texture(eff->tx_old, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(eff->tx_new->tx, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(eff->tx_new->tx, progress * 255);
render_effect_texture(eff->tx_new, NULL, &eff->dst_rect);
SDL_SetTextureAlphaMod(eff->tx_new->tx, 255);
SDL_SetTextureBlendMode(eff->tx_new->tx, SDL_BLENDMODE_NONE);
SDL_RenderPresent(sdl_renderer);
}
@@ -218,7 +267,7 @@ static void crossfade_free(struct sdl_effect *eff) {
free(eff);
}
static struct sdl_effect *fallback_effect_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *fallback_effect_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
WARNING("Effect %d is not supported in this system. Falling back to crossfade.", type);
return crossfade_new(rect, old, new);
}
@@ -228,7 +277,7 @@ static struct sdl_effect *fallback_effect_new(SDL_Rect *rect, SDL_Surface *old,
static void crossfade_animation_step(struct sdl_effect *eff, float progress);
static void crossfade_animation_free(struct sdl_effect *eff);
static struct sdl_effect *crossfade_animation_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *crossfade_animation_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -238,7 +287,7 @@ static struct sdl_effect *crossfade_animation_new(SDL_Rect *rect, SDL_Surface *o
return eff;
}
static void crossfade_animation_step_sub(SDL_Rect *rect, SDL_Texture *tx, int tx_x, int tx_y, float progress, int band_width, bool lr, bool flip) {
static void crossfade_animation_step_sub(SDL_Rect *rect, EffectTexture *tx, int tx_x, int tx_y, float progress, int band_width, bool lr, bool flip) {
int maxstep = (lr ? rect->w : rect->h) + band_width;
int band_top = maxstep * progress - band_width;
if (band_top > 0) {
@@ -253,10 +302,10 @@ static void crossfade_animation_step_sub(SDL_Rect *rect, SDL_Texture *tx, int tx
SDL_Rect dr = sr;
move_rect(&sr, tx_x, tx_y);
move_rect(&dr, rect->x, rect->y);
SDL_RenderCopy(sdl_renderer, tx, &sr, &dr);
render_effect_texture(tx, &sr, &dr);
}
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_BLEND);
SDL_SetTextureBlendMode(tx->tx, SDL_BLENDMODE_BLEND);
for (int i = 0; i < band_width; i++) {
SDL_Rect sr;
if (lr) {
@@ -277,14 +326,15 @@ static void crossfade_animation_step_sub(SDL_Rect *rect, SDL_Texture *tx, int tx
SDL_Rect dr = sr;
move_rect(&sr, tx_x, tx_y);
move_rect(&dr, rect->x, rect->y);
SDL_SetTextureAlphaMod(tx, 255 - (i + 1) * (256 / band_width));
SDL_RenderCopy(sdl_renderer, tx, &sr, &dr);
SDL_SetTextureAlphaMod(tx->tx, 255 - (i + 1) * (256 / band_width));
render_effect_texture(tx, &sr, &dr);
}
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_NONE);
SDL_SetTextureAlphaMod(tx->tx, 255);
SDL_SetTextureBlendMode(tx->tx, SDL_BLENDMODE_NONE);
}
static void crossfade_animation_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
render_effect_texture(eff->tx_old, NULL, &eff->dst_rect);
switch (eff->type) {
case EFFECT_CROSSFADE_DOWN:
@@ -343,7 +393,7 @@ struct mosaic_effect {
static void mosaic_step(struct sdl_effect *eff, float progress);
static void mosaic_free(struct sdl_effect *eff);
static struct sdl_effect *mosaic_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *mosaic_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
if (!SDL_RenderTargetSupported(sdl_renderer))
return fallback_effect_new(rect, old, new, type);
@@ -359,7 +409,7 @@ static struct sdl_effect *mosaic_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surfa
return &eff->eff;
}
static void mosaic(SDL_Texture *src, SDL_Texture *tmp, SDL_Texture *dst, int w, int h, float scale) {
static void mosaic(EffectTexture *src, SDL_Texture *tmp, SDL_Texture *dst, int w, int h, float scale) {
int cx = w / 2;
int cy = h / 2;
SDL_FRect fr = {
@@ -369,7 +419,7 @@ static void mosaic(SDL_Texture *src, SDL_Texture *tmp, SDL_Texture *dst, int w,
.h = h / scale,
};
SDL_SetRenderTarget(sdl_renderer, tmp);
SDL_RenderCopyF(sdl_renderer, src, NULL, &fr);
SDL_RenderCopyF(sdl_renderer, src->tx, &src->rect, &fr);
SDL_Rect dstr = {
.x = w * (1 - scale) / 2,
@@ -427,7 +477,7 @@ static void mosaic_free(struct sdl_effect *eff) {
static void brightness_step(struct sdl_effect *eff, float progress);
static void brightness_free(struct sdl_effect *eff);
static struct sdl_effect *brightness_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *brightness_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -438,7 +488,7 @@ static struct sdl_effect *brightness_new(SDL_Rect *rect, SDL_Surface *old, SDL_S
}
static void brightness_step(struct sdl_effect *eff, float progress) {
SDL_Texture *texture;
EffectTexture *texture;
int color;
int alpha;
switch (eff->type) {
@@ -475,7 +525,7 @@ static void brightness_step(struct sdl_effect *eff, float progress) {
default:
assert(!"Cannot happen");
}
SDL_RenderCopy(sdl_renderer, texture, NULL, &eff->dst_rect);
render_effect_texture(texture, NULL, &eff->dst_rect);
SDL_SetRenderDrawBlendMode(sdl_renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(sdl_renderer, color, color, color, alpha);
SDL_RenderFillRect(sdl_renderer, &eff->dst_rect);
@@ -494,7 +544,7 @@ static void brightness_free(struct sdl_effect *eff) {
static void dithering_fade_step(struct sdl_effect *eff, float progress);
static void dithering_fade_free(struct sdl_effect *eff);
static SDL_Texture *create_dither_pattern_texture(int w, int h, int val) {
static EffectTexture *create_dither_pattern_texture(int w, int h, int val) {
SDL_PixelFormat *fmt = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888);
Uint32 col = SDL_MapRGBA(fmt, val, val, val, SDL_ALPHA_OPAQUE);
SDL_FreeFormat(fmt);
@@ -508,35 +558,37 @@ static SDL_Texture *create_dither_pattern_texture(int w, int h, int val) {
row[x] = col;
}
SDL_Texture *tx = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
SDL_UpdateTexture(tx, NULL, pixels, w * 4);
EffectTexture *t = calloc(1, sizeof(EffectTexture));
t->tx = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
SDL_UpdateTexture(t->tx, NULL, pixels, w * 4);
free(pixels);
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_BLEND);
return tx;
SDL_SetTextureBlendMode(t->tx, SDL_BLENDMODE_BLEND);
t->rect = (SDL_Rect){ 0, 0, w, h };
return t;
}
static struct sdl_effect *dithering_fade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *dithering_fade_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
switch (type) {
case EFFECT_DITHERING_FADEOUT:
SDL_FreeSurface(new);
destroy_effect_texture(new);
effect_init(eff, rect, old, NULL, type);
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 0);
break;
case EFFECT_DITHERING_FADEIN:
SDL_FreeSurface(old);
destroy_effect_texture(old);
effect_init(eff, rect, new, NULL, type);
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 0);
break;
case EFFECT_DITHERING_WHITEOUT:
SDL_FreeSurface(new);
destroy_effect_texture(new);
effect_init(eff, rect, old, NULL, type);
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 255);
break;
case EFFECT_DITHERING_WHITEIN:
SDL_FreeSurface(old);
destroy_effect_texture(old);
effect_init(eff, rect, new, NULL, type);
eff->tx_new = create_dither_pattern_texture(rect->w, rect->h, 255);
break;
@@ -552,7 +604,7 @@ static void dithering_fade_step(struct sdl_effect *eff, float progress) {
static const int dither_x[16] = {0,2,2,0,1,3,3,1,1,3,3,1,0,2,2,0};
static const int dither_y[16] = {0,2,0,2,1,3,1,3,0,2,0,2,1,3,1,3};
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
render_effect_texture(eff->tx_old, NULL, &eff->dst_rect);
if (eff->type == EFFECT_DITHERING_FADEIN || eff->type == EFFECT_DITHERING_WHITEIN)
progress = 1.f - progress;
@@ -563,17 +615,20 @@ static void dithering_fade_step(struct sdl_effect *eff, float progress) {
for (int i = 0; i < level; i++) {
dr.x = eff->dst_rect.x + dither_x[i];
dr.y = eff->dst_rect.y + dither_y[i];
SDL_RenderCopy(sdl_renderer, eff->tx_new, NULL, &dr);
render_effect_texture(eff->tx_new, NULL, &dr);
}
SDL_RenderPresent(sdl_renderer);
}
static void dithering_fade_free(struct sdl_effect *eff) {
if (eff->type == EFFECT_DITHERING_FADEOUT)
SDL_FillRect(sdl_display, &eff->dst_rect, SDL_MapRGB(sdl_display->format, 0, 0, 0));
else if (eff->type == EFFECT_DITHERING_WHITEOUT)
SDL_FillRect(sdl_display, &eff->dst_rect, SDL_MapRGB(sdl_display->format, 255, 255, 255));
if (eff->type == EFFECT_DITHERING_FADEOUT) {
SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255);
SDL_RenderFillRect(sdl_renderer, &eff->dst_rect);
} else if (eff->type == EFFECT_DITHERING_WHITEOUT) {
SDL_SetRenderDrawColor(sdl_renderer, 255, 255, 255, 255);
SDL_RenderFillRect(sdl_renderer, &eff->dst_rect);
}
effect_finish(eff, false);
free(eff);
}
@@ -583,7 +638,7 @@ static void dithering_fade_free(struct sdl_effect *eff) {
static void pan_in_step(struct sdl_effect *eff, float progress);
static void pan_in_free(struct sdl_effect *eff);
static struct sdl_effect *pan_in_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *pan_in_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -594,7 +649,7 @@ static struct sdl_effect *pan_in_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surfa
}
static void pan_in_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
render_effect_texture(eff->tx_old, NULL, &eff->dst_rect);
int h = eff->dst_rect.h * progress;
SDL_Rect sr = { 0, 0, eff->dst_rect.w, h };
@@ -605,7 +660,7 @@ static void pan_in_step(struct sdl_effect *eff, float progress) {
} else {
dr.y += eff->dst_rect.h - h;
}
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
render_effect_texture(eff->tx_new, &sr, &dr);
SDL_RenderPresent(sdl_renderer);
}
@@ -620,7 +675,7 @@ static void pan_in_free(struct sdl_effect *eff) {
static void skip_line_step(struct sdl_effect *eff, float progress);
static void skip_line_free(struct sdl_effect *eff);
static struct sdl_effect *skip_line_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *skip_line_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -631,7 +686,7 @@ static struct sdl_effect *skip_line_new(SDL_Rect *rect, SDL_Surface *old, SDL_Su
}
static void skip_line_step(struct sdl_effect *eff, float progress) {
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
render_effect_texture(eff->tx_old, NULL, &eff->dst_rect);
if (eff->type == EFFECT_SKIP_LINE_UP_DOWN) {
int h = eff->dst_rect.h * progress;
@@ -643,13 +698,13 @@ static void skip_line_step(struct sdl_effect *eff, float progress) {
for (int y = 0; y < h; y += 2) {
sr.y = y;
dr.y = eff->dst_rect.y + y;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
render_effect_texture(eff->tx_new, &sr, &dr);
if (y == 0 && eff->dst_rect.h & 1)
continue;
sr.y = bottom - y;
dr.y = eff->dst_rect.y + bottom - y;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
render_effect_texture(eff->tx_new, &sr, &dr);
}
} else {
int w = eff->dst_rect.w * progress;
@@ -661,13 +716,13 @@ static void skip_line_step(struct sdl_effect *eff, float progress) {
for (int x = 0; x < w; x += 2) {
sr.x = x;
dr.x = eff->dst_rect.x + x;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
render_effect_texture(eff->tx_new, &sr, &dr);
if (x == 0 && eff->dst_rect.w & 1)
continue;
sr.x = right - x;
dr.x = eff->dst_rect.x + right - x;
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
render_effect_texture(eff->tx_new, &sr, &dr);
}
}
@@ -684,7 +739,7 @@ static void skip_line_free(struct sdl_effect *eff) {
static void wipe_step(struct sdl_effect *eff, float progress);
static void wipe_free(struct sdl_effect *eff);
static struct sdl_effect *wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *wipe_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -695,8 +750,8 @@ static struct sdl_effect *wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface
}
static void wipe_step(struct sdl_effect *eff, float progress) {
SDL_Texture *bg = eff->tx_old;
SDL_Texture *fg = eff->tx_new;
EffectTexture *bg = eff->tx_old;
EffectTexture *fg = eff->tx_new;
if (eff->type == EFFECT_WIPE_RL ||
eff->type == EFFECT_WIPE_UP ||
eff->type == EFFECT_WIPE_IN ||
@@ -707,7 +762,7 @@ static void wipe_step(struct sdl_effect *eff, float progress) {
progress = 1.f - progress;
}
SDL_RenderCopy(sdl_renderer, bg, NULL, &eff->dst_rect);
render_effect_texture(bg, NULL, &eff->dst_rect);
SDL_Rect sr = { 0, 0, eff->dst_rect.w, eff->dst_rect.h };
SDL_Rect dr = eff->dst_rect;
@@ -743,7 +798,7 @@ static void wipe_step(struct sdl_effect *eff, float progress) {
default:
assert(!"Cannot happen");
}
SDL_RenderCopy(sdl_renderer, fg, &sr, &dr);
render_effect_texture(fg, &sr, &dr);
SDL_RenderPresent(sdl_renderer);
}
@@ -758,7 +813,7 @@ static void wipe_free(struct sdl_effect *eff) {
static void circle_wipe_step(struct sdl_effect *eff, float progress);
static void circle_wipe_free(struct sdl_effect *eff);
static struct sdl_effect *circle_wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *circle_wipe_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -769,14 +824,14 @@ static struct sdl_effect *circle_wipe_new(SDL_Rect *rect, SDL_Surface *old, SDL_
}
static void circle_wipe_step(struct sdl_effect *eff, float progress) {
SDL_Texture *bg = eff->tx_old;
SDL_Texture *fg = eff->tx_new;
EffectTexture *bg = eff->tx_old;
EffectTexture *fg = eff->tx_new;
if (eff->type == EFFECT_CIRCLE_WIPE_IN) {
bg = eff->tx_new;
fg = eff->tx_old;
progress = 1 - progress;
}
SDL_RenderCopy(sdl_renderer, bg, NULL, &eff->dst_rect);
render_effect_texture(bg, NULL, &eff->dst_rect);
int hw = eff->dst_rect.w / 2;
int hh = eff->dst_rect.h / 2;
@@ -789,7 +844,7 @@ static void circle_wipe_step(struct sdl_effect *eff, float progress) {
if (y*y + x*x <= r*r) {
SDL_Rect sr = {hw + x, hh + y, -2*x, 1};
SDL_Rect dr = {eff->dst_rect.x + hw + x, eff->dst_rect.y + hh + y, -2*x, 1};
SDL_RenderCopy(sdl_renderer, fg, &sr, &dr);
render_effect_texture(fg, &sr, &dr);
break;
}
}
@@ -808,7 +863,7 @@ static void circle_wipe_free(struct sdl_effect *eff) {
static void blind_step(struct sdl_effect *eff, float progress);
static void blind_free(struct sdl_effect *eff);
static struct sdl_effect *blind_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *blind_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -818,7 +873,7 @@ static struct sdl_effect *blind_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surfac
return eff;
}
static void blind_vstep(float progress, SDL_Rect *rect, SDL_Texture *tx_new, int offset_y, bool flip) {
static void blind_vstep(float progress, SDL_Rect *rect, EffectTexture *tx_new, int offset_y, bool flip) {
const int N = 16;
int nr_bands = rect->h / N + N - 1;
@@ -834,7 +889,7 @@ static void blind_vstep(float progress, SDL_Rect *rect, SDL_Texture *tx_new, int
SDL_Rect dr = sr;
move_rect(&dr, rect->x, rect->y);
sr.y += offset_y;
SDL_RenderCopy(sdl_renderer, tx_new, &sr, &dr);
render_effect_texture(tx_new, &sr, &dr);
}
for (int i = 1; i < N; i++) {
int y = (step - i) * N;
@@ -846,14 +901,14 @@ static void blind_vstep(float progress, SDL_Rect *rect, SDL_Texture *tx_new, int
SDL_Rect dr = sr;
move_rect(&dr, rect->x, rect->y);
sr.y += offset_y;
SDL_RenderCopy(sdl_renderer, tx_new, &sr, &dr);
render_effect_texture(tx_new, &sr, &dr);
}
}
static void blind_step(struct sdl_effect *eff, float progress) {
const int N = 16;
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, &eff->dst_rect);
render_effect_texture(eff->tx_old, NULL, &eff->dst_rect);
if (eff->type == EFFECT_BLIND_DOWN || eff->type == EFFECT_BLIND_UP || eff->type == EFFECT_BLIND_DOWN_LR) {
blind_vstep(progress, &eff->dst_rect, eff->tx_new, 0, eff->type == EFFECT_BLIND_UP);
@@ -882,7 +937,7 @@ static void blind_step(struct sdl_effect *eff, float progress) {
flip_rect_h(&sr, eff->dst_rect.w);
SDL_Rect dr = sr;
move_rect(&dr, eff->dst_rect.x, eff->dst_rect.y);
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
render_effect_texture(eff->tx_new, &sr, &dr);
}
for (int i = 1; i < N; i++) {
int x = (step - i) * N;
@@ -893,7 +948,7 @@ static void blind_step(struct sdl_effect *eff, float progress) {
flip_rect_h(&sr, eff->dst_rect.w);
SDL_Rect dr = sr;
move_rect(&dr, eff->dst_rect.x, eff->dst_rect.y);
SDL_RenderCopy(sdl_renderer, eff->tx_new, &sr, &dr);
render_effect_texture(eff->tx_new, &sr, &dr);
}
}
@@ -910,7 +965,7 @@ static void blind_free(struct sdl_effect *eff) {
static void blend_animation_step(struct sdl_effect *eff, float progress);
static void blend_animation_free(struct sdl_effect *eff);
static struct sdl_effect *blend_animation_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *blend_animation_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -923,7 +978,7 @@ static struct sdl_effect *blend_animation_new(SDL_Rect *rect, SDL_Surface *old,
static void blend_animation_step(struct sdl_effect *eff, float progress) {
const bool lr = eff->type == EFFECT_BLEND_LR_RL;
SDL_Texture *bg, *fg;
EffectTexture *bg, *fg;
if (progress < 0.5f) {
bg = eff->tx_old;
fg = eff->tx_new;
@@ -933,10 +988,10 @@ static void blend_animation_step(struct sdl_effect *eff, float progress) {
progress = 1.f - progress;
}
SDL_RenderCopy(sdl_renderer, bg, NULL, &eff->dst_rect);
render_effect_texture(bg, NULL, &eff->dst_rect);
int k = (lr ? eff->dst_rect.w : eff->dst_rect.h) * progress;
SDL_SetTextureBlendMode(fg, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(fg, 127);
SDL_SetTextureBlendMode(fg->tx, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(fg->tx, 127);
SDL_Rect sr = {0, 0, eff->dst_rect.w, eff->dst_rect.h};
SDL_Rect dr = eff->dst_rect;
@@ -944,7 +999,7 @@ static void blend_animation_step(struct sdl_effect *eff, float progress) {
sr.w = dr.w = k;
else
sr.h = dr.h = k;
SDL_RenderCopy(sdl_renderer, fg, &sr, &dr);
render_effect_texture(fg, &sr, &dr);
if (lr) {
sr.x = eff->dst_rect.w - k;
@@ -953,9 +1008,10 @@ static void blend_animation_step(struct sdl_effect *eff, float progress) {
sr.y = eff->dst_rect.h - k;
dr.y += sr.y;
}
SDL_RenderCopy(sdl_renderer, fg, &sr, &dr);
render_effect_texture(fg, &sr, &dr);
SDL_SetTextureBlendMode(fg, SDL_BLENDMODE_NONE);
SDL_SetTextureAlphaMod(fg->tx, 255);
SDL_SetTextureBlendMode(fg->tx, SDL_BLENDMODE_NONE);
SDL_RenderPresent(sdl_renderer);
}
@@ -977,7 +1033,7 @@ struct zoom_blend_blur_effect {
static void zoom_blend_blur_step(struct sdl_effect *eff, float progress);
static void zoom_blend_blur_free(struct sdl_effect *eff);
static struct sdl_effect *zoom_blend_blur_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new) {
static struct sdl_effect *zoom_blend_blur_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new) {
if (!SDL_RenderTargetSupported(sdl_renderer))
return fallback_effect_new(rect, old, new, EFFECT_ZOOM_BLEND_BLUR);
@@ -1007,19 +1063,21 @@ static void zoom_blend_blur_step(struct sdl_effect *eff, float progress) {
.h = h
};
SDL_SetRenderTarget(sdl_renderer, this->tx[this->index]);
SDL_RenderCopy(sdl_renderer, eff->tx_new, &r, NULL);
render_effect_texture(eff->tx_new, &r, NULL);
SDL_SetRenderTarget(sdl_renderer, NULL);
this->index = (this->index + 1) % ZOOM_BLEND_BLUR_STEPS;
SDL_RenderFillRect(sdl_renderer, &eff->dst_rect);
EffectTexture texture_rect = { NULL, { 0, 0, eff->dst_rect.w, eff->dst_rect.h } };
for (int i = 0; i < ZOOM_BLEND_BLUR_STEPS; i++) {
SDL_Texture *tx = this->tx[i] ? this->tx[i] : eff->tx_new;
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_ADD);
SDL_SetTextureAlphaMod(tx, 255 / ZOOM_BLEND_BLUR_STEPS);
SDL_RenderCopy(sdl_renderer, tx, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_NONE);
SDL_SetTextureAlphaMod(tx, 255);
texture_rect.tx = this->tx[i];
EffectTexture *t = this->tx[i] ? &texture_rect : eff->tx_new;
SDL_SetTextureBlendMode(t->tx, SDL_BLENDMODE_ADD);
SDL_SetTextureAlphaMod(t->tx, 255 / ZOOM_BLEND_BLUR_STEPS);
render_effect_texture(t, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(t->tx, SDL_BLENDMODE_NONE);
SDL_SetTextureAlphaMod(t->tx, 255);
}
SDL_RenderPresent(sdl_renderer);
}
@@ -1040,14 +1098,14 @@ static void zoom_blend_blur_free(struct sdl_effect *eff) {
struct linear_blur_effect {
struct sdl_effect eff;
SDL_Texture *blurred_old[LINEAR_BLUR_STEPS];
SDL_Texture *blurred_new[LINEAR_BLUR_STEPS];
EffectTexture *blurred_old[LINEAR_BLUR_STEPS];
EffectTexture *blurred_new[LINEAR_BLUR_STEPS];
};
static void linear_blur_step(struct sdl_effect *eff, float 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) {
static struct sdl_effect *linear_blur_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
if (!SDL_RenderTargetSupported(sdl_renderer))
return fallback_effect_new(rect, old, new, type);
@@ -1060,28 +1118,30 @@ static struct sdl_effect *linear_blur_new(SDL_Rect *rect, SDL_Surface *old, SDL_
return &lbe->eff;
}
static SDL_Texture *blur(struct linear_blur_effect *this, SDL_Texture *src, int stride) {
static EffectTexture *blur(struct linear_blur_effect *this, EffectTexture *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);
EffectTexture *dst = calloc(1, sizeof(EffectTexture));
dst->tx = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, w, h);
dst->rect = (SDL_Rect){0, 0, w, h};
SDL_SetRenderTarget(sdl_renderer, dst);
SDL_SetRenderTarget(sdl_renderer, dst->tx);
SDL_RenderClear(sdl_renderer);
SDL_SetTextureBlendMode(src, SDL_BLENDMODE_ADD);
SDL_SetTextureAlphaMod(src, 127);
SDL_SetTextureBlendMode(src->tx, SDL_BLENDMODE_ADD);
SDL_SetTextureAlphaMod(src->tx, 127);
SDL_Rect dr = {0, 0, w, h};
*(vertical ? &dr. y : &dr.x) = -stride / 2;
SDL_RenderCopy(sdl_renderer, src, NULL, &dr);
render_effect_texture(src, NULL, &dr);
*(vertical ? &dr. y : &dr.x) = max(1, stride / 2);
SDL_RenderCopy(sdl_renderer, src, NULL, &dr);
render_effect_texture(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);
render_effect_texture(src, &sr, &dr);
if (stride > 1) {
if (vertical) {
sr.y = h - 1;
@@ -1090,11 +1150,11 @@ static SDL_Texture *blur(struct linear_blur_effect *this, SDL_Texture *src, int
sr.x = w - 1;
dr.x = w - stride / 2;
}
SDL_RenderCopy(sdl_renderer, src, &sr, &dr);
render_effect_texture(src, &sr, &dr);
}
SDL_SetTextureAlphaMod(src, 255);
SDL_SetTextureBlendMode(src, SDL_BLENDMODE_NONE);
SDL_SetTextureAlphaMod(src->tx, 255);
SDL_SetTextureBlendMode(src->tx, SDL_BLENDMODE_NONE);
SDL_SetRenderTarget(sdl_renderer, NULL);
return dst;
@@ -1105,7 +1165,7 @@ static void linear_blur_step(struct sdl_effect *eff, float progress) {
int step = progress * LINEAR_BLUR_STEPS * 2;
if (step == LINEAR_BLUR_STEPS * 2) {
SDL_RenderCopy(sdl_renderer, eff->tx_new, NULL, NULL);
render_effect_texture(eff->tx_new, NULL, NULL);
SDL_RenderPresent(sdl_renderer);
return;
}
@@ -1118,12 +1178,12 @@ static void linear_blur_step(struct sdl_effect *eff, float progress) {
}
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);
EffectTexture *old = this->blurred_old[i];
EffectTexture *new = this->blurred_new[i];
render_effect_texture(old, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(new->tx, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(new->tx, 255 * progress);
render_effect_texture(new, NULL, &eff->dst_rect);
SDL_RenderPresent(sdl_renderer);
}
@@ -1131,9 +1191,9 @@ 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]);
destroy_effect_texture(this->blurred_old[i]);
if (this->blurred_new[i])
SDL_DestroyTexture(this->blurred_new[i]);
destroy_effect_texture(this->blurred_new[i]);
}
effect_finish(&this->eff, true);
free(this);
@@ -1149,7 +1209,7 @@ struct polygon_mask_effect {
static void polygon_mask_step(struct sdl_effect *eff, float progress);
static void polygon_mask_free(struct sdl_effect *eff);
static struct sdl_effect *polygon_mask_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *polygon_mask_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
#if HAS_SDL_RenderGeometry
if (SDL_RenderTargetSupported(sdl_renderer)) {
struct polygon_mask_effect *pmf = calloc(1, sizeof(struct polygon_mask_effect));
@@ -1357,7 +1417,7 @@ static void polygon_mask_step(struct sdl_effect *eff, float progress) {
int w = eff->dst_rect.w;
int h = eff->dst_rect.h;
SDL_SetRenderTarget(sdl_renderer, this->tx_tmp);
SDL_RenderCopy(sdl_renderer, eff->tx_old, NULL, NULL);
render_effect_texture(eff->tx_old, NULL, NULL);
switch (eff->type) {
case EFFECT_PENTAGRAM_IN_OUT:
draw_pentagram(w / 2, h / 2, max(w, h) * progress, M_PIf * progress);
@@ -1384,7 +1444,7 @@ static void polygon_mask_step(struct sdl_effect *eff, float progress) {
assert(!"Cannot happen");
}
SDL_SetRenderTarget(sdl_renderer, NULL);
SDL_RenderCopy(sdl_renderer, eff->tx_new, NULL, &eff->dst_rect);
render_effect_texture(eff->tx_new, NULL, &eff->dst_rect);
SDL_SetTextureBlendMode(this->tx_tmp, SDL_BLENDMODE_BLEND);
SDL_RenderCopy(sdl_renderer, this->tx_tmp, NULL, &eff->dst_rect);
SDL_RenderPresent(sdl_renderer);
@@ -1404,7 +1464,7 @@ static void polygon_mask_free(struct sdl_effect *eff) {
static void rotate_step(struct sdl_effect *eff, float progress);
static void rotate_free(struct sdl_effect *eff);
static struct sdl_effect *rotate_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *rotate_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -1415,7 +1475,7 @@ static struct sdl_effect *rotate_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surfa
}
static void rotate_step(struct sdl_effect *eff, float progress) {
SDL_Texture *bg_texture, *fg_texture;
EffectTexture *bg_texture, *fg_texture;
float angle = progress * 360;
float scale = progress;
switch (eff->type) {
@@ -1452,8 +1512,8 @@ static void rotate_step(struct sdl_effect *eff, float progress) {
r.y += (1.f - scale) * r.h / 2;
r.w *= scale;
r.h *= scale;
SDL_RenderCopy(sdl_renderer, bg_texture, NULL, &eff->dst_rect);
SDL_RenderCopyEx(sdl_renderer, fg_texture, NULL, &r, angle, NULL, SDL_FLIP_NONE);
render_effect_texture(bg_texture, NULL, &eff->dst_rect);
SDL_RenderCopyEx(sdl_renderer, fg_texture->tx, &fg_texture->rect, &r, angle, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(sdl_renderer);
}
@@ -1467,7 +1527,7 @@ static void rotate_free(struct sdl_effect *eff) {
static void polygon_rotate_step(struct sdl_effect *eff, float progress);
static void polygon_rotate_free(struct sdl_effect *eff);
static struct sdl_effect *polygon_rotate_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new, enum sdl_effect_type type) {
static struct sdl_effect *polygon_rotate_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new, enum sdl_effect_type type) {
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
@@ -1479,7 +1539,7 @@ static struct sdl_effect *polygon_rotate_new(SDL_Rect *rect, SDL_Surface *old, S
static void polygon_rotate_step(struct sdl_effect *eff, float progress) {
bool vertical = eff->type == EFFECT_POLYGON_ROTATE_Y || eff->type == EFFECT_POLYGON_ROTATE_Y_CW;
SDL_Texture *texture = progress < 0.5f ? eff->tx_old : eff->tx_new;
EffectTexture *texture = progress < 0.5f ? eff->tx_old : eff->tx_new;
float angle = progress < 0.5f ? progress * M_PIf : (progress - 1.f) * M_PIf;
if (eff->type == EFFECT_POLYGON_ROTATE_Y_CW || eff->type == EFFECT_POLYGON_ROTATE_X_CW)
angle *= -1;
@@ -1511,7 +1571,7 @@ static void polygon_rotate_step(struct sdl_effect *eff, float progress) {
transpose_rect(&sr);
transpose_rect(&dr);
}
SDL_RenderCopy(sdl_renderer, texture, &sr, &dr);
render_effect_texture(texture, &sr, &dr);
}
SDL_RenderPresent(sdl_renderer);
@@ -1532,7 +1592,7 @@ struct zigzag_crossfade_effect {
static void zigzag_crossfade_step(struct sdl_effect *eff, float progress);
static void zigzag_crossfade_free(struct sdl_effect *eff);
static struct sdl_effect *zigzag_crossfade_new(SDL_Rect *rect, SDL_Surface *old, SDL_Surface *new) {
static struct sdl_effect *zigzag_crossfade_new(SDL_Rect *rect, EffectTexture *old, EffectTexture *new) {
if (!SDL_RenderTargetSupported(sdl_renderer))
return fallback_effect_new(rect, old, new, EFFECT_ZIGZAG_CROSSFADE);
@@ -1547,7 +1607,7 @@ static struct sdl_effect *zigzag_crossfade_new(SDL_Rect *rect, SDL_Surface *old,
return &eff->eff;
}
static void wave_warp_h(SDL_Texture *src, SDL_Texture *dst, int w, int h, float amplitude, float length, float phase) {
static void wave_warp_h(EffectTexture *src, SDL_Texture *dst, int w, int h, float amplitude, float length, float phase) {
SDL_SetRenderTarget(sdl_renderer, dst);
SDL_RenderClear(sdl_renderer);
SDL_Rect sr = {0, 0, w, 1};
@@ -1555,7 +1615,7 @@ static void wave_warp_h(SDL_Texture *src, SDL_Texture *dst, int w, int h, float
for (int y = 0; y < h; y++) {
sr.y = dr.y = y;
dr.x = sinf(phase + y * (2 * M_PIf / 360 * length)) * amplitude;
SDL_RenderCopy(sdl_renderer, src, &sr, &dr);
render_effect_texture(src, &sr, &dr);
}
SDL_SetRenderTarget(sdl_renderer, NULL);
}
@@ -1612,11 +1672,11 @@ struct magnify_effect {
static void magnify_step(struct sdl_effect *eff, float progress);
static void magnify_free(struct sdl_effect *eff);
static struct sdl_effect *magnify_new(SDL_Surface *sf, SDL_Rect *old_rect, SDL_Rect *new_rect) {
static struct sdl_effect *magnify_new(EffectTexture *tx, SDL_Rect *old_rect, SDL_Rect *new_rect) {
struct magnify_effect *eff = calloc(1, sizeof(struct magnify_effect));
if (!eff)
NOMEMERR();
effect_init(&eff->eff, old_rect, sf, NULL, EFFECT_MAGNIFY);
effect_init(&eff->eff, old_rect, tx, NULL, EFFECT_MAGNIFY);
eff->new_rect = *new_rect;
eff->eff.step = magnify_step;
eff->eff.finish = magnify_free;
@@ -1633,7 +1693,7 @@ static void magnify_step(struct sdl_effect *eff, float progress) {
.w = or->w + (nr->w - or->w) * progress,
.h = or->h + (nr->h - or->h) * progress,
};
SDL_RenderCopy(sdl_renderer, eff->tx_old, &r, NULL);
render_effect_texture(eff->tx_old, &r, NULL);
SDL_RenderPresent(sdl_renderer);
}
@@ -1649,10 +1709,12 @@ static void raster_blend_free(struct sdl_effect *eff);
static struct sdl_effect *raster_blend_new(SDL_Rect *rect, int sx, int sy) {
SDL_Surface *sprite = sdl_dib_to_surface_with_alpha(sx, sy, rect->w, rect->h);
EffectTexture *texture = create_effect_texture_from_surface(sprite);
SDL_FreeSurface(sprite);
struct sdl_effect *eff = calloc(1, sizeof(struct sdl_effect));
if (!eff)
NOMEMERR();
effect_init(eff, rect, NULL, sprite, EFFECT_RASTER_BLEND);
effect_init(eff, rect, NULL, texture, EFFECT_RASTER_BLEND);
eff->step = raster_blend_step;
eff->finish = raster_blend_free;
return eff;
@@ -1665,7 +1727,7 @@ static void raster_blend_step(struct sdl_effect *eff, float progress) {
for (int y = 0; y < eff->dst_rect.h; y++) {
float t = 1.f - 4.f * progress + 3.f * y / eff->dst_rect.h;
d_rect.x = eff->dst_rect.x + (t < 0 ? 0 : sinf(2 * M_PIf * t) * 50);
SDL_RenderCopy(sdl_renderer, eff->tx_new, &s_rect, &d_rect);
render_effect_texture(eff->tx_new, &s_rect, &d_rect);
s_rect.y++;
d_rect.y++;
}
@@ -1679,56 +1741,41 @@ static void raster_blend_free(struct sdl_effect *eff) {
// -----------------
static SDL_Surface *create_surface(agsurface_t *as, int x, int y, int w, int h) {
SDL_Surface *sf = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_RGB888);
SDL_Rect rect = { x, y, w, h };
if (!as) {
SDL_BlitSurface(sdl_display, &rect, sf, NULL);
} else if (as == sdl_dibinfo) {
SDL_BlitSurface(sdl_dib, &rect, sf, NULL);
} else {
SDL_Surface *s = com2surface(as);
SDL_BlitSurface(s, &rect, sf, NULL);
SDL_FreeSurface(s);
}
return sf;
}
struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int oy, agsurface_t *new, int nx, int ny, enum sdl_effect_type type) {
SDL_Surface *sf_old = create_surface(old, ox, oy, rect->w, rect->h);
SDL_Surface *sf_new = create_surface(new, nx, ny, rect->w, rect->h);
EffectTexture *tx_old = create_effect_texture(old, ox, oy, rect->w, rect->h);
EffectTexture *tx_new = create_effect_texture(new, nx, ny, rect->w, rect->h);
switch (type) {
case EFFECT_CROSSFADE:
return crossfade_new(rect, sf_old, sf_new);
return crossfade_new(rect, tx_old, tx_new);
case EFFECT_CROSSFADE_DOWN:
case EFFECT_CROSSFADE_UP:
case EFFECT_CROSSFADE_LR:
case EFFECT_CROSSFADE_RL:
case EFFECT_CROSSFADE_LR_RL:
case EFFECT_CROSSFADE_UP_DOWN:
return crossfade_animation_new(rect, sf_old, sf_new, type);
return crossfade_animation_new(rect, tx_old, tx_new, type);
case EFFECT_MOSAIC:
case EFFECT_CROSSFADE_MOSAIC:
return mosaic_new(rect, sf_old, sf_new, type);
return mosaic_new(rect, tx_old, tx_new, type);
case EFFECT_FADEOUT:
case EFFECT_FADEOUT_FROM_NEW:
case EFFECT_FADEIN:
case EFFECT_WHITEOUT:
case EFFECT_WHITEOUT_FROM_NEW:
case EFFECT_WHITEIN:
return brightness_new(rect, sf_old, sf_new, type);
return brightness_new(rect, tx_old, tx_new, type);
case EFFECT_DITHERING_FADEOUT:
case EFFECT_DITHERING_FADEIN:
case EFFECT_DITHERING_WHITEOUT:
case EFFECT_DITHERING_WHITEIN:
return dithering_fade_new(rect, sf_old, sf_new, type);
return dithering_fade_new(rect, tx_old, tx_new, type);
case EFFECT_PAN_IN_DOWN:
case EFFECT_PAN_IN_UP:
return pan_in_new(rect, sf_old, sf_new, type);
return pan_in_new(rect, tx_old, tx_new, type);
case EFFECT_SKIP_LINE_UP_DOWN:
case EFFECT_SKIP_LINE_LR_RL:
return skip_line_new(rect, sf_old, sf_new, type);
return skip_line_new(rect, tx_old, tx_new, type);
case EFFECT_WIPE_IN:
case EFFECT_WIPE_OUT:
case EFFECT_WIPE_LR:
@@ -1739,25 +1786,25 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
case EFFECT_WIPE_IN_V:
case EFFECT_WIPE_OUT_H:
case EFFECT_WIPE_IN_H:
return wipe_new(rect, sf_old, sf_new, type);
return wipe_new(rect, tx_old, tx_new, type);
case EFFECT_CIRCLE_WIPE_OUT:
case EFFECT_CIRCLE_WIPE_IN:
return circle_wipe_new(rect, sf_old, sf_new, type);
return circle_wipe_new(rect, tx_old, tx_new, type);
case EFFECT_BLIND_DOWN:
case EFFECT_BLIND_UP:
case EFFECT_BLIND_LR:
case EFFECT_BLIND_RL:
case EFFECT_BLIND_UP_DOWN:
case EFFECT_BLIND_DOWN_LR:
return blind_new(rect, sf_old, sf_new, type);
return blind_new(rect, tx_old, tx_new, type);
case EFFECT_BLEND_UP_DOWN:
case EFFECT_BLEND_LR_RL:
return blend_animation_new(rect, sf_old, sf_new, type);
return blend_animation_new(rect, tx_old, tx_new, type);
case EFFECT_ZOOM_BLEND_BLUR:
return zoom_blend_blur_new(rect, sf_old, sf_new);
return zoom_blend_blur_new(rect, tx_old, tx_new);
case EFFECT_LINEAR_BLUR:
case EFFECT_LINEAR_BLUR_VERT:
return linear_blur_new(rect, sf_old, sf_new, type);
return linear_blur_new(rect, tx_old, tx_new, type);
case EFFECT_PENTAGRAM_IN_OUT:
case EFFECT_PENTAGRAM_OUT_IN:
case EFFECT_HEXAGRAM_IN_OUT:
@@ -1765,37 +1812,39 @@ struct sdl_effect *sdl_effect_init(SDL_Rect *rect, agsurface_t *old, int ox, int
case EFFECT_WINDMILL:
case EFFECT_WINDMILL_180:
case EFFECT_WINDMILL_360:
return polygon_mask_new(rect, sf_old, sf_new, type);
return polygon_mask_new(rect, tx_old, tx_new, type);
case EFFECT_ZOOM_IN:
case EFFECT_ROTATE_OUT:
case EFFECT_ROTATE_IN:
case EFFECT_ROTATE_OUT_CW:
case EFFECT_ROTATE_IN_CW:
return rotate_new(rect, sf_old, sf_new, type);
return rotate_new(rect, tx_old, tx_new, type);
case EFFECT_POLYGON_ROTATE_Y:
case EFFECT_POLYGON_ROTATE_Y_CW:
case EFFECT_POLYGON_ROTATE_X:
case EFFECT_POLYGON_ROTATE_X_CW:
return polygon_rotate_new(rect, sf_old, sf_new, type);
return polygon_rotate_new(rect, tx_old, tx_new, type);
case EFFECT_ZIGZAG_CROSSFADE:
return zigzag_crossfade_new(rect, sf_old, sf_new);
return zigzag_crossfade_new(rect, tx_old, tx_new);
default:
WARNING("Unknown effect %d", type);
return crossfade_new(rect, sf_old, sf_new);
return crossfade_new(rect, tx_old, tx_new);
}
}
struct sdl_effect *sdl_sprite_effect_init(SDL_Rect *rect, int dx, int dy, int sx, int sy, int col, enum sdl_effect_type type) {
SDL_Surface *sf_old = create_surface(sdl_dibinfo, dx, dy, rect->w, rect->h);
EffectTexture *tx_old = create_effect_texture(sdl_dibinfo, dx, dy, rect->w, rect->h);
SDL_Surface *sprite = sdl_dib_to_surface_colorkey(sx, sy, rect->w, rect->h, col);
EffectTexture *tx_new = create_effect_texture_from_surface(sprite);
SDL_FreeSurface(sprite);
switch (type) {
case EFFECT_PAN_IN_DOWN:
case EFFECT_PAN_IN_UP:
return pan_in_new(rect, sf_old, sprite, type);
return pan_in_new(rect, tx_old, tx_new, type);
case EFFECT_SKIP_LINE_UP_DOWN:
case EFFECT_SKIP_LINE_LR_RL:
return skip_line_new(rect, sf_old, sprite, type);
return skip_line_new(rect, tx_old, tx_new, type);
case EFFECT_RASTER_BLEND:
return raster_blend_new(rect, sx, sy);
default:
@@ -1805,8 +1854,8 @@ struct sdl_effect *sdl_sprite_effect_init(SDL_Rect *rect, int dx, int dy, int sx
}
struct sdl_effect *sdl_effect_magnify_init(agsurface_t *surface, SDL_Rect *view_rect, SDL_Rect *target_rect) {
SDL_Surface *sf = create_surface(surface, view_rect->x, view_rect->y, view_rect->w, view_rect->h);
return magnify_new(sf, view_rect, target_rect);
EffectTexture *tx = create_effect_texture(surface, view_rect->x, view_rect->y, view_rect->w, view_rect->h);
return magnify_new(tx, view_rect, target_rect);
}
void sdl_effect_step(struct sdl_effect *eff, float progress) {
-1
View File
@@ -33,7 +33,6 @@
extern SDL_Window *sdl_window;
extern SDL_Renderer *sdl_renderer;
extern SDL_Texture *sdl_texture;
extern SDL_Surface *sdl_display; // toplevel surface
extern SDL_Surface *sdl_dib; // offscreen surface
extern SDL_Color sdl_col[256]; // color palette
extern agsurface_t *sdl_dibinfo;
+7 -10
View File
@@ -39,7 +39,6 @@
SDL_Window *sdl_window;
SDL_Renderer *sdl_renderer;
SDL_Texture *sdl_texture;
SDL_Surface *sdl_display; // toplevel surface
SDL_Surface *sdl_dib; // offscreen surface
SDL_Color sdl_col[256]; // color palette
agsurface_t *sdl_dibinfo;
@@ -105,12 +104,13 @@ int sdl_Initialize(const char *render_driver) {
}
void sdl_Remove(void) {
if (sdl_display) {
if (sdl_dib)
SDL_FreeSurface(sdl_dib);
if (sdl_renderer)
SDL_DestroyRenderer(sdl_renderer);
if (js)
SDL_JoystickClose(js);
SDL_Quit();
}
SDL_Quit();
}
/* name is UTF-8 */
@@ -258,13 +258,10 @@ void sdl_setWindowSize(int w, int h) {
SDL_SetWindowSize(sdl_window, w, h);
#endif
SDL_RenderSetLogicalSize(sdl_renderer, w, h);
if (sdl_display)
SDL_FreeSurface(sdl_display);
if (sdl_texture)
SDL_DestroyTexture(sdl_texture);
sdl_display = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_RGB888);
sdl_texture = SDL_CreateTexture(sdl_renderer, sdl_display->format->format,
SDL_TEXTUREACCESS_STATIC, w, h);
sdl_texture = SDL_CreateTexture(
sdl_renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, w, h);
#ifdef __EMSCRIPTEN__
EM_ASM( xsystem35.shell.windowSizeChanged(); );
@@ -292,7 +289,7 @@ void sdl_setIntegerScaling(bool enable) {
#ifdef __EMSCRIPTEN__
bool EMSCRIPTEN_KEEPALIVE save_screenshot(const char* path) {
return SDL_SaveBMP(sdl_display, path) == 0;
return SDL_SaveBMP(sdl_dib, path) == 0;
}
#endif
+1 -1
View File
@@ -55,7 +55,7 @@ static void saveScreenshot(void) {
};
if (!GetSaveFileName(&ofn))
return;
if (SDL_SaveBMP(sdl_display, pathbuf) != 0) {
if (SDL_SaveBMP(sdl_dib, pathbuf) != 0) {
sdl_showMessageBox(MESSAGEBOX_ERROR, "xsystem35", SDL_GetError());
SDL_ClearError();
}