From 081347929cc18ed27eb1cbb680bd83aa312ac746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Thu, 7 Aug 2014 23:34:50 -0300 Subject: [PATCH] Implement SDL driver video poke interface --- gfx/scaler/pixconv.c | 28 +++++++++ gfx/scaler/pixconv.h | 4 ++ gfx/scaler/scaler.c | 4 ++ gfx/scaler/scaler.h | 3 +- gfx/sdl_gfx.c | 144 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+), 1 deletion(-) diff --git a/gfx/scaler/pixconv.c b/gfx/scaler/pixconv.c index 592d5e9865..2e8d2912a5 100644 --- a/gfx/scaler/pixconv.c +++ b/gfx/scaler/pixconv.c @@ -310,6 +310,34 @@ void conv_rgb565_argb8888(void *output_, const void *input_, } #endif +void conv_rgba4444_argb8888(void *output_, const void *input_, + int width, int height, + int out_stride, int in_stride) +{ + int h, w; + const uint16_t *input = (const uint16_t*)input_; + uint32_t *output = (uint32_t*)output_; + + for (h = 0; h < height; h++, output += out_stride >> 2, input += in_stride >> 1) + { + for (w = 0; w < width; w++) + { + uint32_t col = input[w]; + uint32_t r = (col >> 12) & 0xf; + uint32_t g = (col >> 8) & 0xf; + uint32_t b = (col >> 4) & 0xf; + uint32_t a = (col >> 0) & 0xf; + r = (r << 4) | r; + g = (g << 4) | g; + b = (b << 4) | b; + a = (a << 4) | a; + + //output[w] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0); + output[w] = (a << 24) | (r << 16) | (g << 8) | (b << 0); + } + } +} + #if defined(__SSE2__) // :( TODO: Make this saner. static inline void store_bgr24_sse2(void *output, __m128i a, __m128i b, __m128i c, __m128i d) diff --git a/gfx/scaler/pixconv.h b/gfx/scaler/pixconv.h index 87d75b3485..688f82de23 100644 --- a/gfx/scaler/pixconv.h +++ b/gfx/scaler/pixconv.h @@ -34,6 +34,10 @@ void conv_rgb565_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); +void conv_rgba4444_argb8888(void *output, const void *input, + int width, int height, + int out_stride, int in_stride); + void conv_bgr24_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); diff --git a/gfx/scaler/scaler.c b/gfx/scaler/scaler.c index 2c47ef5024..551f64d16b 100644 --- a/gfx/scaler/scaler.c +++ b/gfx/scaler/scaler.c @@ -115,6 +115,10 @@ static bool set_pix_conv(struct scaler_ctx *ctx) ctx->in_pixconv = conv_bgr24_argb8888; break; + case SCALER_FMT_RGBA4444: + ctx->in_pixconv = conv_rgba4444_argb8888; + break; + default: return false; } diff --git a/gfx/scaler/scaler.h b/gfx/scaler/scaler.h index 4d72920954..694dc75d65 100644 --- a/gfx/scaler/scaler.h +++ b/gfx/scaler/scaler.h @@ -30,7 +30,8 @@ enum scaler_pix_fmt SCALER_FMT_0RGB1555, SCALER_FMT_RGB565, SCALER_FMT_BGR24, - SCALER_FMT_YUYV + SCALER_FMT_YUYV, + SCALER_FMT_RGBA4444 }; enum scaler_type diff --git a/gfx/sdl_gfx.c b/gfx/sdl_gfx.c index 7bb7c7247f..11b25db4a6 100644 --- a/gfx/sdl_gfx.c +++ b/gfx/sdl_gfx.c @@ -33,6 +33,14 @@ #include "SDL/SDL_syswm.h" +typedef struct sdl_menu_frame +{ + bool active; + SDL_Surface *frame; + struct scaler_ctx scaler; + +} sdl_menu_frame_t; + typedef struct sdl_video { SDL_Surface *screen; @@ -47,6 +55,8 @@ typedef struct sdl_video struct scaler_ctx scaler; unsigned last_width; unsigned last_height; + + sdl_menu_frame_t menu; } sdl_video_t; static void sdl_gfx_free(void *data) @@ -55,6 +65,9 @@ static void sdl_gfx_free(void *data) if (!vid) return; + if (vid->menu.frame) + SDL_FreeSurface(vid->menu.frame); + SDL_QuitSubSystem(SDL_INIT_VIDEO); if (vid->font) @@ -265,6 +278,17 @@ static void *sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu vid->scaler.in_fmt = video->rgb32 ? SCALER_FMT_ARGB8888 : SCALER_FMT_RGB565; vid->scaler.out_fmt = SCALER_FMT_ARGB8888; + vid->menu.scaler = vid->scaler; + vid->menu.scaler.scaler_type = SCALER_TYPE_BILINEAR; + + vid->menu.frame = SDL_ConvertSurface(vid->screen, vid->screen->format, vid->screen->flags | SDL_SRCALPHA); + + if (!vid->menu.frame) + { + RARCH_ERR("Failed to init menu surface: %s\n", SDL_GetError()); + goto error; + } + return vid; error: @@ -320,6 +344,9 @@ static bool sdl_gfx_frame(void *data, const void *frame, unsigned width, unsigne scaler_ctx_scale(&vid->scaler, vid->screen->pixels, frame); RARCH_PERFORMANCE_STOP(sdl_scale); + if (vid->menu.active) + SDL_BlitSurface(vid->menu.frame, NULL, vid->screen, NULL); + if (msg) sdl_render_msg(vid, vid->screen, msg, vid->screen->w, vid->screen->h, vid->screen->format); @@ -363,6 +390,118 @@ static void sdl_gfx_viewport_info(void *data, struct rarch_viewport *vp) vp->height = vp->full_height = vid->screen->h; } +static void sdl_set_filtering(void *data, unsigned index, bool smooth) +{ + sdl_video_t *vid = (sdl_video_t*)data; + vid->scaler.scaler_type = smooth ? SCALER_TYPE_BILINEAR : SCALER_TYPE_POINT; +} + +static void sdl_set_aspect_ratio(void *data, unsigned aspectratio_index) +{ + sdl_video_t *vid = (sdl_video_t*)data; + + switch (aspectratio_index) + { + case ASPECT_RATIO_SQUARE: + gfx_set_square_pixel_viewport(g_extern.system.av_info.geometry.base_width, g_extern.system.av_info.geometry.base_height); + break; + + case ASPECT_RATIO_CORE: + gfx_set_core_viewport(); + break; + + case ASPECT_RATIO_CONFIG: + gfx_set_config_viewport(); + break; + + default: + break; + } + + g_extern.system.aspect_ratio = aspectratio_lut[aspectratio_index].value; +} + +static void sdl_apply_state_changes(void *data) +{ + (void)data; +} + +static void sdl_set_texture_frame(void *data, const void *frame, bool rgb32, + unsigned width, unsigned height, float alpha) +{ + (void) alpha; + sdl_video_t *vid = (sdl_video_t*)data; + + enum scaler_pix_fmt format = rgb32 ? SCALER_FMT_ARGB8888 : SCALER_FMT_RGBA4444; + + vid->menu.scaler.in_stride = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t)); + + if ( + width != vid->menu.scaler.in_width + || height != vid->menu.scaler.in_height + || format != vid->menu.scaler.in_fmt + ) + { + vid->menu.scaler.in_fmt = format; + vid->menu.scaler.in_width = width; + vid->menu.scaler.in_height = height; + + vid->menu.scaler.out_width = vid->screen->w; + vid->menu.scaler.out_height = vid->screen->h; + vid->menu.scaler.out_stride = vid->screen->pitch; + + scaler_ctx_gen_filter(&vid->menu.scaler); + } + + scaler_ctx_scale(&vid->menu.scaler, vid->menu.frame->pixels, frame); + SDL_SetAlpha(vid->menu.frame, SDL_SRCALPHA, 255.0 * alpha); +} + +static void sdl_set_texture_enable(void *data, bool state, bool full_screen) +{ + (void) full_screen; + + sdl_video_t *vid = (sdl_video_t*)data; + vid->menu.active = state; +} + +static void sdl_show_mouse(void *data, bool state) +{ + (void)data; + SDL_ShowCursor(state); +} + +static void sdl_grab_mouse_toggle(void *data) +{ + (void)data; + const SDL_GrabMode mode = SDL_WM_GrabInput(SDL_GRAB_QUERY); + SDL_WM_GrabInput(mode == SDL_GRAB_ON ? SDL_GRAB_OFF : SDL_GRAB_ON); +} + +static const video_poke_interface_t sdl_poke_interface = { + sdl_set_filtering, +#ifdef HAVE_FBO + NULL, + NULL, +#endif + sdl_set_aspect_ratio, + sdl_apply_state_changes, +#ifdef HAVE_MENU + sdl_set_texture_frame, + sdl_set_texture_enable, +#endif + NULL, + sdl_show_mouse, + sdl_grab_mouse_toggle, + NULL +}; + +static void sdl_get_poke_interface(void *data, const video_poke_interface_t **iface) +{ + (void)data; + *iface = &sdl_poke_interface; +} + const video_driver_t video_sdl = { sdl_gfx_init, sdl_gfx_frame, @@ -375,5 +514,10 @@ const video_driver_t video_sdl = { NULL, sdl_gfx_viewport_info, + NULL, +#ifdef HAVE_OVERLAY + NULL, +#endif + sdl_get_poke_interface };