SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; int screen = ((SDL_DisplayData *) SDL_GetDisplayFromWindow(window)-> driverdata)->screen; XWindowAttributes xattr; XVisualInfo v, *vinfo; int n; GLXContext context = NULL; /* We do this to create a clean separation between X and GLX errors. */ XSync(display, False); XGetWindowAttributes(display, data->window, &xattr); v.screen = screen; v.visualid = XVisualIDFromVisual(xattr.visual); vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n); if (vinfo) { if (_this->gl_config.major_version < 3) { context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True); } else { /* If we want a GL 3.0 context or later we need to get a temporary context to grab the new context creation function */ GLXContext temp_context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True); if (!temp_context) { SDL_SetError("Could not create GL context"); return NULL; } else { int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, GLX_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 }; /* Get a pointer to the context creation function for GL 3.0 */ PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> glXGetProcAddress((GLubyte *) "glXCreateContextAttribsARB"); if (!glXCreateContextAttribs) { SDL_SetError("GL 3.x is not supported"); context = temp_context; } else { /* Create a GL 3.x context */ GLXFBConfig *framebuffer_config = NULL; int fbcount = 0; GLXFBConfig *(*glXChooseFBConfig) (Display * disp, int screen, const int *attrib_list, int *nelements); glXChooseFBConfig = (GLXFBConfig * (*)(Display *, int, const int *, int *)) _this->gl_data-> glXGetProcAddress((GLubyte *) "glXChooseFBConfig"); if (!glXChooseFBConfig || !(framebuffer_config = glXChooseFBConfig(display, DefaultScreen(display), NULL, &fbcount))) { SDL_SetError ("No good framebuffers found. GL 3.x disabled"); context = temp_context; } else { context = glXCreateContextAttribs(display, framebuffer_config[0], NULL, True, attribs); _this->gl_data->glXDestroyContext(display, temp_context); } } } } XFree(vinfo); } XSync(display, False); if (!context) { SDL_SetError("Could not create GL context"); return NULL; } if (X11_GL_MakeCurrent(_this, window, context) < 0) { X11_GL_DeleteContext(_this, context); return NULL; } return context; }
/** * return prefered frame format (if this is 100% correct, I eat my shorts ;) */ static const char *_format() { if(!_c.display) NFT_LOG_NULL(NULL); /* our result */ char *res = "error"; /* get XVisualInfo */ XVisualInfo vi_proto = { .screen = _c.screen }; XVisualInfo *vi; int nvi = 0; vi = XGetVisualInfo(_c.display, VisualScreenMask, &vi_proto, &nvi); if(!nvi) { NFT_LOG(L_ERROR, "No VisualInfo's returned?!"); return NULL; } /* get default visual id */ VisualID id; id = XVisualIDFromVisual(DefaultVisual(_c.display, _c.screen)); /* get our VisualInfo */ XVisualInfo *myvi = NULL; int i; for(i=0; i<nvi; i++) { if((vi[i].visualid) == id) { myvi = &vi[i]; break; } } /* this may not happen */ if(!myvi) { NFT_LOG(L_ERROR, "Didn't find our VisualID?!"); goto _f_exit; } /* decide about bits-per-component */ switch(myvi->bits_per_rgb) { case 8: { res = "ARGB u8"; break; } case 16: { res = "ARGB u16"; break; } case 32: { res = "ARGB u32"; break; } default: { NFT_LOG(L_ERROR, "Invalid bits-per-component: %d", myvi->bits_per_rgb); return NULL; } } _f_exit: NFT_LOG(L_VERBOSE, "Depth: %d Red-mask: 0x%lx Green-mask: " "0x%lx Blue-mask: 0x%lx Bits per component: %d", myvi->depth, myvi->red_mask, myvi->green_mask, myvi->blue_mask, myvi->bits_per_rgb); XFree(vi); return (const char *) res; } /** * return whether capture mechanism delivers big-endian ordered data */ static bool _is_big_endian() { if(XImageByteOrder(_c.display) == LSBFirst) return TRUE; else return FALSE; } /** descriptor of this mechanism */ CaptureMechanism XLIB = { .name = "Xlib", .init = _init, .deinit = _deinit, .capture = _capture, .format = _format, .is_big_endian = _is_big_endian, };
XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings) { // Retrieve all the visuals int count; XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count); if (visuals) { // Evaluate all the returned visuals, and pick the best one int bestScore = 0x7FFFFFFF; XVisualInfo bestVisual; for (int i = 0; i < count; ++i) { // Check mandatory attributes int doubleBuffer; glXGetConfig(display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); if (!doubleBuffer) continue; // Extract the components of the current visual int red, green, blue, alpha, depth, stencil, multiSampling, samples; glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red); glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE, &green); glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE, &blue); glXGetConfig(display, &visuals[i], GLX_ALPHA_SIZE, &alpha); glXGetConfig(display, &visuals[i], GLX_DEPTH_SIZE, &depth); glXGetConfig(display, &visuals[i], GLX_STENCIL_SIZE, &stencil); if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED) { glXGetConfig(display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); glXGetConfig(display, &visuals[i], GLX_SAMPLES_ARB, &samples); } else { multiSampling = 0; samples = 0; } // TODO: Replace this with proper acceleration detection bool accelerated = true; // Evaluate the visual int color = red + green + blue + alpha; int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0, accelerated); // If it's better than the current best, make it the new best if (score < bestScore) { bestScore = score; bestVisual = visuals[i]; } } // Free the array of visuals XFree(visuals); return bestVisual; } else { // Should never happen... err() << "No GLX visual found. You should check your graphics driver" << std::endl; return XVisualInfo(); } }
Visual * createVisual(bool doubleBuffer, unsigned samples, Profile profile) { EGLint api_bits; if (profile.api == glprofile::API_GL) { api_bits = EGL_OPENGL_BIT; if (profile.core && !has_EGL_KHR_create_context) { return NULL; } } else if (profile.api == glprofile::API_GLES) { switch (profile.major) { case 1: api_bits = EGL_OPENGL_ES_BIT; break; case 3: if (has_EGL_KHR_create_context) { api_bits = EGL_OPENGL_ES3_BIT; break; } /* fall-through */ case 2: api_bits = EGL_OPENGL_ES2_BIT; break; default: return NULL; } } else { assert(0); return NULL; } Attributes<EGLint> attribs; attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); attribs.add(EGL_RED_SIZE, 1); attribs.add(EGL_GREEN_SIZE, 1); attribs.add(EGL_BLUE_SIZE, 1); attribs.add(EGL_ALPHA_SIZE, 1); attribs.add(EGL_DEPTH_SIZE, 1); attribs.add(EGL_STENCIL_SIZE, 1); attribs.add(EGL_RENDERABLE_TYPE, api_bits); attribs.end(EGL_NONE); EGLint num_configs = 0; if (!eglGetConfigs(eglDisplay, NULL, 0, &num_configs) || num_configs <= 0) { return NULL; } std::vector<EGLConfig> configs(num_configs); if (!eglChooseConfig(eglDisplay, attribs, &configs[0], num_configs, &num_configs) || num_configs <= 0) { return NULL; } // We can't tell what other APIs the trace will use afterwards, therefore // try to pick a config which supports the widest set of APIs. int bestScore = -1; EGLConfig config = configs[0]; for (EGLint i = 0; i < num_configs; ++i) { EGLint renderable_type = EGL_NONE; eglGetConfigAttrib(eglDisplay, configs[i], EGL_RENDERABLE_TYPE, &renderable_type); int score = 0; assert(renderable_type & api_bits); renderable_type &= ~api_bits; if (renderable_type & EGL_OPENGL_ES2_BIT) { score += 1 << 4; } if (renderable_type & EGL_OPENGL_ES3_BIT) { score += 1 << 3; } if (renderable_type & EGL_OPENGL_ES_BIT) { score += 1 << 2; } if (renderable_type & EGL_OPENGL_BIT) { score += 1 << 1; } if (score > bestScore) { config = configs[i]; bestScore = score; } } assert(bestScore >= 0); EGLint visual_id; if (!eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &visual_id)) { assert(0); return NULL; } EglVisual *visual = new EglVisual(profile); visual->config = config; XVisualInfo templ; int num_visuals = 0; templ.visualid = visual_id; visual->visinfo = XGetVisualInfo(display, VisualIDMask, &templ, &num_visuals); assert(visual->visinfo); return visual; }
static bool gfx_ctx_xegl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { EGLint egl_attribs[16]; EGLint *attr; EGLint vid, num_visuals; bool windowed_full; bool true_full = false; int x_off = 0; int y_off = 0; struct sigaction sa = {{0}}; XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); int (*old_handler)(Display*, XErrorEvent*) = NULL; XEvent event; sa.sa_handler = egl_sighandler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); windowed_full = settings->video.windowed_fullscreen; true_full = false; attr = egl_attribs; attr = xegl_fill_attribs(attr); if (!eglGetConfigAttrib(g_egl_dpy, g_egl_config, EGL_NATIVE_VISUAL_ID, &vid)) goto error; temp.visualid = vid; vi = XGetVisualInfo(g_dpy, VisualIDMask, &temp, &num_visuals); if (!vi) goto error; swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_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_dpy, width, height, &g_desktop_mode)) { g_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_screen = settings->video.monitor_index - 1; #ifdef HAVE_XINERAMA if (fullscreen || g_screen != 0) { unsigned new_width = width; unsigned new_height = height; if (x11_get_xinerama_coord(g_dpy, g_screen, &x_off, &y_off, &new_width, &new_height)) RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_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_win = XCreateWindow(g_dpy, RootWindow(g_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_dpy, g_win, 0); g_egl_ctx = eglCreateContext(g_egl_dpy, g_egl_config, EGL_NO_CONTEXT, attr != egl_attribs ? egl_attribs : NULL); RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx); if (g_egl_ctx == EGL_NO_CONTEXT) goto error; if (g_use_hw_ctx) { g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_egl_config, g_egl_ctx, attr != egl_attribs ? egl_attribs : NULL); RARCH_LOG("[X/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx); if (g_egl_hw_ctx == EGL_NO_CONTEXT) goto error; } g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_egl_config, (EGLNativeWindowType)g_win, NULL); if (!g_egl_surf) goto error; if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx)) goto error; RARCH_LOG("[X/EGL]: Current context: %p.\n", (void*)eglGetCurrentContext()); x11_set_window_attr(g_dpy, g_win); if (fullscreen) x11_show_mouse(g_dpy, g_win, false); if (true_full) { RARCH_LOG("[X/EGL]: Using true fullscreen.\n"); XMapRaised(g_dpy, g_win); } else if (fullscreen) { /* We attempted true fullscreen, but failed. * Attempt using windowed fullscreen. */ XMapRaised(g_dpy, g_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_dpy, g_win, x_off, y_off, width, height); x11_windowed_fullscreen(g_dpy, g_win); } else { XMapWindow(g_dpy, g_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_screen) x11_move_window(g_dpy, g_win, x_off, y_off, width, height); } XIfEvent(g_dpy, &event, egl_wait_notify, NULL); g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False); if (g_quit_atom) XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1); gfx_ctx_xegl_swap_interval(data, g_interval); /* This can blow up on some drivers. It's not fatal, * so override errors for this call. */ old_handler = XSetErrorHandler(egl_nul_handler); XSetInputFocus(g_dpy, g_win, RevertToNone, CurrentTime); XSync(g_dpy, False); XSetErrorHandler(old_handler); XFree(vi); g_has_focus = true; g_inited = true; if (!x11_create_input_context(g_dpy, g_win, &g_xim, &g_xic)) goto error; driver->display_type = RARCH_DISPLAY_X11; driver->video_display = (uintptr_t)g_dpy; driver->video_window = (uintptr_t)g_win; g_true_full = true_full; return true; error: if (vi) XFree(vi); gfx_ctx_xegl_destroy(data); return false; }
static bool gfx_ctx_xegl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { XEvent event; EGLint egl_attribs[16]; EGLint *attr; EGLint vid, num_visuals; bool windowed_full; bool true_full = false; int x_off = 0; int y_off = 0; XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); int (*old_handler)(Display*, XErrorEvent*) = NULL; x11_install_sighandlers(); windowed_full = settings->video.windowed_fullscreen; attr = egl_attribs; attr = xegl_fill_attribs(attr); if (!eglGetConfigAttrib(g_egl_dpy, g_egl_config, EGL_NATIVE_VISUAL_ID, &vid)) goto error; 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, &g_desktop_mode)) { g_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_screen = settings->video.monitor_index - 1; #ifdef HAVE_XINERAMA if (fullscreen || g_screen != 0) { unsigned new_width = width; unsigned new_height = height; if (x11_get_xinerama_coord(g_x11_dpy, g_screen, &x_off, &y_off, &new_width, &new_height)) RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_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((attr != egl_attribs) ? egl_attribs : NULL)) { egl_report_error(); goto error; } if (!egl_create_surface((EGLNativeWindowType)g_x11_win)) goto error; x11_set_window_attr(g_x11_dpy, g_x11_win); 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_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(); egl_set_swap_interval(data, g_interval); /* This can blow up on some drivers. It's not fatal, * so override errors for this call. */ old_handler = XSetErrorHandler(egl_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; }
Status XeviGetVisualInfo( register Display *dpy, VisualID *visual, int n_visual, ExtendedVisualInfo **evi_return, int *n_info_return) { XExtDisplayInfo *info = find_display (dpy); register xEVIGetVisualInfoReq *req; xEVIGetVisualInfoReply rep; int sz_info, sz_xInfo, sz_conflict, sz_xConflict; VisualID32 *temp_conflict, *temp_visual, *xConflictPtr; VisualID *conflict; xExtendedVisualInfo *temp_xInfo; XVisualInfo *vinfo; register ExtendedVisualInfo *infoPtr; register xExtendedVisualInfo *xInfoPtr; register int n_data, visualIndex, vinfoIndex; Bool isValid; XeviCheckExtension (dpy, info, 0); *n_info_return = 0; *evi_return = NULL; vinfo = XGetVisualInfo(dpy, 0, NULL, &sz_info); if (!vinfo) { return BadValue; } if (!n_visual || !visual) { /* copy the all visual */ temp_visual = (VisualID32 *)Xmalloc(sz_VisualID32 * sz_info); n_visual = 0; for (vinfoIndex = 0; vinfoIndex < sz_info; vinfoIndex++) if (notInList(temp_visual, n_visual, vinfo[vinfoIndex].visualid)) temp_visual[n_visual++] = vinfo[vinfoIndex].visualid; } else { /* check if the visual is valid */ for (visualIndex = 0; visualIndex < n_visual; visualIndex++) { isValid = False; for (vinfoIndex = 0; vinfoIndex < sz_info; vinfoIndex++) { if (visual[visualIndex] == vinfo[vinfoIndex].visualid) { isValid = True; break; } } if (!isValid) { XFree(vinfo); return BadValue; } } temp_visual = (VisualID32 *)Xmalloc(sz_VisualID32 * n_visual); for (visualIndex = 0; visualIndex < n_visual; visualIndex++) temp_visual[visualIndex] = visual[visualIndex]; } XFree(vinfo); LockDisplay(dpy); GetReq(EVIGetVisualInfo, req); req->reqType = info->codes->major_opcode; req->xeviReqType = X_EVIGetVisualInfo; req->n_visual = n_visual; SetReqLen(req, n_visual, 1); Data(dpy, (char *)temp_visual, n_visual * sz_VisualID32); if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { UnlockDisplay(dpy); SyncHandle(); Xfree(temp_visual); return BadAccess; } Xfree(temp_visual); sz_info = rep.n_info * sizeof(ExtendedVisualInfo); sz_xInfo = rep.n_info * sz_xExtendedVisualInfo; sz_conflict = rep.n_conflicts * sizeof(VisualID); sz_xConflict = rep.n_conflicts * sz_VisualID32; infoPtr = *evi_return = (ExtendedVisualInfo *)Xmalloc(sz_info + sz_conflict); xInfoPtr = temp_xInfo = (xExtendedVisualInfo *)Xmalloc(sz_xInfo); xConflictPtr = temp_conflict = (VisualID32 *)Xmalloc(sz_xConflict); if (!*evi_return || !temp_xInfo || !temp_conflict) { _XEatData(dpy, (sz_xInfo + sz_xConflict + 3) & ~3); UnlockDisplay(dpy); SyncHandle(); if (evi_return) Xfree(evi_return); if (temp_xInfo) Xfree(temp_xInfo); if (temp_conflict) Xfree(temp_conflict); return BadAlloc; } _XRead(dpy, (char *)temp_xInfo, sz_xInfo); _XRead(dpy, (char *)temp_conflict, sz_xConflict); UnlockDisplay(dpy); SyncHandle(); n_data = rep.n_info; conflict = (VisualID *)(infoPtr + n_data); while (n_data-- > 0) { infoPtr->core_visual_id = xInfoPtr->core_visual_id; infoPtr->screen = xInfoPtr->screen; infoPtr->level = xInfoPtr->level; infoPtr->transparency_type = xInfoPtr->transparency_type; infoPtr->transparency_value = xInfoPtr->transparency_value; infoPtr->min_hw_colormaps = xInfoPtr->min_hw_colormaps; infoPtr->max_hw_colormaps = xInfoPtr->max_hw_colormaps; infoPtr->num_colormap_conflicts = xInfoPtr->num_colormap_conflicts; infoPtr->colormap_conflicts = conflict; conflict += infoPtr->num_colormap_conflicts; infoPtr++; xInfoPtr++; } n_data = rep.n_conflicts; conflict = (VisualID *)(infoPtr); while (n_data-- > 0) *conflict++ = *xConflictPtr++; Xfree(temp_xInfo); Xfree(temp_conflict); *n_info_return = rep.n_info; return Success; }
static bool gfx_ctx_x_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { XEvent event; bool true_full = false, windowed_full; int val, x_off = 0, y_off = 0; XVisualInfo *vi = NULL; XSetWindowAttributes swa = {0}; int (*old_handler)(Display*, XErrorEvent*) = NULL; settings_t *settings = config_get_ptr(); gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data; x11_install_sighandlers(); if (!x) return false; windowed_full = settings->video.windowed_fullscreen; true_full = false; switch (x_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_OPENGL vi = glXGetVisualFromFBConfig(g_x11_dpy, x->g_fbc); if (!vi) goto error; #endif break; case GFX_CTX_NONE: default: { XVisualInfo vi_template; /* For default case, just try to obtain a visual from template. */ int nvisuals = 0; memset(&vi_template, 0, sizeof(vi_template)); vi_template.screen = DefaultScreen(g_x11_dpy); vi = XGetVisualInfo(g_x11_dpy, VisualScreenMask, &vi_template, &nvisuals); if (!vi || nvisuals < 1) goto error; } break; } swa.colormap = g_x11_cmap = XCreateColormap(g_x11_dpy, RootWindow(g_x11_dpy, vi->screen), vi->visual, AllocNone); swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonReleaseMask | ButtonPressMask; swa.override_redirect = fullscreen ? True : False; if (fullscreen && !windowed_full) { if (x11_enter_fullscreen(g_x11_dpy, width, height, &x->g_desktop_mode)) { x->g_should_reset_mode = true; true_full = true; } else RARCH_ERR("[GLX]: 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("[GLX]: Using Xinerama on screen #%u.\n", g_x11_screen); else RARCH_LOG("[GLX]: Xinerama is not active on screen.\n"); if (fullscreen) { width = new_width; height = new_height; } } #endif RARCH_LOG("[GLX]: 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); switch (x_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_OPENGL x->g_glx_win = glXCreateWindow(g_x11_dpy, x->g_fbc, g_x11_win, 0); #endif break; case GFX_CTX_NONE: default: break; } 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("[GLX]: 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("[GLX]: 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); switch (x_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_OPENGL if (!x->g_ctx) { if (x->g_core_es || x->g_debug) { int attribs[16]; int *aptr = attribs; if (x->g_core_es) { *aptr++ = GLX_CONTEXT_MAJOR_VERSION_ARB; *aptr++ = g_major; *aptr++ = GLX_CONTEXT_MINOR_VERSION_ARB; *aptr++ = g_minor; if (x->g_core_es_core) { /* Technically, we don't have core/compat until 3.2. * Version 3.1 is either compat or not depending on * GL_ARB_compatibility. */ *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB; #ifdef HAVE_OPENGLES2 *aptr++ = GLX_CONTEXT_ES_PROFILE_BIT_EXT; #else *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; #endif } } if (x->g_debug) { *aptr++ = GLX_CONTEXT_FLAGS_ARB; *aptr++ = GLX_CONTEXT_DEBUG_BIT_ARB; } *aptr = None; x->g_ctx = glx_create_context_attribs(g_x11_dpy, x->g_fbc, NULL, True, attribs); if (x->g_use_hw_ctx) { RARCH_LOG("[GLX]: Creating shared HW context.\n"); x->g_hw_ctx = glx_create_context_attribs(g_x11_dpy, x->g_fbc, x->g_ctx, True, attribs); if (!x->g_hw_ctx) RARCH_ERR("[GLX]: Failed to create new shared context.\n"); } } else { x->g_ctx = glXCreateNewContext(g_x11_dpy, x->g_fbc, GLX_RGBA_TYPE, 0, True); if (x->g_use_hw_ctx) { x->g_hw_ctx = glXCreateNewContext(g_x11_dpy, x->g_fbc, GLX_RGBA_TYPE, x->g_ctx, True); if (!x->g_hw_ctx) RARCH_ERR("[GLX]: Failed to create new shared context.\n"); } } if (!x->g_ctx) { RARCH_ERR("[GLX]: Failed to create new context.\n"); goto error; } } else { video_driver_ctl(RARCH_DISPLAY_CTL_SET_VIDEO_CACHE_CONTEXT_ACK, NULL); RARCH_LOG("[GLX]: Using cached GL context.\n"); } glXMakeContextCurrent(g_x11_dpy, x->g_glx_win, x->g_glx_win, x->g_ctx); #endif break; case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN { bool quit, resize; unsigned width, height; x11_check_window(x, &quit, &resize, &width, &height, 0); /* Use XCB surface since it's the most supported WSI. * We can obtain the XCB connection directly from X11. */ if (!vulkan_surface_create(&x->vk, VULKAN_WSI_XCB, g_x11_dpy, &g_x11_win, width, height, x->g_interval)) goto error; } #endif break; case GFX_CTX_NONE: default: break; } XSync(g_x11_dpy, False); x11_install_quit_atom(); switch (x_api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: #ifdef HAVE_OPENGL glXGetConfig(g_x11_dpy, vi, GLX_DOUBLEBUFFER, &val); x->g_is_double = val; if (x->g_is_double) { const char *swap_func = NULL; g_pglSwapIntervalEXT = (void (*)(Display*, GLXDrawable, int)) glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT"); g_pglSwapIntervalSGI = (int (*)(int)) glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI"); g_pglSwapInterval = (int (*)(int)) glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA"); if (g_pglSwapIntervalEXT) swap_func = "glXSwapIntervalEXT"; else if (g_pglSwapInterval) swap_func = "glXSwapIntervalMESA"; else if (g_pglSwapIntervalSGI) swap_func = "glXSwapIntervalSGI"; if (!g_pglSwapInterval && !g_pglSwapIntervalEXT && !g_pglSwapIntervalSGI) RARCH_WARN("[GLX]: Cannot find swap interval call.\n"); else RARCH_LOG("[GLX]: Found swap function: %s.\n", swap_func); } else RARCH_WARN("[GLX]: Context is not double buffered!.\n"); #endif break; case GFX_CTX_NONE: default: break; } gfx_ctx_x_swap_interval(data, x->g_interval); /* 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); vi = NULL; if (!x11_input_ctx_new(true_full)) goto error; return true; error: if (vi) XFree(vi); gfx_ctx_x_destroy_resources(x); if (x) free(x); g_x11_screen = 0; return false; }
Status XmuLookupStandardColormap(Display *dpy, int screen, VisualID visualid, unsigned int depth, Atom property, Bool replace, Bool retain) /* * dpy - specifies X server connection * screen - specifies screen of display * visualid - specifies the visual type * depth - specifies the visual type * property - a standard colormap property * replace - specifies whether to replace * retain - specifies whether to retain */ { Display *odpy; /* original display connection */ XStandardColormap *colormap; XVisualInfo vinfo_template, *vinfo; /* visual */ long vinfo_mask; unsigned long r_max, g_max, b_max; /* allocation */ int count; Colormap cmap; /* colormap ID */ Status status = 0; /* Match the requested visual */ vinfo_template.visualid = visualid; vinfo_template.screen = screen; vinfo_template.depth = depth; vinfo_mask = VisualIDMask | VisualScreenMask | VisualDepthMask; if ((vinfo = XGetVisualInfo(dpy, vinfo_mask, &vinfo_template, &count)) == NULL) return 0; /* Monochrome visuals have no standard maps */ if (vinfo->colormap_size <= 2) { XFree((char *) vinfo); return 0; } /* If the requested property already exists on this screen, and, * if the replace flag has not been set to true, return success. * lookup() will remove a pre-existing map if replace is true. */ if (lookup(dpy, screen, visualid, property, (XStandardColormap *) NULL, replace) && !replace) { XFree((char *) vinfo); return 1; } /* Determine the best allocation for this property under the requested * visualid and depth, and determine whether or not to use the default * colormap of the screen. */ if (!XmuGetColormapAllocation(vinfo, property, &r_max, &g_max, &b_max)) { XFree((char *) vinfo); return 0; } cmap = (property == XA_RGB_DEFAULT_MAP && visualid == XVisualIDFromVisual(DefaultVisual(dpy, screen))) ? DefaultColormap(dpy, screen) : None; /* If retaining resources, open a new connection to the same server */ if (retain) { odpy = dpy; if ((dpy = XOpenDisplay(XDisplayString(odpy))) == NULL) { XFree((char *) vinfo); return 0; } } /* Create the standard colormap */ colormap = XmuStandardColormap(dpy, screen, visualid, depth, property, cmap, r_max, g_max, b_max); /* Set the standard colormap property */ if (colormap) { XGrabServer(dpy); if (lookup(dpy, screen, visualid, property, colormap, replace) && !replace) { /* Someone has defined the property since we last looked. * Since we will not replace it, release our own resources. * If this is the default map, our allocations will be freed * when this connection closes. */ if (colormap->killid == ReleaseByFreeingColormap) XFreeColormap(dpy, colormap->colormap); } else if (retain) { XSetCloseDownMode(dpy, RetainPermanent); } XUngrabServer(dpy); XFree((char *) colormap); status = 1; } if (retain) XCloseDisplay(dpy); XFree((char *) vinfo); return status; }
VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config) { VisualID visualId = 0; EGLint eglValue = 0; EGLint configRedSize = 0; eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize); EGLint configGreenSize = 0; eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize); EGLint configBlueSize = 0; eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize); EGLint configAlphaSize = 0; eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize); eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue); int configId = eglValue; // See if EGL provided a valid VisualID: eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue); visualId = (VisualID)eglValue; if (visualId) { // EGL has suggested a visual id, so get the rest of the visual info for that id: XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); visualInfoTemplate.visualid = visualId; XVisualInfo *chosenVisualInfo; int matchingCount = 0; chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount); if (chosenVisualInfo) { // Skip size checks if implementation supports non-matching visual // and config (QTBUG-9444). if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) { XFree(chosenVisualInfo); return visualId; } int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask); int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask); int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask); int visualAlphaSize = chosenVisualInfo->depth == 32 ? 8 : 0; const bool visualMatchesConfig = visualRedSize == configRedSize && visualGreenSize == configGreenSize && visualBlueSize == configBlueSize && visualAlphaSize == configAlphaSize; // In some cases EGL tends to suggest a 24-bit visual for 8888 // configs. In such a case we have to fall back to XGetVisualInfo. if (!visualMatchesConfig) { visualId = 0; #ifdef QT_DEBUG_X11_VISUAL_SELECTION qWarning("Warning: EGL suggested using X Visual ID %d (%d %d %d depth %d) for EGL config %d (%d %d %d %d), but this is incompatible", (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, chosenVisualInfo->depth, configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize); #endif } } else { qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", (int)visualId, configId); visualId = 0; } XFree(chosenVisualInfo); } #ifdef QT_DEBUG_X11_VISUAL_SELECTION else qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); #endif if (visualId) { #ifdef QT_DEBUG_X11_VISUAL_SELECTION if (configAlphaSize > 0) qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId); else qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId); #endif return visualId; } // Finally, try to use XGetVisualInfo and only use the bit depths to match on: if (!visualId) { XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); XVisualInfo *matchingVisuals; int matchingCount = 0; visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize; matchingVisuals = XGetVisualInfo(display, VisualDepthMask, &visualInfoTemplate, &matchingCount); if (!matchingVisuals) { // Try again without taking the alpha channel into account: visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize; matchingVisuals = XGetVisualInfo(display, VisualDepthMask, &visualInfoTemplate, &matchingCount); } if (matchingVisuals) { visualId = matchingVisuals[0].visualid; XFree(matchingVisuals); } } if (visualId) { #ifdef QT_DEBUG_X11_VISUAL_SELECTION qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId); #endif return visualId; } qWarning("Unable to find an X11 visual which matches EGL config %d", configId); return (VisualID)0; }
QXcbWindow::QXcbWindow(QWidget *tlw) : QPlatformWindow(tlw) , m_context(0) { m_screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(tlw)); setConnection(m_screen->connection()); const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_BACK_PIXMAP XCB_NONE, // XCB_CW_EVENT_MASK XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE }; #if defined(XCB_USE_GLX) || defined(XCB_USE_EGL) if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL) || tlw->platformWindowFormat().alpha()) { #if defined(XCB_USE_GLX) XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen),m_screen->screenNumber(), tlw->platformWindowFormat()); #elif defined(XCB_USE_EGL) EGLDisplay eglDisplay = connection()->egl_display(); EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,tlw->platformWindowFormat(),true); VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig); XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); visualInfoTemplate.visualid = id; XVisualInfo *visualInfo; int matchingCount = 0; visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount); #endif //XCB_USE_GLX if (visualInfo) { m_depth = visualInfo->depth; m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone); XSetWindowAttributes a; a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber()); a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(this), m_screen->screenNumber()); a.colormap = cmap; m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(), 0, visualInfo->depth, InputOutput, visualInfo->visual, CWBackPixel|CWBorderPixel|CWColormap, &a); printf("created GL window: %d\n", m_window); } else { qFatal("no window!"); } } else #endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) { m_window = xcb_generate_id(xcb_connection()); m_depth = m_screen->screen()->root_depth; m_format = (m_depth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; Q_XCB_CALL(xcb_create_window(xcb_connection(), XCB_COPY_FROM_PARENT, // depth -- same as root m_window, // window id m_screen->root(), // parent window id tlw->x(), tlw->y(), tlw->width(), tlw->height(), 0, // border width XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class m_screen->screen()->root_visual, // visual 0, // value mask 0)); // value list printf("created regular window: %d\n", m_window); } Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); xcb_atom_t properties[4]; int propertyCount = 0; properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW); properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); if (m_screen->syncRequestSupported()) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::WM_PROTOCOLS), XCB_ATOM_ATOM, 32, propertyCount, properties)); m_syncValue.hi = 0; m_syncValue.lo = 0; if (m_screen->syncRequestSupported()) { m_syncCounter = xcb_generate_id(xcb_connection()); Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue)); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER), XCB_ATOM_CARDINAL, 32, 1, &m_syncCounter)); } if (isTransient(tlw) && tlw->parentWidget()) { // ICCCM 4.1.2.6 QWidget *p = tlw->parentWidget()->window(); xcb_window_t parentWindow = p->winId(); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, 1, &parentWindow)); } // set the PID to let the WM kill the application if unresponsive long pid = getpid(); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, 1, &pid)); }
bool QGLContext::chooseContext( const QGLContext* shareContext ) { Display* disp = paintDevice->x11Display(); vi = chooseVisual(); if ( !vi ) return FALSE; if ( deviceIsPixmap() && ((XVisualInfo*)vi)->depth != paintDevice->x11Depth() ) { XFree( vi ); XVisualInfo appVisInfo; memset( &appVisInfo, 0, sizeof(XVisualInfo) ); appVisInfo.visualid = XVisualIDFromVisual( (Visual*)paintDevice->x11Visual() ); int nvis; vi = XGetVisualInfo( disp, VisualIDMask, &appVisInfo, &nvis ); if ( !vi ) return FALSE; int useGL; glXGetConfig( disp, (XVisualInfo*)vi, GLX_USE_GL, &useGL ); if ( !useGL ) return FALSE; //# Chickening out already... } int res; glXGetConfig( disp, (XVisualInfo*)vi, GLX_LEVEL, &res ); glFormat.setPlane( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_DOUBLEBUFFER, &res ); glFormat.setDoubleBuffer( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_DEPTH_SIZE, &res ); glFormat.setDepth( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_RGBA, &res ); glFormat.setRgba( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_ALPHA_SIZE, &res ); glFormat.setAlpha( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_ACCUM_RED_SIZE, &res ); glFormat.setAccum( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_STENCIL_SIZE, &res ); glFormat.setStencil( res ); glXGetConfig( disp, (XVisualInfo*)vi, GLX_STEREO, &res ); glFormat.setStereo( res ); Bool direct = format().directRendering() ? True : False; if ( shareContext && ( !shareContext->isValid() || !shareContext->cx ) ) { #if defined(CHECK_NULL) qWarning("QGLContext::chooseContext(): Cannot share with invalid context"); #endif shareContext = 0; } // sharing between rgba and color-index will give wrong colors if ( shareContext && ( format().rgba() != shareContext->format().rgba() ) ) shareContext = 0; cx = 0; if ( shareContext ) { cx = glXCreateContext( disp, (XVisualInfo *)vi, (GLXContext)shareContext->cx, direct ); if ( cx ) sharing = TRUE; } if ( !cx ) cx = glXCreateContext( disp, (XVisualInfo *)vi, None, direct ); if ( !cx ) return FALSE; glFormat.setDirectRendering( glXIsDirect( disp, (GLXContext)cx ) ); if ( deviceIsPixmap() ) { #if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) gpm = glXCreateGLXPixmapMESA( disp, (XVisualInfo *)vi, paintDevice->handle(), choose_cmap( disp, (XVisualInfo *)vi ) ); #else gpm = (Q_UINT32)glXCreateGLXPixmap( disp, (XVisualInfo *)vi, paintDevice->handle() ); #endif if ( !gpm ) return FALSE; } return TRUE; }
void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { // Save the creation settings m_settings = settings; // Retrieve the attributes of the target window XWindowAttributes windowAttributes; if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) { err() << "Failed to get the window attributes" << std::endl; return; } // Get its visuals XVisualInfo tpl; tpl.screen = DefaultScreen(m_display); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // There are no GLX versions prior to 1.0 int major = 0; int minor = 0; if (!glXQueryVersion(m_display, &major, &minor)) err() << "Failed to query GLX version, limited to legacy context creation" << std::endl; // Make sure that extensions are initialized if this is not the shared context // The shared context is the context used to initialize the extensions if (shared) ensureExtensionsInit(m_display, DefaultScreen(m_display)); // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater) bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3)); // Check if we need to use glXCreateContextAttribsARB bool needCreateContextArb = false; if (m_settings.attributeFlags) needCreateContextArb = true; else if (m_settings.majorVersion >= 3) needCreateContextArb = true; // Create the OpenGL context -- first try using glXCreateContextAttribsARB if we need to if (hasCreateContextArb && needCreateContextArb) { // Get a GLXFBConfig that matches the the window's visual, for glXCreateContextAttribsARB GLXFBConfig* config = NULL; // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); for (int i = 0; configs && (i < nbConfigs); ++i) { XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); if (!visual) continue; if (visual->visualid == visualInfo->visualid) { config = &configs[i]; break; } } if (!config) err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl; while (config && !m_context && m_settings.majorVersion) { // Check if setting the profile is supported if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED) { int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0; // Create the context int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), GLX_CONTEXT_PROFILE_MASK_ARB, profile, GLX_CONTEXT_FLAGS_ARB, debug, 0, 0 }; // RAII GLX error handler (we simply ignore errors here) // On an error, glXCreateContextAttribsARB will return 0 anyway GlxErrorHandler handler(m_display); m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes); } else { if ((m_settings.attributeFlags & ContextSettings::Core) || (m_settings.attributeFlags & ContextSettings::Debug)) err() << "Selecting a profile during context creation is not supported," << "disabling comptibility and debug" << std::endl; m_settings.attributeFlags = ContextSettings::Default; // Create the context int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), 0, 0 }; // RAII GLX error handler (we simply ignore errors here) // On an error, glXCreateContextAttribsARB will return 0 anyway GlxErrorHandler handler(m_display); m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes); } if (!m_context) { // If we couldn't create the context, first try disabling flags, // then lower the version number and try again -- stop at 0.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (m_settings.attributeFlags != ContextSettings::Default) { m_settings.attributeFlags = ContextSettings::Default; } else if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; m_settings.attributeFlags = settings.attributeFlags; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; m_settings.attributeFlags = settings.attributeFlags; } } } if (configs) XFree(configs); } // If glXCreateContextAttribsARB failed, use glXCreateContext if (!m_context) { // set the context version to 2.1 (arbitrary) and disable flags m_settings.majorVersion = 2; m_settings.minorVersion = 1; m_settings.attributeFlags = ContextSettings::Default; #if defined(GLX_DEBUGGING) GlxErrorHandler handler(m_display); #endif // Create the context, using the target window's visual m_context = glXCreateContext(m_display, visualInfo, toShare, true); #if defined(GLX_DEBUGGING) if (glxErrorOccurred) err() << "GLX error in GlxContext::createContext()" << std::endl; #endif } if (!m_context) { err() << "Failed to create an OpenGL context for this window" << std::endl; } else { // Update the creation settings from the chosen format int depth, stencil, multiSampling, samples; glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth); glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil); if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED) { glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples); } else { multiSampling = 0; samples = 0; } m_settings.depthBits = static_cast<unsigned int>(depth); m_settings.stencilBits = static_cast<unsigned int>(stencil); m_settings.antialiasingLevel = multiSampling ? samples : 0; } // Free the visual info XFree(visualInfo); }
/* * Create an RGB, double-buffered X window. * Return the window and context handles. */ static void make_x_window(Display *x_dpy, EGLDisplay egl_dpy, const char *name, int x, int y, int width, int height, int es_ver, Window *winRet, EGLContext *ctxRet, EGLSurface *surfRet) { EGLint attribs[] = { EGL_RENDERABLE_TYPE, 0x0, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_NONE }; EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 0, EGL_NONE }; int scrnum; XSetWindowAttributes attr; unsigned long mask; Window root; Window win; XVisualInfo *visInfo, visTemplate; int num_visuals; EGLContext ctx; EGLConfig config; EGLint num_configs; EGLint vid; scrnum = DefaultScreen( x_dpy ); root = RootWindow( x_dpy, scrnum ); if (es_ver == 1) attribs[1] = EGL_OPENGL_ES_BIT; else attribs[1] = EGL_OPENGL_ES2_BIT; ctx_attribs[1] = es_ver; if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) { printf("Error: couldn't get an EGL visual config\n"); exit(1); } assert(config); assert(num_configs > 0); if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { printf("Error: eglGetConfigAttrib() failed\n"); exit(1); } /* The X window visual must match the EGL config */ visTemplate.visualid = vid; visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); if (!visInfo) { printf("Error: couldn't get X visual\n"); exit(1); } /* window attributes */ attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow( x_dpy, root, 0, 0, width, height, 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr ); /* set hints and properties */ { XSizeHints sizehints; sizehints.x = x; sizehints.y = y; sizehints.width = width; sizehints.height = height; sizehints.flags = USSize | USPosition; XSetNormalHints(x_dpy, win, &sizehints); XSetStandardProperties(x_dpy, win, name, name, None, (char **)NULL, 0, &sizehints); } eglBindAPI(EGL_OPENGL_ES_API); ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs ); if (!ctx) { printf("Error: eglCreateContext failed\n"); exit(1); } *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL); if (!*surfRet) { printf("Error: eglCreateWindowSurface failed\n"); exit(1); } XFree(visInfo); *winRet = win; *ctxRet = ctx; }
break; sleep(1); } if (server.num_desktops == 0) { server.num_desktops = 1; fprintf(stderr, "warning : WM doesn't respect NETWM specs. tint2 default to 1 desktop.\n"); } } void server_init_visual() { // inspired by freedesktops fdclock ;) XVisualInfo templ = {.screen = server.screen, .depth = 32, .class = TrueColor}; int nvi; XVisualInfo *xvi = XGetVisualInfo(server.display, VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nvi); Visual *visual = NULL; if (xvi) { XRenderPictFormat *format; for (int i = 0; i < nvi; i++) { format = XRenderFindVisualFormat(server.display, xvi[i].visual); if (format->type == PictTypeDirect && format->direct.alphaMask) { visual = xvi[i].visual; break; } } } XFree(xvi); // check composite manager
Visual *XAbstractGui::GetBestVisual(Display *dpy, int *vClass, int *depth) { int default_depth; XVisualInfo vTemplate; XVisualInfo *visualList = nullptr; Visual *visual = nullptr; int nrOfVisuals; vTemplate.screen = DefaultScreen(dpy); default_depth = DefaultDepth(dpy, vTemplate.screen); switch (default_depth) { case 8: *vClass = vTemplate.c_class = PseudoColor; visualList = XGetVisualInfo(dpy, VisualScreenMask | VisualClassMask, &vTemplate, &nrOfVisuals); if (nrOfVisuals > 0) { *depth = visualList[0].depth; visual = visualList[0].visual; } else { *vClass = vTemplate.c_class = TrueColor; visualList = XGetVisualInfo(dpy, VisualScreenMask | VisualClassMask, &vTemplate, &nrOfVisuals); if (nrOfVisuals > 0) { *depth = visualList[0].depth; visual = visualList[0].visual; } else { *vClass = vTemplate.c_class = GrayScale; visualList = XGetVisualInfo(dpy, VisualScreenMask | VisualClassMask, &vTemplate, &nrOfVisuals); if (nrOfVisuals > 0) { *depth = visualList[0].depth; visual = visualList[0].visual; } } } break; case 16: case 24: case 32: *vClass = vTemplate.c_class = TrueColor; visualList = XGetVisualInfo(dpy, VisualScreenMask | VisualClassMask, &vTemplate, &nrOfVisuals); if (nrOfVisuals > 0) { *depth = visualList[0].depth; visual = visualList[0].visual; } break; } XFree(visualList); return visual; }
WindowEGL::WindowEGL(const Window::Properties & properties) : WindowX11(properties), eglData(new WindowEGLData) { eglData->shareContext = properties.shareContext; eglData->display = eglGetDisplay(x11Data->display); if (eglData->display == EGL_NO_DISPLAY) { throw std::runtime_error("Failed to open display."); } EGLint versionMajor; EGLint versionMinor; if (eglInitialize(eglData->display, &versionMajor, &versionMinor) == EGL_FALSE) { throw std::runtime_error("Failed to initialize display."); } // EGL version 1.3 is needed for EGL_CONTEXT_CLIENT_VERSION if ((versionMajor < 1) || ((versionMajor == 1) && (versionMinor < 3))) { throw std::runtime_error("EGL version less than 1.3 detected."); } EGLenum api; EGLint glesVersion = 0; switch(properties.renderingAPI) { case Properties::RenderingAPI::GL_ES_1: api = EGL_OPENGL_ES_API; glesVersion = 1; break; case Properties::RenderingAPI::GL_ES_2: api = EGL_OPENGL_ES_API; glesVersion = 2; break; case Properties::RenderingAPI::GL_ES_3: api = EGL_OPENGL_ES_API; glesVersion = 3; break; case Properties::RenderingAPI::GL: api = EGL_OPENGL_API; break; default: throw std::runtime_error("Unsupported rendering API."); } if (EGL_TRUE != eglBindAPI(api)) { throw std::runtime_error("Cannot bind API."); } // Define attributes of desired framebuffer configurations EGLint fbAttribs[] = { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_BUFFER_SIZE, 24, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 8, EGL_NATIVE_RENDERABLE, EGL_TRUE, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; // Request a single framebuffer configuration EGLConfig fbConfig; EGLint fbCount; if (eglChooseConfig(eglData->display, fbAttribs, &fbConfig, 1, &fbCount) == EGL_FALSE) { throw std::runtime_error("Failed to retrieve a matching framebuffer configuration."); } if (fbCount == 0) { // FIXME: Workaround: Use eglGetConfigs instead of eglChooseConfig, because sometimes eglChooseConfig does not find matching configurations. EGLConfig fbConfigs[200]; eglGetConfigs(eglData->display, fbConfigs, 200, &fbCount); for (EGLint i = 0; i < fbCount; ++i) { EGLint value; // We want to render into a window eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_SURFACE_TYPE, &value); if (!(value & EGL_WINDOW_BIT)) { continue; } // We want a configuration with a depth buffer eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_DEPTH_SIZE, &value); if (value == 0) { continue; } fbConfig = fbConfigs[i]; } } if (fbCount == 0) { throw std::runtime_error("No matching framebuffer configurations found."); } EGLint visualID; eglGetConfigAttrib(eglData->display, fbConfig, EGL_NATIVE_VISUAL_ID, &visualID); EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, glesVersion, EGL_NONE }; if (0 == glesVersion) { contextAttribs[0] = EGL_NONE; contextAttribs[1] = EGL_NONE; } // Check for existing GL context if(properties.shareContext) { eglData->context = eglGetCurrentContext(); } if (eglData->context == EGL_NO_CONTEXT) { eglData->context = eglCreateContext(eglData->display, fbConfig, EGL_NO_CONTEXT, contextAttribs); } if (eglData->context == EGL_NO_CONTEXT) { throw std::runtime_error("Failed to create context: " + eglErrorToString(eglGetError())); } // Create X11 window XVisualInfo templateInfo; templateInfo.visualid = visualID; int visualCount; XVisualInfo * visualsInfo = XGetVisualInfo(x11Data->display, VisualIDMask, &templateInfo, &visualCount); if (visualsInfo == nullptr) { throw std::runtime_error("Failed to find a matching visual."); } else if (visualCount != 1) { XFree(visualsInfo); throw std::runtime_error("More than one visual found."); } x11Data->colorMap = XCreateColormap(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen), visualsInfo[0].visual, AllocNone); x11Data->freeColorMap = true; XSetWindowAttributes windowAttribs; windowAttribs.colormap = x11Data->colorMap; windowAttribs.background_pixmap = None; windowAttribs.border_pixel = 0; windowAttribs.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; x11Data->window = XCreateWindow(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen), 0, 0, properties.clientAreaWidth, properties.clientAreaHeight, 0, visualsInfo[0].depth, InputOutput, visualsInfo[0].visual, CWBorderPixel | CWColormap | CWEventMask, &windowAttribs); XFree(visualsInfo); if (!x11Data->window) { throw std::runtime_error("Failed to create window."); } else { x11Data->freeWindow = true; } if (properties.borderless) { x11Data->removeWindowBorder(); } if (!properties.resizable) { x11Data->fixWindowSize(static_cast<int>(properties.clientAreaWidth), static_cast<int>(properties.clientAreaHeight)); } x11Data->inputMethod = XOpenIM(x11Data->display, nullptr, nullptr, nullptr); if (x11Data->inputMethod == nullptr) { throw std::runtime_error("Failed to create input method."); } x11Data->inputContext = XCreateIC(x11Data->inputMethod, XNInputStyle, XIMPreeditNone | XIMStatusNone, XNClientWindow, x11Data->window, XNFocusWindow, x11Data->window, nullptr); if (x11Data->inputContext == nullptr) { throw std::runtime_error("Failed to create input context."); } XStoreName(x11Data->display, x11Data->window, properties.title.c_str()); XMapWindow(x11Data->display, x11Data->window); if (properties.positioned) { XMoveWindow(x11Data->display, x11Data->window, properties.posX, properties.posY); } eglData->surface = eglCreateWindowSurface(eglData->display, fbConfig, x11Data->window, nullptr); if (eglData->surface == EGL_NO_SURFACE) { throw std::runtime_error("Failed to create window surface."); } eglMakeCurrent(eglData->display, eglData->surface, eglData->surface, eglData->context); }
static EGLBoolean egl_manager_create_window(struct egl_manager *eman, const char *name, EGLint w, EGLint h, EGLBoolean need_surface, EGLBoolean fullscreen, const EGLint *attrib_list) { XVisualInfo vinfo_template, *vinfo = NULL; EGLint val, num_vinfo; Window root; XSetWindowAttributes attrs; unsigned long mask; EGLint x = 0, y = 0; if (!eglGetConfigAttrib(eman->dpy, eman->conf, EGL_NATIVE_VISUAL_ID, &val)) { printf("eglGetConfigAttrib() failed\n"); return EGL_FALSE; } if (val) { vinfo_template.visualid = (VisualID) val; vinfo = XGetVisualInfo(eman->xdpy, VisualIDMask, &vinfo_template, &num_vinfo); } /* try harder if window surface is not needed */ if (!vinfo && !need_surface && eglGetConfigAttrib(eman->dpy, eman->conf, EGL_BUFFER_SIZE, &val)) { if (val == 32) val = 24; vinfo_template.depth = val; vinfo = XGetVisualInfo(eman->xdpy, VisualDepthMask, &vinfo_template, &num_vinfo); } if (!vinfo) { printf("XGetVisualInfo() failed\n"); return EGL_FALSE; } root = DefaultRootWindow(eman->xdpy); if (fullscreen) { x = y = 0; w = DisplayWidth(eman->xdpy, DefaultScreen(eman->xdpy)); h = DisplayHeight(eman->xdpy, DefaultScreen(eman->xdpy)); } /* window attributes */ attrs.background_pixel = 0; attrs.border_pixel = 0; attrs.colormap = XCreateColormap(eman->xdpy, root, vinfo->visual, AllocNone); attrs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; attrs.override_redirect = fullscreen; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; eman->xwin = XCreateWindow(eman->xdpy, root, x, y, w, h, 0, vinfo->depth, InputOutput, vinfo->visual, mask, &attrs); XFree(vinfo); /* set hints and properties */ { XSizeHints sizehints; sizehints.x = x; sizehints.y = y; sizehints.width = w; sizehints.height = h; sizehints.flags = USSize | USPosition; XSetNormalHints(eman->xdpy, eman->xwin, &sizehints); XSetStandardProperties(eman->xdpy, eman->xwin, name, name, None, (char **)NULL, 0, &sizehints); } if (need_surface) { eman->win = eglCreateWindowSurface(eman->dpy, eman->conf, eman->xwin, attrib_list); if (eman->win == EGL_NO_SURFACE) { printf("eglCreateWindowSurface() failed\n"); XDestroyWindow(eman->xdpy, eman->xwin); eman->xwin = None; return EGL_FALSE; } } eman->gc = XCreateGC(eman->xdpy, eman->xwin, 0, NULL); XMapWindow(eman->xdpy, eman->xwin); return EGL_TRUE; }
bool NativeStateX11::create_window(WindowProperties const& properties) { static const char *win_name("glmark2 "GLMARK_VERSION); if (!xdpy_) { Log::error("Error: X11 Display has not been initialized!\n"); return false; } /* Recreate an existing window only if it has actually been resized */ if (xwin_) { if (properties_.fullscreen != properties.fullscreen || (properties.fullscreen == false && (properties_.width != properties.width || properties_.height != properties.height))) { XDestroyWindow(xdpy_, xwin_); xwin_ = 0; } else { return true; } } /* Set desired attributes */ properties_.fullscreen = properties.fullscreen; properties_.visual_id = properties.visual_id; if (properties_.fullscreen) { /* Get the screen (root window) size */ XWindowAttributes window_attr; XGetWindowAttributes(xdpy_, RootWindow(xdpy_, DefaultScreen(xdpy_)), &window_attr); properties_.width = window_attr.width; properties_.height = window_attr.height; } else { properties_.width = properties.width; properties_.height = properties.height; } XVisualInfo vis_tmpl; XVisualInfo *vis_info = 0; int num_visuals; /* The X window visual must match the supplied visual id */ vis_tmpl.visualid = properties_.visual_id; vis_info = XGetVisualInfo(xdpy_, VisualIDMask, &vis_tmpl, &num_visuals); if (!vis_info) { Log::error("Error: Could not get a valid XVisualInfo!\n"); return false; } Log::debug("Creating XWindow W: %d H: %d VisualID: 0x%x\n", properties_.width, properties_.height, vis_info->visualid); /* window attributes */ XSetWindowAttributes attr; unsigned long mask; Window root = RootWindow(xdpy_, DefaultScreen(xdpy_)); attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(xdpy_, root, vis_info->visual, AllocNone); attr.event_mask = KeyPressMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; xwin_ = XCreateWindow(xdpy_, root, 0, 0, properties_.width, properties_.height, 0, vis_info->depth, InputOutput, vis_info->visual, mask, &attr); XFree(vis_info); if (!xwin_) { Log::error("Error: XCreateWindow() failed!\n"); return false; } /* set hints and properties */ Atom fs_atom = None; if (properties_.fullscreen) { fs_atom = XInternAtom(xdpy_, "_NET_WM_STATE_FULLSCREEN", True); if (fs_atom == None) Log::debug("Warning: Could not set EWMH Fullscreen hint.\n"); } if (fs_atom != None) { XChangeProperty(xdpy_, xwin_, XInternAtom(xdpy_, "_NET_WM_STATE", True), XA_ATOM, 32, PropModeReplace, reinterpret_cast<unsigned char*>(&fs_atom), 1); } else { XSizeHints sizehints; sizehints.min_width = properties_.width; sizehints.min_height = properties_.height; sizehints.max_width = properties_.width; sizehints.max_height = properties_.height; sizehints.flags = PMaxSize | PMinSize; XSetWMProperties(xdpy_, xwin_, NULL, NULL, NULL, 0, &sizehints, NULL, NULL); } /* Set the window name */ XStoreName(xdpy_ , xwin_, win_name); /* Gracefully handle Window Delete event from window manager */ Atom wmDelete = XInternAtom(xdpy_, "WM_DELETE_WINDOW", True); XSetWMProtocols(xdpy_, xwin_, &wmDelete, 1); return true; }
void initSpace(Window window) { Display *display = dsp; XWindowAttributes xwa; (void) XGetWindowAttributes(dsp, window, &xwa); int n; XVisualInfo *wantVis, vTemplate; int VisualClassWanted=-1; vTemplate.screen = screen; vTemplate.depth = xwa.depth; if (VisualClassWanted == -1) { vTemplate.c_class = DefaultVisual(display, screen)->c_class; } else { vTemplate.c_class = VisualClassWanted; } wantVis = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask | VisualClassMask, &vTemplate, &n); if (VisualClassWanted != -1 && n == 0) { /* Wanted visual not found so use default */ vTemplate.c_class = DefaultVisual(display, screen)->c_class; wantVis = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask | VisualClassMask, &vTemplate, &n); } /* if User asked for color, try that first, then try mono */ /* if User asked for mono. Might fail on 16/24 bit displays, so fall back on color, but keep the mono "look & feel". */ if (!getVisual(wantVis, n)) { if (!getVisual(wantVis, n)) { kdError() << i18n("GL can not render with root visual\n") << endl; return; } } /* PURIFY 3.0a on SunOS4 reports a 104 byte memory leak on the next line each * time that morph3d mode is run in random mode. */ glx_context = glXCreateContext(display, wantVis, 0, True); XFree((char *) wantVis); glXMakeCurrent(display, window, glx_context); glDrawBuffer(GL_FRONT); if (mono) { glIndexi(WhitePixel(display, screen)); glClearIndex(BlackPixel(display, screen)); } retqshape(xwa.width, xwa.height); Init(); }
QT_BEGIN_NAMESPACE QXlibWindow::QXlibWindow(QWidget *window) : QPlatformWindow(window) , mGLContext(0) , mScreen(QXlibScreen::testLiteScreenForWidget(window)) { int x = window->x(); int y = window->y(); int w = window->width(); int h = window->height(); #if !defined(QT_NO_OPENGL) if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL && QApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL) || window->platformWindowFormat().alpha()) { #if !defined(QT_OPENGL_ES_2) XVisualInfo *visualInfo = qglx_findVisualInfo(mScreen->display()->nativeDisplay(),mScreen->xScreenNumber(),window->platformWindowFormat()); #else QPlatformWindowFormat windowFormat = correctColorBuffers(window->platformWindowFormat()); EGLDisplay eglDisplay = mScreen->eglDisplay(); EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,windowFormat); VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(), eglDisplay, eglConfig); XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); visualInfoTemplate.visualid = id; XVisualInfo *visualInfo; int matchingCount = 0; visualInfo = XGetVisualInfo(mScreen->display()->nativeDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount); #endif //!defined(QT_OPENGL_ES_2) if (visualInfo) { mDepth = visualInfo->depth; mFormat = (mDepth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; mVisual = visualInfo->visual; Colormap cmap = XCreateColormap(mScreen->display()->nativeDisplay(), mScreen->rootWindow(), visualInfo->visual, AllocNone); XSetWindowAttributes a; a.background_pixel = WhitePixel(mScreen->display()->nativeDisplay(), mScreen->xScreenNumber()); a.border_pixel = BlackPixel(mScreen->display()->nativeDisplay(), mScreen->xScreenNumber()); a.colormap = cmap; x_window = XCreateWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(),x, y, w, h, 0, visualInfo->depth, InputOutput, visualInfo->visual, CWBackPixel|CWBorderPixel|CWColormap, &a); } else { qFatal("no window!"); } } else #endif //!defined(QT_NO_OPENGL) { mDepth = mScreen->depth(); mFormat = (mDepth == 32) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; mVisual = mScreen->defaultVisual(); x_window = XCreateSimpleWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(), x, y, w, h, 0 /*border_width*/, mScreen->blackPixel(), mScreen->whitePixel()); } #ifdef MYX11_DEBUG qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window; #endif XSetWindowBackgroundPixmap(mScreen->display()->nativeDisplay(), x_window, XNone); XSelectInput(mScreen->display()->nativeDisplay(), x_window, ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PropertyChangeMask | StructureNotifyMask); gc = createGC(); Atom protocols[5]; int n = 0; protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_DELETE_WINDOW); // support del window protocol protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_TAKE_FOCUS); // support take focus window protocol // protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING); // support _NET_WM_PING protocol #ifndef QT_NO_XSYNC protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol #endif // QT_NO_XSYNC if (window->windowFlags() & Qt::WindowContextHelpButtonHint) protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_CONTEXT_HELP); XSetWMProtocols(mScreen->display()->nativeDisplay(), x_window, protocols, n); }
VisualID QEgl::getCompatibleVisualId(EGLConfig config) { VisualID visualId = 0; EGLint eglValue = 0; EGLint configRedSize = 0; eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &configRedSize); EGLint configGreenSize = 0; eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &configGreenSize); EGLint configBlueSize = 0; eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &configBlueSize); EGLint configAlphaSize = 0; eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &configAlphaSize); eglGetConfigAttrib(display(), config, EGL_CONFIG_ID, &eglValue); int configId = eglValue; // See if EGL provided a valid VisualID: eglGetConfigAttrib(display(), config, EGL_NATIVE_VISUAL_ID, &eglValue); visualId = (VisualID)eglValue; if (visualId) { // EGL has suggested a visual id, so get the rest of the visual info for that id: XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); visualInfoTemplate.visualid = visualId; XVisualInfo *chosenVisualInfo; int matchingCount = 0; chosenVisualInfo = XGetVisualInfo(X11->display, VisualIDMask, &visualInfoTemplate, &matchingCount); if (chosenVisualInfo) { // Skip size checks if implementation supports non-matching visual // and config (http://bugreports.qt-project.org/browse/QTBUG-9444). if (QEgl::hasExtension("EGL_NV_post_convert_rounding")) { XFree(chosenVisualInfo); return visualId; } int visualRedSize = countBits(chosenVisualInfo->red_mask); int visualGreenSize = countBits(chosenVisualInfo->green_mask); int visualBlueSize = countBits(chosenVisualInfo->blue_mask); int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size #if !defined(QT_NO_XRENDER) if (X11->use_xrender) { // If we have XRender, actually check the visual supplied by EGL is ARGB XRenderPictFormat *format; format = XRenderFindVisualFormat(X11->display, chosenVisualInfo->visual); if (format && (format->type == PictTypeDirect)) visualAlphaSize = countBits(format->direct.alphaMask); } #endif bool visualMatchesConfig = false; if ( visualRedSize == configRedSize && visualGreenSize == configGreenSize && visualBlueSize == configBlueSize ) { // We need XRender to check the alpha channel size of the visual. If we don't have // the alpha size, we don't check it against the EGL config's alpha size. if (visualAlphaSize >= 0) visualMatchesConfig = visualAlphaSize == configAlphaSize; else visualMatchesConfig = true; } if (!visualMatchesConfig) { if (visualAlphaSize >= 0) { qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable", (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize, configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize); } else { qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable", (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, configId, configRedSize, configGreenSize, configBlueSize); } visualId = 0; } } else { qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", (int)visualId, configId); visualId = 0; } XFree(chosenVisualInfo); } #ifdef QT_DEBUG_X11_VISUAL_SELECTION else qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); #endif if (visualId) { #ifdef QT_DEBUG_X11_VISUAL_SELECTION if (configAlphaSize > 0) qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId); else qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId); #endif return visualId; } // If EGL didn't give us a valid visual ID, try XRender #if !defined(QT_NO_XRENDER) if (!visualId && X11->use_xrender) { XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); visualInfoTemplate.c_class = TrueColor; XVisualInfo *matchingVisuals; int matchingCount = 0; matchingVisuals = XGetVisualInfo(X11->display, VisualClassMask, &visualInfoTemplate, &matchingCount); for (int i = 0; i < matchingCount; ++i) { XRenderPictFormat *format; format = XRenderFindVisualFormat(X11->display, matchingVisuals[i].visual); // Check the format for the visual matches the EGL config if ( (countBits(format->direct.redMask) == configRedSize) && (countBits(format->direct.greenMask) == configGreenSize) && (countBits(format->direct.blueMask) == configBlueSize) && (countBits(format->direct.alphaMask) == configAlphaSize) ) { visualId = matchingVisuals[i].visualid; break; } } if (matchingVisuals) XFree(matchingVisuals); } if (visualId) { # ifdef QT_DEBUG_X11_VISUAL_SELECTION if (configAlphaSize > 0) qDebug("Using ARGB Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId); else qDebug("Using Opaque Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId); # endif // QT_DEBUG_X11_VISUAL_SELECTION return visualId; } # ifdef QT_DEBUG_X11_VISUAL_SELECTION else qDebug("Failed to find an XVisual which matches EGL config %d using XRender", configId); # endif // QT_DEBUG_X11_VISUAL_SELECTION #endif //!defined(QT_NO_XRENDER) // Finally, if XRender also failed to find a visual (or isn't present), try to // use XGetVisualInfo and only use the bit depths to match on: if (!visualId) { XVisualInfo visualInfoTemplate; memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); XVisualInfo *matchingVisuals; int matchingCount = 0; visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize; matchingVisuals = XGetVisualInfo(X11->display, VisualDepthMask, &visualInfoTemplate, &matchingCount); if (!matchingVisuals) { // Try again without taking the alpha channel into account: visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize; matchingVisuals = XGetVisualInfo(X11->display, VisualDepthMask, &visualInfoTemplate, &matchingCount); } if (matchingVisuals) { visualId = matchingVisuals[0].visualid; XFree(matchingVisuals); } } if (visualId) { #ifdef QT_DEBUG_X11_VISUAL_SELECTION qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId); #endif return visualId; } qWarning("Unable to find an X11 visual which matches EGL config %d", configId); return (VisualID)0; }
ibool MGLAPI XWINDC_initDriver(void *data,MGLDC *dc,int driverId,int modeId,ulong hwnd, int virtualX,int virtualY,int numBuffers,ibool stereo,int refreshRate) /**************************************************************************** * * Function: XWINDC_initDriver * Parameters: dc - Device context. * Returns: True if the device was correctly initialised. * * Description: Initialises the device driver, and starts the specified * graphics mode. This is also where we fill in all of the * vectors in the device context to initialise our device * context properly. * ****************************************************************************/ { Screen *scr; XSetWindowAttributes xswa; Display *dpy = dc->wm.xwindc.dpy; XVisualInfo *visinfo, vis; int nvis, npfv; Window root; int x,y; unsigned int w,h, bw, d; XPixmapFormatValues *pfv; _MGL_initInternal(); dc->deviceType = MGL_WINDOWED_DEVICE; dc->xInch = dc->yInch = 0; g_state.d.hardwareCursor = false; dc->v = &g_state; dc->v->m.refCount++; dc->wm.xwindc.scr = scr = DefaultScreenOfDisplay(dpy); dc->wm.xwindc.gc = DefaultGCOfScreen(scr); xswa.background_pixel = BlackPixel(dpy,XScreenNumberOfScreen(scr)); xswa.backing_store = Always; dc->wm.xwindc.wnd = hwnd; XGetGeometry(dpy, hwnd, &root, &x, &y, &w, &h, &bw, &d); dc->mi.xRes = w; dc->mi.yRes = h; dc->mi.maxPage = 0; dc->mi.bytesPerLine = 0; dc->mi.pageSize = 0; dc->surface = NULL; dc->mi.bitsPerPixel = dc->wm.xwindc.depth = d; vis.visualid = XVisualIDFromVisual(DefaultVisual(dpy, XScreenNumberOfScreen(scr))); visinfo = XGetVisualInfo(dpy, VisualIDMask, &vis, &nvis); pfv = XListPixmapFormats(dpy, &npfv); switch (d) { case 8: dc->mi.maxColor = 0xFFUL; break; case 15: dc->mi.maxColor = 0x7FFFUL; dc->pf= _MGL_pixelFormats[pfRGB555]; break; case 16: dc->mi.maxColor = 0xFFFFUL; dc->pf= _MGL_pixelFormats[visinfo->green_mask==0x7e0 ? pfRGB565 : pfRGB555]; break; case 24: { int i; dc->mi.maxColor = 0xFFFFFFUL; for(i=0; i<npfv; i++) if(pfv[i].depth == 24) break; if(pfv[i].bits_per_pixel==32){ dc->mi.bitsPerPixel = 32; dc->pf= _MGL_pixelFormats[pfARGB32]; }else dc->pf= _MGL_pixelFormats[pfRGB24]; break; } case 32: dc->mi.maxColor = 0xFFFFFFFFUL; dc->pf= _MGL_pixelFormats[pfARGB32]; break; } XFree(visinfo); if(d == 8){ // Set up the private colormap if necesary dc->wm.xwindc.hpal = xswa.colormap = XCreateColormap(dpy, hwnd, DefaultVisualOfScreen(scr), AllocAll); XChangeWindowAttributes(dpy, hwnd, CWColormap, &xswa); } XMapRaised(dpy, hwnd); XClearWindow(dpy, hwnd); XWIN_initInternal(dc); dc->v->w.destroy = destroyDC; dc->r.realizePalette = XWIN_realizePalette; dc->r.getDefaultPalette = XWIN_getDefaultPalette; dc->r.putImage = XWIN_putImage; return true; }
// NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't // match the one for the passed in EGLConfig EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *properties) { int devType = device->devType(); if (devType == QInternal::Pbuffer) { // TODO return EGL_NO_SURFACE; } QX11PixmapData *x11PixmapData = 0; if (devType == QInternal::Pixmap) { QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data(); if (pmd->classId() == QPixmapData::X11Class) x11PixmapData = static_cast<QX11PixmapData*>(pmd); else { // TODO: Replace the pixmap's data with a new QX11PixmapData qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PixmapData"); return EGL_NO_SURFACE; } } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) { qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType); return EGL_NO_SURFACE; } VisualID visualId = QEgl::getCompatibleVisualId(config); EGLint alphaSize; eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize); if (devType == QInternal::Widget) { QWidget *widget = static_cast<QWidget*>(device); VisualID currentVisualId = 0; if (widget->testAttribute(Qt::WA_WState_Created)) currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual()); if (currentVisualId != visualId) { // The window is either not created or has the wrong visual. Either way, we need // to create a window with the correct visual and call create() on the widget: bool visible = widget->isVisible(); if (visible) widget->hide(); XVisualInfo visualInfo; visualInfo.visualid = visualId; { XVisualInfo *visualInfoPtr; int matchingCount = 0; visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask, &visualInfo, &matchingCount); Q_ASSERT(visualInfoPtr); // visualId really should be valid! visualInfo = *visualInfoPtr; XFree(visualInfoPtr); } Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen()); if (widget->parentWidget()) parentWindow = widget->parentWidget()->winId(); XSetWindowAttributes windowAttribs; QColormap colmap = QColormap::instance(widget->x11Info().screen()); windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole())); windowAttribs.border_pixel = colmap.pixel(Qt::black); unsigned int valueMask = CWBackPixel|CWBorderPixel; if (alphaSize > 0) { windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow, visualInfo.visual, AllocNone); valueMask |= CWColormap; } Window window = XCreateWindow(widget->x11Info().display(), parentWindow, widget->x(), widget->y(), widget->width(), widget->height(), 0, visualInfo.depth, InputOutput, visualInfo.visual, valueMask, &windowAttribs); // This is a nasty hack to get round the fact that we can't be a friend of QWidget: qt_set_winid_on_widget(widget, window); if (visible) widget->show(); } // At this point, the widget's window should be created and have the correct visual. Now we // just need to create the EGL surface for it: const int *props; if (properties) props = properties->properties(); else props = 0; EGLSurface surf = eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), props); if (surf == EGL_NO_SURFACE) qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); return surf; } if (x11PixmapData) { // X11 Pixmaps are only created with a depth, so that's all we need to check EGLint configDepth; eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth); if (x11PixmapData->depth() != configDepth) { // The bit depths are wrong which means the EGLConfig isn't compatable with // this pixmap. So we need to replace the pixmap's existing data with a new // one which is created with the correct depth: #ifndef QT_NO_XRENDER if (configDepth == 32) { qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32", x11PixmapData->depth()); x11PixmapData->convertToARGB32(true); } else #endif { qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)", configDepth, x11PixmapData->depth()); } } QEglProperties surfaceAttribs; // If the pixmap can't be bound to a texture, it's pretty useless surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D); if (alphaSize > 0) surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA); else surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB); EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config, (EGLNativePixmapType) x11PixmapData->handle(), surfaceAttribs.properties()); x11PixmapData->gl_surface = (void*)surf; QImagePixmapCleanupHooks::enableCleanupHooks(x11PixmapData); return surf; } return EGL_NO_SURFACE; }
int main (void) { int i; int allocateOK; ximg = NULL; d = XOpenDisplay (NULL); if (!d) fputs ("Couldn't open display\n", stderr), exit (1); screen = DefaultScreen (d); gc = DefaultGC (d, screen); /* Find a visual */ vis.screen = screen; vlist = XGetVisualInfo (d, VisualScreenMask, &vis, &match); if (!vlist) fputs ("No matched visuals\n", stderr), exit (1); vis = vlist[0]; XFree (vlist); // That's not a fair comparison colormap_size is depth in bits! // if (vis.colormap_size < COLORS) // printf("Colormap is too small: %i.\n",vis.colormap_size); // , exit (1); printf("Colour depth: %i\n",vis.colormap_size); win = XCreateSimpleWindow (d, DefaultRootWindow (d), 0, 0, WIN_W, WIN_H, 0, WhitePixel (d, screen), BlackPixel (d, screen)); int xclass=get_xvisinfo_class(vis); // printf("class = %i\n",xclass); stylee = ( vis.depth > 8 ? styleeTrueColor : styleePrivate ); // printf("stylee=%i\n",stylee); if ( get_xvisinfo_class(vis) % 2 == 1) { /* The odd numbers can redefine colors */ // printf("%i\n",get_xvisinfo_class(vis)); colormap = DefaultColormap (d, screen); Visual *defaultVisual=DefaultVisual(d,screen); /* Allocate cells */ allocateOK = (XAllocColorCells (d, colormap, 1, NULL, 0, color, COLORS) != 0); // printf("Allocated OK? %i\n",allocateOK); if (allocateOK) { // printf("Allocated OK\n"); // This doesn't work for installed colormap! /* Modify the colorcells */ for (i = 0; i < COLORS; i++) xrgb[i].pixel = color[i]; XStoreColors (d, colormap, xrgb, COLORS); } else { colormap = XCreateColormap(d,win,defaultVisual,AllocNone); // redocolors(); } // black = XBlackPixel(d,screen); // white = XWhitePixel(d,screen); } else if ( get_xvisinfo_class(vis) == TrueColor) { colormap = DefaultColormap (d, screen); // printf("TrueColor %i = %i\n",xclass,TrueColor); /* This will lookup the color and sets the xrgb[i].pixel value */ // for (i = 0; i < COLORS; i++) // XAllocColor (d, colormap, &xrgb[i]); } else fprintf (stderr, "Not content with visual class %d.\n", get_xvisinfo_class(vis) ), exit (1); /* Find out if MITSHM is supported and useable */ printf ("MITSHM: "); if (XShmQueryVersion (d, &mitshm_major_code, &mitshm_minor_code, &shared_pixmaps)) { int (*handler) (Display *, XErrorEvent *); ximg = XShmCreateImage (d, vis.visual, vis.depth, XShmPixmapFormat (d), NULL, &shminfo, WIN_W, WIN_H); shminfo.shmid = shmget (IPC_PRIVATE, ximg->bytes_per_line * ximg->height, IPC_CREAT | 0777); shminfo.shmaddr = (char *)shmat (shminfo.shmid, 0, 0); ximg->data = (char *)shminfo.shmaddr; handler = XSetErrorHandler (mitshm_handler); XShmAttach (d, &shminfo); /* Tell the server to attach */ XSync (d, 0); XSetErrorHandler (handler); shmctl (shminfo.shmid, IPC_RMID, 0); /* Mark this shm segment for deletion at once. The segment will * automatically become released when both the server and this * client have detached from it. * (Process termination automagically detach shm segments) */ if (!can_use_mitshm) { shmdt (shminfo.shmaddr); ximg = NULL; } } if (ximg == NULL) { can_use_mitshm = 0; /* XInitImage(ximg); */ ximg = XCreateImage (d, vis.visual, vis.depth, ZPixmap, 0, (char *)malloc (WIN_W * WIN_H), WIN_W, WIN_H, 8, 0); } if (can_use_mitshm) printf ("YES!\n"); else printf ("NO, using fallback instead.\n"); // DrawFractal (ximg,xrgb); XSelectInput (d, win, ButtonPressMask | ExposureMask); XMapWindow (d, win); real_main(); // XNextEvent (d, &ev); // switch (ev.type) { // case ButtonPress: // should_quit = 1; // break; // case Expose: // if (can_use_mitshm) // XShmPutImage (d, win, gc, img, 0, 0, 0, 0, WIN_W, WIN_H, True); // else // XPutImage (d, win, gc, img, 0, 0, 0, 0, WIN_W, WIN_H); // break; // default: // break; // } if (get_xvisinfo_class(vis) % 2 == 1 || get_xvisinfo_class(vis) == TrueColor) { unsigned long color[COLORS]; if (allocateOK) { for (i = 0; i < COLORS; i++) color[i] = xrgb[i].pixel; XFreeColors (d, colormap, color, COLORS, 0); } /* Allocated colors freed */ } else { XUninstallColormap (d, colormap); } if (can_use_mitshm) { XShmDetach (d, &shminfo); /* Server detached */ XDestroyImage (ximg); /* Image struct freed */ shmdt (shminfo.shmaddr); /* We're detached */ } else XDestroyImage (ximg); /* Image struct freed */ XDestroyWindow (d, win); /* Window removed */ XCloseDisplay (d); /* Display disconnected */ /* So you can see how your computer compares to your friend's */ getrusage (RUSAGE_SELF, &resource_utilization); float seconds=(float)resource_utilization.ru_utime.tv_sec +(float)resource_utilization.ru_utime.tv_usec*0.000000001; printf("CPU seconds per frame: %f\n",seconds/(float)frameno); // printf ("CPU seconds consumed: %ds and %dµs\n", // (int) resource_utilization.ru_utime.tv_sec, // (int) resource_utilization.ru_utime.tv_usec); return 0; }
static bool gfx_ctx_xegl_set_video_mode(void *data, video_frame_info_t *video_info, unsigned width, unsigned height, bool fullscreen) { XEvent event; EGLint egl_attribs[16]; EGLint vid, num_visuals; EGLint *attr = NULL; bool true_full = false; int x_off = 0; int y_off = 0; XVisualInfo temp = {0}; XSetWindowAttributes swa = {0}; XVisualInfo *vi = NULL; char *wm_name = NULL; xegl_ctx_data_t *xegl = (xegl_ctx_data_t*)data; settings_t *settings = config_get_ptr(); int (*old_handler)(Display*, XErrorEvent*) = NULL; frontend_driver_install_signal_handler(); 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 = False; if (fullscreen && !video_info->windowed_fullscreen) { if (x11_enter_fullscreen(video_info, g_x11_dpy, width, height)) { xegl->should_reset_mode = true; true_full = true; } else RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n"); } wm_name = x11_get_wm_name(g_x11_dpy); if (wm_name) { RARCH_LOG("[X/EGL]: Window manager is %s.\n", wm_name); if (true_full && strcasestr(wm_name, "xfwm")) { RARCH_LOG("[X/EGL]: Using override-redirect workaround.\n"); swa.override_redirect = True; } free(wm_name); } if (!x11_has_net_wm_fullscreen(g_x11_dpy) && true_full) swa.override_redirect = True; if (video_info->monitor_index) g_x11_screen = video_info->monitor_index - 1; #ifdef HAVE_XINERAMA if (fullscreen || g_x11_screen != 0) { unsigned new_width = width; unsigned new_height = height; if (xinerama_get_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 | CWOverrideRedirect, &swa); XSetWindowBackground(g_x11_dpy, g_x11_win, 0); if (fullscreen && settings && settings->bools.video_disable_composition) { uint32_t value = 1; Atom cardinal = XInternAtom(g_x11_dpy, "CARDINAL", False); Atom net_wm_bypass_compositor = XInternAtom(g_x11_dpy, "_NET_WM_BYPASS_COMPOSITOR", False); RARCH_LOG("[X/EGL]: Requesting compositor bypass.\n"); XChangeProperty(g_x11_dpy, g_x11_win, net_wm_bypass_compositor, cardinal, 32, PropModeReplace, (const unsigned char*)&value, 1); } 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_title(NULL, video_info); 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); x11_set_net_wm_fullscreen(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_set_net_wm_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 make_x_window(struct app_data *data, const char *name, int x, int y, int width, int height) { static const EGLint attribs[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_DEPTH_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, EGL_NONE }; static const EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE }; int scrnum; XSetWindowAttributes attr; unsigned long mask; Window root; Window win; XVisualInfo *visInfo, visTemplate; int num_visuals; EGLConfig config; EGLint num_configs; EGLint vid; scrnum = DefaultScreen( data->xdpy ); root = RootWindow( data->xdpy, scrnum ); if (!eglChooseConfig( data->dpy, attribs, &config, 1, &num_configs)) { printf("Error: couldn't get an EGL visual config\n"); exit(1); } assert(config); assert(num_configs > 0); if (!eglGetConfigAttrib(data->dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { printf("Error: eglGetConfigAttrib() failed\n"); exit(1); } /* The X window visual must match the EGL config */ visTemplate.visualid = vid; visInfo = XGetVisualInfo(data->xdpy, VisualIDMask, &visTemplate, &num_visuals); if (!visInfo) { printf("Error: couldn't get X visual\n"); exit(1); } /* window attributes */ attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap( data->xdpy, root, visInfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | ButtonMotionMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow( data->xdpy, root, 0, 0, width * 2, height, 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr ); /* set hints and properties */ { XSizeHints sizehints; sizehints.x = x; sizehints.y = y; sizehints.width = width; sizehints.height = height; sizehints.flags = USSize | USPosition; XSetNormalHints(data->xdpy, win, &sizehints); XSetStandardProperties(data->xdpy, win, name, name, None, (char **)NULL, 0, &sizehints); } data->canvas = win; attr.event_mask = 0x0; win = XCreateWindow( data->xdpy, win, width, 0, width, height, 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr ); data->cube = win; eglBindAPI(EGL_OPENGL_ES_API); data->ctx = eglCreateContext(data->dpy, config, EGL_NO_CONTEXT, ctx_attribs ); if (!data->ctx) { printf("Error: eglCreateContext failed\n"); exit(1); } data->surf = eglCreateWindowSurface(data->dpy, config, data->cube, NULL); if (!data->surf) { printf("Error: eglCreateWindowSurface failed\n"); exit(1); } XFree(visInfo); return (data->canvas && data->cube && data->ctx && data->surf); }
static XVisualInfo* getVisual(PuglView* view) { PuglInternals* const impl = view->impl; XVisualInfo* vi = NULL; #ifdef PUGL_HAVE_GL if (view->ctx_type == PUGL_GL) { /** Attributes for single-buffered RGBA with at least 4 bits per color and a 16 bit depth buffer. */ int attrListSgl[] = { GLX_RGBA, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, GLX_ARB_multisample, 1, None }; /** Attributes for double-buffered RGBA with at least 4 bits per color and a 16 bit depth buffer. */ int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, GLX_ARB_multisample, 1, None }; /** Attributes for double-buffered RGBA with multi-sampling (antialiasing) */ int attrListDblMS[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_ALPHA_SIZE, 4, GLX_DEPTH_SIZE, 16, GLX_SAMPLE_BUFFERS, 1, GLX_SAMPLES, 4, None }; impl->doubleBuffered = True; vi = glXChooseVisual(impl->display, impl->screen, attrListDblMS); if (vi == NULL) { vi = glXChooseVisual(impl->display, impl->screen, attrListDbl); PUGL_LOG("multisampling (antialiasing) is not available\n"); } if (vi == NULL) { vi = glXChooseVisual(impl->display, impl->screen, attrListSgl); impl->doubleBuffered = False; PUGL_LOG("singlebuffered rendering will be used, no doublebuffering available\n"); } } #endif #ifdef PUGL_HAVE_CAIRO if (view->ctx_type == PUGL_CAIRO) { XVisualInfo pat; int n; pat.screen = impl->screen; vi = XGetVisualInfo(impl->display, VisualScreenMask, &pat, &n); } #endif return vi; }
void GlxContext::createContext(GlxContext* shared) { // Get a working copy of the context settings ContextSettings settings = m_settings; XVisualInfo* visualInfo = NULL; if (m_pbuffer) { unsigned int fbConfigId = 0; glXQueryDrawable(m_display, m_pbuffer, GLX_FBCONFIG_ID, &fbConfigId); int attributes[] = { GLX_FBCONFIG_ID, static_cast<int>(fbConfigId), 0, 0 }; int count = 0; GLXFBConfig* fbconfig = glXChooseFBConfig(m_display, DefaultScreen(m_display), attributes, &count); if (count == 1) visualInfo = glXGetVisualFromFBConfig(m_display, *fbconfig); if (fbconfig) XFree(fbconfig); } else { // Retrieve the attributes of the target window XWindowAttributes windowAttributes; if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) { err() << "Failed to get the window attributes" << std::endl; return; } // Get its visuals XVisualInfo tpl; tpl.screen = DefaultScreen(m_display); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); } if (!visualInfo) { err() << "Failed to get visual info" << std::endl; return; } // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // There are no GLX versions prior to 1.0 int major = 0; int minor = 0; if (!glXQueryVersion(m_display, &major, &minor)) err() << "Failed to query GLX version, limited to legacy context creation" << std::endl; // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater) bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3)); // Create the OpenGL context -- first try using glXCreateContextAttribsARB if (hasCreateContextArb) { // Get a GLXFBConfig that matches the window's visual, for glXCreateContextAttribsARB GLXFBConfig* config = NULL; // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); for (int i = 0; configs && (i < nbConfigs); ++i) { XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); if (!visual) continue; if (visual->visualid == visualInfo->visualid) { config = &configs[i]; break; } } if (!config) err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl; while (config && !m_context && m_settings.majorVersion) { std::vector<int> attributes; // Check if the user requested a specific context version (anything > 1.1) if ((m_settings.majorVersion > 1) || ((m_settings.majorVersion == 1) && (m_settings.minorVersion > 1))) { attributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); attributes.push_back(m_settings.majorVersion); attributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); attributes.push_back(m_settings.minorVersion); } // Check if setting the profile is supported if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED) { int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0; attributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); attributes.push_back(profile); attributes.push_back(GLX_CONTEXT_FLAGS_ARB); attributes.push_back(debug); } else { if ((m_settings.attributeFlags & ContextSettings::Core) || (m_settings.attributeFlags & ContextSettings::Debug)) err() << "Selecting a profile during context creation is not supported," << "disabling comptibility and debug" << std::endl; m_settings.attributeFlags = ContextSettings::Default; } // Append the terminating 0 attributes.push_back(0); attributes.push_back(0); // RAII GLX error handler (we simply ignore errors here) // On an error, glXCreateContextAttribsARB will return 0 anyway GlxErrorHandler handler(m_display); // Create the context m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, &attributes[0]); if (!m_context) { // If we couldn't create the context, first try disabling flags, // then lower the version number and try again -- stop at 0.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (m_settings.attributeFlags != ContextSettings::Default) { m_settings.attributeFlags = ContextSettings::Default; } else if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; m_settings.attributeFlags = settings.attributeFlags; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; m_settings.attributeFlags = settings.attributeFlags; } } } if (configs) XFree(configs); } // If glXCreateContextAttribsARB failed, use glXCreateContext if (!m_context) { // set the context version to 2.1 (arbitrary) and disable flags m_settings.majorVersion = 2; m_settings.minorVersion = 1; m_settings.attributeFlags = ContextSettings::Default; #if defined(GLX_DEBUGGING) GlxErrorHandler handler(m_display); #endif // Create the context, using the target window's visual m_context = glXCreateContext(m_display, visualInfo, toShare, true); #if defined(GLX_DEBUGGING) if (glxErrorOccurred) err() << "GLX error in GlxContext::createContext()" << std::endl; #endif } if (!m_context) err() << "Failed to create an OpenGL context for this window" << std::endl; // Free the visual info XFree(visualInfo); }
gboolean gst_imx_egl_viv_sink_egl_platform_init_window(GstImxEglVivSinkEGLPlatform *platform, guintptr window_handle, gboolean event_handling, GstVideoInfo *video_info, gboolean fullscreen, gint x_coord, gint y_coord, guint width, guint height, gboolean borderless) { EGLint num_configs; EGLConfig config; Window x11_window; Display *x11_display = (Display *)(platform->native_display); static EGLint const eglconfig_attribs[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; static EGLint const ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; if (!eglChooseConfig(platform->egl_display, eglconfig_attribs, &config, 1, &num_configs)) { GST_ERROR("eglChooseConfig failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string()); return FALSE; } EGL_PLATFORM_LOCK(platform); { EGLint native_visual_id; XVisualInfo visual_info_template; XVisualInfo *visual_info; int num_matching_visuals; XSetWindowAttributes attr; int screen_num; Window root_window; Atom net_wm_state_atom, net_wm_state_fullscreen_atom; guint chosen_width, chosen_height; GST_INFO("Creating new X11 window with EGL context (parent window: %" G_GUINTPTR_FORMAT ")", window_handle); if (!eglGetConfigAttrib(platform->egl_display, config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) { GST_ERROR("eglGetConfigAttrib failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string()); EGL_PLATFORM_UNLOCK(platform); return FALSE; } screen_num = DefaultScreen(x11_display); root_window = RootWindow(x11_display, screen_num); memset(&visual_info_template, 0, sizeof(visual_info_template)); visual_info_template.visualid = native_visual_id; visual_info = XGetVisualInfo(x11_display, VisualIDMask, &visual_info_template, &num_matching_visuals); if (visual_info == NULL) { GST_ERROR("Could not get visual info for native visual ID %d", native_visual_id); EGL_PLATFORM_UNLOCK(platform); return FALSE; } memset(&attr, 0, sizeof(attr)); attr.background_pixmap = None; attr.background_pixel = BlackPixel(x11_display, screen_num); attr.border_pixmap = CopyFromParent; attr.border_pixel = BlackPixel(x11_display, screen_num); attr.backing_store = NotUseful; attr.override_redirect = borderless ? True : False; attr.cursor = None; if (window_handle != 0) { platform->parent_window = (Window)window_handle; /* Out of the parent window events, only the structure * notifications are of interest here */ XSelectInput(x11_display, platform->parent_window, StructureNotifyMask); } // TODO: xlib error handler platform->fixed_window_width = width; platform->fixed_window_height = height; platform->video_width = GST_VIDEO_INFO_WIDTH(video_info); platform->video_height = GST_VIDEO_INFO_HEIGHT(video_info); platform->fullscreen = fullscreen; /* If either no fixed size is set, or fullscreen is requested, use the video frame size * In the fullscreen case, the size is actually irrelevant, since it will be overwritten * with the screen size. But passing zero for the width/height values is invalid, the * video frame size is used. */ chosen_width = ((width == 0) || fullscreen) ? platform->video_width : width; chosen_height = ((height == 0) || fullscreen) ? platform->video_height : height; /* This video output window can be embedded into other windows, for example inside * media player user interfaces. This is done by making the specified window as * the parent of the video playback window. */ x11_window = XCreateWindow( x11_display, (window_handle != 0) ? platform->parent_window : root_window, x_coord, y_coord, chosen_width, chosen_height, 0, visual_info->depth, InputOutput, visual_info->visual, CWBackPixel | CWColormap | CWBorderPixel | CWBackingStore | CWOverrideRedirect, &attr ); platform->native_window = (EGLNativeWindowType)x11_window; net_wm_state_atom = XInternAtom(x11_display, "_NET_WM_STATE", True); net_wm_state_fullscreen_atom = XInternAtom(x11_display, "_NET_WM_STATE_FULLSCREEN", True); platform->wm_delete_atom = XInternAtom(x11_display, "WM_DELETE_WINDOW", True); XSetWMProtocols(x11_display, x11_window, &(platform->wm_delete_atom), 1); XStoreName(x11_display, x11_window, "eglvivsink window"); gst_imx_egl_viv_sink_egl_platform_set_event_handling_nolock(platform, event_handling); XSizeHints sizehints; sizehints.x = 0; sizehints.y = 0; sizehints.width = chosen_width; sizehints.height = chosen_height; sizehints.flags = PPosition | PSize; XSetNormalHints(x11_display, x11_window, &sizehints); if (fullscreen) { XChangeProperty( x11_display, x11_window, net_wm_state_atom, XA_ATOM, 32, PropModeReplace, (unsigned char*)&net_wm_state_fullscreen_atom, 1 ); } XClearWindow(x11_display, x11_window); XMapRaised(x11_display, x11_window); if (fullscreen) { XEvent event; event.type = ClientMessage; event.xclient.window = x11_window; event.xclient.message_type = net_wm_state_atom; event.xclient.format = 32; event.xclient.data.l[0] = 1; event.xclient.data.l[1] = net_wm_state_fullscreen_atom; event.xclient.data.l[3] = 0l; XSendEvent( x11_display, root_window, 0, SubstructureNotifyMask, &event ); } XSync(x11_display, False); } eglBindAPI(EGL_OPENGL_ES_API); platform->egl_context = eglCreateContext(platform->egl_display, config, EGL_NO_CONTEXT, ctx_attribs); if (platform->egl_context == EGL_NO_CONTEXT) { GST_ERROR("eglCreateContext failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string()); EGL_PLATFORM_UNLOCK(platform); return FALSE; } platform->egl_surface = eglCreateWindowSurface(platform->egl_display, config, platform->native_window, NULL); if (platform->egl_surface == EGL_NO_SURFACE) { GST_ERROR("eglCreateWindowSurface failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string()); EGL_PLATFORM_UNLOCK(platform); return FALSE; } if (!eglMakeCurrent(platform->egl_display, platform->egl_surface, platform->egl_surface, platform->egl_context)) { GST_ERROR("eglMakeCurrent failed: %s", gst_imx_egl_viv_sink_egl_platform_get_last_error_string()); EGL_PLATFORM_UNLOCK(platform); return FALSE; } { XWindowAttributes window_attr; XGetWindowAttributes(x11_display, x11_window, &window_attr); if (fullscreen || (platform->fixed_window_width != 0) || (platform->fixed_window_height != 0)) { platform->fixed_window_width = window_attr.width; platform->fixed_window_height = window_attr.height; } if (platform->window_resized_event_cb != NULL) platform->window_resized_event_cb(platform, window_attr.width, window_attr.height, platform->user_context); else glViewport(0, 0, window_attr.width, window_attr.height); } EGL_PLATFORM_UNLOCK(platform); return TRUE; }