Fixed input handling in GUI (WIP)

This commit is contained in:
Dimitris Panokostas 2019-10-09 23:51:17 +02:00
parent caf089680b
commit 1aa4b30e13
6 changed files with 165 additions and 98 deletions

View file

@ -40,14 +40,6 @@
#include "jit/compemu.h"
#include <iostream>
#ifdef USE_DISPMANX
#elif USE_SDL2
SDL_Window* sdlWindow;
SDL_Renderer* renderer;
SDL_Texture* texture;
SDL_DisplayMode sdlMode;
#endif
#include <linux/kd.h>
#include <sys/ioctl.h>
#include "keyboard.h"

View file

@ -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 <android/log.h>
#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, &current);
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
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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<int*>(nullptr));
}
/* Do nothing; thread exits if thread function returns. */