static bool gfx_ctx_mali_fbdev_set_video_mode(void *data, video_frame_info_t *video_info, unsigned width, unsigned height, bool fullscreen) { struct fb_var_screeninfo vinfo; static const EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, /* Use version 2, even for GLES3. */ EGL_NONE }; mali_ctx_data_t *mali = (mali_ctx_data_t*)data; RFILE *fd = filestream_open("/dev/fb0", RFILE_MODE_READ_WRITE, -1); int fb = filestream_get_fd(fd); if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) { RARCH_ERR("Error obtaining framebuffer info.\n"); goto error; } filestream_close(fd); width = vinfo.xres; height = vinfo.yres; mali->width = width; mali->height = height; mali->native_window.width = vinfo.xres; mali->native_window.height = vinfo.yres; #ifdef HAVE_EGL if (!egl_create_context(&mali->egl, attribs)) { egl_report_error(); goto error; } #endif #ifdef HAVE_EGL if (!egl_create_surface(&mali->egl, &mali->native_window)) goto error; #endif return true; error: if (fd) filestream_close(fd); RARCH_ERR("[Mali fbdev]: EGL error: %d.\n", eglGetError()); gfx_ctx_mali_fbdev_destroy(data); return false; }
static void gfx_ctx_swap_interval(unsigned interval) { g_interval = interval; if (g_egl_dpy && eglGetCurrentContext()) { RARCH_LOG("[X/EGL]: eglSwapInterval(%u)\n", g_interval); if (!eglSwapInterval(g_egl_dpy, g_interval)) { RARCH_ERR("[X/EGL]: eglSwapInterval() failed.\n"); egl_report_error(); } } }
static void *gfx_ctx_vivante_init(void *video_driver) { #ifdef HAVE_EGL EGLint n; EGLint major, minor; EGLint format; static const EGLint attribs[] = { #if 0 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, #endif EGL_BLUE_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_RED_SIZE, 5, EGL_ALPHA_SIZE, 0, EGL_SAMPLES, 0, EGL_NONE }; #endif vivante_ctx_data_t *viv = (vivante_ctx_data_t*)calloc(1, sizeof(*viv)); if (!viv) return NULL; #ifdef HAVE_EGL frontend_driver_install_signal_handler(); #endif /* Disable cursor blinking so it's not visible in RetroArch. */ system("setterm -cursor off"); #ifdef HAVE_EGL if (!egl_init_context(&viv->egl, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); goto error; } #endif return viv; error: RARCH_ERR("[Vivante fbdev]: EGL error: %d.\n", eglGetError()); gfx_ctx_vivante_destroy(viv); return NULL; }
static void gfx_ctx_xegl_swap_interval(void *data, unsigned interval) { (void)data; g_interval = interval; if (!g_egl_dpy) return; if (!(eglGetCurrentContext())) return; RARCH_LOG("[X/EGL]: eglSwapInterval(%u)\n", g_interval); if (!eglSwapInterval(g_egl_dpy, g_interval)) { RARCH_ERR("[X/EGL]: eglSwapInterval() failed.\n"); egl_report_error(); } }
static void *gfx_ctx_opendingux_init(video_frame_info_t *video_info, void *video_driver) { #ifdef HAVE_EGL EGLint n; EGLint major, minor; EGLint format; static const EGLint attribs[] = { #if 0 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, #endif EGL_BLUE_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_RED_SIZE, 5, EGL_ALPHA_SIZE, 0, EGL_SAMPLES, 0, EGL_NONE }; #endif opendingux_ctx_data_t *viv = (opendingux_ctx_data_t*) calloc(1, sizeof(*viv)); if (!viv) return NULL; #ifdef HAVE_EGL frontend_driver_install_signal_handler(); if (!egl_init_context(&viv->egl, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); goto error; } #endif return viv; error: #ifdef HAVE_EGL RARCH_ERR("[opendingux fbdev]: EGL error: %d.\n", eglGetError()); #endif gfx_ctx_opendingux_destroy(viv); return NULL; }
static bool gfx_ctx_wl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { EGLint egl_attribs[16]; EGLint *attr = NULL; gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; egl_install_sighandlers(); attr = egl_fill_attribs(wl, egl_attribs); wl->width = width ? width : DEFAULT_WINDOWED_WIDTH; wl->height = height ? height : DEFAULT_WINDOWED_HEIGHT; wl->surface = wl_compositor_create_surface(wl->compositor); wl->win = wl_egl_window_create(wl->surface, wl->width, wl->height); wl->shell_surf = wl_shell_get_shell_surface(wl->shell, wl->surface); wl_shell_surface_add_listener(wl->shell_surf, &shell_surface_listener, NULL); wl_shell_surface_set_toplevel(wl->shell_surf); wl_shell_surface_set_class(wl->shell_surf, "RetroArch"); wl_shell_surface_set_title(wl->shell_surf, "RetroArch"); if (!egl_create_context(wl, (attr != egl_attribs) ? egl_attribs : NULL)) { egl_report_error(); goto error; } if (!egl_create_surface(wl, (EGLNativeWindowType)wl->win)) goto error; egl_set_swap_interval(wl, wl->egl.interval); if (fullscreen) wl_shell_surface_set_fullscreen(wl->shell_surf, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); flush_wayland_fd(wl); return true; error: gfx_ctx_wl_destroy(data); return false; }
static bool gfx_ctx_vivante_set_video_mode(void *data, video_frame_info_t *video_info, unsigned width, unsigned height, bool fullscreen) { #ifdef HAVE_EGL static const EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, /* Use version 2, even for GLES3. */ EGL_NONE }; #endif vivante_ctx_data_t *viv = (vivante_ctx_data_t*)data; /* Pick some arbitrary default. */ if (!width || !fullscreen) width = 1280; if (!height || !fullscreen) height = 1024; viv->width = width; viv->height = height; #ifdef HAVE_EGL if (!egl_create_context(&viv->egl, attribs)) { egl_report_error(); goto error; } #endif viv->native_window = fbCreateWindow(fbGetDisplayByIndex(0), 0, 0, 0, 0); #ifdef HAVE_EGL if (!egl_create_surface(&viv->egl, viv->native_window)) goto error; #endif return true; error: RARCH_ERR("[Vivante fbdev]: EGL error: %d.\n", eglGetError()); gfx_ctx_vivante_destroy(data); return false; }
static void *gfx_ctx_mali_fbdev_init(video_frame_info_t *video_info, void *video_driver) { #ifdef HAVE_EGL EGLint n; EGLint major, minor; EGLint format; static const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE }; #endif mali_ctx_data_t *mali = (mali_ctx_data_t*)calloc(1, sizeof(*mali)); if (!mali) return NULL; #ifdef HAVE_EGL frontend_driver_install_signal_handler(); #endif #ifdef HAVE_EGL if (!egl_init_context(&mali->egl, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); goto error; } #endif return mali; error: RARCH_ERR("[Mali fbdev]: EGL error: %d.\n", eglGetError()); gfx_ctx_mali_fbdev_destroy(video_driver); return NULL; }
static bool orbis_ctx_set_video_mode(void *data, video_frame_info_t *video_info, unsigned width, unsigned height, bool fullscreen) { /* Create an EGL rendering context */ static const EGLint contextAttributeList[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)data; ctx_orbis->width = ATTR_ORBISGL_WIDTH; ctx_orbis->height = ATTR_ORBISGL_HEIGHT; ctx_orbis->native_window.width = ctx_orbis->width; ctx_orbis->native_window.height = ctx_orbis->height; ctx_orbis->refresh_rate = 60; #ifdef HAVE_EGL if (!egl_create_context(&ctx_orbis->egl, contextAttributeList)) { egl_report_error(); goto error; } #endif #ifdef HAVE_EGL if (!egl_create_surface(&ctx_orbis->egl, &ctx_orbis->native_window)) goto error; #endif return true; error: printf("[ctx_orbis]: EGL error: %d.\n", eglGetError()); orbis_ctx_destroy(data); return false; }
void egl_set_swap_interval(void *data, unsigned interval) { /* Can be called before initialization. * Some contexts require that swap interval * is known at startup time. */ g_interval = interval; if (g_egl_dpy == EGL_NO_DISPLAY) return; if (!(eglGetCurrentContext())) return; RARCH_LOG("[EGL]: eglSwapInterval(%u)\n", interval); if (!eglSwapInterval(g_egl_dpy, interval)) { RARCH_ERR("[EGL]: eglSwapInterval() failed.\n"); egl_report_error(); } }
static void *gfx_ctx_mali_fbdev_init(void *video_driver) { EGLint n; EGLint major, minor; EGLint format; static const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE }; mali_ctx_data_t *mali = (mali_ctx_data_t*)calloc(1, sizeof(*mali)); if (!mali) return NULL; egl_install_sighandlers(); /* Disable cursor blinking so it's not visible in RetroArch. */ system("setterm -cursor off"); if (!egl_init_context(mali, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); goto error; } return mali; error: RARCH_ERR("[Mali fbdev]: EGL error: %d.\n", eglGetError()); gfx_ctx_mali_fbdev_destroy(video_driver); return NULL; }
static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) { #ifdef HAVE_OPENGL static const EGLint egl_attribs_gl[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE, }; #endif #ifdef HAVE_OPENGLES #ifdef HAVE_OPENGLES2 static const EGLint egl_attribs_gles[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; #endif #ifdef HAVE_OPENGLES3 #ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; #endif #endif #endif #ifdef HAVE_EGL static const EGLint egl_attribs_vg[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; EGLint major = 0, minor = 0; EGLint n; const EGLint *attrib_ptr = NULL; #endif gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*) calloc(1, sizeof(gfx_ctx_wayland_data_t)); if (!wl) return NULL; (void)video_driver; #ifdef HAVE_EGL switch (wl_api) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL attrib_ptr = egl_attribs_gl; #endif break; case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_OPENGLES #ifdef HAVE_OPENGLES3 #ifdef EGL_KHR_create_context if (g_egl_major >= 3) attrib_ptr = egl_attribs_gles3; else #endif #endif #ifdef HAVE_OPENGLES2 attrib_ptr = egl_attribs_gles; #endif #endif break; case GFX_CTX_OPENVG_API: #ifdef HAVE_VG attrib_ptr = egl_attribs_vg; #endif break; case GFX_CTX_NONE: default: break; } #endif frontend_driver_destroy_signal_handler_state(); wl->input.dpy = wl_display_connect(NULL); wl->buffer_scale = 1; if (!wl->input.dpy) { RARCH_ERR("[Wayland]: Failed to connect to Wayland server.\n"); goto error; } frontend_driver_install_signal_handler(); wl->registry = wl_display_get_registry(wl->input.dpy); wl_registry_add_listener(wl->registry, ®istry_listener, wl); wl_display_roundtrip(wl->input.dpy); if (!wl->compositor) { RARCH_ERR("[Wayland]: Failed to create compositor.\n"); goto error; } if (!wl->shm) { RARCH_ERR("[Wayland]: Failed to create shm.\n"); goto error; } if (!wl->shell) { RARCH_ERR("[Wayland]: Failed to create shell.\n"); goto error; } wl->input.fd = wl_display_get_fd(wl->input.dpy); switch (wl_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: case GFX_CTX_OPENVG_API: #ifdef HAVE_EGL if (!egl_init_context(&wl->egl, EGL_PLATFORM_WAYLAND_KHR, (EGLNativeDisplayType)wl->input.dpy, &major, &minor, &n, attrib_ptr)) { egl_report_error(); goto error; } if (n == 0 || !egl_has_config(&wl->egl)) goto error; #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN if (!vulkan_context_init(&wl->vk, VULKAN_WSI_WAYLAND)) goto error; #endif break; case GFX_CTX_NONE: default: break; } wl->input.keyboard_focus = true; wl->input.mouse.focus = true; wl->cursor.surface = wl_compositor_create_surface(wl->compositor); wl->cursor.theme = wl_cursor_theme_load(NULL, 16, wl->shm); wl->cursor.default_cursor = wl_cursor_theme_get_cursor(wl->cursor.theme, "left_ptr"); flush_wayland_fd(&wl->input); return wl; error: gfx_ctx_wl_destroy_resources(wl); if (wl) free(wl); return NULL; }
static bool gfx_ctx_xegl_init(void *data) { static const EGLint egl_attribs_gl[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE, }; static const EGLint egl_attribs_gles[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; #ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; #endif static const EGLint egl_attribs_vg[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; const EGLint *attrib_ptr; EGLint major, minor; EGLint n; if (g_egl_inited) return false; XInitThreads(); switch (g_egl_api) { case GFX_CTX_OPENGL_API: attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: #ifdef EGL_KHR_create_context if (g_major >= 3) attrib_ptr = egl_attribs_gles3; else #endif attrib_ptr = egl_attribs_gles; break; case GFX_CTX_OPENVG_API: attrib_ptr = egl_attribs_vg; break; default: attrib_ptr = NULL; } if (!x11_connect()) goto error; if (!egl_init_context((EGLNativeDisplayType)g_x11_dpy, &major, &minor, &n, attrib_ptr)) { egl_report_error(); goto error; } if (n == 0 || !g_egl_config) { RARCH_ERR("[X/EGL]: No EGL configurations available.\n"); goto error; } return true; error: gfx_ctx_xegl_destroy(data); return false; }
static bool gfx_ctx_wl_set_video_mode(void *data, video_frame_info_t *video_info, unsigned width, unsigned height, bool fullscreen) { #ifdef HAVE_EGL EGLint egl_attribs[16]; EGLint *attr = egl_fill_attribs( (gfx_ctx_wayland_data_t*)data, egl_attribs); #endif gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; wl->width = width ? width : DEFAULT_WINDOWED_WIDTH; wl->height = height ? height : DEFAULT_WINDOWED_HEIGHT; wl->surface = wl_compositor_create_surface(wl->compositor); wl_surface_set_buffer_scale(wl->surface, wl->buffer_scale); switch (wl_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: case GFX_CTX_OPENVG_API: #ifdef HAVE_EGL wl->win = wl_egl_window_create(wl->surface, wl->width, wl->height); #endif break; case GFX_CTX_NONE: default: break; } wl->shell_surf = wl_shell_get_shell_surface(wl->shell, wl->surface); wl_shell_surface_add_listener(wl->shell_surf, &shell_surface_listener, wl); wl_shell_surface_set_toplevel(wl->shell_surf); wl_shell_surface_set_class(wl->shell_surf, "RetroArch"); wl_shell_surface_set_title(wl->shell_surf, "RetroArch"); switch (wl_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: case GFX_CTX_OPENVG_API: #ifdef HAVE_EGL if (!egl_create_context(&wl->egl, (attr != egl_attribs) ? egl_attribs : NULL)) { egl_report_error(); goto error; } if (!egl_create_surface(&wl->egl, (EGLNativeWindowType)wl->win)) goto error; egl_set_swap_interval(&wl->egl, wl->egl.interval); #endif break; case GFX_CTX_NONE: default: break; } if (fullscreen) wl_shell_surface_set_fullscreen(wl->shell_surf, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); flush_wayland_fd(&wl->input); switch (wl_api) { case GFX_CTX_VULKAN_API: wl_display_roundtrip(wl->input.dpy); #ifdef HAVE_VULKAN if (!vulkan_surface_create(&wl->vk, VULKAN_WSI_WAYLAND, wl->input.dpy, wl->surface, wl->width, wl->height, wl->swap_interval)) goto error; #endif break; case GFX_CTX_NONE: default: break; } if (fullscreen) { wl->cursor.visible = false; gfx_ctx_wl_show_mouse(wl, false); } else wl->cursor.visible = true; return true; error: gfx_ctx_wl_destroy(data); return false; }
static void *gfx_ctx_vc_init(void *video_driver) { VC_DISPMANX_ALPHA_T alpha; EGLint n, major, minor; static EGL_DISPMANX_WINDOW_T nativewindow; DISPMANX_ELEMENT_HANDLE_T dispman_element; DISPMANX_DISPLAY_HANDLE_T dispman_display; DISPMANX_UPDATE_HANDLE_T dispman_update; DISPMANX_MODEINFO_T dispman_modeinfo; VC_RECT_T dst_rect; VC_RECT_T src_rect; #ifdef HAVE_EGL static const EGLint attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; static const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; #endif settings_t *settings = config_get_ptr(); vc_ctx_data_t *vc = NULL; if (g_egl_inited) { RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n"); return NULL; } vc = (vc_ctx_data_t*)calloc(1, sizeof(*vc)); if (!vc) return NULL; bcm_host_init(); #ifdef HAVE_EGL if (!egl_init_context(&vc->egl, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribute_list)) { egl_report_error(); goto error; } if (!egl_create_context(&vc->egl, (vc_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL)) { egl_report_error(); goto error; } #endif /* Create an EGL window surface. */ if (graphics_get_display_size(0 /* LCD */, &vc->fb_width, &vc->fb_height) < 0) goto error; dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = vc->fb_width; dst_rect.height = vc->fb_height; src_rect.x = 0; src_rect.y = 0; /* Use dispmanx upscaling if fullscreen_x * and fullscreen_y are set. */ if (settings->video.fullscreen_x != 0 && settings->video.fullscreen_y != 0) { /* Keep input and output aspect ratio equal. * There are other aspect ratio settings which can be used to stretch video output. */ /* Calculate source and destination aspect ratios. */ float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y; float dstAspect = (float)vc->fb_width / (float)vc->fb_height; /* If source and destination aspect ratios are not equal correct source width. */ if (srcAspect != dstAspect) src_rect.width = (unsigned)(settings->video.fullscreen_y * dstAspect) << 16; else src_rect.width = settings->video.fullscreen_x << 16; src_rect.height = settings->video.fullscreen_y << 16; } else { src_rect.width = vc->fb_width << 16; src_rect.height = vc->fb_height << 16; } dispman_display = vc_dispmanx_display_open(0 /* LCD */); vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo); dispman_update = vc_dispmanx_update_start(0); alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; alpha.opacity = 255; alpha.mask = 0; dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer*/, &dst_rect, 0 /*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, DISPMANX_NO_ROTATE); nativewindow.element = dispman_element; /* Use dispmanx upscaling if fullscreen_x and fullscreen_y are set. */ if (settings->video.fullscreen_x != 0 && settings->video.fullscreen_y != 0) { /* Keep input and output aspect ratio equal. * There are other aspect ratio settings which * can be used to stretch video output. */ /* Calculate source and destination aspect ratios. */ float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y; float dstAspect = (float)vc->fb_width / (float)vc->fb_height; /* If source and destination aspect ratios are not equal correct source width. */ if (srcAspect != dstAspect) nativewindow.width = (unsigned)(settings->video.fullscreen_y * dstAspect); else nativewindow.width = settings->video.fullscreen_x; nativewindow.height = settings->video.fullscreen_y; } else { nativewindow.width = vc->fb_width; nativewindow.height = vc->fb_height; } vc_dispmanx_update_submit_sync(dispman_update); #ifdef HAVE_EGL if (!egl_create_surface(&vc->egl, &nativewindow)) goto error; #endif return vc; error: gfx_ctx_vc_destroy(video_driver); return NULL; }
static bool gfx_ctx_xegl_init(void *data) { static const EGLint egl_attribs_gl[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE, }; static const EGLint egl_attribs_gles[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; #ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; #endif static const EGLint egl_attribs_vg[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; const EGLint *attrib_ptr; EGLint egl_major, egl_minor; EGLint num_configs; if (g_inited) return false; XInitThreads(); switch (g_api) { case GFX_CTX_OPENGL_API: attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: #ifdef EGL_KHR_create_context if (g_major >= 3) attrib_ptr = egl_attribs_gles3; else #endif attrib_ptr = egl_attribs_gles; break; case GFX_CTX_OPENVG_API: attrib_ptr = egl_attribs_vg; break; default: attrib_ptr = NULL; } g_quit = 0; /* Keep one g_dpy alive the entire process lifetime. * This is necessary for nVidia's EGL implementation for now. */ if (!g_dpy) { g_dpy = XOpenDisplay(NULL); if (!g_dpy) goto error; } g_egl_dpy = eglGetDisplay((EGLNativeDisplayType)g_dpy); if (g_egl_dpy == EGL_NO_DISPLAY) { RARCH_ERR("[X/EGL]: EGL display not available.\n"); egl_report_error(); goto error; } if (!eglInitialize(g_egl_dpy, &egl_major, &egl_minor)) { RARCH_ERR("[X/EGL]: Unable to initialize EGL.\n"); egl_report_error(); goto error; } RARCH_LOG("[X/EGL]: EGL version: %d.%d\n", egl_major, egl_minor); if (!eglChooseConfig(g_egl_dpy, attrib_ptr, &g_egl_config, 1, &num_configs)) { RARCH_ERR("[X/EGL]: eglChooseConfig failed with 0x%x.\n", eglGetError()); goto error; } if (num_configs == 0 || !g_egl_config) { RARCH_ERR("[X/EGL]: No EGL configurations available.\n"); goto error; } return true; error: gfx_ctx_xegl_destroy(data); return false; }
static bool gfx_ctx_drm_egl_set_video_mode(gfx_ctx_drm_data_t *drm) { const EGLint *attrib_ptr = NULL; static const EGLint egl_attribs_gl[] = { DRM_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE, }; static const EGLint egl_attribs_gles[] = { DRM_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; #ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { DRM_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; #endif #ifdef HAVE_VG static const EGLint egl_attribs_vg[] = { DRM_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; #endif EGLint major; EGLint minor; EGLint n; EGLint egl_attribs[16]; EGLint *egl_attribs_ptr = NULL; EGLint *attr = NULL; switch (drm_api) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: #ifdef EGL_KHR_create_context if (drm->egl.major >= 3) attrib_ptr = egl_attribs_gles3; else #endif attrib_ptr = egl_attribs_gles; #endif break; case GFX_CTX_OPENVG_API: #ifdef HAVE_VG attrib_ptr = egl_attribs_vg; #endif break; case GFX_CTX_NONE: default: break; } switch (drm_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: case GFX_CTX_OPENVG_API: #ifdef HAVE_EGL if (!egl_init_context(&drm->egl, (EGLNativeDisplayType)g_gbm_dev, &major, &minor, &n, attrib_ptr)) goto error; attr = gfx_ctx_drm_egl_fill_attribs(drm, egl_attribs); egl_attribs_ptr = &egl_attribs[0]; if (!egl_create_context(&drm->egl, (attr != egl_attribs_ptr) ? egl_attribs_ptr : NULL)) goto error; if (!egl_create_surface(&drm->egl, (EGLNativeWindowType)g_gbm_surface)) return false; #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) glClear(GL_COLOR_BUFFER_BIT); #endif #endif break; case GFX_CTX_NONE: default: break; } egl_swap_buffers(drm); return true; error: egl_report_error(); return false; }
static void *gfx_ctx_vc_init(video_frame_info_t *video_info, void *video_driver) { VC_DISPMANX_ALPHA_T alpha; EGLint n, major, minor; DISPMANX_ELEMENT_HANDLE_T dispman_element; DISPMANX_DISPLAY_HANDLE_T dispman_display; DISPMANX_UPDATE_HANDLE_T dispman_update; DISPMANX_MODEINFO_T dispman_modeinfo; VC_RECT_T dst_rect; VC_RECT_T src_rect; #ifdef HAVE_EGL static const EGLint attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; static const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; #endif settings_t *settings = config_get_ptr(); vc_ctx_data_t *vc = NULL; if (g_egl_inited) { RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n"); return NULL; } vc = (vc_ctx_data_t*)calloc(1, sizeof(*vc)); if (!vc) return NULL; /* If we set this env variable, Broadcom's EGL implementation will block * on vsync with a double buffer when we call eglSwapBuffers. Less input lag! * Has to be done before any EGL call. * NOTE this is commented out because it should be the right way to do it, but * currently it doesn't work, so we are using an vsync callback based solution.*/ /* if (video_info->max_swapchain_images <= 2) setenv("V3D_DOUBLE_BUFFER", "1", 1); else setenv("V3D_DOUBLE_BUFFER", "0", 1); */ bcm_host_init(); #ifdef HAVE_EGL if (!egl_init_context(&vc->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribute_list)) { egl_report_error(); goto error; } if (!egl_create_context(&vc->egl, (vc_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL)) { egl_report_error(); goto error; } #endif /* Create an EGL window surface. */ if (graphics_get_display_size(0 /* LCD */, &vc->fb_width, &vc->fb_height) < 0) goto error; dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = vc->fb_width; dst_rect.height = vc->fb_height; src_rect.x = 0; src_rect.y = 0; /* Use dispmanx upscaling if fullscreen_x * and fullscreen_y are set. */ if ((settings->uints.video_fullscreen_x != 0) && (settings->uints.video_fullscreen_y != 0)) { /* Keep input and output aspect ratio equal. * There are other aspect ratio settings which can be used to stretch video output. */ /* Calculate source and destination aspect ratios. */ float srcAspect = (float)settings->uints.video_fullscreen_x / (float)settings->uints.video_fullscreen_y; float dstAspect = (float)vc->fb_width / (float)vc->fb_height; /* If source and destination aspect ratios are not equal correct source width. */ if (srcAspect != dstAspect) src_rect.width = (unsigned)(settings->uints.video_fullscreen_y * dstAspect) << 16; else src_rect.width = settings->uints.video_fullscreen_x << 16; src_rect.height = settings->uints.video_fullscreen_y << 16; } else { src_rect.width = vc->fb_width << 16; src_rect.height = vc->fb_height << 16; } dispman_display = vc_dispmanx_display_open(0 /* LCD */); vc->dispman_display = dispman_display; vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo); dispman_update = vc_dispmanx_update_start(0); alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; alpha.opacity = 255; alpha.mask = 0; dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display, 0 /*layer*/, &dst_rect, 0 /*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, DISPMANX_NO_ROTATE); vc->native_window.element = dispman_element; /* Use dispmanx upscaling if fullscreen_x and fullscreen_y are set. */ if (settings->uints.video_fullscreen_x != 0 && settings->uints.video_fullscreen_y != 0) { /* Keep input and output aspect ratio equal. * There are other aspect ratio settings which * can be used to stretch video output. */ /* Calculate source and destination aspect ratios. */ float srcAspect = (float)settings->uints.video_fullscreen_x / (float)settings->uints.video_fullscreen_y; float dstAspect = (float)vc->fb_width / (float)vc->fb_height; /* If source and destination aspect ratios are not equal correct source width. */ if (srcAspect != dstAspect) vc->native_window.width = (unsigned)(settings->uints.video_fullscreen_y * dstAspect); else vc->native_window.width = settings->uints.video_fullscreen_x; vc->native_window.height = settings->uints.video_fullscreen_y; } else { vc->native_window.width = vc->fb_width; vc->native_window.height = vc->fb_height; } vc_dispmanx_update_submit_sync(dispman_update); #ifdef HAVE_EGL if (!egl_create_surface(&vc->egl, &vc->native_window)) goto error; #endif /* For vsync after eglSwapBuffers when max_swapchain < 3 */ vc->vsync_condition = scond_new(); vc->vsync_condition_mutex = slock_new(); vc->vsync_callback_set = false; if (video_info->max_swapchain_images <= 2) { /* Start sending vsync callbacks so we can wait for vsync after eglSwapBuffers */ vc_dispmanx_vsync_callback(vc->dispman_display, dispmanx_vsync_callback, (void*)vc); vc->vsync_callback_set = true; } return vc; error: gfx_ctx_vc_destroy(video_driver); return NULL; }
static bool gfx_ctx_qnx_init(void *data) { EGLint n; EGLint major, minor; EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; int angle, size[2]; int usage, format = SCREEN_FORMAT_RGBX8888; /* Create a screen context that will be used to * create an EGL surface to receive libscreen events */ RARCH_LOG("Initializing screen context...\n"); if (!screen_ctx) { screen_create_context(&screen_ctx, 0); if (screen_request_events(screen_ctx) != BPS_SUCCESS) { RARCH_ERR("screen_request_events failed.\n"); goto screen_error; } if (navigator_request_events(0) != BPS_SUCCESS) { RARCH_ERR("navigator_request_events failed.\n"); goto screen_error; } if (navigator_rotation_lock(false) != BPS_SUCCESS) { RARCH_ERR("navigator_location_lock failed.\n"); goto screen_error; } } usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_ROTATION; if (!eglBindAPI(EGL_OPENGL_ES_API)) { RARCH_ERR("eglBindAPI failed.\n"); goto error; } if (!egl_init_context(EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); goto error; } if (!egl_create_context(context_attributes)) { egl_report_error(); goto error; } if(!screen_win) { if (screen_create_window(&screen_win, screen_ctx)) { RARCH_ERR("screen_create_window failed:.\n"); goto error; } } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_FORMAT] failed.\n"); goto error; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_USAGE] failed.\n"); goto error; } if (screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp)) { RARCH_ERR("screen_get_window_property_pv [SCREEN_PROPERTY_DISPLAY] failed.\n"); goto error; } int screen_resolution[2]; if (screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution)) { RARCH_ERR("screen_get_window_property_iv [SCREEN_PROPERTY_SIZE] failed.\n"); goto error; } #ifndef HAVE_BB10 angle = atoi(getenv("ORIENTATION")); screen_display_mode_t screen_mode; if (screen_get_display_property_pv(screen_disp, SCREEN_PROPERTY_MODE, (void**)&screen_mode)) { RARCH_ERR("screen_get_display_property_pv [SCREEN_PROPERTY_MODE] failed.\n"); goto error; } if (screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, size)) { RARCH_ERR("screen_get_window_property_iv [SCREEN_PROPERTY_BUFFER_SIZE] failed.\n"); goto error; } int buffer_size[2] = {size[0], size[1]}; if ((angle == 0) || (angle == 180)) { if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) || ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else if ((angle == 90) || (angle == 270)) { if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) || ((screen_mode.width < screen_mode.height && size[0] < size[1]))) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else { RARCH_ERR("Navigator returned an unexpected orientation angle.\n"); goto error; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_BUFFER_SIZE] failed.\n"); goto error; } if (screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ROTATION, &angle)) { RARCH_ERR("screen_set_window_property_iv [SCREEN_PROPERTY_ROTATION] failed.\n"); goto error; } #endif if (screen_create_window_buffers(screen_win, WINDOW_BUFFERS)) { RARCH_ERR("screen_create_window_buffers failed.\n"); goto error; } if (!egl_create_surface(screen_win)) goto error; return true; error: RARCH_ERR("EGL error: %d.\n", eglGetError()); gfx_ctx_qnx_destroy(data); screen_error: screen_stop_events(screen_ctx); return false; }
static void *android_gfx_ctx_init(video_frame_info_t *video_info, void *video_driver) { #ifdef HAVE_OPENGLES EGLint n, major, minor; EGLint format; #if 0 struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); bool debug = hwr->debug_context; #endif EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, g_es3 ? 3 : 2, #if 0 EGL_CONTEXT_FLAGS_KHR, debug ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0, #endif EGL_NONE }; EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_NONE }; #endif struct android_app *android_app = (struct android_app*)g_android; android_ctx_data_t *and = (android_ctx_data_t*)calloc(1, sizeof(*and)); if (!android_app || !and) return false; #ifdef HAVE_OPENGLES if (g_es3) attribs[1] = EGL_OPENGL_ES3_BIT_KHR; #endif switch (android_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_EGL RARCH_LOG("Android EGL: GLES version = %d.\n", g_es3 ? 3 : 2); if (!egl_init_context(&and->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs)) { egl_report_error(); goto error; } if (!egl_get_native_visual_id(&and->egl, &format)) goto error; #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN if (!vulkan_context_init(&and->vk, VULKAN_WSI_ANDROID)) goto error; #endif break; case GFX_CTX_NONE: default: break; } slock_lock(android_app->mutex); if (!android_app->window) goto unlock_error; switch (android_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: ANativeWindow_setBuffersGeometry(android_app->window, 0, 0, format); #ifdef HAVE_EGL if (!egl_create_context(&and->egl, context_attributes)) { egl_report_error(); goto unlock_error; } if (!egl_create_surface(&and->egl, android_app->window)) goto unlock_error; #endif break; case GFX_CTX_NONE: default: break; } slock_unlock(android_app->mutex); return and; unlock_error: slock_unlock(android_app->mutex); error: android_gfx_ctx_destroy(and); return NULL; }
static void *gfx_ctx_xegl_init(void *video_driver) { #ifdef HAVE_EGL static const EGLint egl_attribs_gl[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE, }; static const EGLint egl_attribs_gles[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; #ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; #endif #ifdef HAVE_VG static const EGLint egl_attribs_vg[] = { XEGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; #endif const EGLint *attrib_ptr = NULL; EGLint major, minor; EGLint n; #endif xegl_ctx_data_t *xegl; if (g_egl_inited) return NULL; XInitThreads(); xegl = (xegl_ctx_data_t*)calloc(1, sizeof(xegl_ctx_data_t)); if (!xegl) return NULL; switch (x_api) { case GFX_CTX_OPENGL_API: attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: #ifdef EGL_KHR_create_context if (xegl->egl.major >= 3) attrib_ptr = egl_attribs_gles3; else #endif attrib_ptr = egl_attribs_gles; break; case GFX_CTX_OPENVG_API: #ifdef HAVE_VG attrib_ptr = egl_attribs_vg; #endif break; default: break; } if (!x11_connect()) goto error; #ifdef HAVE_EGL if (!egl_init_context(&xegl->egl, (EGLNativeDisplayType)g_x11_dpy, &major, &minor, &n, attrib_ptr)) { egl_report_error(); goto error; } if (n == 0 || !egl_has_config(&xegl->egl)) goto error; #endif return xegl; error: gfx_ctx_xegl_destroy(xegl); return NULL; }
static void *orbis_ctx_init(video_frame_info_t *video_info, void *video_driver) { #ifdef HAVE_EGL int ret; EGLint n; EGLint major, minor; static const EGLint attribs[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, 0, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE}; #endif orbis_ctx_data_t *ctx_orbis = (orbis_ctx_data_t *)calloc(1, sizeof(*ctx_orbis)); if (!ctx_orbis) return NULL; nx_ctx_ptr = ctx_orbis; #ifdef HAVE_EGL memset(&ctx_orbis->pgl_config, 0, sizeof(ctx_orbis->pgl_config)); { ctx_orbis->pgl_config.size=sizeof(ctx_orbis->pgl_config); ctx_orbis->pgl_config.flags=SCE_PGL_FLAGS_USE_COMPOSITE_EXT | SCE_PGL_FLAGS_USE_FLEXIBLE_MEMORY | 0x60; ctx_orbis->pgl_config.processOrder=1; ctx_orbis->pgl_config.systemSharedMemorySize=0x200000; ctx_orbis->pgl_config.videoSharedMemorySize=0x2400000; ctx_orbis->pgl_config.maxMappedFlexibleMemory=0xAA00000; ctx_orbis->pgl_config.drawCommandBufferSize=0xC0000; ctx_orbis->pgl_config.lcueResourceBufferSize=0x10000; ctx_orbis->pgl_config.dbgPosCmd_0x40=ATTR_ORBISGL_WIDTH; ctx_orbis->pgl_config.dbgPosCmd_0x44=ATTR_ORBISGL_HEIGHT; ctx_orbis->pgl_config.dbgPosCmd_0x48=0; ctx_orbis->pgl_config.dbgPosCmd_0x4C=0; ctx_orbis->pgl_config.unk_0x5C=2; } ret = scePigletSetConfigurationVSH(&ctx_orbis->pgl_config); if (!ret) { printf("[ORBISGL] scePigletSetConfigurationVSH failed 0x%08X.\n",ret); goto error; } if (!egl_init_context(&ctx_orbis->egl, EGL_NONE, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribs, NULL)) { egl_report_error(); printf("[ORBIS]: EGL error: %d.\n", eglGetError()); goto error; } #endif return ctx_orbis; error: orbis_ctx_destroy(video_driver); return NULL; }
static bool gfx_ctx_xegl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { XEvent event; EGLint egl_attribs[16]; EGLint vid, num_visuals; EGLint *attr = NULL; bool windowed_full = false; bool true_full = false; int x_off = 0; int y_off = 0; XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; settings_t *settings = config_get_ptr(); xegl_ctx_data_t *xegl = (xegl_ctx_data_t*)data; int (*old_handler)(Display*, XErrorEvent*) = NULL; frontend_driver_install_signal_handler(); windowed_full = settings->video.windowed_fullscreen; attr = egl_attribs; attr = xegl_fill_attribs(xegl, attr); #ifdef HAVE_EGL if (!egl_get_native_visual_id(&xegl->egl, &vid)) goto error; #endif temp.visualid = vid; vi = XGetVisualInfo(g_x11_dpy, VisualIDMask, &temp, &num_visuals); if (!vi) goto error; swa.colormap = g_x11_cmap = XCreateColormap( g_x11_dpy, RootWindow(g_x11_dpy, vi->screen), vi->visual, AllocNone); swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask; swa.override_redirect = fullscreen ? True : False; if (fullscreen && !windowed_full) { if (x11_enter_fullscreen(g_x11_dpy, width, height, &xegl->desktop_mode)) { xegl->should_reset_mode = true; true_full = true; } else RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } if (settings->video.monitor_index) g_x11_screen = settings->video.monitor_index - 1; #ifdef HAVE_XINERAMA if (fullscreen || g_x11_screen != 0) { unsigned new_width = width; unsigned new_height = height; if (x11_get_xinerama_coord(g_x11_dpy, g_x11_screen, &x_off, &y_off, &new_width, &new_height)) RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_x11_screen); else RARCH_LOG("[X/EGL]: Xinerama is not active on screen.\n"); if (fullscreen) { width = new_width; height = new_height; } } #endif RARCH_LOG("[X/EGL]: X = %d, Y = %d, W = %u, H = %u.\n", x_off, y_off, width, height); g_x11_win = XCreateWindow(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen), x_off, y_off, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa); XSetWindowBackground(g_x11_dpy, g_x11_win, 0); if (!egl_create_context(&xegl->egl, (attr != egl_attribs) ? egl_attribs : NULL)) { egl_report_error(); goto error; } if (!egl_create_surface(&xegl->egl, (void*)g_x11_win)) goto error; x11_set_window_attr(g_x11_dpy, g_x11_win); x11_update_window_title(NULL); if (fullscreen) x11_show_mouse(g_x11_dpy, g_x11_win, false); if (true_full) { RARCH_LOG("[X/EGL]: Using true fullscreen.\n"); XMapRaised(g_x11_dpy, g_x11_win); } else if (fullscreen) { /* We attempted true fullscreen, but failed. * Attempt using windowed fullscreen. */ XMapRaised(g_x11_dpy, g_x11_win); RARCH_LOG("[X/EGL]: Using windowed fullscreen.\n"); /* We have to move the window to the screen we * want to go fullscreen on first. * x_off and y_off usually get ignored in XCreateWindow(). */ x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height); x11_windowed_fullscreen(g_x11_dpy, g_x11_win); } else { XMapWindow(g_x11_dpy, g_x11_win); /* If we want to map the window on a different screen, * we'll have to do it by force. * * Otherwise, we should try to let the window manager sort it out. * x_off and y_off usually get ignored in XCreateWindow(). */ if (g_x11_screen) x11_move_window(g_x11_dpy, g_x11_win, x_off, y_off, width, height); } x11_event_queue_check(&event); x11_install_quit_atom(); #ifdef HAVE_EGL gfx_ctx_xegl_set_swap_interval(&xegl->egl, xegl->egl.interval); #endif /* This can blow up on some drivers. It's not fatal, * so override errors for this call. */ old_handler = XSetErrorHandler(x_nul_handler); XSetInputFocus(g_x11_dpy, g_x11_win, RevertToNone, CurrentTime); XSync(g_x11_dpy, False); XSetErrorHandler(old_handler); XFree(vi); g_egl_inited = true; if (!x11_input_ctx_new(true_full)) goto error; return true; error: if (vi) XFree(vi); gfx_ctx_xegl_destroy(data); return false; }
static void *gfx_ctx_emscripten_init(void *video_driver) { #ifdef HAVE_EGL unsigned width, height; EGLint major, minor; EGLint n; static const EGLint attribute_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; static const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; #endif emscripten_ctx_data_t *emscripten = (emscripten_ctx_data_t*) calloc(1, sizeof(*emscripten)); if (!emscripten) return NULL; (void)video_driver; #ifdef HAVE_EGL if (g_egl_inited) { RARCH_LOG("[EMSCRIPTEN/EGL]: Attempted to re-initialize driver.\n"); return (void*)"emscripten"; } if (!egl_init_context(&emscripten->egl, EGL_DEFAULT_DISPLAY, &major, &minor, &n, attribute_list)) { egl_report_error(); goto error; } if (!egl_create_context(&emscripten->egl, context_attributes)) { egl_report_error(); goto error; } if (!egl_create_surface(&emscripten->egl, 0)) goto error; egl_get_video_size(&emscripten->egl, &width, &height); emscripten->fb_width = width; emscripten->fb_height = height; RARCH_LOG("[EMSCRIPTEN/EGL]: Dimensions: %ux%u\n", width, height); #endif return emscripten; error: gfx_ctx_emscripten_destroy(video_driver); return NULL; }
static void *gfx_ctx_wl_init(void *video_driver) { static const EGLint egl_attribs_gl[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE, }; static const EGLint egl_attribs_gles[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE, }; #ifdef EGL_KHR_create_context static const EGLint egl_attribs_gles3[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, EGL_NONE, }; #endif static const EGLint egl_attribs_vg[] = { WL_EGL_ATTRIBS_BASE, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, EGL_NONE, }; EGLint major = 0, minor = 0; EGLint n; const EGLint *attrib_ptr; gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*) calloc(1, sizeof(gfx_ctx_wayland_data_t)); (void)video_driver; if (!wl) return NULL; switch (wl->egl.api) { case GFX_CTX_OPENGL_API: attrib_ptr = egl_attribs_gl; break; case GFX_CTX_OPENGL_ES_API: #ifdef EGL_KHR_create_context if (g_egl_major >= 3) attrib_ptr = egl_attribs_gles3; else #endif attrib_ptr = egl_attribs_gles; break; case GFX_CTX_OPENVG_API: attrib_ptr = egl_attribs_vg; break; default: attrib_ptr = NULL; } g_egl_quit = 0; wl->dpy = wl_display_connect(NULL); if (!wl->dpy) { RARCH_ERR("Failed to connect to Wayland server.\n"); goto error; } wl->registry = wl_display_get_registry(wl->dpy); wl_registry_add_listener(wl->registry, ®istry_listener, wl); wl_display_dispatch(wl->dpy); wl_display_roundtrip(wl->dpy); if (!wl->compositor) { RARCH_ERR("Failed to create compositor.\n"); goto error; } if (!wl->shell) { RARCH_ERR("Failed to create shell.\n"); goto error; } wl->fd = wl_display_get_fd(wl->dpy); if (!egl_init_context(wl, (EGLNativeDisplayType)wl->dpy, &major, &minor, &n, attrib_ptr)) { egl_report_error(); goto error; } if (n == 0 || !egl_has_config(wl)) goto error; return wl; error: gfx_ctx_wl_destroy_resources(wl); if (wl) free(wl); return NULL; }