static bool gfx_ctx_glx_init(void *data) { static const int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_DOUBLEBUFFER , True, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 0, GLX_STENCIL_SIZE , 0, None }; int nelements, major, minor; GLXFBConfig *fbcs = NULL; gfx_ctx_glx_data_t *glx = (gfx_ctx_glx_data_t*)calloc(1, sizeof(gfx_ctx_glx_data_t)); const struct retro_hw_render_callback *hw_render = (const struct retro_hw_render_callback*)video_driver_callback(); if (!glx) return false; XInitThreads(); if (!x11_connect()) goto error; glXQueryVersion(g_x11_dpy, &major, &minor); /* GLX 1.3+ minimum required. */ if ((major * 1000 + minor) < 1003) goto error; glx_create_context_attribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); #ifdef GL_DEBUG glx->g_debug = true; #else glx->g_debug = hw_render->debug_context; #endif /* Have to use ContextAttribs */ #ifdef HAVE_OPENGLES2 glx->g_core_es = true; glx->g_core_es_core = true; #else glx->g_core_es = (g_major * 1000 + g_minor) >= 3001; glx->g_core_es_core = (g_major * 1000 + g_minor) >= 3002; #endif if ((glx->g_core_es || glx->g_debug) && !glx_create_context_attribs) goto error; fbcs = glXChooseFBConfig(g_x11_dpy, DefaultScreen(g_x11_dpy), visual_attribs, &nelements); if (!fbcs) goto error; if (!nelements) { XFree(fbcs); goto error; } glx->g_fbc = fbcs[0]; XFree(fbcs); gfx_ctx_data_set(glx); return true; error: ctx_glx_destroy_resources(glx); if (glx) free(glx); g_x11_screen = 0; return false; }
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 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 void *gfx_ctx_x_init(void *data) { int nelements, major, minor; #ifdef HAVE_OPENGL static const int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_DOUBLEBUFFER , True, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 0, GLX_STENCIL_SIZE , 0, None }; GLXFBConfig *fbcs = NULL; #endif gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*) calloc(1, sizeof(gfx_ctx_x_data_t)); #ifndef GL_DEBUG struct retro_hw_render_callback *hwr = NULL; video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr); #endif if (!x) return NULL; XInitThreads(); if (!x11_connect()) goto error; switch (x_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_OPENGL glXQueryVersion(g_x11_dpy, &major, &minor); /* GLX 1.3+ minimum required. */ if ((major * 1000 + minor) < 1003) goto error; glx_create_context_attribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); #ifdef GL_DEBUG x->g_debug = true; #else x->g_debug = hwr->debug_context; #endif /* Have to use ContextAttribs */ #ifdef HAVE_OPENGLES2 x->g_core_es = true; x->g_core_es_core = true; #else x->g_core_es = (g_major * 1000 + g_minor) >= 3001; x->g_core_es_core = (g_major * 1000 + g_minor) >= 3002; #endif if ((x->g_core_es || x->g_debug) && !glx_create_context_attribs) goto error; fbcs = glXChooseFBConfig(g_x11_dpy, DefaultScreen(g_x11_dpy), visual_attribs, &nelements); if (!fbcs) goto error; if (!nelements) { XFree(fbcs); goto error; } x->g_fbc = fbcs[0]; XFree(fbcs); #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN /* Use XCB WSI since it's the most supported WSI over legacy Xlib. */ if (!vulkan_context_init(&x->vk, VULKAN_WSI_XCB)) goto error; #endif break; case GFX_CTX_NONE: default: break; } return x; error: if (x) { gfx_ctx_x_destroy_resources(x); free(x); } g_x11_screen = 0; return NULL; }
struct gui_instance * gui_instance (struct gui_definition *definition) { struct gui_instance *result; XRenderPictureAttributes pa; result = malloc (sizeof (*result)); memset (result, 0, sizeof (*result)); result->definition = *definition; x11_connect (); memset (&result->window_attr, 0, sizeof (result->window_attr)); result->window_attr.cursor = XCreateFontCursor (GUI_display, XC_left_ptr); result->window_attr.colormap = DefaultColormap (GUI_display, GUI_screenidx); result->window_attr.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | ExposureMask; result->width = 640; result->height = 480; result->last_event = CurrentTime; result->window = XCreateWindow (GUI_display, RootWindow (GUI_display, GUI_screenidx), 0, 0, result->width, result->height, 0, GUI_visual_info->depth, InputOutput, GUI_visual, CWColormap | CWEventMask | CWCursor, &result->window_attr); if (!result->window) errx (EXIT_FAILURE, "Failed to create X window (XCreateWindow)"); if (instance_count == instance_alloc) { instance_alloc = instance_alloc * 2 + 1; instances = realloc (instances, sizeof(*instances) * instance_alloc); if(!instances) errx(EXIT_FAILURE, "realloc failed: %s", strerror(errno)); } instances[instance_count++] = result; if(definition->init) definition->init(result); result->xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, result->window, XNFocusWindow, result->window, NULL); if(!result->xic) errx(EXIT_FAILURE, "Failed to create X Input Context (XCreateIC)"); XMapWindow(GUI_display, result->window); memset(&pa, 0, sizeof(pa)); pa.subwindow_mode = IncludeInferiors; result->front_buffer = XRenderCreatePicture(GUI_display, result->window, xrenderpictformat, CPSubwindowMode, &pa); if(!result->front_buffer) errx(EXIT_FAILURE, "Failed to create front buffer for X window (XRenderCreatePicture)"); return result; }
static void *gfx_ctx_x_init(video_frame_info_t *video_info, void *data) { int nelements = 0; int major = 0; int minor = 0; #ifdef HAVE_OPENGL static const int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_DOUBLEBUFFER , True, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 0, GLX_STENCIL_SIZE , 0, GLX_SAMPLE_BUFFERS , 0, GLX_SAMPLES , 0, None }; GLXFBConfig *fbcs = NULL; #endif gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*) calloc(1, sizeof(gfx_ctx_x_data_t)); #ifndef GL_DEBUG struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); #endif if (!x) return NULL; current_context_data = x; XInitThreads(); if (!x11_connect()) goto error; switch (x_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: #if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) glXQueryVersion(g_x11_dpy, &major, &minor); /* GLX 1.3+ minimum required. */ if ((major * 1000 + minor) < 1003) goto error; glx_create_context_attribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); #ifdef GL_DEBUG x->g_debug = true; #else x->g_debug = hwr->debug_context; #endif /* Have to use ContextAttribs */ #ifdef HAVE_OPENGLES2 x->g_core_es = true; x->g_core_es_core = true; #else x->g_core_es = (g_major * 1000 + g_minor) >= 3001; x->g_core_es_core = (g_major * 1000 + g_minor) >= 3002; #endif if ((x->g_core_es || x->g_debug) && !glx_create_context_attribs) goto error; fbcs = glXChooseFBConfig(g_x11_dpy, DefaultScreen(g_x11_dpy), visual_attribs, &nelements); if (!fbcs) goto error; if (!nelements) { XFree(fbcs); goto error; } x->g_fbc = fbcs[0]; XFree(fbcs); #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN /* Use XCB WSI since it's the most supported WSI over legacy Xlib. */ if (!vulkan_context_init(&x->vk, VULKAN_WSI_XCB)) goto error; #endif break; case GFX_CTX_NONE: default: break; } switch (x_api) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL if (GLXExtensionSupported(g_x11_dpy, "GLX_EXT_swap_control_tear")) { RARCH_LOG("[GLX]: GLX_EXT_swap_control_tear supported.\n"); x_adaptive_vsync = true; } if (GLXExtensionSupported(g_x11_dpy, "GLX_OML_sync_control") && GLXExtensionSupported(g_x11_dpy, "GLX_MESA_swap_control") ) { RARCH_LOG("[GLX]: GLX_OML_sync_control and GLX_MESA_swap_control supported, using better swap control method...\n"); x->swap_mode = 1; glXGetSyncValuesOML = (GLXGETSYNCVALUESOMLPROC)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML"); glXGetMscRateOML = (GLXGETMSCRATEOMLPROC)glXGetProcAddress((unsigned char *)"glXGetMscRateOML"); glXSwapBuffersMscOML = (GLXSWAPBUFFERSMSCOMLPROC)glXGetProcAddress((unsigned char *)"glXSwapBuffersMscOML"); glXWaitForMscOML = (GLXWAITFORMSCOMLPROC)glXGetProcAddress((unsigned char *)"glXWaitForMscOML"); glXWaitForSbcOML = (GLXWAITFORSBCOMLPROC)glXGetProcAddress((unsigned char *)"glXWaitForSbcOML"); glXGetSyncValuesOML(g_x11_dpy, g_x11_win, &x->ust, &x->msc, &x->sbc); #if 0 RARCH_LOG("[GLX]: UST: %d, MSC: %d, SBC: %d\n", x->ust, x->msc, x->sbc); #endif } #endif break; default: break; } return x; error: if (x) { gfx_ctx_x_destroy_resources(x); free(x); } g_x11_screen = 0; return NULL; }