static void X11_CheckWindowManager(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; Display *display = data->display; Atom _NET_SUPPORTING_WM_CHECK; int status, real_format; Atom real_type; unsigned long items_read = 0, items_left = 0; unsigned char *propdata = NULL; Window wm_window = 0; #ifdef DEBUG_WINDOW_MANAGER char *wm_name; #endif /* Set up a handler to gracefully catch errors */ X11_XSync(display, False); handler = X11_XSetErrorHandler(X11_CheckWindowManagerErrorHandler); _NET_SUPPORTING_WM_CHECK = X11_XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False); status = X11_XGetWindowProperty(display, DefaultRootWindow(display), _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata); if (status == Success) { if (items_read) { wm_window = ((Window*)propdata)[0]; } if (propdata) { X11_XFree(propdata); propdata = NULL; } } if (wm_window) { status = X11_XGetWindowProperty(display, wm_window, _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata); if (status != Success || !items_read || wm_window != ((Window*)propdata)[0]) { wm_window = None; } if (status == Success && propdata) { X11_XFree(propdata); propdata = NULL; } } /* Reset the error handler, we're done checking */ X11_XSync(display, False); X11_XSetErrorHandler(handler); if (!wm_window) { #ifdef DEBUG_WINDOW_MANAGER printf("Couldn't get _NET_SUPPORTING_WM_CHECK property\n"); #endif return; } data->net_wm = SDL_TRUE; #ifdef DEBUG_WINDOW_MANAGER wm_name = X11_GetWindowTitle(_this, wm_window); printf("Window manager: %s\n", wm_name); SDL_free(wm_name); #endif }
int X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) { Display *display = ((SDL_VideoData *) _this->driverdata)->display; Window drawable = (context ? ((SDL_WindowData *) window->driverdata)->xwindow : None); GLXContext glx_context = (GLXContext) context; int rc; if (!_this->gl_data) { return SDL_SetError("OpenGL not initialized"); } /* We do this to create a clean separation between X and GLX errors. */ X11_XSync(display, False); errorHandlerOperation = "make GL context current"; errorBase = _this->gl_data->errorBase; errorCode = Success; handler = X11_XSetErrorHandler(X11_GL_ErrorHandler); rc = _this->gl_data->glXMakeCurrent(display, drawable, glx_context); X11_XSetErrorHandler(handler); if (errorCode != Success) { /* uhoh, an X error was thrown! */ return -1; /* the error handler called SDL_SetError() already. */ } else if (!rc) { /* glXMakeCurrent() failed without throwing an X error */ return SDL_SetError("Unable to make GL context current"); } return 0; }
static SDL_VideoDevice * X11_CreateDevice(int devindex) { SDL_VideoDevice *device; SDL_VideoData *data; const char *display = NULL; /* Use the DISPLAY environment variable */ if (!SDL_X11_LoadSymbols()) { return NULL; } /* Need for threading gl calls. This is also required for the proprietary nVidia driver to be threaded. */ X11_XInitThreads(); /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { SDL_OutOfMemory(); return NULL; } data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); if (!data) { SDL_free(device); SDL_OutOfMemory(); return NULL; } device->driverdata = data; data->global_mouse_changed = SDL_TRUE; /* FIXME: Do we need this? if ( (SDL_strncmp(X11_XDisplayName(display), ":", 1) == 0) || (SDL_strncmp(X11_XDisplayName(display), "unix:", 5) == 0) ) { local_X11 = 1; } else { local_X11 = 0; } */ data->display = X11_XOpenDisplay(display); #if defined(__osf__) && defined(SDL_VIDEO_DRIVER_X11_DYNAMIC) /* On Tru64 if linking without -lX11, it fails and you get following message. * Xlib: connection to ":0.0" refused by server * Xlib: XDM authorization key matches an existing client! * * It succeeds if retrying 1 second later * or if running xhost +localhost on shell. */ if (data->display == NULL) { SDL_Delay(1000); data->display = X11_XOpenDisplay(display); } #endif if (data->display == NULL) { SDL_free(device->driverdata); SDL_free(device); SDL_SetError("Couldn't open X11 display"); return NULL; } #ifdef X11_DEBUG X11_XSynchronize(data->display, True); #endif /* Hook up an X11 error handler to recover the desktop resolution. */ safety_net_triggered = SDL_FALSE; orig_x11_errhandler = X11_XSetErrorHandler(X11_SafetyNetErrHandler); /* Set the function pointers */ device->VideoInit = X11_VideoInit; device->VideoQuit = X11_VideoQuit; device->GetDisplayModes = X11_GetDisplayModes; device->GetDisplayBounds = X11_GetDisplayBounds; device->GetDisplayUsableBounds = X11_GetDisplayUsableBounds; device->GetDisplayDPI = X11_GetDisplayDPI; device->SetDisplayMode = X11_SetDisplayMode; device->SuspendScreenSaver = X11_SuspendScreenSaver; device->PumpEvents = X11_PumpEvents; device->CreateWindow = X11_CreateWindow; device->CreateWindowFrom = X11_CreateWindowFrom; device->SetWindowTitle = X11_SetWindowTitle; device->SetWindowIcon = X11_SetWindowIcon; device->SetWindowPosition = X11_SetWindowPosition; device->SetWindowSize = X11_SetWindowSize; device->SetWindowMinimumSize = X11_SetWindowMinimumSize; device->SetWindowMaximumSize = X11_SetWindowMaximumSize; device->GetWindowBordersSize = X11_GetWindowBordersSize; device->SetWindowOpacity = X11_SetWindowOpacity; device->SetWindowModalFor = X11_SetWindowModalFor; device->SetWindowInputFocus = X11_SetWindowInputFocus; device->ShowWindow = X11_ShowWindow; device->HideWindow = X11_HideWindow; device->RaiseWindow = X11_RaiseWindow; device->MaximizeWindow = X11_MaximizeWindow; device->MinimizeWindow = X11_MinimizeWindow; device->RestoreWindow = X11_RestoreWindow; device->SetWindowBordered = X11_SetWindowBordered; device->SetWindowResizable = X11_SetWindowResizable; device->SetWindowFullscreen = X11_SetWindowFullscreen; device->SetWindowGammaRamp = X11_SetWindowGammaRamp; device->SetWindowGrab = X11_SetWindowGrab; device->DestroyWindow = X11_DestroyWindow; device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer; device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer; device->GetWindowWMInfo = X11_GetWindowWMInfo; device->SetWindowHitTest = X11_SetWindowHitTest; device->shape_driver.CreateShaper = X11_CreateShaper; device->shape_driver.SetWindowShape = X11_SetWindowShape; device->shape_driver.ResizeWindowShape = X11_ResizeWindowShape; #if SDL_VIDEO_OPENGL_GLX device->GL_LoadLibrary = X11_GL_LoadLibrary; device->GL_GetProcAddress = X11_GL_GetProcAddress; device->GL_UnloadLibrary = X11_GL_UnloadLibrary; device->GL_CreateContext = X11_GL_CreateContext; device->GL_MakeCurrent = X11_GL_MakeCurrent; device->GL_SetSwapInterval = X11_GL_SetSwapInterval; device->GL_GetSwapInterval = X11_GL_GetSwapInterval; device->GL_SwapWindow = X11_GL_SwapWindow; device->GL_DeleteContext = X11_GL_DeleteContext; #elif SDL_VIDEO_OPENGL_EGL device->GL_LoadLibrary = X11_GLES_LoadLibrary; device->GL_GetProcAddress = X11_GLES_GetProcAddress; device->GL_UnloadLibrary = X11_GLES_UnloadLibrary; device->GL_CreateContext = X11_GLES_CreateContext; device->GL_MakeCurrent = X11_GLES_MakeCurrent; device->GL_SetSwapInterval = X11_GLES_SetSwapInterval; device->GL_GetSwapInterval = X11_GLES_GetSwapInterval; device->GL_SwapWindow = X11_GLES_SwapWindow; device->GL_DeleteContext = X11_GLES_DeleteContext; #endif device->SetClipboardText = X11_SetClipboardText; device->GetClipboardText = X11_GetClipboardText; device->HasClipboardText = X11_HasClipboardText; device->StartTextInput = X11_StartTextInput; device->StopTextInput = X11_StopTextInput; device->SetTextInputRect = X11_SetTextInputRect; device->free = X11_DeleteDevice; return device; }
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_GetDisplayForWindow(window)->driverdata)->screen; XWindowAttributes xattr; XVisualInfo v, *vinfo; int n; GLXContext context = NULL, share_context; if (_this->gl_config.share_with_current_context) { share_context = (GLXContext)SDL_GL_GetCurrentContext(); } else { share_context = NULL; } /* We do this to create a clean separation between X and GLX errors. */ X11_XSync(display, False); errorHandlerOperation = "create GL context"; errorBase = _this->gl_data->errorBase; errorCode = Success; handler = X11_XSetErrorHandler(X11_GL_ErrorHandler); X11_XGetWindowAttributes(display, data->xwindow, &xattr); v.screen = screen; v.visualid = X11_XVisualIDFromVisual(xattr.visual); vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n); if (vinfo) { if (_this->gl_config.major_version < 3 && _this->gl_config.profile_mask == 0 && _this->gl_config.flags == 0) { /* Create legacy context */ context = _this->gl_data->glXCreateContext(display, vinfo, share_context, True); } else { /* max 10 attributes plus terminator */ int attribs[11] = { GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, GLX_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 }; int iattr = 4; /* SDL profile bits match GLX profile bits */ if( _this->gl_config.profile_mask != 0 ) { attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[iattr++] = _this->gl_config.profile_mask; } /* SDL flags match GLX flags */ if( _this->gl_config.flags != 0 ) { attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB; attribs[iattr++] = _this->gl_config.flags; } /* only set if glx extension is available */ if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) { attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB; attribs[iattr++] = _this->gl_config.release_behavior ? GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB : GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB; } attribs[iattr++] = 0; /* Get a pointer to the context creation function for GL 3.0 */ if (!_this->gl_data->glXCreateContextAttribsARB) { SDL_SetError("OpenGL 3.0 and later are not supported by this system"); } else { int glxAttribs[64]; /* Create a GL 3.x context */ GLXFBConfig *framebuffer_config = NULL; int fbcount = 0; X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE); if (!_this->gl_data->glXChooseFBConfig || !(framebuffer_config = _this->gl_data->glXChooseFBConfig(display, DefaultScreen(display), glxAttribs, &fbcount))) { SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable"); } else { context = _this->gl_data->glXCreateContextAttribsARB(display, framebuffer_config[0], share_context, True, attribs); X11_XFree(framebuffer_config); } } } X11_XFree(vinfo); } X11_XSync(display, False); X11_XSetErrorHandler(handler); if (!context) { if (errorCode == Success) { 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; }
int X11_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; XGCValues gcv; XVisualInfo vinfo; /* Free the old framebuffer surface */ X11_DestroyWindowFramebuffer(_this, window); /* Create the graphics context for drawing */ gcv.graphics_exposures = False; data->gc = X11_XCreateGC(display, data->xwindow, GCGraphicsExposures, &gcv); if (!data->gc) { return SDL_SetError("Couldn't create graphics context"); } /* Find out the pixel format and depth */ if (X11_GetVisualInfoFromVisual(display, data->visual, &vinfo) < 0) { return SDL_SetError("Couldn't get window visual information"); } *format = X11_GetPixelFormatFromVisualInfo(display, &vinfo); if (*format == SDL_PIXELFORMAT_UNKNOWN) { return SDL_SetError("Unknown window pixel format"); } /* Calculate pitch */ *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3); /* Create the actual image */ #ifndef NO_SHARED_MEMORY if (have_mitshm()) { XShmSegmentInfo *shminfo = &data->shminfo; shminfo->shmid = shmget(IPC_PRIVATE, window->h*(*pitch), IPC_CREAT | 0777); if ( shminfo->shmid >= 0 ) { shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0); shminfo->readOnly = False; if ( shminfo->shmaddr != (char *)-1 ) { shm_error = False; X_handler = X11_XSetErrorHandler(shm_errhandler); X11_XShmAttach(display, shminfo); X11_XSync(display, True); X11_XSetErrorHandler(X_handler); if ( shm_error ) shmdt(shminfo->shmaddr); } else { shm_error = True; } shmctl(shminfo->shmid, IPC_RMID, NULL); } else { shm_error = True; } if (!shm_error) { data->ximage = X11_XShmCreateImage(display, data->visual, vinfo.depth, ZPixmap, shminfo->shmaddr, shminfo, window->w, window->h); if (!data->ximage) { X11_XShmDetach(display, shminfo); X11_XSync(display, False); shmdt(shminfo->shmaddr); } else { /* Done! */ data->use_mitshm = SDL_TRUE; *pixels = shminfo->shmaddr; return 0; } } } #endif /* not NO_SHARED_MEMORY */ *pixels = SDL_malloc(window->h*(*pitch)); if (*pixels == NULL) { return SDL_OutOfMemory(); } data->ximage = X11_XCreateImage(display, data->visual, vinfo.depth, ZPixmap, 0, (char *)(*pixels), window->w, window->h, 32, 0); if (!data->ximage) { SDL_free(*pixels); return SDL_SetError("Couldn't create XImage"); } return 0; }
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_GetDisplayForWindow(window)->driverdata)->screen; XWindowAttributes xattr; XVisualInfo v, *vinfo; int n; GLXContext context = NULL, share_context; PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL; if (_this->gl_config.share_with_current_context) { share_context = (GLXContext)SDL_GL_GetCurrentContext(); } else { share_context = NULL; } /* We do this to create a clean separation between X and GLX errors. */ X11_XSync(display, False); errorBase = _this->gl_data->errorBase; handler = X11_XSetErrorHandler(X11_GL_CreateContextErrorHandler); X11_XGetWindowAttributes(display, data->xwindow, &xattr); v.screen = screen; v.visualid = X11_XVisualIDFromVisual(xattr.visual); vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n); if (vinfo) { if (_this->gl_config.major_version < 3 && _this->gl_config.profile_mask == 0 && _this->gl_config.flags == 0) { /* Create legacy context */ context = _this->gl_data->glXCreateContext(display, vinfo, share_context, 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) { /* max 8 attributes plus terminator */ int attribs[9] = { GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, GLX_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 }; int iattr = 4; /* SDL profile bits match GLX profile bits */ if( _this->gl_config.profile_mask != 0 ) { attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[iattr++] = _this->gl_config.profile_mask; } /* SDL flags match GLX flags */ if( _this->gl_config.flags != 0 ) { attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB; attribs[iattr++] = _this->gl_config.flags; } attribs[iattr++] = 0; /* Get a pointer to the context creation function for GL 3.0 */ glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> glXGetProcAddress((GLubyte *) "glXCreateContextAttribsARB"); if (!glXCreateContextAttribs) { SDL_SetError("GL 3.x is not supported"); context = temp_context; } else { int glxAttribs[64]; /* 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"); X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE); if (!glXChooseFBConfig || !(framebuffer_config = glXChooseFBConfig(display, DefaultScreen(display), glxAttribs, &fbcount))) { SDL_SetError ("No good framebuffers found. GL 3.x disabled"); context = temp_context; } else { context = glXCreateContextAttribs(display, framebuffer_config[0], share_context, True, attribs); _this->gl_data->glXDestroyContext(display, temp_context); } } } } X11_XFree(vinfo); } X11_XSync(display, False); X11_XSetErrorHandler(handler); 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; }