Make agsurface_t backed by SDL_Surface

This adds `sdl_surface` field to agsurface_t. `agsurface->pixel` is now
set to `agsurfae->sdl_surface->pixels`.

Note that the `sdl_surface` field does not have alpha; transparent
surfaces have a separate alpha plane in `agsurface->alpha`.
This commit is contained in:
kichikuou
2025-02-16 13:13:13 +09:00
parent 64abb3c582
commit e711d5786e
11 changed files with 46 additions and 89 deletions
+4 -20
View File
@@ -69,33 +69,17 @@ static int find_null_surface() {
}
static void sf_free_one(int no) {
surface_t *s;
if (no == 0) return;
s = suf[no];
if (s == NULL) return;
if (s->pixel) free(s->pixel);
if (s->alpha) free(s->alpha);
free(s);
if (no == 0 || !suf[no]) return;
sf_free(suf[no]);
suf[no] = NULL;
pre_freesurfno = no;
}
static void sf_free_all() {
int i;
surface_t *s;
for (i = 1; i < MAX_SURFACE; i++) {
if (suf[i] == NULL) continue;
s = suf[i];
if (s->pixel) free(s->pixel);
if (s->alpha) free(s->alpha);
free(s);
for (int i = 1; i < MAX_SURFACE; i++) {
sf_free(suf[i]);
suf[i] = NULL;
}
pre_freesurfno = 1;
}
+1
View File
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "portab.h"
#include "nact.h"
+4 -1
View File
@@ -14,7 +14,10 @@ static surface_t *stretch(surface_t *src, int dw, int dh, int mirror) {
dst->bytes_per_pixel = src->bytes_per_pixel;
if (src->pixel) {
dst->pixel = malloc(dh * dst->bytes_per_line);
dst->sdl_surface = SDL_CreateRGBSurfaceWithFormat(0, dw, dh, src->depth, src->sdl_surface->format->format);
dst->pixel = dst->sdl_surface->pixels;
dst->bytes_per_line = dst->sdl_surface->pitch;
dst->bytes_per_pixel = dst->sdl_surface->format->BytesPerPixel;
}
if (src->alpha) {
dst->alpha = malloc(dw * dh);
+1
View File
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "portab.h"
#include "nact.h"
+4 -1
View File
@@ -14,7 +14,10 @@ static surface_t *stretch(surface_t *src, int dw, int dh, int mirror) {
dst->bytes_per_pixel = src->bytes_per_pixel;
if (src->pixel) {
dst->pixel = malloc(dh * dst->bytes_per_line);
dst->sdl_surface = SDL_CreateRGBSurfaceWithFormat(0, dw, dh, src->depth, src->sdl_surface->format->format);
dst->pixel = dst->sdl_surface->pixels;
dst->bytes_per_line = dst->sdl_surface->pitch;
dst->bytes_per_pixel = dst->sdl_surface->format->BytesPerPixel;
}
if (src->alpha) {
dst->alpha = malloc(dw * dh);
+16 -50
View File
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SDL.h>
#include "portab.h"
#include "surface.h"
@@ -19,26 +20,26 @@ static surface_t *create(int width, int height, int depth, bool has_pixel, bool
s->depth = depth;
if (has_pixel) {
uint32_t format = 0;
switch (s->depth) {
case 8:
s->pixel = calloc(width * (height +1), sizeof(uint8_t));
s->bytes_per_line = width;
s->bytes_per_pixel = 1;
format = SDL_PIXELFORMAT_INDEX8;
break;
case 16:
s->pixel = calloc(width * (height +1) * 2, sizeof(uint8_t));
s->bytes_per_line = width * 2;
s->bytes_per_pixel = 2;
format = SDL_PIXELFORMAT_RGB565;
break;
case 24:
case 32:
s->pixel = calloc(width * (height +1) * 4, sizeof(uint8_t));
s->bytes_per_line = width * 4;
s->bytes_per_pixel = 4;
format = SDL_PIXELFORMAT_RGB888;
depth = 32;
break;
default:
WARNING("depth %d is not supported", s->depth);
SYSERROR("depth %d is not supported", s->depth);
}
s->sdl_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, format);
s->pixel = s->sdl_surface->pixels;
s->bytes_per_line = s->sdl_surface->pitch;
s->bytes_per_pixel = s->sdl_surface->format->BytesPerPixel;
}
if (has_alpha) {
@@ -87,7 +88,7 @@ surface_t *sf_create_pixel(int width, int height, int depth) {
*/
void sf_free(surface_t *s) {
if (s == NULL) return;
if (s->pixel) free(s->pixel);
if (s->sdl_surface) SDL_FreeSurface(s->sdl_surface);
if (s->alpha) free(s->alpha);
free(s);
}
@@ -107,9 +108,10 @@ surface_t *sf_dup(surface_t *in) {
memcpy(sf, in, sizeof(surface_t));
if (in->pixel) {
len = sf->bytes_per_line * sf->height;
sf->pixel = malloc(sizeof(uint8_t) * (len + sf->bytes_per_line));
memcpy(sf->pixel, in->pixel, len);
sf->sdl_surface = SDL_ConvertSurface(in->sdl_surface, in->sdl_surface->format, 0);
sf->pixel = sf->sdl_surface->pixels;
sf->bytes_per_line = sf->sdl_surface->pitch;
sf->bytes_per_pixel = sf->sdl_surface->format->BytesPerPixel;
}
if (in->alpha) {
@@ -148,39 +150,3 @@ void sf_copyall(surface_t *dst, surface_t *src) {
memcpy(dst->pixel, src->pixel, len);
}
}
/**
* surface の複製
* @param in: 複製もと
* @param copypixel: pixelをコピーするか
* @param copyalpha: alpha pixel をコピーするか
* @return: 複製した surface
*/
surface_t *sf_dup2(surface_t *in, bool copypixel, bool copyalpha) {
surface_t *sf;
int len;
if (in == NULL) return NULL;
sf = malloc(sizeof(surface_t));
memcpy(sf, in, sizeof(surface_t));
if (in->pixel) {
len = sf->bytes_per_line * sf->height;
sf->pixel = malloc(sizeof(uint8_t) * (len + sf->bytes_per_line));
if (copypixel) {
memcpy(sf->pixel, in->pixel, len);
}
}
if (in->alpha) {
len = sf->width * sf->height;
sf->alpha = malloc(sizeof(uint8_t) * (len + sf->width));
if (copyalpha) {
memcpy(sf->alpha, in->alpha, len);
}
}
return sf;
}
-1
View File
@@ -11,7 +11,6 @@ extern surface_t *sf_create_alpha(int width, int height);
extern surface_t *sf_create_pixel(int width, int height, int depth);
extern void sf_free(surface_t *s);
extern surface_t *sf_dup(surface_t *in);
extern surface_t *sf_dup2(surface_t *in, bool copypixel, bool copyalpha);
extern void sf_copyall(surface_t *dst, surface_t *src);
+4
View File
@@ -45,6 +45,8 @@
#define CURSOR_UPARROW 12
#define CURSOR_WAIT 13
struct SDL_Surface;
/* RGB <-> alpha plane copy type */
typedef enum {
FROM_16H,
@@ -69,6 +71,8 @@ struct agsurface {
uint8_t *pixel; /* pixel data (can be NULL) */
uint8_t *alpha; /* alpha pixel data (can be NULL) */
struct SDL_Surface *sdl_surface;
};
typedef struct agsurface agsurface_t;
+1 -1
View File
@@ -48,7 +48,7 @@ extern bool sdl_isFullscreen(void);
extern void sdl_raiseWindow(void);
extern agsurface_t *sdl_getDIB(void);
extern void sdl_setIntegerScaling(bool enable);
extern SDL_Surface *sdl_createSurfaceView(agsurface_t *s, int x, int y, int w, int h);
extern SDL_Surface *sdl_createSurfaceView(SDL_Surface *sf, int x, int y, int w, int h);
/* 画面更新 */
extern void sdl_updateArea(MyRectangle *src, MyPoint *dst);
+1 -1
View File
@@ -137,7 +137,7 @@ static EffectTexture *create_effect_texture(agsurface_t *as, int x, int y, int w
t->tx = sdl_texture;
t->rect = (SDL_Rect){ x, y, w, h };
} else {
SDL_Surface *sf = sdl_createSurfaceView(as, x, y, w, h);
SDL_Surface *sf = sdl_createSurfaceView(as->sdl_surface, x, y, w, h);
t->tx = SDL_CreateTextureFromSurface(sdl_renderer, sf);
SDL_FreeSurface(sf);
t->rect = (SDL_Rect){ 0, 0, w, h };
+10 -14
View File
@@ -198,6 +198,7 @@ static void makeDIB(int width, int height, int depth) {
sdl_dibinfo->width = width;
sdl_dibinfo->height = height;
sdl_dibinfo->alpha = NULL;
sdl_dibinfo->sdl_surface = sdl_dib;
image_setdepth(sdl_dibinfo->depth);
}
@@ -222,19 +223,14 @@ agsurface_t *sdl_getDIB(void) {
return sdl_dibinfo;
}
SDL_Surface *sdl_createSurfaceView(agsurface_t *s, int x, int y, int w, int h) {
if (s == sdl_dibinfo) {
uint8_t *pixels = sdl_dib->pixels;
pixels += y * sdl_dib->pitch + x * sdl_dib->format->BytesPerPixel;
SDL_Surface *view = SDL_CreateRGBSurfaceWithFormatFrom(
pixels, w, h, sdl_dib->format->BitsPerPixel, sdl_dib->pitch, sdl_dib->format->format);
if (sdl_dib->format->palette)
SDL_SetSurfacePalette(view, sdl_dib->format->palette);
return view;
} else {
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);
}
SDL_Surface *sdl_createSurfaceView(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);
if (sf->format->palette)
SDL_SetSurfacePalette(view, sf->format->palette);
return view;
}
/* AutoRepeat の設定 */
@@ -303,7 +299,7 @@ void sdl_setIntegerScaling(bool enable) {
bool EMSCRIPTEN_KEEPALIVE save_screenshot(const char* path) {
SDL_Rect *r = &nact->ags.view_area;
SDL_Surface *view = sdl_createSurfaceView(sdl_dibinfo, r->x, r->y, r->w, r->h);
SDL_Surface *view = sdl_createSurfaceView(sdl_dib, r->x, r->y, r->w, r->h);
bool ok = SDL_SaveBMP(view, path) == 0;
SDL_FreeSurface(view);
return ok;