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 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 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; }
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_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_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_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 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 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(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; }