#define AL_LOG_SECTION "glfm" #include #include #include "window_glfm.h" #include "common.h" #include "keys.h" f64 stl_scale_scroll(f64 v, f64 factor) { return v / factor; } static struct stl_glfm_global global = { 0 }; void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata) { (void)output_discovered; (void)userdata; } bool stl_global_init(bool skip_graphics) { (void)skip_graphics; global.did_main = false; return false; } s32 stl_global_get_poll_fd(void) { al_assert_and_return(-1); } void stl_global_process_events(void) { al_assert(false); } void stl_global_close(void) { } static void onSurfaceCreated(GLFMDisplay *display, s32 width, s32 height) { (void)width; (void)height; if (!global.did_main) { stl_platform_main(0, NULL); global.did_main = true; } GLFMRenderingAPI api = glfmGetRenderingAPI(display); log_info("Created GLES context of version %s.", api == GLFMRenderingAPIOpenGLES32 ? "3.2" : api == GLFMRenderingAPIOpenGLES31 ? "3.1" : api == GLFMRenderingAPIOpenGLES3 ? "3.0" : "2.0"); } static void onDraw(GLFMDisplay *display) { struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display); stl_window_send_render_event(&glfm->w); } static void onSurfaceDestroyed(GLFMDisplay *display) { struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display); stl_window_send_should_close_event(&glfm->w); } static void swap_dimensions_and_send_resize(struct stl_window_glfm *glfm) { SWAP(glfm->w.width, glfm->w.height); stl_window_send_resize_event(&glfm->w, glfm->w.width, glfm->w.height); } static void onOrientationChanged(GLFMDisplay *display, GLFMInterfaceOrientation orientation) { struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display); if (orientation & (GLFMInterfaceOrientationPortrait | GLFMInterfaceOrientationPortraitUpsideDown)) { if (!(global.orientation & (GLFMInterfaceOrientationPortrait | GLFMInterfaceOrientationPortraitUpsideDown))) { swap_dimensions_and_send_resize(glfm); } } else if (orientation & (GLFMInterfaceOrientationLandscapeLeft | GLFMInterfaceOrientationLandscapeRight)) { if (!(global.orientation & (GLFMInterfaceOrientationLandscapeLeft | GLFMInterfaceOrientationLandscapeRight))) { swap_dimensions_and_send_resize(glfm); } } global.orientation = orientation; } static u8 glfm_to_stela_button_action[] = { [GLFMKeyActionPressed] = STELA_BUTTON_PRESSED, [GLFMKeyActionReleased] = STELA_BUTTON_RELEASED }; static bool onKey(GLFMDisplay *display, GLFMKeyCode key, GLFMKeyAction action, s32 modifiers) { struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display); (void)modifiers; u8 mapped_action = glfm_to_stela_button_action[action]; switch (key) { case GLFMKeyCodeVolumeUp: return stl_window_send_key_immediate_event(&glfm->w, mapped_action, STELA_KEY_RIGHT); case GLFMKeyCodeVolumeDown: return stl_window_send_key_immediate_event(&glfm->w, mapped_action, STELA_KEY_LEFT); case GLFMKeyCodeNavigationBack: default: break; } return true; } static u8 glfm_to_stela_touch[] = { [GLFMTouchPhaseHover] = STELA_TOUCH_HOVER, [GLFMTouchPhaseBegan] = STELA_TOUCH_BEGAN, [GLFMTouchPhaseMoved] = STELA_TOUCH_MOVED, [GLFMTouchPhaseEnded] = STELA_TOUCH_ENDED, [GLFMTouchPhaseCancelled] = STELA_TOUCH_CANCELLED }; static bool onTouch(GLFMDisplay *display, s32 touch, GLFMTouchPhase phase, f64 x, f64 y) { struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display); stl_window_send_touch_event(&glfm->w, touch, glfm_to_stela_touch[phase], x, y); return true; } void glfmMain(GLFMDisplay *display) { nn_common_init("glfmMain"); stl_global_init(false); global.display = display; #define STELA_INCLUDE_DEPTH_BUFFER glfmSetDisplayConfig(display, GLFMRenderingAPIOpenGLES32, GLFMColorFormatRGBA8888, #ifdef STELA_INCLUDE_DEPTH_BUFFER GLFMDepthFormat24, GLFMStencilFormat8, #else GLFMDepthFormatNone, GLFMStencilFormatNone, #endif GLFMMultisampleNone); global.orientation = glfmGetInterfaceOrientation(display); glfmSetDisplayChrome(display, GLFMUserInterfaceChromeNone); glfmSetMultitouchEnabled(display, true); glfmSetSurfaceCreatedFunc(display, onSurfaceCreated); glfmSetRenderFunc(display, onDraw); glfmSetSurfaceDestroyedFunc(display, onSurfaceDestroyed); glfmSetOrientationChangedFunc(display, onOrientationChanged); glfmSetKeyFunc(display, onKey); glfmSetTouchFunc(display, onTouch); } static bool window_glfm_create_window(struct stl_window *window, u32 width, u32 height, u32 flags, const char *monitor, const char *name, const char *app_id) { struct stl_window_glfm *glfm = (struct stl_window_glfm *)window; (void)width; (void)height; (void)monitor; (void)name; (void)app_id; glfmSetUserData(global.display, glfm); s32 display_width, display_height; glfmGetDisplaySize(global.display, &display_width, &display_height); al_assert(display_width > 0 && display_height > 0); stl_window_created(&glfm->w, (u32)display_width, (u32)display_height, flags); #ifdef STELA_USE_EGL glfm->w.egl_display = (EGLDisplay)glfmGetEglDisplay(global.display); glfm->w.egl_context = (EGLContext)glfmGetEglContext(global.display); #endif return true; } static void window_glfm_resize_internal(struct stl_window *window, u32 width, u32 height) { (void)window; (void)width; (void)height; } static void window_glfm_resize(struct stl_window *window, u32 width, u32 height) { (void)window; (void)width; (void)height; } static void window_glfm_toggle_fullscreen(struct stl_window *window) { (void)window; } #ifdef STELA_POLL_INLINE static void window_glfm_poll(struct stl_window *window, bool block) { (void)window; (void)block; } #ifdef STELA_PAUSE static void window_glfm_wake(struct stl_window *window) { (void)window; } #endif #endif static void window_glfm_process_events(struct stl_window *window) { (void)window; } #ifdef STELA_PAUSE static bool window_glfm_should_refresh(struct stl_window *window) { (void)window; return true; } #endif static void window_glfm_free(struct stl_window **window) { (void)window; } #if defined STELA_API_OPENGL static bool window_glfm_gl_loader_load(void *window) { (void)window; return true; } static bool window_glfm_gl_make_current(void *window) { (void)window; return true; } static void window_glfm_gl_release_current(void *window) { (void)window; } static void window_glfm_gl_swap_buffers(void *window) { struct stl_window_glfm *glfm = (struct stl_window_glfm *)window; (void)glfm; glfmSwapBuffers(global.display); } #endif struct stl_window *stl_window_create(void) { log_info("Wrapping GLFM window."); struct stl_window_glfm *glfm = al_alloc_object(struct stl_window_glfm); stl_window_init(&glfm->w); glfm->w.fullscreen = false; glfm->w.create_window = window_glfm_create_window; glfm->w.resize_internal = window_glfm_resize_internal; glfm->w.resize = window_glfm_resize; glfm->w.toggle_fullscreen = window_glfm_toggle_fullscreen; #ifdef STELA_POLL_INLINE glfm->w.poll = window_glfm_poll; #ifdef STELA_PAUSE glfm->w.wake = window_glfm_wake; #endif #endif glfm->w.process_events = window_glfm_process_events; #ifdef STELA_PAUSE glfm->w.should_refresh = window_glfm_should_refresh; #endif glfm->w.free = window_glfm_free; #if defined STELA_API_OPENGL glfm->w.get_gl_proc_address = glfmGetProcAddress; glfm->w.gl_loader_load = window_glfm_gl_loader_load; glfm->w.gl_make_current = window_glfm_gl_make_current; glfm->w.gl_release_current = window_glfm_gl_release_current; glfm->w.gl_swap_buffers = window_glfm_gl_swap_buffers; #endif return (struct stl_window *)glfm; }