/* * Remembers the current visual settings, so that * we can change them and restore later... */ static void fghRememberState( void ) { #if TARGET_HOST_POSIX_X11 int event_base, error_base; /* * Remember the current pointer location before going fullscreen * for restoring it later: */ Window junk_window; unsigned int junk_mask; XQueryPointer(fgDisplay.Display, fgDisplay.RootWindow, &junk_window, &junk_window, &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY, &fgDisplay.DisplayPointerX, &fgDisplay.DisplayPointerY, &junk_mask); # ifdef HAVE_X11_EXTENSIONS_XRANDR_H if(XRRQueryExtension(fgDisplay.Display, &event_base, &error_base)) { XRRScreenConfiguration *xrr_config; XRRScreenSize *ssizes; Rotation rot; int ssize_count, curr; if((xrr_config = XRRGetScreenInfo(fgDisplay.Display, fgDisplay.RootWindow))) { ssizes = XRRConfigSizes(xrr_config, &ssize_count); curr = XRRConfigCurrentConfiguration(xrr_config, &rot); fgDisplay.prev_xsz = ssizes[curr].width; fgDisplay.prev_ysz = ssizes[curr].height; fgDisplay.prev_refresh = -1; # if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) if(fgState.GameModeRefresh != -1) { fgDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config); } # endif fgDisplay.prev_size_valid = 1; XRRFreeScreenConfigInfo(xrr_config); } } # endif /* * This highly depends on the XFree86 extensions, * not approved as X Consortium standards */ # ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H if(!XF86VidModeQueryExtension(fgDisplay.Display, &event_base, &error_base)) { return; } /* * Remember the current ViewPort location of the screen to be able to * restore the ViewPort on LeaveGameMode(): */ if( !XF86VidModeGetViewPort( fgDisplay.Display, fgDisplay.Screen, &fgDisplay.DisplayViewPortX, &fgDisplay.DisplayViewPortY ) ) fgWarning( "XF86VidModeGetViewPort failed" ); /* Query the current display settings: */ fgDisplay.DisplayModeValid = XF86VidModeGetModeLine( fgDisplay.Display, fgDisplay.Screen, &fgDisplay.DisplayModeClock, &fgDisplay.DisplayMode ); if( !fgDisplay.DisplayModeValid ) fgWarning( "XF86VidModeGetModeLine failed" ); # endif #elif TARGET_HOST_MS_WINDOWS /* DEVMODE devMode; */ /* Grab the current desktop settings... */ /* hack to get around my stupid cross-gcc headers */ #define FREEGLUT_ENUM_CURRENT_SETTINGS -1 EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &fgDisplay.DisplayMode ); /* Make sure we will be restoring all settings needed */ fgDisplay.DisplayMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; #endif }
int _glfwGetClosestVideoMode(int screen, int* width, int* height, int* rate) { int i, match, bestmatch; if (_glfwLibrary.X11.RandR.available) { #if defined(_GLFW_HAS_XRANDR) int sizecount, bestsize; int ratecount, bestrate; short* ratelist; XRRScreenConfiguration* sc; XRRScreenSize* sizelist; sc = XRRGetScreenInfo(_glfwLibrary.X11.display, RootWindow(_glfwLibrary.X11.display, screen)); sizelist = XRRConfigSizes(sc, &sizecount); // Find the best matching mode bestsize = -1; bestmatch = INT_MAX; for (i = 0; i < sizecount; i++) { match = (*width - sizelist[i].width) * (*width - sizelist[i].width) + (*height - sizelist[i].height) * (*height - sizelist[i].height); if (match < bestmatch) { bestmatch = match; bestsize = i; } } if (bestsize != -1) { // Report width & height of best matching mode *width = sizelist[bestsize].width; *height = sizelist[bestsize].height; if (*rate > 0) { ratelist = XRRConfigRates(sc, bestsize, &ratecount); bestrate = -1; bestmatch = INT_MAX; for (i = 0; i < ratecount; i++) { match = abs(ratelist[i] - *rate); if (match < bestmatch) { bestmatch = match; bestrate = ratelist[i]; } } if (bestrate != -1) *rate = bestrate; } } XRRFreeScreenConfigInfo(sc); if (bestsize != -1) return bestsize; #endif /*_GLFW_HAS_XRANDR*/ } else if (_glfwLibrary.X11.VidMode.available) { #if defined(_GLFW_HAS_XF86VIDMODE) XF86VidModeModeInfo** modelist; int bestmode, modecount; // Get a list of all available display modes XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, screen, &modecount, &modelist); // Find the best matching mode bestmode = -1; bestmatch = INT_MAX; for (i = 0; i < modecount; i++) { match = (*width - modelist[i]->hdisplay) * (*width - modelist[i]->hdisplay) + (*height - modelist[i]->vdisplay) * (*height - modelist[i]->vdisplay); if (match < bestmatch) { bestmatch = match; bestmode = i; } } if (bestmode != -1) { // Report width & height of best matching mode *width = modelist[bestmode]->hdisplay; *height = modelist[bestmode]->vdisplay; } XFree(modelist); if (bestmode != -1) return bestmode; #endif /*_GLFW_HAS_XF86VIDMODE*/ } // Default: Simply use the screen resolution *width = DisplayWidth(_glfwLibrary.X11.display, screen); *height = DisplayHeight(_glfwLibrary.X11.display, screen); return 0; }
//-------------------------------------------------------------------------------------------------// GLXGLSupport::GLXGLSupport() : mGLDisplay(0), mXDisplay(0) { // A connection that might be shared with the application for GL rendering: mGLDisplay = getGLDisplay(); // A connection that is NOT shared to enable independent event processing: mXDisplay = getXDisplay(); int dummy; if (XQueryExtension(mXDisplay, "RANDR", &dummy, &dummy, &dummy)) { XRRScreenConfiguration *screenConfig; screenConfig = XRRGetScreenInfo(mXDisplay, DefaultRootWindow(mXDisplay)); if (screenConfig) { XRRScreenSize *screenSizes; int nSizes = 0; Rotation currentRotation; int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, ¤tRotation); screenSizes = XRRConfigSizes(screenConfig, &nSizes); mCurrentMode.first.first = screenSizes[currentSizeID].width; mCurrentMode.first.second = screenSizes[currentSizeID].height; mCurrentMode.second = XRRConfigCurrentRate(screenConfig); mOriginalMode = mCurrentMode; for(int sizeID = 0; sizeID < nSizes; sizeID++) { short *rates; int nRates = 0; rates = XRRConfigRates(screenConfig, sizeID, &nRates); for (int rate = 0; rate < nRates; rate++) { VideoMode mode; mode.first.first = screenSizes[sizeID].width; mode.first.second = screenSizes[sizeID].height; mode.second = rates[rate]; mVideoModes.push_back(mode); } } XRRFreeScreenConfigInfo(screenConfig); } } else { mCurrentMode.first.first = DisplayWidth(mXDisplay, DefaultScreen(mXDisplay)); mCurrentMode.first.second = DisplayHeight(mXDisplay, DefaultScreen(mXDisplay)); mCurrentMode.second = 0; mOriginalMode = mCurrentMode; mVideoModes.push_back(mCurrentMode); } GLXFBConfig *fbConfigs; int config, nConfigs = 0; fbConfigs = chooseFBConfig(NULL, &nConfigs); for (config = 0; config < nConfigs; config++) { int caveat, samples; getFBConfigAttrib (fbConfigs[config], GLX_CONFIG_CAVEAT, &caveat); if (caveat != GLX_SLOW_CONFIG) { getFBConfigAttrib (fbConfigs[config], GLX_SAMPLES, &samples); mSampleLevels.push_back(StringConverter::toString(samples)); } } XFree (fbConfigs); remove_duplicates(mSampleLevels); }
Bool SelectResolution(uint32 width, uint32 height) { ResolutionInfoX11Type *resInfoX = &resolutionInfoX11; XRRScreenConfiguration* xrrConfig; XRRScreenSize *xrrSizes; Rotation xrrCurRotation; uint32 xrrNumSizes; uint32 i; uint32 bestFitIndex = 0; uint64 bestFitSize = 0; uint64 potentialSize; Bool perfectMatch; #ifndef NO_MULTIMON if (resInfoX->canUseRandR12) { xXineramaScreenInfo display; display.x_org = 0; display.y_org = 0; display.width = width; display.height = height; return RandR12_SetTopology(resInfoX->display, DefaultScreen(resInfoX->display), resInfoX->rootWindow, 1, &display, width, height); } #endif xrrConfig = XRRGetScreenInfo(resInfoX->display, resInfoX->rootWindow); xrrSizes = XRRConfigSizes(xrrConfig, &xrrNumSizes); bestFitIndex = XRRConfigCurrentConfiguration(xrrConfig, &xrrCurRotation); /* * Iterate thru the list finding the best fit that is still <= in both width * and height. */ for (i = 0; i < xrrNumSizes; i++) { potentialSize = xrrSizes[i].width * xrrSizes[i].height; if (xrrSizes[i].width <= width && xrrSizes[i].height <= height && potentialSize > bestFitSize ) { bestFitSize = potentialSize; bestFitIndex = i; } } if (bestFitSize > 0) { Status rc; g_debug("Setting guest resolution to: %dx%d (requested: %d, %d)\n", xrrSizes[bestFitIndex].width, xrrSizes[bestFitIndex].height, width, height); rc = XRRSetScreenConfig(resInfoX->display, xrrConfig, resInfoX->rootWindow, bestFitIndex, xrrCurRotation, GDK_CURRENT_TIME); g_debug("XRRSetScreenConfig returned %d (result: %dx%d)\n", rc, xrrSizes[bestFitIndex].width, xrrSizes[bestFitIndex].height); } else { g_debug("Can't find a suitable guest resolution, ignoring request for %dx%d\n", width, height); } perfectMatch = xrrSizes[bestFitIndex].width == width && xrrSizes[bestFitIndex].height == height; XRRFreeScreenConfigInfo(xrrConfig); return perfectMatch; }
void _glfwSetVideoModeMODE(int screen, int mode, int rate) { if (_glfwLibrary.X11.RandR.available) { #if defined(_GLFW_HAS_XRANDR) XRRScreenConfiguration* sc; Window root; root = RootWindow(_glfwLibrary.X11.display, screen); sc = XRRGetScreenInfo(_glfwLibrary.X11.display, root); // Remember old size and flag that we have changed the mode if (!_glfwLibrary.X11.FS.modeChanged) { _glfwLibrary.X11.FS.oldSizeID = XRRConfigCurrentConfiguration(sc, &_glfwLibrary.X11.FS.oldRotation); _glfwLibrary.X11.FS.oldWidth = DisplayWidth(_glfwLibrary.X11.display, screen); _glfwLibrary.X11.FS.oldHeight = DisplayHeight(_glfwLibrary.X11.display, screen); _glfwLibrary.X11.FS.modeChanged = GL_TRUE; } if (rate > 0) { // Set desired configuration XRRSetScreenConfigAndRate(_glfwLibrary.X11.display, sc, root, mode, RR_Rotate_0, (short) rate, CurrentTime); } else { // Set desired configuration XRRSetScreenConfig(_glfwLibrary.X11.display, sc, root, mode, RR_Rotate_0, CurrentTime); } XRRFreeScreenConfigInfo(sc); #endif /*_GLFW_HAS_XRANDR*/ } else if (_glfwLibrary.X11.VidMode.available) { #if defined(_GLFW_HAS_XF86VIDMODE) XF86VidModeModeInfo **modelist; int modecount; // Get a list of all available display modes XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, screen, &modecount, &modelist); // Unlock mode switch if necessary if (_glfwLibrary.X11.FS.modeChanged) XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, screen, 0); // Change the video mode to the desired mode XF86VidModeSwitchToMode(_glfwLibrary.X11.display, screen, modelist[mode]); // Set viewport to upper left corner (where our window will be) XF86VidModeSetViewPort(_glfwLibrary.X11.display, screen, 0, 0); // Lock mode switch XF86VidModeLockModeSwitch(_glfwLibrary.X11.display, screen, 1); // Remember old mode and flag that we have changed the mode if (!_glfwLibrary.X11.FS.modeChanged) { _glfwLibrary.X11.FS.oldMode = *modelist[0]; _glfwLibrary.X11.FS.modeChanged = GL_TRUE; } XFree(modelist); #endif /*_GLFW_HAS_XF86VIDMODE*/ } }
int apply_transform (Display *display, Window root, RRCrtc crtcnum, const char *input_name) { int ret; ret = EXIT_SUCCESS; if (ret != EXIT_FAILURE) { XRRScreenConfiguration *sconf; XRRScreenResources *res; XRRCrtcInfo *crtc; XRRCrtcTransformAttributes *transform; Status status; double amx[3][3]; double sina, cosa; double hscale, vscale, hoffs, voffs; XRRScreenSize *ssize; int nsizes; Rotation srot; res = XRRGetScreenResourcesCurrent (display, root); sconf = XRRGetScreenInfo (display, root); ssize = XRRConfigSizes(sconf, &nsizes) + XRRConfigCurrentConfiguration (sconf, &srot); crtc = XRRGetCrtcInfo (display, res, crtcnum); if (verbose) { fprintf (stderr, "Screen: (%u, %u) 0x%02x\n", ssize->width, ssize->height, srot); fprintf (stderr, "CRTC: (%i, %i) (%u, %u) 0x%02x\n", crtc->x, crtc->y, crtc->width, crtc->height, crtc->rotation); } switch (srot) { case RR_Rotate_0: case RR_Rotate_180: hscale = (double)crtc->width/(double)ssize->width; vscale = (double)crtc->height/(double)ssize->height; break; case RR_Rotate_90: case RR_Rotate_270: hscale = (double)crtc->width/(double)ssize->height; vscale = (double)crtc->height/(double)ssize->width; break; default: ret = EXIT_FAILURE; fprintf (stderr, "The screen rotation/reflection 0x%02x is not supported yet. Sorry.\n", srot); } switch (crtc->rotation) { case RR_Rotate_0: sina = 0; cosa = 1; hoffs = 0; voffs = 0; break; case RR_Rotate_90: sina = 1; cosa = 0; hoffs = 1; voffs = 0; break; case RR_Rotate_180: sina = 0; cosa = -1; hoffs = 1; voffs = 1; break; case RR_Rotate_270: sina = -1; cosa = 0; hoffs = 0; voffs = 1; break; default: ret = EXIT_FAILURE; fprintf (stderr, "The rotation/reflection 0x%02x is not supported yet. Sorry.\n", crtc->rotation); } if (ret != EXIT_FAILURE) { amx[0][0] = cosa*hscale; amx[0][1] = -sina*hscale; amx[0][2] = hoffs*hscale + crtc->x/ssize->width; amx[1][0] = sina*vscale; amx[1][1] = cosa*vscale; amx[1][2] = voffs*vscale + crtc->y/ssize->height; amx[2][0] = 0; amx[2][1] = 0; amx[2][2] = 1; status = XRRGetCrtcTransform (display, crtcnum, &transform); if (!status) { fprintf (stderr, "Unable to get the current transformation\n"); ret = EXIT_FAILURE; } } if (ret != EXIT_FAILURE) { static char strmx[3][3][8]; static const char *args[11]; double mx[3][3]; int i, j; for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++) { XFixed fv = transform->currentTransform.matrix[j][i]; mx[j][i] = XFixedToDouble (fv); } } args[0] = input_name; args[1] = "Coordinate Transformation Matrix"; for (j = 0; j < 3; j++) { for (i = 0; i < 3; i++) { double v = mx[0][i]*amx[j][0] + mx[1][i]*amx[j][1] + mx[2][i]*amx[j][2]; snprintf (strmx[j][i], 8, "%8.6f", v); args[2 + i + j*3] = strmx[j][i]; } } if (verbose) { fprintf (stderr, "Debug: set-float-prop"); for (i = 0; i < 11; i++) { fprintf (stderr, " %s", args[i]); } fprintf (stderr, "\n"); } ret = set_float_prop(display, 11, args, "set-float-prop", ": error calling function, please report a bug."); XFree (transform); } XRRFreeCrtcInfo (crtc); XRRFreeScreenResources (res); XRRFreeScreenConfigInfo (sconf); } return ret; }
bool CIrrDeviceLinux::createWindow() { #ifdef _IRR_COMPILE_WITH_X11_ #ifdef _DEBUG os::Printer::log("Creating X window...", ELL_INFORMATION); XSetErrorHandler(IrrPrintXError); #endif display = XOpenDisplay(0); if (!display) { os::Printer::log("Error: Need running XServer to start Irrlicht Engine.", ELL_ERROR); os::Printer::log("Could not open display", XDisplayName(0), ELL_ERROR); return false; } screennr = DefaultScreen(display); // query extension if (CreationParams.Fullscreen) { getVideoModeList(); #if defined(_IRR_LINUX_X11_VIDMODE_) || defined(_IRR_LINUX_X11_RANDR_) s32 eventbase, errorbase; s32 bestMode = -1; #endif #ifdef _IRR_LINUX_X11_VIDMODE_ if (XF86VidModeQueryExtension(display, &eventbase, &errorbase)) { // enumerate video modes s32 modeCount; XF86VidModeModeInfo** modes; XF86VidModeGetAllModeLines(display, screennr, &modeCount, &modes); // find fitting mode for (s32 i = 0; i<modeCount; ++i) { if (bestMode==-1 && modes[i]->hdisplay >= Width && modes[i]->vdisplay >= Height) bestMode = i; else if (bestMode!=-1 && modes[i]->hdisplay >= Width && modes[i]->vdisplay >= Height && modes[i]->hdisplay < modes[bestMode]->hdisplay && modes[i]->vdisplay < modes[bestMode]->vdisplay) bestMode = i; } if (bestMode != -1) { os::Printer::log("Starting fullscreen mode...", ELL_INFORMATION); XF86VidModeSwitchToMode(display, screennr, modes[bestMode]); XF86VidModeSetViewPort(display, screennr, 0, 0); UseXVidMode=true; } else { os::Printer::log("Could not find specified video mode, running windowed.", ELL_WARNING); CreationParams.Fullscreen = false; } XFree(modes); } else #endif #ifdef _IRR_LINUX_X11_RANDR_ if (XRRQueryExtension(display, &eventbase, &errorbase)) { s32 modeCount; XRRScreenConfiguration *config=XRRGetScreenInfo(display,DefaultRootWindow(display)); XRRScreenSize *modes=XRRConfigSizes(config,&modeCount); for (s32 i = 0; i<modeCount; ++i) { if (bestMode==-1 && (u32)modes[i].width >= Width && (u32)modes[i].height >= Height) bestMode = i; else if (bestMode!=-1 && (u32)modes[i].width >= Width && (u32)modes[i].height >= Height && modes[i].width < modes[bestMode].width && modes[i].height < modes[bestMode].height) bestMode = i; } if (bestMode != -1) { XRRSetScreenConfig(display,config,DefaultRootWindow(display),bestMode,oldRandrRotation,CurrentTime); UseXRandR=true; } XRRFreeScreenConfigInfo(config); } else #endif { os::Printer::log("VidMode or RandR extension must be installed to allow Irrlicht " "to switch to fullscreen mode. Running in windowed mode instead.", ELL_WARNING); CreationParams.Fullscreen = false; } } #ifdef _IRR_COMPILE_WITH_OPENGL_ GLXFBConfig glxFBConfig; int major, minor; bool isAvailableGLX=false; if (CreationParams.DriverType==video::EDT_OPENGL) { isAvailableGLX=glXQueryExtension(display,&major,&minor); if (isAvailableGLX && glXQueryVersion(display, &major, &minor)) { if (major==1 && minor>2) { const int MAX_SAMPLES = 16; // attribute array for the draw buffer int visualAttrBuffer[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_ALPHA_SIZE, CreationParams.WithAlphaChannel?1:0, GLX_DEPTH_SIZE, CreationParams.ZBufferBits, GLX_DOUBLEBUFFER, GL_TRUE, GLX_STENCIL_SIZE, 1, GLX_SAMPLE_BUFFERS_ARB, 1, GLX_SAMPLES_ARB, MAX_SAMPLES, None }; GLXFBConfig *configList=0; int nitems=0; if (!CreationParams.AntiAlias) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; } if (CreationParams.Stencilbuffer) { configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { visualAttrBuffer[19] >>= 1; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); CreationParams.AntiAlias=false; } else { //reenable multisampling visualAttrBuffer[17] = 1; visualAttrBuffer[19] = MAX_SAMPLES; } } } } // Next try without stencil buffer if (!configList) { if (CreationParams.Stencilbuffer) os::Printer::log("No stencilbuffer available, disabling stencil shadows.", ELL_WARNING); CreationParams.Stencilbuffer = false; visualAttrBuffer[15]=0; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { visualAttrBuffer[19] >>= 1; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); CreationParams.AntiAlias=false; } else { //reenable multisampling visualAttrBuffer[17] = 1; visualAttrBuffer[19] = MAX_SAMPLES; } } } } // Next try without double buffer if (!configList) { os::Printer::log("No doublebuffering available.", ELL_WARNING); visualAttrBuffer[13] = GL_FALSE; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (!configList && CreationParams.AntiAlias) { while (!configList && (visualAttrBuffer[19]>1)) { visualAttrBuffer[19] >>= 1; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); } if (!configList) { visualAttrBuffer[17] = 0; visualAttrBuffer[19] = 0; configList=glXChooseFBConfig(display, screennr, visualAttrBuffer,&nitems); if (configList) { os::Printer::log("No FSAA available.", ELL_WARNING); CreationParams.AntiAlias=false; } else { //reenable multisampling visualAttrBuffer[17] = 1; visualAttrBuffer[19] = MAX_SAMPLES; } } } } if (configList) { glxFBConfig=configList[0]; XFree(configList); UseGLXWindow=true; visual = glXGetVisualFromFBConfig(display,glxFBConfig); } }
bool DisplayResX::SwitchToVideoMode(int width, int height, double desired_rate) { double rate; DisplayResScreen desired_screen(width, height, 0, 0, -1.0, desired_rate); int idx = DisplayResScreen::FindBestMatch(m_videoModesUnsorted, desired_screen, rate); if (idx >= 0) { short finalrate; MythXDisplay *display = nullptr; XRRScreenConfiguration *cfg = GetScreenConfig(display); if (!cfg) return false; Rotation rot; XRRConfigCurrentConfiguration(cfg, &rot); // Search real xrandr rate for desired_rate finalrate = (short) rate; for (uint i = 0; i < m_videoModes.size(); i++) { if ((m_videoModes[i].Width() == width) && (m_videoModes[i].Height() == height)) { if (m_videoModes[i].Custom()) { finalrate = m_videoModes[i].realRates[rate]; LOG(VB_PLAYBACK, LOG_INFO, QString("Dynamic TwinView rate found, set %1Hz as " "XRandR %2") .arg(rate) .arg(finalrate)); } break; } } Window root = display->GetRoot(); Status status = XRRSetScreenConfigAndRate(display->GetDisplay(), cfg, root, idx, rot, finalrate, CurrentTime); XRRFreeScreenConfigInfo(cfg); // Force refresh of xf86VidMode current modeline cfg = XRRGetScreenInfo(display->GetDisplay(), root); if (cfg) { XRRFreeScreenConfigInfo(cfg); } delete display; if (RRSetConfigSuccess != status) LOG(VB_GENERAL, LOG_ERR, "XRRSetScreenConfigAndRate() call failed."); return RRSetConfigSuccess == status; } LOG(VB_GENERAL, LOG_ERR, "Desired Resolution and FrameRate not found."); return false; }
static int xrandr_resize(int xsz, int ysz, int rate, int just_checking) { #ifdef HAVE_X11_EXTENSIONS_XRANDR_H int event_base, error_base, ver_major, ver_minor, use_rate; XRRScreenConfiguration *xrr_config = 0; Status result = -1; /* must check at runtime for the availability of the extension */ if(!XRRQueryExtension(fgDisplay.Display, &event_base, &error_base)) { return -1; } XRRQueryVersion(fgDisplay.Display, &ver_major, &ver_minor); /* we only heed the rate if we CAN actually use it (Xrandr >= 1.1) and * the user actually cares about it (rate > 0) */ use_rate = ( rate > 0 ) && ( ( ver_major >= 1 ) || ( ver_major == 1 ) && ( ver_minor >= 1 ) ); /* this loop is only so that the whole thing will be repeated if someone * else changes video mode between our query the current information and * the attempt to change it. */ do { XRRScreenSize *ssizes; short *rates; Rotation rot; int i, ssizes_count, rates_count, curr, res_idx = -1; Time timestamp, cfg_timestamp; if(xrr_config) { XRRFreeScreenConfigInfo(xrr_config); } if(!(xrr_config = XRRGetScreenInfo(fgDisplay.Display, fgDisplay.RootWindow))) { fgWarning("XRRGetScreenInfo failed"); break; } ssizes = XRRConfigSizes(xrr_config, &ssizes_count); curr = XRRConfigCurrentConfiguration(xrr_config, &rot); timestamp = XRRConfigTimes(xrr_config, &cfg_timestamp); /* if either of xsz or ysz are unspecified, use the current values */ if(xsz <= 0) xsz = fgState.GameModeSize.X = ssizes[curr].width; if(ysz <= 0) ysz = fgState.GameModeSize.Y = ssizes[curr].height; if(xsz == ssizes[curr].width && ysz == ssizes[curr].height) { /* no need to switch, we're already in the requested resolution */ res_idx = curr; } else { for(i=0; i<ssizes_count; i++) { if(ssizes[i].width == xsz && ssizes[i].height == ysz) { res_idx = i; break; /* found it */ } } } if(res_idx == -1) break; /* no matching resolution */ #if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) if(rate <= 0) { fgState.GameModeRefresh = XRRConfigCurrentRate(xrr_config); } if(use_rate) { rate = fgState.GameModeRefresh; /* for the selected resolution, let's find out if there is * a matching refresh rate available. */ rates = XRRConfigRates(xrr_config, res_idx, &rates_count); for(i=0; i<rates_count; i++) { if(rates[i] == rate) { break; } } if(i == rates_count) { break; /* no matching rate */ } } #endif if(just_checking) { result = 0; break; } #if ( RANDR_MAJOR >= 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) if(use_rate) result = XRRSetScreenConfigAndRate(fgDisplay.Display, xrr_config, fgDisplay.RootWindow, res_idx, rot, rate, timestamp); else #endif result = XRRSetScreenConfig(fgDisplay.Display, xrr_config, fgDisplay.RootWindow, res_idx, rot, timestamp); } while(result == RRSetConfigInvalidTime); if(xrr_config) { XRRFreeScreenConfigInfo(xrr_config); } if(result == 0) { return 0; } #endif /* HAVE_X11_EXTENSIONS_XRANDR_H */ return -1; }
/* * Remembers the current visual settings, so that * we can change them and restore later... */ void fgPlatformRememberState( void ) { int event_base, error_base; /* * Remember the current pointer location before going fullscreen * for restoring it later: */ Window junk_window; unsigned int junk_mask; XQueryPointer(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow, &junk_window, &junk_window, &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &fgDisplay.pDisplay.DisplayPointerX, &fgDisplay.pDisplay.DisplayPointerY, &junk_mask); # ifdef HAVE_X11_EXTENSIONS_XRANDR_H if(XRRQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { XRRScreenConfiguration *xrr_config; XRRScreenSize *ssizes; Rotation rot; int ssize_count, curr; if((xrr_config = XRRGetScreenInfo(fgDisplay.pDisplay.Display, fgDisplay.pDisplay.RootWindow))) { ssizes = XRRConfigSizes(xrr_config, &ssize_count); curr = XRRConfigCurrentConfiguration(xrr_config, &rot); fgDisplay.pDisplay.prev_xsz = ssizes[curr].width; fgDisplay.pDisplay.prev_ysz = ssizes[curr].height; fgDisplay.pDisplay.prev_refresh = -1; # if ( RANDR_MAJOR > 1 ) || ( ( RANDR_MAJOR == 1 ) && ( RANDR_MINOR >= 1 ) ) if(fgState.GameModeRefresh != -1) { fgDisplay.pDisplay.prev_refresh = XRRConfigCurrentRate(xrr_config); } # endif fgDisplay.pDisplay.prev_size_valid = 1; XRRFreeScreenConfigInfo(xrr_config); } } # endif /* * This highly depends on the XFree86 extensions, * not approved as X Consortium standards */ # ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H if(!XF86VidModeQueryExtension(fgDisplay.pDisplay.Display, &event_base, &error_base)) { return; } /* * Remember the current ViewPort location of the screen to be able to * restore the ViewPort on LeaveGameMode(): */ if( !XF86VidModeGetViewPort( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, &fgDisplay.pDisplay.DisplayViewPortX, &fgDisplay.pDisplay.DisplayViewPortY ) ) fgWarning( "XF86VidModeGetViewPort failed" ); /* Query the current display settings: */ fgDisplay.pDisplay.DisplayModeValid = XF86VidModeGetModeLine( fgDisplay.pDisplay.Display, fgDisplay.pDisplay.Screen, &fgDisplay.pDisplay.DisplayModeClock, &fgDisplay.pDisplay.DisplayMode ); if( !fgDisplay.pDisplay.DisplayModeValid ) fgWarning( "XF86VidModeGetModeLine failed" ); # endif }
std::vector<VideoMode> VideoModeImpl::getFullscreenModes() { std::vector<VideoMode> modes; // Open a connection with the X server Display* display = OpenDisplay(); if (display) { // Retrieve the default screen number int screen = DefaultScreen(display); // Check if the XRandR extension is present int version; if (XQueryExtension(display, "RANDR", &version, &version, &version)) { // Get the current configuration XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen)); if (config) { // Get the available screen sizes int nbSizes; XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes); if (sizes && (nbSizes > 0)) { // Get the list of supported depths int nbDepths = 0; int* depths = XListDepths(display, screen, &nbDepths); if (depths && (nbDepths > 0)) { // Combine depths and sizes to fill the array of supported modes for (int i = 0; i < nbDepths; ++i) { for (int j = 0; j < nbSizes; ++j) { // Convert to VideoMode VideoMode mode(sizes[j].width, sizes[j].height, depths[i]); // Add it only if it is not already in the array if (std::find(modes.begin(), modes.end(), mode) == modes.end()) modes.push_back(mode); } } // Free the array of depths XFree(depths); } } // Free the configuration instance XRRFreeScreenConfigInfo(config); } else { // Failed to get the screen configuration err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl; } } else { // XRandr extension is not supported : we cannot get the video modes err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl; } // Close the connection with the X server CloseDisplay(display); } else { // We couldn't connect to the X server err() << "Failed to connect to the X server while trying to get the supported video modes" << std::endl; } return modes; }
XRRScreenConfiguration * uaw::ConcreteX11Connection::GetConfig (Display *display) const { return XRRGetScreenInfo (display, DefaultRootWindow (display)); }
int32_t run(Filesystem* fs, ConfigSettings* cs) { // http://tronche.com/gui/x/xlib/display/XInitThreads.html Status xs = XInitThreads(); CE_ASSERT(xs != 0, "XInitThreads: error"); CE_UNUSED(xs); _x11_display = XOpenDisplay(NULL); CE_ASSERT(_x11_display != NULL, "XOpenDisplay: error"); int screen = DefaultScreen(_x11_display); int depth = DefaultDepth(_x11_display, screen); Visual* visual = DefaultVisual(_x11_display, screen); _x11_parent_window = (cs->parent_window == 0) ? RootWindow(_x11_display, screen) : (Window) cs->parent_window; // Create main window XSetWindowAttributes win_attribs; win_attribs.background_pixmap = 0; win_attribs.border_pixel = 0; win_attribs.event_mask = FocusChangeMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; _x11_window = XCreateWindow(_x11_display , _x11_parent_window , 0 , 0 , cs->window_width , cs->window_height , 0 , depth , InputOutput , visual , CWBorderPixel | CWEventMask , &win_attribs); CE_ASSERT(_x11_window != None, "XCreateWindow: error"); // Do we have detectable autorepeat? Bool detectable; _x11_detectable_autorepeat = (bool) XkbSetDetectableAutoRepeat(_x11_display, true, &detectable); // Build hidden cursor Pixmap bm_no; XColor black, dummy; Colormap colormap; static char no_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; colormap = XDefaultColormap(_x11_display, screen); XAllocNamedColor(_x11_display, colormap, "black", &black, &dummy); bm_no = XCreateBitmapFromData(_x11_display, _x11_window, no_data, 8, 8); _x11_hidden_cursor = XCreatePixmapCursor(_x11_display, bm_no, bm_no, &black, &black, 0, 0); _wm_delete_message = XInternAtom(_x11_display, "WM_DELETE_WINDOW", False); XSetWMProtocols(_x11_display, _x11_window, &_wm_delete_message, 1); oswindow_set_window(_x11_display, _x11_window); bgfx::x11SetDisplayWindow(_x11_display, _x11_window); XMapRaised(_x11_display, _x11_window); // Save screen configuration _screen_config = XRRGetScreenInfo(_x11_display, RootWindow(_x11_display, screen)); Rotation rr_old_rot; const SizeID rr_old_sizeid = XRRConfigCurrentConfiguration(_screen_config, &rr_old_rot); // Start main thread MainThreadArgs mta; mta.fs = fs; mta.cs = cs; Thread main_thread; main_thread.start(func, &mta); while (!s_exit) { pump_events(); } main_thread.stop(); // Restore previous screen configuration Rotation rr_rot; const SizeID rr_sizeid = XRRConfigCurrentConfiguration(_screen_config, &rr_rot); if (rr_rot != rr_old_rot || rr_sizeid != rr_old_sizeid) { XRRSetScreenConfig(_x11_display , _screen_config , RootWindow(_x11_display, screen) , rr_old_sizeid , rr_old_rot , CurrentTime); } XRRFreeScreenConfigInfo(_screen_config); XDestroyWindow(_x11_display, _x11_window); XCloseDisplay(_x11_display); return EXIT_SUCCESS; }
GtkEGLSupport::GtkEGLSupport() { mNativeDisplay = getNativeDisplay(); mGLDisplay = getGLDisplay(); int dummy; if (XQueryExtension((Display*)mNativeDisplay, "RANDR", &dummy, &dummy, &dummy)) { XRRScreenConfiguration *screenConfig; mRandr = true; screenConfig = XRRGetScreenInfo((Display*)mNativeDisplay, DefaultRootWindow((Display*)mNativeDisplay)); if (screenConfig) { XRRScreenSize *screenSizes; int nSizes = 0; Rotation currentRotation; int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, ¤tRotation); screenSizes = XRRConfigSizes(screenConfig, &nSizes); mCurrentMode.first.first = screenSizes[currentSizeID].width; mCurrentMode.first.second = screenSizes[currentSizeID].height; mCurrentMode.second = XRRConfigCurrentRate(screenConfig); mOriginalMode = mCurrentMode; for (int sizeID = 0; sizeID < nSizes; sizeID++) { short *rates; int nRates = 0; rates = XRRConfigRates(screenConfig, sizeID, &nRates); for (int rate = 0; rate < nRates; rate++) { VideoMode mode; mode.first.first = screenSizes[sizeID].width; mode.first.second = screenSizes[sizeID].height; mode.second = rates[rate]; mVideoModes.push_back(mode); } } XRRFreeScreenConfigInfo(screenConfig); } } else { mCurrentMode.first.first = DisplayWidth((Display*)mNativeDisplay, DefaultScreen(mNativeDisplay)); mCurrentMode.first.second = DisplayHeight((Display*)mNativeDisplay, DefaultScreen(mNativeDisplay)); mCurrentMode.second = 0; mOriginalMode = mCurrentMode; mVideoModes.push_back(mCurrentMode); } EGLConfig *glConfigs; int config, nConfigs = 0; glConfigs = chooseGLConfig(NULL, &nConfigs); for (config = 0; config < nConfigs; config++) { int caveat, samples; getGLConfigAttrib(glConfigs[config], EGL_CONFIG_CAVEAT, &caveat); if (caveat != EGL_SLOW_CONFIG) { getGLConfigAttrib(glConfigs[config], EGL_SAMPLES, &samples); mSampleLevels.push_back(StringConverter::toString(samples)); } } free(glConfigs); removeDuplicates(mSampleLevels); }