From e81b987fc1e567f92298087e32e5d9f01fce0aa7 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 21 Dec 2012 00:19:34 +0200 Subject: [PATCH] add some sdl code from rearmed --- pandora/plat.c | 2 +- plat.h | 6 +- plat_sdl.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++ plat_sdl.h | 11 +++ 4 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 plat_sdl.c create mode 100644 plat_sdl.h diff --git a/pandora/plat.c b/pandora/plat.c index f97cb83..26ec297 100644 --- a/pandora/plat.c +++ b/pandora/plat.c @@ -43,7 +43,7 @@ static void scan_for_filters(void) { struct dirent *ent; int i, count = 0; - char **mfilters; + const char **mfilters; char buff[64]; DIR *dir; diff --git a/plat.h b/plat.h index 51be346..ab9b3e7 100644 --- a/plat.h +++ b/plat.h @@ -16,7 +16,11 @@ struct plat_target { int (*lcdrate_set)(int is_pal); int (*gamma_set)(int val, int black_level); int (*step_volume)(int is_up); - char **hwfilters; + const char **vout_methods; + int vout_method; + int vout_fullscreen; + const char **hwfilters; + int hwfilter; }; extern struct plat_target plat_target; diff --git a/plat_sdl.c b/plat_sdl.c new file mode 100644 index 0000000..c5cf64c --- /dev/null +++ b/plat_sdl.c @@ -0,0 +1,252 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2012 + * + * This work is licensed under the terms of any of these licenses + * (at your option): + * - GNU GPL, version 2 or later. + * - GNU LGPL, version 2.1 or later. + * - MAME license. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include + +#include "menu.h" +#include "plat.h" +#include "gl.h" +#include "plat_sdl.h" + +// XXX: maybe determine this instead.. +#define WM_DECORATION_H 32 + +SDL_Surface *plat_sdl_screen; +SDL_Overlay *plat_sdl_overlay; +int plat_sdl_gl_active; + +static int window_w, window_h; +static int fs_w, fs_h; +static int old_fullscreen; +static int vout_mode_overlay = -1, vout_mode_gl = -1; +static void *display, *window; + +int plat_sdl_change_video_mode(int w, int h) +{ + static int prev_w, prev_h; + + if (w == 0) + w = prev_w; + else + prev_w = w; + if (h == 0) + h = prev_h; + else + prev_h = h; + + if (plat_sdl_overlay != NULL) { + SDL_FreeYUVOverlay(plat_sdl_overlay); + plat_sdl_overlay = NULL; + } + if (plat_sdl_gl_active) { + gl_finish(); + plat_sdl_gl_active = 0; + } + + if (plat_target.vout_method != 0) { + Uint32 flags = SDL_RESIZABLE | SDL_SWSURFACE; + int win_w = window_w; + int win_h = window_h; + + if (plat_target.vout_fullscreen) { + flags |= SDL_FULLSCREEN; + win_w = fs_w; + win_h = fs_h; + } + + // XXX: workaround some occasional mysterious deadlock in SDL_SetVideoMode + SDL_PumpEvents(); + + plat_sdl_screen = SDL_SetVideoMode(win_w, win_h, 0, flags); + if (plat_sdl_screen == NULL) { + fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); + plat_target.vout_method = 0; + } + } + + if (plat_target.vout_method == vout_mode_overlay) { + plat_sdl_overlay = SDL_CreateYUVOverlay(w, h, SDL_UYVY_OVERLAY, plat_sdl_screen); + if (plat_sdl_overlay != NULL) { + if ((long)plat_sdl_overlay->pixels[0] & 3) + fprintf(stderr, "warning: overlay pointer is unaligned\n"); + + plat_sdl_overlay_clear(); + } + else { + fprintf(stderr, "warning: could not create overlay.\n"); + plat_target.vout_method = 0; + } + } + else if (plat_target.vout_method == vout_mode_gl) { + plat_sdl_gl_active = (gl_init(display, window) == 0); + if (!plat_sdl_gl_active) { + fprintf(stderr, "warning: could not init GL.\n"); + plat_target.vout_method = 0; + } + } + + if (plat_target.vout_method == 0) { + SDL_PumpEvents(); + + plat_sdl_screen = SDL_SetVideoMode(w, h, 16, SDL_SWSURFACE); + if (plat_sdl_screen == NULL) { + fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); + return -1; + } + } + + old_fullscreen = plat_target.vout_fullscreen; + return 0; +} + +void plat_sdl_event_handler(void *event_) +{ + SDL_Event *event = event_; + + if (event->type == SDL_VIDEORESIZE) { + //printf("resize %dx%d\n", event->resize.w, event->resize.h); + if (plat_target.vout_method != 0 + && !plat_target.vout_fullscreen && !old_fullscreen) + { + window_w = event->resize.w; + window_h = event->resize.h; + plat_sdl_change_video_mode(0, 0); + } + } +} + +int plat_sdl_init(void) +{ + static const char *vout_list[] = { NULL, NULL, NULL, NULL }; + const SDL_VideoInfo *info; + SDL_SysWMinfo wminfo; + int overlay_works = 0; + int gl_works = 0; + int i, ret, h; + + ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); + if (ret != 0) { + fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); + return -1; + } + + info = SDL_GetVideoInfo(); + if (info != NULL) { + fs_w = info->current_w; + fs_h = info->current_h; + } + + g_menuscreen_w = 640; + if (fs_w != 0 && g_menuscreen_w > fs_w) + g_menuscreen_w = fs_w; + g_menuscreen_h = 480; + if (fs_h != 0) { + h = fs_h; + if (info && info->wm_available && h > WM_DECORATION_H) + h -= WM_DECORATION_H; + if (g_menuscreen_h > h) + g_menuscreen_h = h; + } + + ret = plat_sdl_change_video_mode(g_menuscreen_w, g_menuscreen_h); + if (ret != 0) { + plat_sdl_screen = SDL_SetVideoMode(0, 0, 16, SDL_SWSURFACE); + if (plat_sdl_screen == NULL) { + fprintf(stderr, "SDL_SetVideoMode failed: %s\n", SDL_GetError()); + goto fail; + } + + if (plat_sdl_screen->w < 320 || plat_sdl_screen->h < 240) { + fprintf(stderr, "resolution %dx%d is too small, sorry.\n", + plat_sdl_screen->w, plat_sdl_screen->h); + goto fail; + } + } + g_menuscreen_w = window_w = plat_sdl_screen->w; + g_menuscreen_h = window_h = plat_sdl_screen->h; + + plat_sdl_overlay = SDL_CreateYUVOverlay(plat_sdl_screen->w, plat_sdl_screen->h, + SDL_UYVY_OVERLAY, plat_sdl_screen); + if (plat_sdl_overlay != NULL) { + printf("overlay: fmt %x, planes: %d, pitch: %d, hw: %d\n", + plat_sdl_overlay->format, plat_sdl_overlay->planes, *plat_sdl_overlay->pitches, + plat_sdl_overlay->hw_overlay); + + if (plat_sdl_overlay->hw_overlay) + overlay_works = 1; + else + fprintf(stderr, "warning: video overlay is not hardware accelerated, " + "not going to use it.\n"); + SDL_FreeYUVOverlay(plat_sdl_overlay); + plat_sdl_overlay = NULL; + } + else + fprintf(stderr, "overlay is not available.\n"); + + SDL_VERSION(&wminfo.version); + SDL_GetWMInfo(&wminfo); + display = wminfo.info.x11.display; + window = (void *)wminfo.info.x11.window; + + ret = gl_init(display, window); + if (ret == 0) { + gl_works = 1; + gl_finish(); + } + + i = 0; + vout_list[i++] = "SDL Window"; + if (overlay_works) { + plat_target.vout_method = vout_mode_overlay = i; + vout_list[i++] = "Video Overlay"; + } + if (gl_works) { + plat_target.vout_method = vout_mode_gl = i; + vout_list[i++] = "OpenGL"; + } + plat_target.vout_methods = vout_list; + + return 0; + +fail: + SDL_Quit(); + return -1; +} + +void plat_sdl_finish(void) +{ + if (plat_sdl_overlay != NULL) { + SDL_FreeYUVOverlay(plat_sdl_overlay); + plat_sdl_overlay = NULL; + } + if (plat_sdl_gl_active) { + gl_finish(); + plat_sdl_gl_active = 0; + } + SDL_Quit(); +} + +void plat_sdl_overlay_clear(void) +{ + int pixels = plat_sdl_overlay->w * plat_sdl_overlay->h; + int *dst = (int *)plat_sdl_overlay->pixels[0]; + int v = 0x10801080; + + for (; pixels > 0; dst += 4, pixels -= 2 * 4) + dst[0] = dst[1] = dst[2] = dst[3] = v; + + for (; pixels > 0; dst++, pixels -= 2) + *dst = v; +} + +// vim:shiftwidth=2:expandtab diff --git a/plat_sdl.h b/plat_sdl.h new file mode 100644 index 0000000..c22561d --- /dev/null +++ b/plat_sdl.h @@ -0,0 +1,11 @@ +#include + +extern SDL_Surface *plat_sdl_screen; +extern SDL_Overlay *plat_sdl_overlay; +extern int plat_sdl_gl_active; + +int plat_sdl_init(void); +int plat_sdl_change_video_mode(int w, int h); +void plat_sdl_overlay_clear(void); +void plat_sdl_event_handler(void *event_); +void plat_sdl_finish(void); -- 2.39.2