From 5e819121253bab89994101244dfc48b7535b6b90 Mon Sep 17 00:00:00 2001 From: Duilio Protti Date: Fri, 1 Jul 2016 00:25:36 -0300 Subject: [PATCH] Initial port to SDL2 - WIP --- configure.ac | 2 +- src/display.c | 151 ++++++++++++++++++---------------- src/display.h | 2 +- src/infinity.c | 219 +++++++++++++++++++++++++++++++++---------------- src/types.h | 2 +- 5 files changed, 234 insertions(+), 142 deletions(-) diff --git a/configure.ac b/configure.ac index f4f1e92..4a0e4a6 100644 --- a/configure.ac +++ b/configure.ac @@ -38,7 +38,7 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28,,) AC_SUBST(GLIB_LIBS) AC_SUBST(GLIB_CFLAGS) -PKG_CHECK_MODULES(SDL, sdl >= 1.2,,) +PKG_CHECK_MODULES(SDL, sdl2 >= 2,,) AC_SUBST(SDL_LIBS) AC_SUBST(SDL_CFLAGS) diff --git a/src/display.c b/src/display.c index 866a2d2..371f126 100644 --- a/src/display.c +++ b/src/display.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "config.h" #include "display.h" @@ -25,7 +26,7 @@ #define wrap(a) (a < 0 ? 0 : (a > 255 ? 255 : a)) #define assign_max(p, a) (*p <= a ? *p = a : 0) -#define VIDEO_FLAGS ((Uint32)(SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_RESIZABLE)) +#define VIDEO_FLAGS ((Uint32)(SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE)) typedef struct sincos { gint32 i; @@ -33,7 +34,7 @@ typedef struct sincos { } sincos_t; static gint16 pcm_data[2][512]; -static SDL_mutex *pcm_data_mutex; +G_LOCK_DEFINE_STATIC(pcm_data); static gint32 width, height, scale; @@ -43,7 +44,10 @@ static sincos_t sinw = { 0, NULL }; static vector_field_t *vector_field; -static SDL_Surface *screen = NULL; +static SDL_Window *window; +static SDL_Renderer *sdl_renderer; +static SDL_Surface *screen; +static SDL_Texture *texture; static SDL_Color color_table[NB_PALETTES][256]; static gint16 current_colors[256]; @@ -52,25 +56,48 @@ static byte *surface1; static Player *player; static gchar error_msg[256]; +static gboolean initialized; -static gboolean sdl_init(gint32 _width, gint32 _height, gint32 _scale) -{ - if (SDL_Init((Uint32)(SDL_INIT_VIDEO | SDL_INIT_TIMER)) < 0) { - g_snprintf(error_msg, 256, "Infinity cannot initialize SDL: %s", SDL_GetError()); - player->notify_critical_error(error_msg); - return FALSE; +static gboolean allocate_screen_and_texture() { + if (screen != NULL) { + SDL_FreeSurface(screen); } - screen = SDL_SetVideoMode(_width * _scale, _height * _scale, 16, VIDEO_FLAGS); + screen = SDL_CreateRGBSurface(0, width, height, 16, 0, 0, 0, 0); if (screen == NULL) { g_snprintf(error_msg, 256, "Infinity cannot create display: %s", SDL_GetError()); player->notify_critical_error(error_msg); return FALSE; } - (void)SDL_ShowCursor(0); - (void)SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + SDL_SetSurfaceBlendMode(screen, SDL_BLENDMODE_NONE); + if (texture != NULL) { + SDL_DestroyTexture(texture); + } + texture = SDL_CreateTexture(sdl_renderer, + SDL_PIXELFORMAT_RGB565, + SDL_TEXTUREACCESS_STREAMING, + width, height); + if (texture == NULL) { + g_snprintf(error_msg, 256, "Infinity cannot create SDL texture: %s", SDL_GetError()); + player->notify_critical_error(error_msg); + return FALSE; + } return TRUE; } +static gboolean sdl_init() +{ + SDL_InitSubSystem(SDL_INIT_EVENTS); + int res = SDL_CreateWindowAndRenderer(width, height, VIDEO_FLAGS, &window, &sdl_renderer); + if (res < 0) { + g_snprintf(error_msg, 256, "Infinity cannot initialize SDL: %s", SDL_GetError()); + player->notify_critical_error(error_msg); + return FALSE; + } + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // make the scaled rendering look smoother. + SDL_RenderSetLogicalSize(sdl_renderer, width, height); + return allocate_screen_and_texture(); +} + static void generate_colors() { gint32 i, k; @@ -97,53 +124,31 @@ static void display_surface() gint32 i, j; gint16 *pdest; byte *psrc; - gboolean screen_locked; + gboolean screen_locked = FALSE; if (SDL_MUSTLOCK(screen)) { if (SDL_LockSurface(screen) < 0) { - g_error("Infinity: Cannot lock screen: %s", SDL_GetError()); + g_critical("Infinity cannot lock SDL surface: %s", SDL_GetError()); return; } screen_locked = TRUE; - } else { - screen_locked = FALSE; } - if (scale > 1) { - for (i = 0; i < height; i++) { - pdest = (gint16 *)(screen->pixels + i * screen->pitch * scale); - psrc = surface1 + i * width; - if (scale == 2) { - for (j = 1; j < width; j++) { - *(pdest++) = current_colors[*psrc++]; - *(pdest) = *(pdest - 1); - pdest++; - } - memcpy(screen->pixels + i * screen->pitch * 2 + screen->pitch, - screen->pixels + i * screen->pitch * 2, screen->pitch); - } /* else { - * for (j=1;jpixels+i*screen->pitch*3+screen->pitch, - * screen->pixels+i*screen->pitch*3,screen->pitch); - * memcpy(screen->pixels+i*screen->pitch*3+screen->pitch*2, - * screen->pixels+i*screen->pitch*3,screen->pitch); - * } */ - } /* for */ - } else { - psrc = surface1; - for (i = 0; i < height; i++) { - pdest = (gint16 *)(screen->pixels + i * screen->pitch); - for (j = 0; j < width; j++) - *pdest++ = current_colors[*psrc++]; - } + + psrc = surface1; + for (i = 0; i < height; i++) { + pdest = (gint16 *)(screen->pixels + i * screen->pitch); + for (j = 0; j < width; j++) + *pdest++ = current_colors[*psrc++]; } + SDL_UpdateTexture(texture, NULL, screen->pixels, screen->pitch); + if (screen_locked) SDL_UnlockSurface(screen); - else - (void)SDL_Flip(screen); + else { + SDL_RenderClear(sdl_renderer); + SDL_RenderCopy(sdl_renderer, texture, NULL, NULL); + SDL_RenderPresent(sdl_renderer); + } } #define plot1(x, y, c) \ @@ -226,9 +231,8 @@ gboolean display_init(gint32 _width, gint32 _height, gint32 _scale, Player *_pla scale = _scale; player = _player; - pcm_data_mutex = SDL_CreateMutex(); compute_init(width, height, scale); - sdl_ok = sdl_init(width, height, scale); + sdl_ok = sdl_init(); generate_colors(); effects_load_effects(); vector_field = compute_vector_field_new(width, height); @@ -236,36 +240,39 @@ gboolean display_init(gint32 _width, gint32 _height, gint32 _scale, Player *_pla if (!sdl_ok) { display_quit(); } + initialized = TRUE; return sdl_ok; } void display_quit(void) { + if (! initialized) + return; compute_vector_field_destroy(vector_field); compute_quit(); - SDL_DestroyMutex(pcm_data_mutex); if (screen != NULL) SDL_FreeSurface(screen); screen = NULL; - SDL_Quit(); + if (window != NULL) + SDL_DestroyWindow(window); + window = NULL; + // do not call SDL_Quit() since there is another plugin that use + // SDL inside Audacious + SDL_QuitSubSystem(SDL_INIT_EVENTS); + initialized = FALSE; } gboolean display_resize(gint32 _width, gint32 _height) { width = _width; height = _height; - screen = SDL_SetVideoMode(width * scale, height * scale, 16, VIDEO_FLAGS); - if (screen == NULL) { - g_snprintf(error_msg, 256, "Infinity cannot resize display to %dx%d pixels: %s", - width * scale, height * scale, SDL_GetError()); - player->notify_critical_error(error_msg); - return FALSE; - } + + gboolean screen_ok = allocate_screen_and_texture(); compute_vector_field_destroy(vector_field); vector_field = compute_vector_field_new(width, height); compute_resize(width, height); compute_generate_vector_field(vector_field); - return TRUE; + return screen_ok; } inline void display_set_pcm_data(const float *data, int channels) @@ -274,12 +281,10 @@ inline void display_set_pcm_data(const float *data, int channels) g_critical("Unsupported number of channels (%d)\n", channels); return; } - /* begin CS */ - g_return_if_fail(SDL_mutexP(pcm_data_mutex) >= 0); + G_LOCK(pcm_data); // TODO check this out, different types here... memcpy(pcm_data, data, 2 * 512 * sizeof(gint16)); - g_return_if_fail(SDL_mutexV(pcm_data_mutex) >= 0); - /* end CS */ + G_UNLOCK(pcm_data); } void change_color(gint32 t2, gint32 t1, gint32 w) @@ -320,8 +325,7 @@ void spectral(t_effect *current_effect) const gint32 step = 4; const gint32 shift = (current_effect->spectral_shift * height) >> 8; - /* begin CS */ - g_return_if_fail(SDL_mutexP(pcm_data_mutex) >= 0); + G_LOCK(pcm_data); y1 = (gfloat)((((pcm_data[0][0] + pcm_data[1][0]) >> 9) * current_effect->spectral_amplitude * height) >> 12); y2 = (gfloat)((((pcm_data[0][0] + pcm_data[1][0]) >> 9) * current_effect->spectral_amplitude * height) >> 12); if (cosw.i != width || sinw.i != width) { @@ -411,7 +415,7 @@ void spectral(t_effect *current_effect) break; } } - g_return_if_fail(SDL_mutexV(pcm_data_mutex) >= 0); + G_UNLOCK(pcm_data); if (current_effect->mode_spectre == 3 || current_effect->mode_spectre == 4) { line(halfwidth + cosw.f[width - step] * (shift + y1), halfheight + sinw.f[width - step] * (shift + y1), @@ -450,8 +454,15 @@ void curve(t_effect *current_effect) void display_toggle_fullscreen(void) { - if (SDL_WM_ToggleFullScreen(screen) < 0) - g_warning("Cannot toggle to fullscreen mode: %s", SDL_GetError()); + Uint32 is_fullscreen = SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN; + if (SDL_SetWindowFullscreen(window, is_fullscreen ? 0 : SDL_WINDOW_FULLSCREEN) < 0) + g_warning("Infinity cannot change fullscreen mode: %s", SDL_GetError()); + SDL_ShowCursor(is_fullscreen); +} + +void display_set_title(const gchar *title) { + g_return_if_fail(window != NULL); + SDL_SetWindowTitle(window, title); } void display_save_screen(void) diff --git a/src/display.h b/src/display.h index a839af5..c9da5ec 100644 --- a/src/display.h +++ b/src/display.h @@ -16,7 +16,6 @@ #ifndef __INFINITY_DISPLAY__ #define __INFINITY_DISPLAY__ -#include #include #include "compute.h" @@ -84,6 +83,7 @@ void curve(t_effect *current_effect); */ void display_toggle_fullscreen(void); +void display_set_title(const gchar *title); void display_save_screen(void); void display_save_effect(t_effect *effect); void display_load_random_effect(t_effect *effect); diff --git a/src/infinity.c b/src/infinity.c index f5d4870..cb94324 100644 --- a/src/infinity.c +++ b/src/infinity.c @@ -18,9 +18,8 @@ #include #include -#include -#include -/*#include */ +#include +#include #include "config.h" #include "display.h" @@ -50,7 +49,7 @@ static t_num_effect t_last_effect; static gboolean must_resize; static gboolean finished; static gboolean resizing; -static SDL_mutex *resizing_mutex; +G_LOCK_DEFINE_STATIC(resizing); static gboolean initializing = FALSE; static gboolean visible; static gboolean quiting; @@ -61,7 +60,7 @@ static GTimer *title_timer; static SDL_Thread *thread; -static gint32 event_filter(const SDL_Event *event); +static int event_filter(void*, SDL_Event *event); static void check_events(); static int renderer(void *); static void set_title(void); @@ -101,7 +100,6 @@ void infinity_init(InfParameters * _params, Player * _player) finished = FALSE; must_resize = FALSE; resizing = FALSE; - resizing_mutex = SDL_CreateMutex(); mode_interactif = FALSE; visible = TRUE; quiting = FALSE; @@ -113,15 +111,9 @@ void infinity_init(InfParameters * _params, Player * _player) g_timer_start(title_timer); display_load_random_effect(¤t_effect); - (void)SDL_EventState((Uint8)SDL_ALLEVENTS, SDL_IGNORE); - (void)SDL_EventState((Uint8)SDL_VIDEORESIZE, SDL_ENABLE); - (void)SDL_EventState((Uint8)SDL_ACTIVEEVENT, SDL_ENABLE); - (void)SDL_EventState((Uint8)SDL_KEYDOWN, SDL_ENABLE); - (void)SDL_EventState((Uint8)SDL_QUIT, SDL_ENABLE); + SDL_SetEventFilter(event_filter, NULL); - SDL_SetEventFilter(event_filter); - - thread = SDL_CreateThread(renderer, NULL); + thread = SDL_CreateThread(renderer, "infinity_renderer", NULL); } void infinity_finish(void) @@ -142,7 +134,6 @@ void infinity_finish(void) quiting = TRUE; finished = TRUE; SDL_WaitThread(thread, NULL); - SDL_DestroyMutex(resizing_mutex); /* * Take some time to let it know infinity_render_multi_pcm() * that must not call display_set_pcm_data(). @@ -153,13 +144,13 @@ void infinity_finish(void) * * See display.h::display_set_pcm_data() */ - g_usleep(10000 * SDL_TIMESLICE); + g_usleep(1000000); display_quit(); g_timer_destroy(title_timer); player->disable_plugin(); - g_message("Infinity: Closing..."); + g_message("Infinity is shut down"); } void infinity_render_multi_pcm(const float *data, int channels) @@ -168,27 +159,85 @@ void infinity_render_multi_pcm(const float *data, int channels) display_set_pcm_data(data, channels); } -/* - * Private functions - */ -static gint32 event_filter(const SDL_Event *event) +// TODO really needed? +static int event_filter(void *user_data, SDL_Event *event) { if (!event) { g_warning("Infinity: SDL_Event is NULL"); return 0; } - switch (event->type) { + if (event->type == SDL_WINDOWEVENT) { + switch (event->window.event) { + case SDL_WINDOWEVENT_SHOWN: + SDL_Log("Window %d shown", event->window.windowID); + break; + case SDL_WINDOWEVENT_HIDDEN: + SDL_Log("Window %d hidden", event->window.windowID); + break; + case SDL_WINDOWEVENT_EXPOSED: + SDL_Log("Window %d exposed", event->window.windowID); + break; + case SDL_WINDOWEVENT_MOVED: + SDL_Log("Window %d moved to %d,%d", + event->window.windowID, event->window.data1, + event->window.data2); + break; + case SDL_WINDOWEVENT_RESIZED: + SDL_Log("Window %d resized to %dx%d", + event->window.windowID, event->window.data1, + event->window.data2); + break; + case SDL_WINDOWEVENT_SIZE_CHANGED: + SDL_Log("Window %d size changed to %dx%d", + event->window.windowID, event->window.data1, + event->window.data2); + break; + case SDL_WINDOWEVENT_MINIMIZED: + SDL_Log("Window %d minimized", event->window.windowID); + break; + case SDL_WINDOWEVENT_MAXIMIZED: + SDL_Log("Window %d maximized", event->window.windowID); + break; + case SDL_WINDOWEVENT_RESTORED: + SDL_Log("Window %d restored", event->window.windowID); + break; + case SDL_WINDOWEVENT_ENTER: + SDL_Log("Mouse entered window %d", + event->window.windowID); + break; + case SDL_WINDOWEVENT_LEAVE: + SDL_Log("Mouse left window %d", event->window.windowID); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + SDL_Log("Window %d gained keyboard focus", + event->window.windowID); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + SDL_Log("Window %d lost keyboard focus", + event->window.windowID); + break; + case SDL_WINDOWEVENT_CLOSE: + SDL_Log("event_filter Window %d closed", event->window.windowID); + break; + default: + SDL_Log("Window %d got unknown event %d", + event->window.windowID, event->window.event); + break; + } + } + + /*switch (event->type) { case SDL_VIDEORESIZE: - g_return_val_if_fail(SDL_LockMutex(resizing_mutex) >= 0, 0); + G_LOCK(resizing); if (resizing) { - g_return_val_if_fail(SDL_UnlockMutex(resizing_mutex) >= 0, 0); + G_UNLOCK(resizing); /* * VIDEORESIZE event dropped from event queue - */ + * return 0; } else { - g_return_val_if_fail(SDL_UnlockMutex(resizing_mutex) >= 0, 0); + G_UNLOCK(resizing); return 1; } g_assert_not_reached(); @@ -209,20 +258,84 @@ static gint32 event_filter(const SDL_Event *event) break; default: break; - } + }*/ return 1; } +static void handle_window_event(SDL_Event *event) { + switch (event->window.event) { + case SDL_WINDOWEVENT_SHOWN: + SDL_Log("Window %d shown", event->window.windowID); + break; + case SDL_WINDOWEVENT_HIDDEN: + SDL_Log("Window %d hidden", event->window.windowID); + break; + case SDL_WINDOWEVENT_EXPOSED: + SDL_Log("Window %d exposed", event->window.windowID); + break; + case SDL_WINDOWEVENT_MOVED: + SDL_Log("Window %d moved to %d,%d", + event->window.windowID, event->window.data1, + event->window.data2); + break; + case SDL_WINDOWEVENT_RESIZED: + SDL_Log("Window %d resized to %dx%d", + event->window.windowID, event->window.data1, + event->window.data2); + G_LOCK(resizing); + resizing = TRUE; + G_UNLOCK(resizing); + width = event->window.data1; + height = event->window.data2; + g_message("Infinity: Screen resized to %dx%d pixels^2", width, height); + must_resize = TRUE; + break; + case SDL_WINDOWEVENT_SIZE_CHANGED: + SDL_Log("Window %d size changed to %dx%d", + event->window.windowID, event->window.data1, + event->window.data2); + break; + case SDL_WINDOWEVENT_MINIMIZED: + SDL_Log("Window %d minimized", event->window.windowID); + break; + case SDL_WINDOWEVENT_MAXIMIZED: + SDL_Log("Window %d maximized", event->window.windowID); + break; + case SDL_WINDOWEVENT_RESTORED: + SDL_Log("Window %d restored", event->window.windowID); + break; + case SDL_WINDOWEVENT_ENTER: + SDL_Log("Mouse entered window %d", + event->window.windowID); + break; + case SDL_WINDOWEVENT_LEAVE: + SDL_Log("Mouse left window %d", event->window.windowID); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + SDL_Log("Window %d gained keyboard focus", + event->window.windowID); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + SDL_Log("Window %d lost keyboard focus", + event->window.windowID); + break; + case SDL_WINDOWEVENT_CLOSE: + SDL_Log("Window %d closed", event->window.windowID); + //infinity_finish(); + player->disable_plugin(); + break; + default: + SDL_Log("Window %d got unknown event %d", + event->window.windowID, event->window.event); + break; + } +} + static void check_events() { SDL_Event event; - /*XEvent *xevent; - * XWindowChanges changes; - * XWindowAttributes attr; - * XSetWindowAttributes s_attr;*/ - if (params->must_show_title()) { if (g_timer_elapsed(title_timer, NULL) > 1.0) { if (player->is_playing()) { @@ -241,43 +354,11 @@ static void check_events() while (SDL_PollEvent(&event)) { switch (event.type) { - /*case SDL_SYSWMEVENT: - * g_message ("Infinity: SDL_SYSWMEVENT"); - * if (event.syswm.msg != NULL) { - * if (event.syswm.msg->subsystem == SDL_SYSWM_X11) { - * xevent = &(event.syswm.msg->event.xevent); - * if (xevent == NULL) - * continue; - * if (first_xevent) { - * changes.x = config_get_x(); - * changes.y = config_get_y(); - * XConfigureWindow (xevent->xany.display, - * xevent->xany.window, - * CWX | CWY, &changes); - * first_xevent = FALSE; - * g_message ("Infinity: window moved to (%d,%d)", - * changes.x, changes.y); - * } else { - * XGetWindowAttributes (xevent->xany.display, - * xevent->xany.window, - * &attr); - * g_message ("Infinity: GetWindowAttributes (%d,%d)", - * attr.x, attr.y); - * } - * } - * } - * break;*/ case SDL_QUIT: player->disable_plugin(); break; - case SDL_VIDEORESIZE: - g_return_if_fail(SDL_LockMutex(resizing_mutex) >= 0); - resizing = TRUE; - g_return_if_fail(SDL_UnlockMutex(resizing_mutex) >= 0); - width = event.resize.w; - height = event.resize.h; - g_message("Infinity: Screen resized to %dx%d pixels^2", width, height); - must_resize = TRUE; + case SDL_WINDOWEVENT: + handle_window_event(&event); break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { @@ -418,9 +499,9 @@ static int renderer(void *arg) params->set_width(width); params->set_height(height); must_resize = FALSE; - g_return_val_if_fail(SDL_LockMutex(resizing_mutex) >= 0, -1); + G_LOCK(resizing); resizing = FALSE; - g_return_val_if_fail(SDL_UnlockMutex(resizing_mutex) >= 0, -1); + G_UNLOCK(resizing); } t_begin = g_get_monotonic_time(); if (has_mmx) @@ -480,5 +561,5 @@ static int renderer(void *arg) static void set_title(void) { - SDL_WM_SetCaption(current_title, "Infinity"); + display_set_title(current_title); } diff --git a/src/types.h b/src/types.h index 796e02b..f08eab3 100644 --- a/src/types.h +++ b/src/types.h @@ -16,7 +16,7 @@ #ifndef __INFINITY_TYPES__ #define __INFINITY_TYPES__ -#include +#include typedef Uint8 byte;