/* * Mesa 3-D graphics library * Version: 6.5 * Copyright (C) 1995-2006 Brian Paul * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Library for glut using mesa fbdev driver * * Written by Sean D'Epagnier (c) 2006 */ #include #include #include #include #include #include "internal.h" 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 GameMode; case GLUT_GAME_MODE_POSSIBLE: return ModePossible; case GLUT_GAME_MODE_DISPLAY_CHANGED: return DispChanged; } if(!ModePossible) return -1; switch(mode) { case GLUT_GAME_MODE_WIDTH: return GameVarInfo.xres; case GLUT_GAME_MODE_HEIGHT: return GameVarInfo.yres; case GLUT_GAME_MODE_PIXEL_DEPTH: return GameVarInfo.bits_per_pixel; case GLUT_GAME_MODE_REFRESH_RATE: 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); } }