diff options
Diffstat (limited to 'src/glut/fbdev')
-rw-r--r-- | src/glut/fbdev/Makefile | 7 | ||||
-rw-r--r-- | src/glut/fbdev/colormap.c | 7 | ||||
-rw-r--r-- | src/glut/fbdev/cursor.c | 10 | ||||
-rw-r--r-- | src/glut/fbdev/ext.c | 1 | ||||
-rw-r--r-- | src/glut/fbdev/fbdev.c | 465 | ||||
-rw-r--r-- | src/glut/fbdev/gamemode.c | 268 | ||||
-rw-r--r-- | src/glut/fbdev/input.c | 94 | ||||
-rw-r--r-- | src/glut/fbdev/internal.h | 20 | ||||
-rw-r--r-- | src/glut/fbdev/menu.c | 42 | ||||
-rw-r--r-- | src/glut/fbdev/state.c | 13 | ||||
-rw-r--r-- | src/glut/fbdev/vidresize.c | 55 |
11 files changed, 722 insertions, 260 deletions
diff --git a/src/glut/fbdev/Makefile b/src/glut/fbdev/Makefile index 39a48f36343..4f70efe2794 100644 --- a/src/glut/fbdev/Makefile +++ b/src/glut/fbdev/Makefile @@ -6,8 +6,8 @@ include $(TOP)/configs/current GLX_SHARED = $(TOP)/src/glut/glx SHAPES = $(TOP)/src/glut/mini -GLUT_MAJOR = 3 -GLUT_MINOR = 7 +GLUT_MAJOR = 5 +GLUT_MINOR = 0 GLUT_TINY = 1 INCLUDES = -I$(TOP)/include -I$(GLX_SHARED) @@ -22,7 +22,8 @@ CORE_SOURCES = \ state.c \ input.c \ callback.c \ - gamemode.c + gamemode.c \ + vidresize.c GLX_SHARED_SOURCES = \ $(GLX_SHARED)/glut_8x13.c \ diff --git a/src/glut/fbdev/colormap.c b/src/glut/fbdev/colormap.c index 9a6dea20dc9..157296d15c1 100644 --- a/src/glut/fbdev/colormap.c +++ b/src/glut/fbdev/colormap.c @@ -29,7 +29,6 @@ #include <linux/fb.h> #include <GL/gl.h> -#include <GL/glfbdev.h> #include <GL/glut.h> #include "internal.h" @@ -53,9 +52,9 @@ static void FindReverseMap(int r, int g, int b) unsigned int minv = -1, mini = 0; for(i=0; i<256; i++) { int val = 0; - val += abs(r-(ColorMap.red[i]>>shift)); - val += abs(g-(ColorMap.green[i]>>shift)); - val += abs(b-(ColorMap.blue[i]>>shift)); + val += abs(r-(RedColorMap[i]>>shift)); + val += abs(g-(GreenColorMap[i]>>shift)); + val += abs(b-(BlueColorMap[i]>>shift)); if(val < minv) { minv = val; mini = i; diff --git a/src/glut/fbdev/cursor.c b/src/glut/fbdev/cursor.c index b753a5c9ff5..06ae2d6f54e 100644 --- a/src/glut/fbdev/cursor.c +++ b/src/glut/fbdev/cursor.c @@ -44,7 +44,7 @@ static unsigned char *MouseBuffer; void InitializeCursor(void) { - if((MouseBuffer = malloc(CURSOR_WIDTH * CURSOR_HEIGHT + if(!MouseBuffer && (MouseBuffer = malloc(CURSOR_WIDTH * CURSOR_HEIGHT * VarInfo.bits_per_pixel / 8)) == NULL) { sprintf(exiterror, "malloc failure\n"); exit(0); @@ -216,10 +216,10 @@ void SwapCursor(void) if(miny < 0) miny = 0; - if(minx + sizex > VarInfo.xres) - sizex = VarInfo.xres - minx; - if(miny + sizey > VarInfo.yres) - sizey = VarInfo.yres - miny; + if(minx + sizex > VarInfo.xres - CURSOR_WIDTH) + sizex = VarInfo.xres - CURSOR_WIDTH - minx; + if(miny + sizey > VarInfo.yres - CURSOR_HEIGHT) + sizey = VarInfo.yres - CURSOR_HEIGHT - miny; off = FixedInfo.line_length * miny + minx * VarInfo.bits_per_pixel / 8; stride = (sizex + CURSOR_WIDTH) * VarInfo.bits_per_pixel / 8; diff --git a/src/glut/fbdev/ext.c b/src/glut/fbdev/ext.c index 1746bf33e9c..4a3c185a16d 100644 --- a/src/glut/fbdev/ext.c +++ b/src/glut/fbdev/ext.c @@ -25,7 +25,6 @@ */ #include <GL/gl.h> -#include <GL/glfbdev.h> #include <GL/glut.h> #include "internal.h" diff --git a/src/glut/fbdev/fbdev.c b/src/glut/fbdev/fbdev.c index fcbd4f8da28..ce7d187b66d 100644 --- a/src/glut/fbdev/fbdev.c +++ b/src/glut/fbdev/fbdev.c @@ -22,6 +22,9 @@ * Library for glut using mesa fbdev driver * * Written by Sean D'Epagnier (c) 2006 + * + * To improve on this library, maybe support subwindows or overlays, + * I (sean at depagnier dot com) will do my best to help. */ #include <errno.h> @@ -41,16 +44,15 @@ #include <linux/vt.h> #include <GL/gl.h> -#include <GL/glfbdev.h> #include <GL/glut.h> #include "internal.h" #define FBMODES "/etc/fb.modes" - struct fb_fix_screeninfo FixedInfo; -struct fb_var_screeninfo VarInfo, OrigVarInfo; +struct fb_var_screeninfo VarInfo; +static struct fb_var_screeninfo OrigVarInfo; static int DesiredDepth = 0; @@ -64,9 +66,9 @@ struct GlutTimer *GlutTimers = NULL; struct timeval StartTime; /* per window data */ -static GLFBDevContextPtr Context; -static GLFBDevBufferPtr Buffer; -static GLFBDevVisualPtr Visual; +GLFBDevContextPtr Context; +GLFBDevBufferPtr Buffer; +GLFBDevVisualPtr Visual; int Redisplay; int Visible; @@ -75,13 +77,9 @@ int Active; /* we have to poll to see if we are visible on a framebuffer that is not active */ int VisiblePoll; +int Swapping, VTSwitch; static int FramebufferIndex; -static int RequiredWidth; -static int RequiredHeight; -static int InitialWidthHint; -static int InitialHeightHint; - static int Initialized; char exiterror[256]; @@ -105,6 +103,9 @@ void TestVisible(void) { static void Cleanup(void) { + if(GameMode) + glutLeaveGameMode(); + if(ConsoleFD != -1) RestoreVT(); @@ -136,7 +137,7 @@ static void Cleanup(void) if(exiterror[0]) fprintf(stderr, "[glfbdev glut] %s", exiterror); -} + } static void CrashHandler(int sig) { @@ -162,10 +163,9 @@ static void removeArgs(int *argcp, char **argv, int num) void glutInit (int *argcp, char **argv) { - int i; - int nomouse = 0; - int nokeyboard = 0; - int usestdin = 0; + int i, nomouse = 0, nokeyboard = 0, usestdin = 0; + int RequiredWidth = 0, RequiredHeight; + char *fbdev; /* parse out args */ for (i = 1; i < *argcp;) { @@ -242,6 +242,61 @@ void glutInit (int *argcp, char **argv) if(nokeyboard == 0) InitializeVT(usestdin); + fbdev = getenv("FRAMEBUFFER"); + if(fbdev) { +#ifdef MULTIHEAD + if(!sscanf(fbdev, "/dev/fb%d", &FramebufferIndex)) + if(!sscanf(fbdev, "/dev/fb/%d", &FramebufferIndex)) + sprintf(exiterror, "Could not determine Framebuffer index!\n"); +#endif + } else { + static char fb[128]; + struct fb_con2fbmap confb; + int fd = open("/dev/fb0", O_RDWR); + + FramebufferIndex = 0; + + confb.console = CurrentVT; + if(ioctl(fd, FBIOGET_CON2FBMAP, &confb) != -1) + FramebufferIndex = confb.framebuffer; + sprintf(fb, "/dev/fb%d", FramebufferIndex); + fbdev = fb; + close(fd); + } + + /* open the framebuffer device */ + FrameBufferFD = open(fbdev, O_RDWR); + if (FrameBufferFD < 0) { + sprintf(exiterror, "Error opening %s: %s\n", fbdev, strerror(errno)); + exit(0); + } + + /* Get the fixed screen info */ + if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) { + sprintf(exiterror, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n", + strerror(errno)); + exit(0); + } + + /* get the variable screen info */ + if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) { + sprintf(exiterror, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n", + strerror(errno)); + exit(0); + } + + /* operate on a copy */ + VarInfo = OrigVarInfo; + + /* set the depth, resolution, etc */ + if(RequiredWidth) + if(!ParseFBModes(RequiredWidth, RequiredWidth, RequiredHeight, + RequiredHeight, 0, MAX_VSYNC)) { + sprintf(exiterror, "No mode (%dx%d) found in "FBMODES"\n", + RequiredWidth, RequiredHeight); + exit(0); + } + Initialized = 1; } @@ -250,17 +305,109 @@ void glutInitDisplayMode (unsigned int mode) DisplayMode = mode; } +static const char *GetStrVal(const char *p, int *set, int min, int max) +{ + char *endptr; + int comp = *p, val; + + if(p[1] == '=') + p++; + + if(*p == '\0') + return p; + + val = strtol(p+1, &endptr, 10); + + if(endptr == p+1) + return p; + + switch(comp) { + case '!': + if(val == min) + val = max; + else + val = min; + break; + case '<': + val = min; + break; + case '>': + val = max; + break; + } + + if(val < min || val > max) { + sprintf(exiterror, "display string value out of range\n"); + exit(0); + } + + *set = val; + + return endptr; +} + +static void SetAttrib(int val, int attr) +{ + if(val) + DisplayMode |= attr; + else + DisplayMode &= ~attr; +} + +void glutInitDisplayString(const char *string) +{ + const char *p = string; + int val; + while(*p) { + if(*p == ' ') + p++; + else + if(memcmp(p, "acca", 4) == 0) { + p = GetStrVal(p+4, &AccumSize, 1, 32); + SetAttrib(AccumSize, GLUT_ACCUM); + } else + if(memcmp(p, "acc", 3) == 0) { + p = GetStrVal(p+3, &AccumSize, 1, 32); + SetAttrib(AccumSize, GLUT_ACCUM); + } else + if(memcmp(p, "depth", 5) == 0) { + p = GetStrVal(p+5, &DepthSize, 12, 32); + SetAttrib(DepthSize, GLUT_DEPTH); + } else + if(memcmp(p, "double", 6) == 0) { + val = 1; + p = GetStrVal(p+6, &val, 0, 1); + SetAttrib(val, GLUT_DOUBLE); + } else + if(memcmp(p, "index", 5) == 0) { + val = 1; + p = GetStrVal(p+5, &val, 0, 1); + SetAttrib(val, GLUT_INDEX); + } else + if(memcmp(p, "stencil", 7) == 0) { + p = GetStrVal(p+7, &StencilSize, 0, 1); + SetAttrib(StencilSize, GLUT_STENCIL); + } else + if(memcmp(p, "samples", 7) == 0) { + NumSamples = 1; + p = GetStrVal(p+7, &NumSamples, 0, 16); + SetAttrib(NumSamples, GLUT_MULTISAMPLE); + } else + if(p = strchr(p, ' ')) + p++; + else + break; + } +} + void glutInitWindowPosition (int x, int y) { } void glutInitWindowSize (int width, int height) { - InitialWidthHint = width; - InitialHeightHint = height; } - static void ProcessTimers(void) { if(GlutTimers && GlutTimers->time < glutGet(GLUT_ELAPSED_TIME)) { @@ -289,10 +436,12 @@ void glutMainLoop(void) else if(VisiblePoll) TestVisible(); + else + usleep(1); if(IdleFunc) IdleFunc(); - + if(VisibleSwitch) { VisibleSwitch = 0; if(VisibilityFunc) @@ -314,7 +463,7 @@ void glutMainLoop(void) } } -static void ParseFBModes(void) +int ParseFBModes(int minw, int maxw, int minh, int maxh, int minf, int maxf) { char buf[1024]; struct fb_var_screeninfo vi = VarInfo; @@ -322,44 +471,34 @@ static void ParseFBModes(void) FILE *fbmodes = fopen(FBMODES, "r"); if(!fbmodes) { - sprintf(exiterror, "Warning: could not open " - FBMODES" using current mode\n"); - return; + sprintf(exiterror, "Warning: could not open "FBMODES"\n"); + return 0; } - if(InitialWidthHint == 0 && InitialHeightHint == 0 - && RequiredWidth == 0) - return; /* use current mode */ - while(fgets(buf, sizeof buf, fbmodes)) { char *c; - int v; + int v, bpp, freq; if(!(c = strstr(buf, "geometry"))) continue; v = sscanf(c, "geometry %d %d %d %d %d", &vi.xres, &vi.yres, - &vi.xres_virtual, &vi.yres_virtual, &vi.bits_per_pixel); + &vi.xres_virtual, &vi.yres_virtual, &bpp); if(v != 5) continue; - /* now we have to decide what is best */ - if(RequiredWidth) { - if(RequiredWidth != vi.xres || RequiredHeight != vi.yres) + if(maxw < minw) { + if(maxw < vi.xres && minw > vi.xres) continue; - } else { - if(VarInfo.xres < vi.xres && VarInfo.xres < InitialWidthHint) - v++; - if(VarInfo.xres > vi.xres && vi.xres > InitialWidthHint) - v++; - - if(VarInfo.yres < vi.yres && VarInfo.yres < InitialHeightHint) - v++; - if(VarInfo.yres > vi.yres && vi.yres > InitialHeightHint) - v++; - - if(v < 7) + } else + if(maxw < vi.xres || minw > vi.xres) + continue; + + if(maxh < minh) { + if(maxh < vi.yres && minh > vi.yres) + continue; + } else + if(maxh < vi.yres || minh > vi.yres) continue; - } fgets(buf, sizeof buf, fbmodes); if(!(c = strstr(buf, "timings"))) @@ -368,103 +507,34 @@ static void ParseFBModes(void) v = sscanf(c, "timings %d %d %d %d %d %d %d", &vi.pixclock, &vi.left_margin, &vi.right_margin, &vi.upper_margin, &vi.lower_margin, &vi.hsync_len, &vi.vsync_len); + if(v != 7) continue; - VarInfo = vi; /* finally found a better mode */ - if(RequiredWidth) { - fclose(fbmodes); - return; - } + freq = 1E12/vi.pixclock + /(vi.left_margin + vi.xres + vi.right_margin + vi.hsync_len) + /(vi.upper_margin + vi.yres + vi.lower_margin + vi.vsync_len); + + if(maxf < minf) { + if(maxf < freq && minf > freq) + continue; + } else + if(maxf < freq || minf > freq) + continue; + + VarInfo = vi; + fclose(fbmodes); + return 1; } fclose(fbmodes); - if(RequiredWidth) { - sprintf(exiterror, "No mode (%dx%d) found in "FBMODES"\n", - RequiredWidth, RequiredHeight); - exit(0); - } + return 0; } /* ---------- Window Management ----------*/ -int glutCreateWindow (const char *title) +void SetVideoMode(void) { - char *fbdev; - int attribs[9], i, mask, size; - - if(Initialized == 0) { - int argc = 0; - char *argv[] = {NULL}; - glutInit(&argc, argv); - } - - if(Context) - return 0; - - fbdev = getenv("FRAMEBUFFER"); - if(fbdev) { -#ifdef MULTIHEAD - if(!sscanf(fbdev, "/dev/fb%d", &FramebufferIndex)) - if(!sscanf(fbdev, "/dev/fb/%d", &FramebufferIndex)) - sprintf(exiterror, "Could not determine Framebuffer index!\n"); -#endif - } else { - static char fb[128]; - struct fb_con2fbmap confb; - int fd = open("/dev/fb0", O_RDWR); - - FramebufferIndex = 0; - - confb.console = CurrentVT; - if(ioctl(fd, FBIOGET_CON2FBMAP, &confb) != -1) - FramebufferIndex = confb.framebuffer; - sprintf(fb, "/dev/fb%d", FramebufferIndex); - fbdev = fb; - close(fd); - } - - /* open the framebuffer device */ - FrameBufferFD = open(fbdev, O_RDWR); - if (FrameBufferFD < 0) { - sprintf(exiterror, "Error opening %s: %s\n", fbdev, strerror(errno)); - exit(0); - } - - /* Get the fixed screen info */ - if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) { - sprintf(exiterror, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n", - strerror(errno)); - exit(0); - } - - /* get the variable screen info */ - if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) { - sprintf(exiterror, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n", - strerror(errno)); - exit(0); - } - - /* operate on a copy */ - VarInfo = OrigVarInfo; - - /* set the depth, resolution, etc */ - ParseFBModes(); - - if(DisplayMode & GLUT_INDEX) - VarInfo.bits_per_pixel = 8; - else - if(VarInfo.bits_per_pixel == 8) - VarInfo.bits_per_pixel = 32; - - if (DesiredDepth) - VarInfo.bits_per_pixel = DesiredDepth; - - VarInfo.xoffset = 0; - VarInfo.yoffset = 0; - VarInfo.nonstd = 0; - VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */ - /* set new variable screen info */ if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) { sprintf(exiterror, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n", @@ -498,8 +568,16 @@ int glutCreateWindow (const char *title) /* initialize colormap */ LoadColorMap(); +} + +void CreateBuffer() +{ + int size = VarInfo.xres_virtual * VarInfo.yres_virtual + * VarInfo.bits_per_pixel / 8; /* mmap the framebuffer into our address space */ + if(FrameBuffer) + munmap(FrameBuffer, FixedInfo.smem_len); FrameBuffer = mmap(0, FixedInfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, FrameBufferFD, 0); if (FrameBuffer == MAP_FAILED) { @@ -508,8 +586,30 @@ int glutCreateWindow (const char *title) exit(0); } - mask = DisplayMode; - for(i=0; i<8 && mask; i++) { + if(DisplayMode & GLUT_DOUBLE) { + free(BackBuffer); + if(!(BackBuffer = malloc(size))) { + sprintf(exiterror, "Failed to allocate double buffer\n"); + exit(0); + } + } else + BackBuffer = FrameBuffer; + + if(Buffer) + glFBDevDestroyBuffer(Buffer); + + if(!(Buffer = glFBDevCreateBuffer( &FixedInfo, &VarInfo, Visual, + FrameBuffer, BackBuffer, size))) { + sprintf(exiterror, "Failure to create Buffer\n"); + exit(0); + } +} + +void CreateVisual(void) +{ + int i, mask = DisplayMode; + int attribs[20]; + for(i=0; i<sizeof(attribs)/sizeof(*attribs) && mask; i++) { if(mask & GLUT_DOUBLE) { attribs[i] = GLFBDEV_DOUBLE_BUFFER; mask &= ~GLUT_DOUBLE; @@ -549,6 +649,13 @@ int glutCreateWindow (const char *title) i--; continue; } + + if(mask & GLUT_MULTISAMPLE) { + attribs[i] = GLFBDEV_MULTISAMPLE; + attribs[++i] = NumSamples; + mask &= ~GLUT_MULTISAMPLE; + continue; + } sprintf(exiterror, "Invalid mode from glutInitDisplayMode\n"); exit(0); @@ -560,23 +667,37 @@ int glutCreateWindow (const char *title) sprintf(exiterror, "Failure to create Visual\n"); exit(0); } +} - size = VarInfo.xres_virtual * VarInfo.yres_virtual - * VarInfo.bits_per_pixel / 8; - if(DisplayMode & GLUT_DOUBLE) { - if(!(BackBuffer = malloc(size))) { - sprintf(exiterror, "Failed to allocate double buffer\n"); - exit(0); - } - } else - BackBuffer = FrameBuffer; - - if(!(Buffer = glFBDevCreateBuffer( &FixedInfo, &VarInfo, Visual, - FrameBuffer, BackBuffer, size))) { - sprintf(exiterror, "Failure to create Buffer\n"); - exit(0); +int glutCreateWindow (const char *title) +{ + if(Initialized == 0) { + int argc = 0; + char *argv[] = {NULL}; + glutInit(&argc, argv); } + if(Context) + return 0; + + if(DisplayMode & GLUT_INDEX) + VarInfo.bits_per_pixel = 8; + else + if(VarInfo.bits_per_pixel == 8) + VarInfo.bits_per_pixel = 32; + + if (DesiredDepth) + VarInfo.bits_per_pixel = DesiredDepth; + + VarInfo.xoffset = 0; + VarInfo.yoffset = 0; + VarInfo.nonstd = 0; + VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */ + + SetVideoMode(); + CreateVisual(); + CreateBuffer(); + if(!(Context = glFBDevCreateContext(Visual, NULL))) { sprintf(exiterror, "Failure to create Context\n"); exit(0); @@ -590,6 +711,8 @@ int glutCreateWindow (const char *title) InitializeCursor(); InitializeMenus(); + glutSetWindowTitle(title); + Visible = 1; VisibleSwitch = 1; Redisplay = 1; @@ -628,12 +751,21 @@ void glutSwapBuffers(void) { glFlush(); - if(Visible && DisplayMode & GLUT_DOUBLE) { - if(ActiveMenu) - DrawMenus(); - if(MouseEnabled) - DrawCursor(); + if(ActiveMenu) + DrawMenus(); + if(MouseEnabled) + DrawCursor(); + + if(DisplayMode & GLUT_DOUBLE && Visible) { + Swapping = 1; glFBDevSwapBuffers(Buffer); + Swapping = 0; + } + + if(VTSwitch) { + if(ioctl(ConsoleFD, VT_ACTIVATE, VTSwitch) < 0) + sprintf(exiterror, "Error switching console\n"); + VTSwitch = 0; } } @@ -643,6 +775,25 @@ void glutPositionWindow(int x, int y) void glutReshapeWindow(int width, int height) { + if(GameMode) + return; + + if(!ParseFBModes(width, width, height, height, 0, MAX_VSYNC)) + return; + + SetVideoMode(); + CreateBuffer(); + + if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) { + sprintf(exiterror, "Failure to Make Current\n"); + exit(0); + } + + InitializeMenus(); + + if(ReshapeFunc) + ReshapeFunc(VarInfo.xres, VarInfo.yres); + Redisplay = 1; } void glutFullScreen(void) @@ -659,10 +810,12 @@ void glutPushWindow(void) void glutShowWindow(void) { + Visible = 1; } void glutHideWindow(void) { + Visible = 0; } static void UnIconifyWindow(int sig) @@ -677,6 +830,9 @@ static void UnIconifyWindow(int sig) strerror(errno)); exit(0); } + Redisplay = 1; + VisibleSwitch = 1; + Visible = 1; } void glutIconifyWindow(void) @@ -691,6 +847,9 @@ void glutIconifyWindow(void) void glutSetWindowTitle(const char *name) { + /* escape code to set title in screen */ + if(getenv("TERM") && memcmp(getenv("TERM"), "screen", 6) == 0) + printf("\033k%s\033\\", name); } void glutSetIconTitle(const char *name) 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); } } diff --git a/src/glut/fbdev/input.c b/src/glut/fbdev/input.c index 7daec8c9143..4fbd94d0701 100644 --- a/src/glut/fbdev/input.c +++ b/src/glut/fbdev/input.c @@ -126,8 +126,11 @@ static void KeyboardHandler(int sig) if(!release && labelval >= K_F1 && labelval <= K_F12) if(KeyboardModifiers & GLUT_ACTIVE_ALT) { /* VT switch, we must do it */ - if(ioctl(ConsoleFD, VT_ACTIVATE, labelval - K_F1 + 1) < 0) - sprintf(exiterror, "Error switching console\n"); + if(Swapping) + VTSwitch = labelval - K_F1 + 1; + else + if(ioctl(ConsoleFD, VT_ACTIVATE, labelval - K_F1 + 1) < 0) + sprintf(exiterror, "Error switching console\n"); return; } write(kbdpipe[1], &code, 1); @@ -456,6 +459,7 @@ static int ReadMouse(void) PassiveMotionFunc(MouseX, MouseY); EraseCursor(); + if(ActiveMenu) Redisplay = 1; else @@ -515,14 +519,17 @@ void InitializeVT(int usestdin) struct vt_mode vt; char console[128]; - /* terminos settings for straight-through mode */ + signal(SIGIO, SIG_IGN); + + /* save old terminos settings */ if (tcgetattr(0, &OldTermios) < 0) { sprintf(exiterror, "tcgetattr failed\n"); exit(0); } tio = OldTermios; - + + /* terminos settings for straight-through mode */ tio.c_lflag &= ~(ICANON | ECHO | ISIG); tio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); tio.c_iflag |= IGNBRK; @@ -607,8 +614,8 @@ void InitializeVT(int usestdin) } /* use SIGIO so VT switching can work if the program is locked */ - if(ConsoleFD) signal(SIGIO, KeyboardHandler); + pipe(kbdpipe); if(fcntl(kbdpipe[0], F_SETFL, O_NONBLOCK | O_ASYNC) < 0) { @@ -642,64 +649,63 @@ void InitializeVT(int usestdin) void RestoreVT(void) { - if(ConsoleFD >= 0) - if (tcsetattr(0, TCSANOW, &OldTermios) < 0) - fprintf(stderr, "tcsetattr failed\n"); + if(ConsoleFD < 0) + return; - if(ConsoleFD > 0) { - /* restore keyboard state */ - if (ioctl(ConsoleFD, VT_SETMODE, &OldVTMode) < 0) - fprintf(stderr, "Failed to set vtmode\n"); + if (tcsetattr(0, TCSANOW, &OldTermios) < 0) + fprintf(stderr, "tcsetattr failed\n"); - if (ioctl(ConsoleFD, KDSKBMODE, OldKDMode) < 0) - fprintf(stderr, "ioctl KDSKBMODE failed!\n"); + if(ConsoleFD == 0) + return; - /* if we were in text mode, switching to graphics and back restores - the colormap */ - if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) - fprintf(stderr, "ioctl KDSETMODE failed!\n"); + /* restore keyboard state */ + if (ioctl(ConsoleFD, VT_SETMODE, &OldVTMode) < 0) + fprintf(stderr, "Failed to set vtmode\n"); - if(ioctl(ConsoleFD, KDSETMODE, OldMode) < 0) - fprintf(stderr, "ioctl KDSETMODE failed!\n"); + if (ioctl(ConsoleFD, KDSKBMODE, OldKDMode) < 0) + fprintf(stderr, "ioctl KDSKBMODE failed!\n"); - close(ConsoleFD); - } + if(ioctl(ConsoleFD, KDSETMODE, OldMode) < 0) + fprintf(stderr, "ioctl KDSETMODE failed!\n"); + + close(ConsoleFD); } void InitializeMouse(void) { #ifdef HAVE_GPM - if(GpmMouse) { + if(!GpmMouse) +#endif + { + const char *mousedev = getenv("MOUSE"); + if(!mousedev) + mousedev = MOUSEDEV; + if((MouseFD = open(mousedev, O_RDONLY)) >= 0) { + if(!MouseSpeed) + MouseSpeed = 1; + NumMouseButtons = 3; + return; + } + } +#ifdef HAVE_GPM + { Gpm_Connect conn; int c; conn.eventMask = ~0; /* Want to know about all the events */ conn.defaultMask = 0; /* don't handle anything by default */ conn.minMod = 0; /* want everything */ conn.maxMod = ~0; /* all modifiers included */ - if(Gpm_Open(&conn, 0) == -1) { - fprintf(stderr, "Cannot open gpmctl. Continuing without Mouse\n"); + if(Gpm_Open(&conn, 0) != -1) { + if(!MouseSpeed) + MouseSpeed = 8; + NumMouseButtons = 3; return; } - - if(!MouseSpeed) - MouseSpeed = 5; - } else + fprintf(stderr, "Cannot open gpmctl.\n"); + } #endif - { - const char *mousedev = getenv("MOUSE"); - if(!mousedev) - mousedev = MOUSEDEV; - if((MouseFD = open(mousedev, O_RDONLY)) < 0) { - fprintf(stderr,"Cannot open %s.\n" - "Continuing without Mouse\n", MOUSEDEV); - return; - } - - if(!MouseSpeed) - MouseSpeed = 1; - } - - NumMouseButtons = 3; + fprintf(stderr,"Cannot open %s.\n" + "Continuing without Mouse\n", MOUSEDEV); } void CloseMouse(void) diff --git a/src/glut/fbdev/internal.h b/src/glut/fbdev/internal.h index ca5dc1a6397..082cd4f6f3a 100644 --- a/src/glut/fbdev/internal.h +++ b/src/glut/fbdev/internal.h @@ -26,6 +26,7 @@ #include <sys/time.h> #include <linux/fb.h> +#include <GL/glfbdev.h> #define MULTIHEAD /* enable multihead hacks, it allows the program to continue drawing @@ -34,16 +35,23 @@ screen corruption that requires C-l to fix */ #define HAVE_GPM +#define MAX_VSYNC 200 + /* this causes these symbols to not be exported */ #pragma GCC visibility push(hidden) + +/* --------- fbdev ------------ */ extern int Redisplay; extern int Visible; extern int VisibleSwitch; extern int Active; extern int VisiblePoll; +extern int Swapping, VTSwitch; void TestVisible(void); +int ParseFBModes(int, int, int, int, int, int); +void CreateVisual(void); extern int FrameBufferFD; extern unsigned char *FrameBuffer; @@ -53,7 +61,11 @@ extern int DisplayMode; extern char exiterror[256]; extern struct fb_fix_screeninfo FixedInfo; -extern struct fb_var_screeninfo VarInfo, OrigVarInfo; +extern struct fb_var_screeninfo VarInfo; + +extern GLFBDevContextPtr Context; +extern GLFBDevBufferPtr Buffer; +extern GLFBDevVisualPtr Visual; /* --- colormap --- */ #define REVERSECMAPSIZELOG 3 @@ -65,6 +77,7 @@ extern unsigned short RedColorMap[256], extern unsigned char ReverseColorMap[REVERSECMAPSIZE] [REVERSECMAPSIZE] [REVERSECMAPSIZE]; +void LoadOldColorMap(void); void LoadColorMap(void); void UnloadColorMap(void); void RestoreColorMap(void); @@ -108,7 +121,7 @@ void OpenMenu(void); void CloseMenu(void); /* --- state --- */ -extern int AccumSize, DepthSize, StencilSize; +extern int AccumSize, DepthSize, StencilSize, NumSamples; extern struct timeval StartTime; extern int KeyboardModifiers; @@ -156,4 +169,7 @@ struct GlutTimer { extern struct GlutTimer *GlutTimers; +/* ------- Game Mode -------- */ +extern int GameMode; + #pragma GCC visibility pop diff --git a/src/glut/fbdev/menu.c b/src/glut/fbdev/menu.c index 8ac0ed39879..f5a5ef75434 100644 --- a/src/glut/fbdev/menu.c +++ b/src/glut/fbdev/menu.c @@ -42,7 +42,6 @@ int ActiveMenu; int CurrentMenu; static double MenuProjection[16]; -static double MenuModelview[16]; static int AttachedMenus[3]; static int NumMenus = 1; @@ -55,14 +54,8 @@ void InitializeMenus(void) glPushMatrix(); glLoadIdentity(); gluOrtho2D(0.0, VarInfo.xres, VarInfo.yres, 0.0); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glViewport(0, 0, VarInfo.xres, VarInfo.yres); glGetDoublev(GL_PROJECTION_MATRIX, MenuProjection); - glGetDoublev(GL_MODELVIEW_MATRIX, MenuModelview); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); + glPopMatrix(); glPopAttrib(); } @@ -72,7 +65,7 @@ void FreeMenus(void) int i, j; for(i = 1; i<NumMenus; i++) { - for(j = 1; i<Menus[i].NumItems; j++) + for(j = 0; j<Menus[i].NumItems; j++) free(Menus[i].Items[j].name); free(Menus[i].Items); } @@ -101,9 +94,10 @@ static int DrawMenu(int menu, int x, int *y) { int i; int ret = 1; + for(i=0; i < Menus[menu].NumItems; i++) { char *s = Menus[menu].Items[i].name; - int a =0; + int a = 0; if(MouseY >= *y && MouseY < *y + MENU_FONT_HEIGHT && MouseX >= x && MouseX < x + Menus[menu].width) { a = 1; @@ -133,18 +127,26 @@ static int DrawMenu(int menu, int x, int *y) void DrawMenus(void) { - int x = Menus[ActiveMenu].x; - int y = Menus[ActiveMenu].y; + int x, y; + + if(GameMode) + return; + + x = Menus[ActiveMenu].x; + y = Menus[ActiveMenu].y; /* save old settings */ - glPushAttrib(-1); + glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT + | GL_ENABLE_BIT | GL_VIEWPORT_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix(); - glLoadMatrixd(MenuModelview); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadMatrixd(MenuProjection); + glViewport(0, 0, VarInfo.xres, VarInfo.yres); glDisable(GL_DEPTH_TEST); glDisable(GL_ALPHA_TEST); @@ -153,7 +155,7 @@ void DrawMenus(void) glDisable(GL_TEXTURE_2D); glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_AND_REVERSE); - + if(DrawMenu(ActiveMenu, x, &y)) Menus[ActiveMenu].selected = -1; @@ -171,8 +173,14 @@ void OpenMenu(void) MenuStatusFunc(GLUT_MENU_IN_USE, MouseX, MouseY); if(MenuStateFunc) MenuStateFunc(GLUT_MENU_IN_USE); - Menus[ActiveMenu].x = MouseX - Menus[ActiveMenu].width/2; - Menus[ActiveMenu].y = MouseY - Menus[ActiveMenu].NumItems*MENU_FONT_HEIGHT/2; + Menus[ActiveMenu].x = MouseX-Menus[ActiveMenu].width/2; + + if(Menus[ActiveMenu].x < 0) + Menus[ActiveMenu].x = 0; + if(Menus[ActiveMenu].x + Menus[ActiveMenu].width >= VarInfo.xres) + Menus[ActiveMenu].x = VarInfo.xres - Menus[ActiveMenu].width - 1; + + Menus[ActiveMenu].y = MouseY-Menus[ActiveMenu].NumItems*MENU_FONT_HEIGHT/2; Menus[ActiveMenu].selected = -1; } diff --git a/src/glut/fbdev/state.c b/src/glut/fbdev/state.c index dadd2ad7200..bca675c52c4 100644 --- a/src/glut/fbdev/state.c +++ b/src/glut/fbdev/state.c @@ -37,6 +37,7 @@ int AccumSize = 16; /* per channel size of accumulation buffer */ int DepthSize = DEFAULT_SOFTWARE_DEPTH_BITS; int StencilSize = STENCIL_BITS; +int NumSamples = 4; int glutGet(GLenum state) { @@ -89,7 +90,7 @@ int glutGet(GLenum state) return 256; return 0; case GLUT_WINDOW_NUM_SAMPLES: - return 0; + return NumSamples; case GLUT_WINDOW_STEREO: return 0; case GLUT_WINDOW_CURSOR: @@ -174,16 +175,6 @@ int glutDeviceGet(GLenum info) return -1; } -int glutVideoResizeGet(GLenum param) -{ - switch(param) { - case GLUT_VIDEO_RESIZE_POSSIBLE: - return 0; - - } - return -1; -} - int glutGetModifiers(void){ return KeyboardModifiers; } diff --git a/src/glut/fbdev/vidresize.c b/src/glut/fbdev/vidresize.c new file mode 100644 index 00000000000..960b0186233 --- /dev/null +++ b/src/glut/fbdev/vidresize.c @@ -0,0 +1,55 @@ +/* + * 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 + */ + +/* Notice, if you know how to implement these functions correctly + please proceed */ + +#include <stdlib.h> + +#include <GL/glut.h> + +#include "internal.h" + +int glutVideoResizeGet(GLenum param) +{ + return 0; +} + +void glutSetupVideoResizing(void) +{ +} + +void glutStopVideoResizing(void) +{ +} + +void glutVideoResize(int x, int y, int width, int height) +{ +} + +void glutVideoPan(int x, int y, int width, int height) +{ +} |