diff options
author | Sean D'Epagnier <[email protected]> | 2006-08-10 10:21:17 +0000 |
---|---|---|
committer | Sean D'Epagnier <[email protected]> | 2006-08-10 10:21:17 +0000 |
commit | 7196cddb3a404292858101f9cd1a5061e422d2c1 (patch) | |
tree | aa3f79e21b08d9f114c7b1984e6c86c114081cfe /src/glut/fbdev | |
parent | 54e15d65858c1d1eeea7291059766686cf2e1671 (diff) |
Added initial multisampling support to glfbdev driver.
Fully implemented glutGameMode, and added vidresize stubs to make
Added support for glutReshapeDisplay to change video mode but not lose
current mesa context.
implementation glut 5 complient.
Fixed many minor bugs
Updated docs
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) +{ +} |