From 1aa4b30e13d89a5e5dfe5477ddb5fbb928c0fae7 Mon Sep 17 00:00:00 2001 From: Dimitris Panokostas Date: Wed, 9 Oct 2019 23:51:17 +0200 Subject: [PATCH] Fixed input handling in GUI (WIP) --- src/main.cpp | 8 --- src/osdep/amiberry_gfx.cpp | 86 ++++++++++++++---------- src/osdep/amiberry_gfx.h | 7 +- src/osdep/gui/InGameMessage.cpp | 8 +-- src/osdep/gui/main_window.cpp | 114 ++++++++++++++++++++++++-------- src/threaddep/thread.h | 40 +++++------ 6 files changed, 165 insertions(+), 98 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0b1fb54a..9970fda6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,14 +40,6 @@ #include "jit/compemu.h" #include -#ifdef USE_DISPMANX -#elif USE_SDL2 -SDL_Window* sdlWindow; -SDL_Renderer* renderer; -SDL_Texture* texture; -SDL_DisplayMode sdlMode; -#endif - #include #include #include "keyboard.h" diff --git a/src/osdep/amiberry_gfx.cpp b/src/osdep/amiberry_gfx.cpp index c132834a..d68828a9 100644 --- a/src/osdep/amiberry_gfx.cpp +++ b/src/osdep/amiberry_gfx.cpp @@ -31,8 +31,12 @@ static unsigned int current_vsync_frame = 0; unsigned long time_per_frame = 20000; // Default for PAL (50 Hz): 20000 microsecs #elif USE_SDL2 const char* sdl_video_driver; +SDL_Texture* texture; +SDL_DisplayMode sdlMode; #endif +SDL_Renderer* renderer; + #ifdef ANDROIDSDL #include #endif @@ -118,7 +122,6 @@ static int display_thread(void *unused) switch (signal) { case DISPLAY_SIGNAL_SETUP: - //bcm_host_init(); //displayHandle = vc_dispmanx_display_open(0); vc_dispmanx_vsync_callback(displayHandle, vsync_callback, nullptr); break; @@ -176,7 +179,7 @@ static int display_thread(void *unused) screen = SDL_CreateRGBSurface(0, display_width, display_height, depth, 0, 0, 0, 0); - vc_dispmanx_display_get_info(displayHandle, &modeInfo); + displayHandle = vc_dispmanx_display_open(0); amigafb_resource_1 = vc_dispmanx_resource_create(rgb_mode, width, height, &vc_image_ptr); amigafb_resource_2 = vc_dispmanx_resource_create(rgb_mode, width, height, &vc_image_ptr); @@ -272,8 +275,8 @@ static int display_thread(void *unused) case DISPLAY_SIGNAL_QUIT: vc_dispmanx_vsync_callback(displayHandle, nullptr, nullptr); - vc_dispmanx_display_close(displayHandle); - //bcm_host_deinit(); + if (displayHandle) + vc_dispmanx_display_close(displayHandle); display_tid = nullptr; return 0; default: @@ -292,7 +295,8 @@ int graphics_setup(void) #endif #ifdef USE_DISPMANX bcm_host_init(); - displayHandle = vc_dispmanx_display_open(0); + if (!displayHandle) + displayHandle = vc_dispmanx_display_open(0); vc_dispmanx_display_get_info(displayHandle, &modeInfo); can_have_linedouble = modeInfo.height >= 540; @@ -316,6 +320,18 @@ int graphics_setup(void) vchi_disconnect(vchi_instance); } } + + if (sdl_window == nullptr) + { + sdl_window = SDL_CreateWindow("Amiberry", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + 800, + 480, + SDL_WINDOW_FULLSCREEN_DESKTOP); + check_error_sdl(sdl_window == nullptr, "Unable to create window"); + } + #elif USE_SDL2 sdl_video_driver = SDL_GetCurrentVideoDriver(); Uint32 sdl_window_mode; @@ -331,29 +347,23 @@ int graphics_setup(void) sdl_window_mode = SDL_WINDOW_FULLSCREEN_DESKTOP; } - if (sdlWindow == nullptr) + if (sdl_window == nullptr) { - sdlWindow = SDL_CreateWindow("Amiberry", + sdl_window = SDL_CreateWindow("Amiberry", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 480, sdl_window_mode); - check_error_sdl(sdlWindow == nullptr, "Unable to create window"); + check_error_sdl(sdl_window == nullptr, "Unable to create window"); } - if (SDL_GetWindowDisplayMode(sdlWindow, &sdlMode) != 0) + if (SDL_GetWindowDisplayMode(sdl_window, &sdlMode) != 0) { - SDL_Log("Could not get information about SDL Mode! SDL_Error: %s\n", SDL_GetError()); + write_log("Could not get information about SDL Mode! SDL_Error: %s\n", SDL_GetError()); } can_have_linedouble = sdlMode.h >= 540; - if (renderer == nullptr) - { - renderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - check_error_sdl(renderer == nullptr, "Unable to create a renderer"); - } - SDL_DisplayMode current; const auto should_be_zero = SDL_GetCurrentDisplayMode(0, ¤t); if (should_be_zero == 0) @@ -361,8 +371,15 @@ int graphics_setup(void) SDL_ShowCursor(SDL_DISABLE); #endif + + if (renderer == nullptr) + { + renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + check_error_sdl(renderer == nullptr, "Unable to create a renderer"); + } + if (SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1") != SDL_TRUE) - SDL_Log("SDL could not grab the keyboard"); + write_log("SDL could not grab the keyboard"); currprefs.gfx_apmode[1].gfx_refreshrate = host_hz; @@ -388,10 +405,10 @@ void toggle_fullscreen() #ifdef USE_DISPMANX #elif USE_SDL2 const Uint32 fullscreen_flag = SDL_WINDOW_FULLSCREEN_DESKTOP; - if (sdlWindow) + if (sdl_window) { - const bool is_fullscreen = SDL_GetWindowFlags(sdlWindow) & fullscreen_flag; - SDL_SetWindowFullscreen(sdlWindow, is_fullscreen ? 0 : fullscreen_flag); + const bool is_fullscreen = SDL_GetWindowFlags(sdl_window) & fullscreen_flag; + SDL_SetWindowFullscreen(sdl_window, is_fullscreen ? 0 : fullscreen_flag); SDL_ShowCursor(is_fullscreen); } #endif @@ -429,7 +446,6 @@ void graphics_subshutdown() write_comm_pipe_u32(display_pipe, DISPLAY_SIGNAL_SUBSHUTDOWN, 1); uae_sem_wait(&display_sem); } - bcm_host_deinit(); #elif USE_SDL2 #if (defined USE_RENDER_THREAD) if (renderthread) @@ -578,29 +594,29 @@ static void open_screen(struct uae_prefs* p) SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF); SDL_RenderClear(renderer); - if (sdlWindow && strcmp(sdl_video_driver, "x11") == 0) + if (sdl_window && strcmp(sdl_video_driver, "x11") == 0) { - const bool is_fullscreen = SDL_GetWindowFlags(sdlWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP; + const bool is_fullscreen = SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_FULLSCREEN_DESKTOP; if (p->gfx_apmode[0].gfx_fullscreen == GFX_FULLSCREEN) { // Switch to Fullscreen mode, if we don't have it already if (!is_fullscreen) - SDL_SetWindowFullscreen(sdlWindow, SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_SetWindowFullscreen(sdl_window, SDL_WINDOW_FULLSCREEN_DESKTOP); } else { // Switch to Window mode, if we don't have it already if (is_fullscreen) - SDL_SetWindowFullscreen(sdlWindow, 0); + SDL_SetWindowFullscreen(sdl_window, 0); } if (!is_fullscreen) - if ((SDL_GetWindowFlags(sdlWindow) & SDL_WINDOW_MAXIMIZED) == 0) + if ((SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_MAXIMIZED) == 0) { if (screen_is_picasso) - SDL_SetWindowSize(sdlWindow, display_width, display_height); + SDL_SetWindowSize(sdl_window, display_width, display_height); else - SDL_SetWindowSize(sdlWindow, display_width, display_height * 2 >> p->gfx_vresolution); + SDL_SetWindowSize(sdl_window, display_width, display_height * 2 >> p->gfx_vresolution); } } @@ -653,9 +669,7 @@ void update_display(struct uae_prefs* p) { struct amigadisplay *ad = &adisplays; open_screen(p); -#ifdef USE_SDL2 SDL_SetRelativeMouseMode(SDL_TRUE); -#endif SDL_ShowCursor(SDL_DISABLE); ad->framecnt = 1; // Don't draw frame before reset done } @@ -983,25 +997,27 @@ void graphics_leave() uae_sem_destroy(&display_sem); display_sem = nullptr; } + bcm_host_deinit(); #elif USE_SDL2 if (texture) { SDL_DestroyTexture(texture); texture = nullptr; } - +#endif + if (renderer) { SDL_DestroyRenderer(renderer); renderer = nullptr; } - if (sdlWindow) + if (sdl_window) { - SDL_DestroyWindow(sdlWindow); - sdlWindow = nullptr; + SDL_DestroyWindow(sdl_window); + sdl_window = nullptr; } - +#ifdef USE_SDL2 SDL_VideoQuit(); #endif } diff --git a/src/osdep/amiberry_gfx.h b/src/osdep/amiberry_gfx.h index 4ec814e6..5c8588d0 100644 --- a/src/osdep/amiberry_gfx.h +++ b/src/osdep/amiberry_gfx.h @@ -12,20 +12,21 @@ extern DISPMANX_DISPLAY_HANDLE_T displayHandle; extern DISPMANX_MODEINFO_T modeInfo; extern DISPMANX_UPDATE_HANDLE_T updateHandle; extern DISPMANX_ELEMENT_HANDLE_T elementHandle; +extern DISPMANX_ELEMENT_HANDLE_T blackscreen_element; extern VC_RECT_T src_rect; extern VC_RECT_T dst_rect; extern VC_RECT_T blit_rect; +extern VC_RECT_T black_rect; extern VC_IMAGE_TYPE_T rgb_mode; #elif USE_SDL2 -extern SDL_Window* sdlWindow; -extern SDL_Renderer* renderer; extern SDL_Texture* texture; extern SDL_Cursor* cursor; extern SDL_Texture* gui_texture; extern SDL_DisplayMode sdlMode; extern const char* sdl_video_driver; #endif - +extern SDL_Renderer* renderer; +extern SDL_Window* sdl_window; extern SDL_Surface* gui_screen; extern bool can_have_linedouble; diff --git a/src/osdep/gui/InGameMessage.cpp b/src/osdep/gui/InGameMessage.cpp index d3ef3d19..fa878c98 100644 --- a/src/osdep/gui/InGameMessage.cpp +++ b/src/osdep/gui/InGameMessage.cpp @@ -164,15 +164,15 @@ void message_gui_init(const char* msg) #ifdef USE_DISPMANX // TODO #elif USE_SDL2 - if (sdlWindow == nullptr) + if (sdl_window == nullptr) { - sdlWindow = SDL_CreateWindow("Amiberry-GUI", + sdl_window = SDL_CreateWindow("Amiberry-GUI", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP); - check_error_sdl(sdlWindow == nullptr, "Unable to create window"); + check_error_sdl(sdl_window == nullptr, "Unable to create window"); } // make the scaled rendering look smoother (linear scaling). SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); @@ -185,7 +185,7 @@ void message_gui_init(const char* msg) if (renderer == nullptr) { - renderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); check_error_sdl(renderer == nullptr, "Unable to create a renderer"); SDL_RenderSetLogicalSize(renderer, GUI_WIDTH, GUI_HEIGHT); } diff --git a/src/osdep/gui/main_window.cpp b/src/osdep/gui/main_window.cpp index 11f86212..c1fac8db 100644 --- a/src/osdep/gui/main_window.cpp +++ b/src/osdep/gui/main_window.cpp @@ -96,8 +96,12 @@ enum SDL_Joystick* gui_joystick; SDL_Surface* gui_screen; SDL_Event gui_event; +SDL_Window* sdl_window; #ifdef USE_DISPMANX DISPMANX_RESOURCE_HANDLE_T gui_resource; +DISPMANX_RESOURCE_HANDLE_T black_gui_resource; +int element_present = 0; +int current_resource = 0; #elif USE_SDL2 SDL_Texture* gui_texture; SDL_Cursor* cursor; @@ -304,31 +308,72 @@ void amiberry_gui_init() //------------------------------------------------- // Create new screen for GUI //------------------------------------------------- - gui_screen = SDL_CreateRGBSurface(0, GUI_WIDTH, GUI_HEIGHT, 16, 0, 0, 0, 0); + if (!gui_screen) + gui_screen = SDL_CreateRGBSurface(0, GUI_WIDTH, GUI_HEIGHT, 16, 0, 0, 0, 0); check_error_sdl(gui_screen == nullptr, "Unable to create GUI surface"); #ifdef USE_DISPMANX - uint32_t vc_image_ptr; - gui_resource = vc_dispmanx_resource_create(rgb_mode, GUI_WIDTH, GUI_HEIGHT, &vc_image_ptr); - + if (!displayHandle) + displayHandle = vc_dispmanx_display_open(0); + + uint32_t vc_gui_image_ptr; + if (!gui_resource) + gui_resource = vc_dispmanx_resource_create(rgb_mode, GUI_WIDTH, GUI_HEIGHT, &vc_gui_image_ptr); + if (!black_gui_resource) + black_gui_resource = vc_dispmanx_resource_create(rgb_mode, GUI_WIDTH, GUI_HEIGHT, &vc_gui_image_ptr); + vc_dispmanx_rect_set(&blit_rect, 0, 0, GUI_WIDTH, GUI_HEIGHT); vc_dispmanx_resource_write_data(gui_resource, rgb_mode, gui_screen->pitch, gui_screen->pixels, &blit_rect); + vc_dispmanx_resource_write_data(black_gui_resource, rgb_mode, gui_screen->pitch, gui_screen->pixels, &blit_rect); vc_dispmanx_rect_set(&src_rect, 0, 0, GUI_WIDTH << 16, GUI_HEIGHT << 16); - vc_dispmanx_rect_set(&dst_rect, 0, 0, modeInfo.width, modeInfo.height); + vc_dispmanx_rect_set(&black_rect, 0, 0, modeInfo.width, modeInfo.height); + // Full screen destination rectangle + //vc_dispmanx_rect_set(&dst_rect, 0, 0, modeInfo.width, modeInfo.height); - updateHandle = vc_dispmanx_update_start(0); + // Scaled display with correct Aspect Ratio + auto want_aspect = float(GUI_WIDTH) / float(GUI_HEIGHT); + auto real_aspect = float(modeInfo.width) / float(modeInfo.height); - VC_DISPMANX_ALPHA_T alpha; - alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE; - alpha.opacity = 255; - alpha.mask = 0; + SDL_Rect viewport; + if (want_aspect > real_aspect) + { + auto scale = float(modeInfo.width) / float(GUI_WIDTH); + viewport.x = 0; + viewport.w = modeInfo.width; + viewport.h = int(std::ceil(GUI_HEIGHT * scale)); + viewport.y = (modeInfo.height - viewport.h) / 2; + } + else + { + auto scale = float(modeInfo.height) / float(GUI_HEIGHT); + viewport.y = 0; + viewport.h = modeInfo.height; + viewport.w = int(std::ceil(GUI_WIDTH * scale)); + viewport.x = (modeInfo.width - viewport.w) / 2; + } + vc_dispmanx_rect_set(&dst_rect, viewport.x, viewport.y, viewport.w, viewport.h); - elementHandle = vc_dispmanx_element_add(updateHandle, displayHandle, 10, - &dst_rect, gui_resource, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, - nullptr, // clamp - DISPMANX_NO_ROTATE); - vc_dispmanx_update_submit_sync(updateHandle); + if (!element_present) + { + element_present = 1; + updateHandle = vc_dispmanx_update_start(0); + VC_DISPMANX_ALPHA_T alpha; + alpha.flags = DISPMANX_FLAGS_ALPHA_FROM_SOURCE; + alpha.opacity = 255; + alpha.mask = 0; + + blackscreen_element = vc_dispmanx_element_add(updateHandle, displayHandle, 0, + &black_rect, black_gui_resource, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, + nullptr, DISPMANX_NO_ROTATE); + + elementHandle = vc_dispmanx_element_add(updateHandle, displayHandle, 1, + &dst_rect, gui_resource, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, + nullptr, // clamp + DISPMANX_NO_ROTATE); + + vc_dispmanx_update_submit_sync(updateHandle); + } #elif USE_SDL2 #ifdef SOFTWARE_CURSOR swcursor(0); @@ -339,23 +384,23 @@ void amiberry_gui_init() setup_cursor(); #endif - if (sdlWindow && strcmp(sdl_video_driver, "x11") == 0) + if (sdl_window && strcmp(sdl_video_driver, "x11") == 0) { // Only resize the window if we're under x11, otherwise we're fullscreen anyway - if ((SDL_GetWindowFlags(sdlWindow) & SDL_WINDOW_MAXIMIZED) == 0) - SDL_SetWindowSize(sdlWindow, GUI_WIDTH, GUI_HEIGHT); + if ((SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_MAXIMIZED) == 0) + SDL_SetWindowSize(sdl_window, GUI_WIDTH, GUI_HEIGHT); } // make the scaled rendering look smoother (linear scaling). SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - SDL_RenderSetLogicalSize(renderer, GUI_WIDTH, GUI_HEIGHT); gui_texture = SDL_CreateTexture(renderer, gui_screen->format->format, SDL_TEXTUREACCESS_STREAMING, gui_screen->w, gui_screen->h); check_error_sdl(gui_texture == nullptr, "Unable to create GUI texture"); #endif + SDL_RenderSetLogicalSize(renderer, GUI_WIDTH, GUI_HEIGHT); SDL_ShowCursor(SDL_ENABLE); SDL_SetRelativeMouseMode(SDL_FALSE); - + //------------------------------------------------- // Create helpers for GUI framework //------------------------------------------------- @@ -387,13 +432,28 @@ void amiberry_gui_halt() gui_screen = nullptr; } #ifdef USE_DISPMANX - //updateHandle = vc_dispmanx_update_start(0); - //vc_dispmanx_element_remove(updateHandle, elementHandle); - //vc_dispmanx_update_submit_sync(updateHandle); - + if (element_present == 1) + { + element_present = 0; + updateHandle = vc_dispmanx_update_start(0); + vc_dispmanx_element_remove(updateHandle, elementHandle); + vc_dispmanx_element_remove(updateHandle, blackscreen_element); + vc_dispmanx_update_submit_sync(updateHandle); + } + if (gui_resource) + { vc_dispmanx_resource_delete(gui_resource); - //vc_dispmanx_display_close(displayHandle); + gui_resource = 0; + } + + if (black_gui_resource) + { + vc_dispmanx_resource_delete(black_gui_resource); + black_gui_resource = 0; + } + if (displayHandle) + vc_dispmanx_display_close(displayHandle); #elif USE_SDL2 if (gui_texture != nullptr) { @@ -684,7 +744,6 @@ void checkInput() // Now we let the Gui object draw itself. uae_gui->draw(); #ifdef USE_DISPMANX - vc_dispmanx_resource_write_data(gui_resource, rgb_mode, gui_screen->pitch, gui_screen->pixels, &blit_rect); #elif USE_SDL2 SDL_UpdateTexture(gui_texture, nullptr, gui_screen->pixels, gui_screen->pitch); #endif @@ -727,8 +786,7 @@ void amiberry_gui_run() SDL_JoystickClose(gui_joystick); gui_joystick = nullptr; joypad_axis_state.clear(); - } - + } } class MainButtonActionListener : public gcn::ActionListener diff --git a/src/threaddep/thread.h b/src/threaddep/thread.h index 1bc6f1d9..40ec4597 100644 --- a/src/threaddep/thread.h +++ b/src/threaddep/thread.h @@ -1,4 +1,4 @@ - /* +/* * UAE - The Un*x Amiga Emulator * * Threading support, using SDL @@ -12,12 +12,12 @@ /* Sempahores. We use POSIX semaphores; if you are porting this to a machine * with different ones, make them look like POSIX semaphores. */ -typedef SDL_sem *uae_sem_t; +typedef SDL_sem* uae_sem_t; -STATIC_INLINE int uae_sem_init(uae_sem_t *sem, int dummy, int init) +STATIC_INLINE int uae_sem_init(uae_sem_t* sem, int dummy, int init) { - *sem = SDL_CreateSemaphore (init); - return (*sem == 0); + *sem = SDL_CreateSemaphore(init); + return (*sem == nullptr); } #define uae_sem_destroy(PSEM) SDL_DestroySemaphore (*PSEM) @@ -28,36 +28,36 @@ STATIC_INLINE int uae_sem_init(uae_sem_t *sem, int dummy, int init) #include "commpipe.h" -typedef SDL_Thread *uae_thread_id; +typedef SDL_Thread* uae_thread_id; #define BAD_THREAD 0 -STATIC_INLINE void uae_set_thread_priority (uae_thread_id *id, int pri) +STATIC_INLINE void uae_set_thread_priority(uae_thread_id* id, int pri) { } -STATIC_INLINE void uae_end_thread (uae_thread_id *tid) +STATIC_INLINE void uae_end_thread(uae_thread_id* tid) { } -STATIC_INLINE long uae_start_thread (const TCHAR *name, int(*f) (void *), void *arg, uae_thread_id *foo) +STATIC_INLINE long uae_start_thread(const TCHAR* name, int (*f)(void*), void* arg, uae_thread_id* foo) { - uae_thread_id id = SDL_CreateThread (f, "StartThread", arg); - if(foo != NULL) - *foo = id; - return (long)id; + uae_thread_id id = SDL_CreateThread(f, "StartThread", arg); + if (foo != nullptr) + *foo = id; + return (long)id; } -STATIC_INLINE long uae_start_thread_fast (int(*f) (void *), void *arg, uae_thread_id *foo) +STATIC_INLINE long uae_start_thread_fast(int (*f)(void*), void* arg, uae_thread_id* foo) { - uae_thread_id id = SDL_CreateThread (f, "StartThreadFast", arg); - if(foo != NULL) - *foo = id; - return (long)id; + uae_thread_id id = SDL_CreateThread(f, "StartThreadFast", arg); + if (foo != nullptr) + *foo = id; + return (long)id; } -STATIC_INLINE void uae_wait_thread (uae_thread_id thread) +STATIC_INLINE void uae_wait_thread(uae_thread_id thread) { - SDL_WaitThread (thread, (int*)0); + SDL_WaitThread(thread, static_cast(nullptr)); } /* Do nothing; thread exits if thread function returns. */