Merge branch 'nouveau-import'
[mesa.git] / src / glut / fbdev / gamemode.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 * Copyright (C) 1995-2006 Brian Paul
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22 * Library for glut using mesa fbdev driver
23 *
24 * Written by Sean D'Epagnier (c) 2006
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <linux/fb.h>
32
33 #include <GL/glut.h>
34
35 #include "internal.h"
36
37 int GameMode;
38
39 static int ModePossible, DispChanged;
40 static struct fb_var_screeninfo NormVarInfo, GameVarInfo;
41
42 static GLFBDevContextPtr GameContext;
43 static GLFBDevVisualPtr NormVisual;
44
45 /* storage for non-gamemode callbacks */
46 void (*KeyFuncs[2])(unsigned char key, int x, int y);
47 static void (*NormFuncs[8])();
48
49 static const char*SetOpers(const char *p, unsigned int *min, unsigned int *max)
50 {
51 char *endptr;
52 int comp = *p, val, neq = 0;
53
54 if(p[1] == '=') {
55 neq = 0;
56 p++;
57 }
58
59 val = strtol(p+1, &endptr, 10);
60 if(endptr == p+1)
61 return p;
62
63 switch(comp) {
64 case '=':
65 *min = *max = val;
66 break;
67 case '!':
68 *min = val + 1;
69 *max = val - 1;
70 break;
71 case '<':
72 *max = val - neq;
73 break;
74 case '>':
75 *min = val + neq;
76 break;
77 }
78 return endptr;
79 }
80
81 void glutGameModeString(const char *string)
82 {
83 const char *p = string;
84 unsigned int minb = 15, maxb = 32;
85 unsigned int minw = 0, maxw = -1;
86 unsigned int minh, maxh = -1;
87 unsigned int minf = 0, maxf = MAX_VSYNC;
88 char *endptr;
89 int count = -1, val;
90
91 ModePossible = 0;
92
93 if(DisplayMode & GLUT_INDEX)
94 minb = maxb = 8;
95
96 again:
97 count++;
98 if((val = strtol(p, &endptr, 10)) && *endptr=='x') {
99 maxw = minw = val;
100 p = endptr + 1;
101 maxh = minh = strtol(p, &endptr, 10);
102 p = endptr;
103 goto again;
104 }
105
106 if(*p == ':') {
107 minb = strtol(p+1, &endptr, 10);
108 p = endptr;
109 if(DisplayMode & GLUT_INDEX) {
110 if(minb != 8)
111 return;
112 } else
113 if(minb != 15 && minb != 16 && minb != 24 && minb != 32)
114 return;
115 maxb = minb;
116 goto again;
117 }
118
119 if(*p == '@') {
120 minf = strtol(p+1, &endptr, 10) - 5;
121 maxf = minf + 10;
122 p = endptr;
123 goto again;
124 }
125
126 if(count == 0)
127 while(*p) {
128 if(*p == ' ')
129 p++;
130 else
131 if(memcmp(p, "bpp", 3) == 0)
132 p = SetOpers(p+3, &minb, &maxb);
133 else
134 if(memcmp(p, "height", 6) == 0)
135 p = SetOpers(p+6, &minh, &maxh);
136 else
137 if(memcmp(p, "hertz", 5) == 0)
138 p = SetOpers(p+5, &minf, &maxf);
139 else
140 if(memcmp(p, "width", 5) == 0)
141 p = SetOpers(p+5, &minw, &maxw);
142 else
143 if(p = strchr(p, ' '))
144 p++;
145 else
146 break;
147 }
148
149 NormVarInfo = VarInfo;
150 if(!ParseFBModes(minw, maxw, minh, maxh, minf, maxf))
151 return;
152
153 GameVarInfo = VarInfo;
154 VarInfo = NormVarInfo;
155
156 /* determine optimal bitdepth, make sure we have enough video memory */
157 if(VarInfo.bits_per_pixel && VarInfo.bits_per_pixel <= maxb)
158 GameVarInfo.bits_per_pixel = VarInfo.bits_per_pixel;
159 else
160 GameVarInfo.bits_per_pixel = maxb;
161
162 while(FixedInfo.smem_len < GameVarInfo.xres * GameVarInfo.yres
163 * GameVarInfo.bits_per_pixel / 8) {
164 if(GameVarInfo.bits_per_pixel < minb)
165 return;
166 GameVarInfo.bits_per_pixel = ((GameVarInfo.bits_per_pixel+1)/8)*8-8;
167 }
168
169 ModePossible = 1;
170 }
171
172 int glutEnterGameMode(void)
173 {
174 if(ActiveMenu)
175 return 0;
176
177 if(!ModePossible)
178 return 0;
179
180 if(GameMode) {
181 if(!memcmp(&GameVarInfo, &VarInfo, sizeof VarInfo)) {
182 DispChanged = 0;
183 return 1;
184 }
185 glutLeaveGameMode();
186 }
187
188 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &GameVarInfo))
189 return 0;
190
191 NormVarInfo = VarInfo;
192 VarInfo = GameVarInfo;
193
194 NormVisual = Visual;
195 SetVideoMode();
196 CreateVisual();
197 CreateBuffer();
198
199 if(!(GameContext = glFBDevCreateContext(Visual, NULL))) {
200 sprintf(exiterror, "Failure to create Context\n");
201 exit(0);
202 }
203
204 if(!glFBDevMakeCurrent( GameContext, Buffer, Buffer )) {
205 sprintf(exiterror, "Failure to Make Game Current\n");
206 exit(0);
207 }
208
209 InitializeCursor();
210
211 KeyFuncs[0] = KeyboardFunc;
212 KeyFuncs[1] = KeyboardUpFunc;
213
214 NormFuncs[0] = DisplayFunc;
215 NormFuncs[1] = ReshapeFunc;
216 NormFuncs[2] = MouseFunc;
217 NormFuncs[3] = MotionFunc;
218 NormFuncs[4] = PassiveMotionFunc;
219 NormFuncs[5] = VisibilityFunc;
220 NormFuncs[6] = SpecialFunc;
221 NormFuncs[7] = SpecialUpFunc;
222
223 DisplayFunc = NULL;
224 ReshapeFunc = NULL;
225 KeyboardFunc = NULL;
226 KeyboardUpFunc = NULL;
227 MouseFunc = NULL;
228 MotionFunc = NULL;
229 PassiveMotionFunc = NULL;
230 VisibilityFunc = NULL;
231 SpecialFunc = SpecialUpFunc = NULL;
232
233 DispChanged = 1;
234 GameMode = 1;
235 Visible = 1;
236 VisibleSwitch = 1;
237 Redisplay = 1;
238 return 1;
239 }
240
241 void glutLeaveGameMode(void)
242 {
243 if(!GameMode)
244 return;
245
246 glFBDevDestroyContext(GameContext);
247 glFBDevDestroyVisual(Visual);
248
249 VarInfo = NormVarInfo;
250 Visual = NormVisual;
251
252 if(Visual) {
253 SetVideoMode();
254 CreateBuffer();
255
256 if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) {
257 sprintf(exiterror, "Failure to Make Current\n");
258 exit(0);
259 }
260
261 Redisplay = 1;
262 }
263
264 KeyboardFunc = KeyFuncs[0];
265 KeyboardUpFunc = KeyFuncs[1];
266
267 DisplayFunc = NormFuncs[0];
268 ReshapeFunc = NormFuncs[1];
269 MouseFunc = NormFuncs[2];
270 MotionFunc = NormFuncs[3];
271 PassiveMotionFunc = NormFuncs[4];
272 VisibilityFunc = NormFuncs[5];
273 SpecialFunc = NormFuncs[6];
274 SpecialUpFunc = NormFuncs[7];
275
276 GameMode = 0;
277 }
278
279 int glutGameModeGet(GLenum mode) {
280 switch(mode) {
281 case GLUT_GAME_MODE_ACTIVE:
282 return GameMode;
283 case GLUT_GAME_MODE_POSSIBLE:
284 return ModePossible;
285 case GLUT_GAME_MODE_DISPLAY_CHANGED:
286 return DispChanged;
287 }
288
289 if(!ModePossible)
290 return -1;
291
292 switch(mode) {
293 case GLUT_GAME_MODE_WIDTH:
294 return GameVarInfo.xres;
295 case GLUT_GAME_MODE_HEIGHT:
296 return GameVarInfo.yres;
297 case GLUT_GAME_MODE_PIXEL_DEPTH:
298 return GameVarInfo.bits_per_pixel;
299 case GLUT_GAME_MODE_REFRESH_RATE:
300 return 1E12/GameVarInfo.pixclock
301 / (GameVarInfo.left_margin + GameVarInfo.xres
302 + GameVarInfo.right_margin + GameVarInfo.hsync_len)
303 / (GameVarInfo.upper_margin + GameVarInfo.yres
304 + GameVarInfo.lower_margin + GameVarInfo.vsync_len);
305 }
306 }