summaryrefslogtreecommitdiffstats
path: root/src/glut/fbdev/gamemode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glut/fbdev/gamemode.c')
-rw-r--r--src/glut/fbdev/gamemode.c268
1 files changed, 248 insertions, 20 deletions
diff --git a/src/glut/fbdev/gamemode.c b/src/glut/fbdev/gamemode.c
index 3407c6e9887..f6d6e4044ef 100644
--- a/src/glut/fbdev/gamemode.c
+++ b/src/glut/fbdev/gamemode.c
@@ -24,10 +24,8 @@
* Written by Sean D'Epagnier (c) 2006
*/
-/* NOTICE: game mode will not be fully implemented until
- glutReshapeWindow is fully implemented */
-
#include <stdlib.h>
+#include <string.h>
#include <linux/fb.h>
@@ -35,44 +33,274 @@
#include "internal.h"
-void glutGameModeString(const char *string)
+int GameMode;
+
+static int ModePossible, DispChanged;
+static struct fb_var_screeninfo NormVarInfo, GameVarInfo;
+
+static GLFBDevContextPtr GameContext;
+static GLFBDevVisualPtr NormVisual;
+
+/* storage for non-gamemode callbacks */
+void (*KeyFuncs[2])(unsigned char key, int x, int y);
+static void (*NormFuncs[8])();
+
+static const char*SetOpers(const char *p, unsigned int *min, unsigned int *max)
{
-
+ char *endptr;
+ int comp = *p, val, neq = 0;
+
+ if(p[1] == '=') {
+ neq = 0;
+ p++;
+ }
+
+ val = strtol(p+1, &endptr, 10);
+ if(endptr == p+1)
+ return p;
+
+ switch(comp) {
+ case '=':
+ *min = *max = val;
+ break;
+ case '!':
+ *min = val + 1;
+ *max = val - 1;
+ break;
+ case '<':
+ *max = val - neq;
+ break;
+ case '>':
+ *min = val + neq;
+ break;
+ }
+ return endptr;
}
+void glutGameModeString(const char *string)
+{
+ const char *p = string;
+ unsigned int minb = 15, maxb = 32;
+ unsigned int minw = 0, maxw = -1;
+ unsigned int minh, maxh = -1;
+ unsigned int minf = 0, maxf = MAX_VSYNC;
+ char *endptr;
+ int count = -1, val;
+
+ ModePossible = 0;
+
+ if(DisplayMode & GLUT_INDEX)
+ minb = maxb = 8;
+
+ again:
+ count++;
+ if((val = strtol(p, &endptr, 10)) && *endptr=='x') {
+ maxw = minw = val;
+ p = endptr + 1;
+ maxh = minh = strtol(p, &endptr, 10);
+ p = endptr;
+ goto again;
+ }
+
+ if(*p == ':') {
+ minb = strtol(p+1, &endptr, 10);
+ p = endptr;
+ if(DisplayMode & GLUT_INDEX) {
+ if(minb != 8)
+ return;
+ } else
+ if(minb != 15 && minb != 16 && minb != 24 && minb != 32)
+ return;
+ maxb = minb;
+ goto again;
+ }
+
+ if(*p == '@') {
+ minf = strtol(p+1, &endptr, 10) - 5;
+ maxf = minf + 10;
+ p = endptr;
+ goto again;
+ }
+
+ if(count == 0)
+ while(*p) {
+ if(*p == ' ')
+ p++;
+ else
+ if(memcmp(p, "bpp", 3) == 0)
+ p = SetOpers(p+3, &minb, &maxb);
+ else
+ if(memcmp(p, "height", 6) == 0)
+ p = SetOpers(p+6, &minh, &maxh);
+ else
+ if(memcmp(p, "hertz", 5) == 0)
+ p = SetOpers(p+5, &minf, &maxf);
+ else
+ if(memcmp(p, "width", 5) == 0)
+ p = SetOpers(p+5, &minw, &maxw);
+ else
+ if(p = strchr(p, ' '))
+ p++;
+ else
+ break;
+ }
+
+ NormVarInfo = VarInfo;
+ if(!ParseFBModes(minw, maxw, minh, maxh, minf, maxf))
+ return;
+
+ GameVarInfo = VarInfo;
+ VarInfo = NormVarInfo;
+
+ /* determine optimal bitdepth, make sure we have enough video memory */
+ if(VarInfo.bits_per_pixel && VarInfo.bits_per_pixel <= maxb)
+ GameVarInfo.bits_per_pixel = VarInfo.bits_per_pixel;
+ else
+ GameVarInfo.bits_per_pixel = maxb;
+
+ while(FixedInfo.smem_len < GameVarInfo.xres * GameVarInfo.yres
+ * GameVarInfo.bits_per_pixel / 8) {
+ if(GameVarInfo.bits_per_pixel < minb)
+ return;
+ GameVarInfo.bits_per_pixel = ((GameVarInfo.bits_per_pixel+1)/8)*8-8;
+ }
+
+ ModePossible = 1;
+}
+
int glutEnterGameMode(void)
{
if(ActiveMenu)
return 0;
+
+ if(!ModePossible)
+ return 0;
+
+ if(GameMode) {
+ if(!memcmp(&GameVarInfo, &VarInfo, sizeof VarInfo)) {
+ DispChanged = 0;
+ return 1;
+ }
+ glutLeaveGameMode();
+ }
+
+ if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &GameVarInfo))
+ return 0;
+
+ NormVarInfo = VarInfo;
+ VarInfo = GameVarInfo;
+
+ NormVisual = Visual;
+ SetVideoMode();
+ CreateVisual();
+ CreateBuffer();
+
+ if(!(GameContext = glFBDevCreateContext(Visual, NULL))) {
+ sprintf(exiterror, "Failure to create Context\n");
+ exit(0);
+ }
+
+ if(!glFBDevMakeCurrent( GameContext, Buffer, Buffer )) {
+ sprintf(exiterror, "Failure to Make Game Current\n");
+ exit(0);
+ }
+
+ InitializeCursor();
+
+ KeyFuncs[0] = KeyboardFunc;
+ KeyFuncs[1] = KeyboardUpFunc;
+
+ NormFuncs[0] = DisplayFunc;
+ NormFuncs[1] = ReshapeFunc;
+ NormFuncs[2] = MouseFunc;
+ NormFuncs[3] = MotionFunc;
+ NormFuncs[4] = PassiveMotionFunc;
+ NormFuncs[5] = VisibilityFunc;
+ NormFuncs[6] = SpecialFunc;
+ NormFuncs[7] = SpecialUpFunc;
+
+ DisplayFunc = NULL;
+ ReshapeFunc = NULL;
+ KeyboardFunc = NULL;
+ KeyboardUpFunc = NULL;
+ MouseFunc = NULL;
+ MotionFunc = NULL;
+ PassiveMotionFunc = NULL;
+ VisibilityFunc = NULL;
+ SpecialFunc = SpecialUpFunc = NULL;
+
+ DispChanged = 1;
+ GameMode = 1;
+ Visible = 1;
+ VisibleSwitch = 1;
+ Redisplay = 1;
return 1;
}
void glutLeaveGameMode(void)
{
+ if(!GameMode)
+ return;
+
+ glFBDevDestroyContext(GameContext);
+ glFBDevDestroyVisual(Visual);
+
+ VarInfo = NormVarInfo;
+ Visual = NormVisual;
+
+ if(Visual) {
+ SetVideoMode();
+ CreateBuffer();
+
+ if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) {
+ sprintf(exiterror, "Failure to Make Current\n");
+ exit(0);
+ }
+
+ Redisplay = 1;
+ }
+
+ KeyboardFunc = KeyFuncs[0];
+ KeyboardUpFunc = KeyFuncs[1];
+
+
+ DisplayFunc = NormFuncs[0];
+ ReshapeFunc = NormFuncs[1];
+ MouseFunc = NormFuncs[2];
+ MotionFunc = NormFuncs[3];
+ PassiveMotionFunc = NormFuncs[4];
+ VisibilityFunc = NormFuncs[5];
+ SpecialFunc = NormFuncs[6];
+ SpecialUpFunc = NormFuncs[7];
+
+ GameMode = 0;
}
int glutGameModeGet(GLenum mode) {
switch(mode) {
case GLUT_GAME_MODE_ACTIVE:
- return 1;
+ return GameMode;
case GLUT_GAME_MODE_POSSIBLE:
- return 1;
+ return ModePossible;
+ case GLUT_GAME_MODE_DISPLAY_CHANGED:
+ return DispChanged;
+ }
+
+ if(!ModePossible)
+ return -1;
+
+ switch(mode) {
case GLUT_GAME_MODE_WIDTH:
- return VarInfo.xres;
+ return GameVarInfo.xres;
case GLUT_GAME_MODE_HEIGHT:
- return VarInfo.yres;
+ return GameVarInfo.yres;
case GLUT_GAME_MODE_PIXEL_DEPTH:
- return VarInfo.bits_per_pixel;
+ return GameVarInfo.bits_per_pixel;
case GLUT_GAME_MODE_REFRESH_RATE:
- if(VarInfo.pixclock) {
- int htotal = VarInfo.left_margin + VarInfo.xres
- + VarInfo.right_margin + VarInfo.hsync_len;
- int vtotal = VarInfo.upper_margin + VarInfo.yres
- + VarInfo.lower_margin + VarInfo.vsync_len;
- return 1E12/VarInfo.pixclock/htotal/vtotal;
- }
- return 0;
- case GLUT_GAME_MODE_DISPLAY_CHANGED:
- return 0;
+ return 1E12/GameVarInfo.pixclock
+ / (GameVarInfo.left_margin + GameVarInfo.xres
+ + GameVarInfo.right_margin + GameVarInfo.hsync_len)
+ / (GameVarInfo.upper_margin + GameVarInfo.yres
+ + GameVarInfo.lower_margin + GameVarInfo.vsync_len);
}
}