Commits (1)
......@@ -47,6 +47,26 @@ aspect_fix(int *x, int *y, int aspect_width, int aspect_height)
*x = bestx;
}
/*
* Corrects width/height to have the specified aspect ratio
*/
void
aspect_fix_low(int *x, int *y, int aspect_width, int aspect_height)
{
int bestx, besty;
// Nothing we can do here...
if (aspect_width == 0 || aspect_height == 0)
return;
bestx = lround((double)*y * aspect_width / aspect_height);
besty = lround((double)*x * aspect_height / aspect_width);
if (bestx < *x && bestx > 0)
*x = bestx;
else
*y = besty;
}
/*
* Given a width/height of a source image, adjust it to match the current aspect
* ratio. Will not reduce either number
......
......@@ -19,3 +19,4 @@ struct graphics_buffer * do_scale(struct rectlist* rect, int xscale, int yscale,
void aspect_correct(int *x, int *y, int aspect_width, int aspect_height);
void aspect_reverse(int *x, int *y, int scrnwidth, int scrnheight, int aspect_width, int aspect_height);
void aspect_fix(int *x, int *y, int aspect_width, int aspect_height);
void aspect_fix_low(int *x, int *y, int aspect_width, int aspect_height);
......@@ -46,6 +46,8 @@ SDL_Cursor *curs=NULL;
SDL_Renderer *renderer=NULL;
SDL_Texture *texture=NULL;
pthread_mutex_t win_mutex;
pthread_mutex_t sdl_mode_mutex;
bool sdl_mode;
SDL_Surface *sdl_icon=NULL;
sem_t sdl_ufunc_ret;
......@@ -187,6 +189,7 @@ const struct sdl_keyvals sdl_keyval[] =
};
void sdl_video_event_thread(void *data);
static void setup_surfaces_locked(void);
static void sdl_user_func(int func, ...)
{
......@@ -348,7 +351,7 @@ window_can_scale_internally(int winwidth, int winheight)
static void
internal_scaling_factors(int winwidth, int winheight, int *x, int *y)
{
aspect_fix(&winwidth, &winheight, cvstat.aspect_width, cvstat.aspect_height);
aspect_fix_low(&winwidth, &winheight, cvstat.aspect_width, cvstat.aspect_height);
aspect_reverse(&winwidth, &winheight, cvstat.scrnwidth, cvstat.scrnheight, cvstat.aspect_width, cvstat.aspect_height);
*x = winwidth / cvstat.scrnwidth;
*y = winheight / cvstat.scrnheight;
......@@ -410,6 +413,9 @@ static int sdl_init_mode(int mode)
cvstat = vstat;
internal_scaling = window_can_scale_internally(vstat.winwidth, vstat.winheight);
pthread_mutex_lock(&sdl_mode_mutex);
sdl_mode = true;
pthread_mutex_unlock(&sdl_mode_mutex);
pthread_mutex_unlock(&vstatlock);
pthread_mutex_unlock(&blinker_lock);
......@@ -607,7 +613,6 @@ static void setup_surfaces_locked(void)
flags |= SDL_WINDOW_ALLOW_HIGHDPI;
#endif
pthread_mutex_lock(&win_mutex);
idealmw = cvstat.scrnwidth;
idealmh = cvstat.scrnheight;
......@@ -620,6 +625,9 @@ static void setup_surfaces_locked(void)
if (win == NULL) {
// SDL2: This is slow sometimes... not sure why.
if (sdl.CreateWindowAndRenderer(cvstat.winwidth, cvstat.winheight, flags, &win, &renderer) == 0) {
sdl.GetWindowSize(win, &idealw, &idealh);
cvstat.winwidth = idealw;
cvstat.winheight = idealh;
sdl.RenderClear(renderer);
if (internal_scaling)
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, idealw, idealh);
......@@ -638,6 +646,9 @@ static void setup_surfaces_locked(void)
else {
sdl.SetWindowMinimumSize(win, idealmw, idealmh);
sdl.SetWindowSize(win, idealw, idealh);
sdl.GetWindowSize(win, &idealw, &idealh);
cvstat.winwidth = idealw;
cvstat.winheight = idealh;
if (internal_scaling)
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, idealw, idealh);
else
......@@ -1022,43 +1033,17 @@ void sdl_video_event_thread(void *data)
case SDL_WINDOWEVENT_SIZE_CHANGED:
// SDL2: User resized window
case SDL_WINDOWEVENT_RESIZED:
{
// SDL2: Something resized window
const char *newh;
pthread_mutex_lock(&vstatlock);
pthread_mutex_lock(&win_mutex);
internal_scaling = window_can_scale_internally(ev.window.data1, ev.window.data2);
if (internal_scaling) {
newh = "0";
}
else {
newh = "2";
}
sdl.GetWindowSize(win, &cvstat.winwidth, &cvstat.winheight);
if (strcmp(newh, sdl.GetHint(SDL_HINT_RENDER_SCALE_QUALITY))) {
SDL_Texture *newtexture;
sdl.SetHint(SDL_HINT_RENDER_SCALE_QUALITY, newh);
if (internal_scaling) {
int idealw, idealh;
idealw = cvstat.winwidth;
idealh = cvstat.winheight;
aspect_fix(&idealw, &idealh, cvstat.aspect_width, cvstat.aspect_height);
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, idealw, idealh);
}
else
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, cvstat.scrnwidth, cvstat.scrnheight);
sdl.RenderClear(renderer);
if (texture)
sdl.DestroyTexture(texture);
texture = newtexture;
}
sdl.RenderClear(renderer);
bitmap_drv_request_pixels();
pthread_mutex_unlock(&win_mutex);
pthread_mutex_unlock(&vstatlock);
pthread_mutex_lock(&sdl_mode_mutex);
if (sdl_mode) {
pthread_mutex_unlock(&sdl_mode_mutex);
break;
}
pthread_mutex_unlock(&sdl_mode_mutex);
pthread_mutex_lock(&vstatlock);
sdl_setwinsize_locked(ev.window.data1, ev.window.data2);
setup_surfaces_locked();
pthread_mutex_unlock(&vstatlock);
break;
case SDL_WINDOWEVENT_EXPOSED:
bitmap_drv_request_pixels();
break;
......@@ -1078,20 +1063,25 @@ void sdl_video_event_thread(void *data)
pthread_mutex_lock(&win_mutex);
if (win != NULL) {
pthread_mutex_lock(&sdl_headlock);
pthread_mutex_lock(&sdl_mode_mutex);
list = update_list;
update_list = update_list_tail = NULL;
bool skipit = sdl_mode;
pthread_mutex_unlock(&sdl_mode_mutex);
pthread_mutex_unlock(&sdl_headlock);
for (; list; list = old_next) {
SDL_Rect src;
SDL_Rect dst;
old_next = list->next;
if (list->next == NULL) {
if (list->next == NULL && !skipit) {
void *pixels;
int pitch;
int row;
int tw, th;
sdl.RenderClear(renderer);
pthread_mutex_lock(&vstatlock);
if (internal_scaling) {
struct graphics_buffer *gb;
int xscale, yscale;
......@@ -1102,8 +1092,10 @@ void sdl_video_event_thread(void *data)
src.y = 0;
src.w = gb->w;
src.h = gb->h;
sdl.QueryTexture(texture, NULL, NULL, &tw, &th);
sdl.LockTexture(texture, &src, &pixels, &pitch);
if (sdl.QueryTexture(texture, NULL, NULL, &tw, &th) != 0)
fprintf(stderr, "Unable to query texture (%s)\n", sdl.GetError());
if (sdl.LockTexture(texture, &src, &pixels, &pitch) != 0)
fprintf(stderr, "Unable to lock texture (%s)\n", sdl.GetError());
if (pitch != gb->w * sizeof(gb->data[0])) {
// If this happens, we need to copy a row at a time...
for (row = 0; row < gb->h && row < th; row++) {
......@@ -1132,8 +1124,10 @@ void sdl_video_event_thread(void *data)
src.y = 0;
src.w = list->rect.width;
src.h = list->rect.height;
sdl.QueryTexture(texture, NULL, NULL, &tw, &th);
sdl.LockTexture(texture, &src, &pixels, &pitch);
if (sdl.QueryTexture(texture, NULL, NULL, &tw, &th) != 0)
fprintf(stderr, "Unable to query texture (%s)\n", sdl.GetError());
if (sdl.LockTexture(texture, &src, &pixels, &pitch) != 0)
fprintf(stderr, "Unable to lock texture (%s)\n", sdl.GetError());
if (pitch != list->rect.width * sizeof(list->data[0])) {
// If this happens, we need to copy a row at a time...
for (row = 0; row < list->rect.height && row < th; row++) {
......@@ -1158,6 +1152,7 @@ void sdl_video_event_thread(void *data)
dst.x = (cvstat.winwidth - dst.w) / 2;
dst.y = (cvstat.winheight - dst.h) / 2;
}
pthread_mutex_unlock(&vstatlock);
if (sdl.RenderCopy(renderer, texture, &src, &dst))
fprintf(stderr, "RenderCopy() failed! (%s)\n", sdl.GetError());
}
......@@ -1165,7 +1160,7 @@ void sdl_video_event_thread(void *data)
}
sdl.RenderPresent(renderer);
}
pthread_mutex_unlock(&win_mutex);
break;
case SDL_USEREVENT_SETNAME:
......@@ -1199,9 +1194,12 @@ void sdl_video_event_thread(void *data)
free(ev.user.data1);
break;
case SDL_USEREVENT_SETVIDMODE:
pthread_mutex_lock(&sdl_mode_mutex);
sdl_mode = false;
pthread_mutex_unlock(&sdl_mode_mutex);
pthread_mutex_lock(&vstatlock);
cvstat.winwidth = ev.user.data1 - NULL;
cvstat.winheight = ev.user.data2 - NULL;
sdl_setwinsize(ev.user.data1 - NULL, ev.user.data2 - NULL);
setup_surfaces_locked();
pthread_mutex_unlock(&vstatlock);
sdl_ufunc_retval=0;
......@@ -1290,6 +1288,7 @@ int sdl_initciolib(int mode)
pthread_mutex_init(&sdl_headlock, NULL);
pthread_mutex_init(&win_mutex, NULL);
pthread_mutex_init(&sdl_keylock, NULL);
pthread_mutex_init(&sdl_mode_mutex, NULL);
return(sdl_init(mode));
}
......