Blender  V2.93
GHOST_DisplayManagerX11.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * Video mode switching
19  * Copyright (C) 1997-2001 Id Software, Inc.
20  * Ported from Quake 2 by Alex Fraser <alex@phatcore.com>
21  */
22 
27 #include <stdio.h>
28 
29 #ifdef WITH_X11_XF86VMODE
30 # include <X11/Xlib.h>
31 # include <X11/extensions/xf86vmode.h>
32 #endif
33 
35 #include "GHOST_SystemX11.h"
36 
38  : GHOST_DisplayManager(), m_system(system)
39 {
40  /* nothing to do. */
41 }
42 
44 {
45  numDisplays = m_system->getNumDisplays();
46  return GHOST_kSuccess;
47 }
48 
50  GHOST_TInt32 &numSettings) const
51 {
52 #ifdef WITH_X11_XF86VMODE
53  int majorVersion, minorVersion;
54  XF86VidModeModeInfo **vidmodes;
55  Display *dpy = m_system->getXDisplay();
56 
57  GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
58 
59  if (dpy == NULL)
60  return GHOST_kFailure;
61 
62  majorVersion = minorVersion = 0;
63  if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
64  fprintf(stderr, "Error: XF86VidMode extension missing!\n");
65  return GHOST_kFailure;
66  }
67 
68  if (XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes)) {
69  XFree(vidmodes);
70  }
71 
72 #else
73  /* We only have one X11 setting at the moment. */
74  GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
75  numSettings = 1;
76 #endif
77 
78  (void)display;
79  return GHOST_kSuccess;
80 }
81 
82 /* from SDL2 */
83 #ifdef WITH_X11_XF86VMODE
84 static int calculate_rate(XF86VidModeModeInfo *info)
85 {
86  return (info->htotal && info->vtotal) ? (1000 * info->dotclock / (info->htotal * info->vtotal)) :
87  0;
88 }
89 #endif
90 
92  GHOST_TInt32 index,
93  GHOST_DisplaySetting &setting) const
94 {
95  Display *dpy = m_system->getXDisplay();
96 
97  if (dpy == NULL)
98  return GHOST_kFailure;
99 
100  (void)display;
101 
102 #ifdef WITH_X11_XF86VMODE
103  int majorVersion, minorVersion;
104 
105  GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
106 
107  majorVersion = minorVersion = 0;
108  if (XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
109  XF86VidModeModeInfo **vidmodes;
110  int numSettings;
111 
112  if (XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes)) {
113  GHOST_ASSERT(index < numSettings, "Requested setting outside of valid range.\n");
114 
115  setting.xPixels = vidmodes[index]->hdisplay;
116  setting.yPixels = vidmodes[index]->vdisplay;
117  setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy));
118  setting.frequency = calculate_rate(vidmodes[index]);
119  XFree(vidmodes);
120 
121  return GHOST_kSuccess;
122  }
123  }
124  else {
125  fprintf(stderr, "Warning: XF86VidMode extension missing!\n");
126  /* fallback to non xf86vmode below */
127  }
128 #endif /* WITH_X11_XF86VMODE */
129 
130  GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
131  GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
132  (void)index;
133 
134  setting.xPixels = DisplayWidth(dpy, DefaultScreen(dpy));
135  setting.yPixels = DisplayHeight(dpy, DefaultScreen(dpy));
136  setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy));
137  setting.frequency = 60.0f;
138 
139  return GHOST_kSuccess;
140 }
141 
143  GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
144 {
145  /* According to the xf86vidmodegetallmodelines man page,
146  * "The first element of the array corresponds to the current video mode."
147  */
148  return getDisplaySetting(display, 0, setting);
149 }
150 
152  GHOST_TUns8 /*display*/, const GHOST_DisplaySetting &setting)
153 {
154 #ifdef WITH_X11_XF86VMODE
155  /* Mode switching code ported from SDL:
156  * See: src/video/x11/SDL_x11modes.c:set_best_resolution
157  */
158  int majorVersion, minorVersion;
159  XF86VidModeModeInfo **vidmodes;
160  Display *dpy = m_system->getXDisplay();
161  int scrnum, num_vidmodes;
162 
163  if (dpy == NULL)
164  return GHOST_kFailure;
165 
166  scrnum = DefaultScreen(dpy);
167 
168  /* Get video mode list */
169  majorVersion = minorVersion = 0;
170  if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
171  fprintf(stderr, "Error: XF86VidMode extension missing!\n");
172  return GHOST_kFailure;
173  }
174 # ifdef DEBUG
175  printf("Using XFree86-VidModeExtension Version %d.%d\n", majorVersion, minorVersion);
176 # endif
177 
178  if (XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes)) {
179  int best_fit = -1;
180 
181  for (int i = 0; i < num_vidmodes; i++) {
182  if (vidmodes[i]->hdisplay < setting.xPixels || vidmodes[i]->vdisplay < setting.yPixels) {
183  continue;
184  }
185 
186  if (best_fit == -1 || (vidmodes[i]->hdisplay < vidmodes[best_fit]->hdisplay) ||
187  (vidmodes[i]->hdisplay == vidmodes[best_fit]->hdisplay &&
188  vidmodes[i]->vdisplay < vidmodes[best_fit]->vdisplay)) {
189  best_fit = i;
190  continue;
191  }
192 
193  if ((vidmodes[i]->hdisplay == vidmodes[best_fit]->hdisplay) &&
194  (vidmodes[i]->vdisplay == vidmodes[best_fit]->vdisplay)) {
195  if (!setting.frequency) {
196  /* Higher is better, right? */
197  if (calculate_rate(vidmodes[i]) > calculate_rate(vidmodes[best_fit])) {
198  best_fit = i;
199  }
200  }
201  else {
202  if (abs(calculate_rate(vidmodes[i]) - (int)setting.frequency) <
203  abs(calculate_rate(vidmodes[best_fit]) - (int)setting.frequency)) {
204  best_fit = i;
205  }
206  }
207  }
208  }
209 
210  if (best_fit != -1) {
211 # ifdef DEBUG
212  printf("Switching to video mode %dx%d %dx%d %d\n",
213  vidmodes[best_fit]->hdisplay,
214  vidmodes[best_fit]->vdisplay,
215  vidmodes[best_fit]->htotal,
216  vidmodes[best_fit]->vtotal,
217  calculate_rate(vidmodes[best_fit]));
218 # endif
219 
220  /* change to the mode */
221  XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
222 
223  /* Move the viewport to top left */
224  XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
225  }
226 
227  XFree(vidmodes);
228  }
229  else {
230  return GHOST_kFailure;
231  }
232 
233  XFlush(dpy);
234  return GHOST_kSuccess;
235 
236 #else
237  (void)setting;
238 
239  /* Just pretend the request was successful. */
240  return GHOST_kSuccess;
241 #endif
242 }
#define GHOST_ASSERT(x, info)
Definition: GHOST_Debug.h:79
int GHOST_TInt32
Definition: GHOST_Types.h:63
GHOST_TSuccess
Definition: GHOST_Types.h:91
@ GHOST_kFailure
Definition: GHOST_Types.h:91
@ GHOST_kSuccess
Definition: GHOST_Types.h:91
unsigned char GHOST_TUns8
Definition: GHOST_Types.h:60
GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting &setting) const
GHOST_DisplayManagerX11(GHOST_SystemX11 *system)
GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting &setting)
GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting &setting) const
GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32 &numSettings) const
GHOST_TSuccess getNumDisplays(GHOST_TUns8 &numDisplays) const
Display * getXDisplay()
GHOST_TUns8 getNumDisplays() const
GHOST_TUns32 bpp
Definition: GHOST_Types.h:584
GHOST_TUns32 xPixels
Definition: GHOST_Types.h:580
GHOST_TUns32 frequency
Definition: GHOST_Types.h:586
GHOST_TUns32 yPixels
Definition: GHOST_Types.h:582
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186