From: Sean D'Epagnier Date: Thu, 10 Aug 2006 10:21:17 +0000 (+0000) Subject: Added initial multisampling support to glfbdev driver. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7196cddb3a404292858101f9cd1a5061e422d2c1;p=mesa.git 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 --- diff --git a/docs/glfbdev-driver.html b/docs/glfbdev-driver.html index f191b390fbe..981df7c088a 100644 --- a/docs/glfbdev-driver.html +++ b/docs/glfbdev-driver.html @@ -70,7 +70,7 @@ tty group as well

4. Using fbdevglut

Almost all of the programs in the progs directory use glut, and they compile with fbdevglut. -Currently glBlendFunc is not working with glFBDev. +

To compile the redbook sample programs:

diff --git a/include/GL/glfbdev.h b/include/GL/glfbdev.h
index d2b12815c9f..4e25e7b0566 100644
--- a/include/GL/glfbdev.h
+++ b/include/GL/glfbdev.h
@@ -49,6 +49,7 @@ typedef struct GLFBDevContextRec *GLFBDevContextPtr;
 #define GLFBDEV_STENCIL_SIZE    103
 #define GLFBDEV_ACCUM_SIZE      104
 #define GLFBDEV_LEVEL           105
+#define GLFBDEV_MULTISAMPLE     106
 #define GLFBDEV_NONE              0
 
 /* For glFBDevGetString */
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 
 
 #include 
-#include 
 #include 
 
 #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 
-#include 
 #include 
 
 #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 
@@ -41,16 +44,15 @@
 #include 
 
 #include 
-#include 
 #include 
 
 #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
+#include 
 
 #include 
 
@@ -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 
 #include 
+#include 
 
 #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= *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 
+
+#include 
+
+#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)
+{
+}
diff --git a/src/mesa/drivers/fbdev/glfbdev.c b/src/mesa/drivers/fbdev/glfbdev.c
index 412c09955f8..21b6165bb14 100644
--- a/src/mesa/drivers/fbdev/glfbdev.c
+++ b/src/mesa/drivers/fbdev/glfbdev.c
@@ -281,7 +281,7 @@ glFBDevGetString( int str )
    case GLFBDEV_VENDOR:
       return "Mesa Project";
    case GLFBDEV_VERSION:
-      return "1.0.0";
+      return "1.0.1";
    default:
       return NULL;
    }
@@ -372,6 +372,10 @@ glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
       case GLFBDEV_LEVEL:
          /* ignored for now */
          break;
+      case GLFBDEV_MULTISAMPLE:
+	 numSamples = attrib[1];
+	 attrib++;
+         break;
       default:
          /* unexpected token */
          _mesa_free(vis);
@@ -420,13 +424,6 @@ glFBDevCreateVisual( const struct fb_fix_screeninfo *fixInfo,
       }
       else {
          _mesa_problem(NULL, "Unsupported fbdev RGB visual/bitdepth!\n");
-         /*
-         printf("fixInfo->visual = 0x%x\n", fixInfo->visual);
-         printf("varInfo->bits_per_pixel = %d\n", varInfo->bits_per_pixel);
-         printf("varInfo->red.offset = %d\n", varInfo->red.offset);
-         printf("varInfo->green.offset = %d\n", varInfo->green.offset);
-         printf("varInfo->blue.offset = %d\n", varInfo->blue.offset);
-         */
          _mesa_free(vis);
          return NULL;
       }
@@ -586,7 +583,6 @@ new_glfbdev_renderbuffer(void *bufferStart, const GLFBDevVisualPtr visual)
    return rb;
 }
 
-
 GLFBDevBufferPtr
 glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
                      const struct fb_var_screeninfo *varInfo,
@@ -600,6 +596,11 @@ glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
    ASSERT(frontBuffer);
    ASSERT(size > 0);
 
+   /* this is to update the visual if there was a resize and the
+      buffer is created again */
+   visual->var = *varInfo;
+   visual->fix = *fixInfo;
+
    if (visual->fix.visual != fixInfo->visual ||
        visual->fix.type != fixInfo->type ||
        visual->var.bits_per_pixel != varInfo->bits_per_pixel ||
@@ -624,7 +625,21 @@ glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
                           &frontrb->Base);
    /* add back renderbuffer */
    if (visual->glvisual.doubleBufferMode) {
+      int malloced = !backBuffer;
+      if (malloced) {
+         /* malloc a back buffer */
+         backBuffer = _mesa_malloc(size);
+         if (!backBuffer) {
+            _mesa_free_framebuffer_data(&buf->glframebuffer);
+            _mesa_free(buf);
+            return NULL;
+         }
+      }
+
       backrb = new_glfbdev_renderbuffer(backBuffer, visual);
+      if(malloced)
+	 backrb->mallocedBuffer = GL_TRUE;
+
       _mesa_add_renderbuffer(&buf->glframebuffer, BUFFER_BACK_LEFT,
                              &backrb->Base);
    }
@@ -637,32 +652,12 @@ glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
                                 GL_FALSE, /* alpha */
                                 GL_FALSE /* aux bufs */);
 
-
-
    buf->fix = *fixInfo;   /* struct assignment */
    buf->var = *varInfo;   /* struct assignment */
    buf->visual = visual;  /* ptr assignment */
    buf->size = size;
    buf->bytesPerPixel = visual->var.bits_per_pixel / 8;
 
-   if (visual->glvisual.doubleBufferMode) {
-      if (!backBuffer) {
-         /* malloc a back buffer */
-         backrb->Base.Data = _mesa_malloc(size);
-         if (!backrb->Base.Data) {
-            _mesa_free_framebuffer_data(&buf->glframebuffer);
-            _mesa_free(buf);
-            return NULL;
-         }
-         backrb->mallocedBuffer = GL_TRUE;
-      }
-   }
-   /* this causes segfault:
-   else {
-      backrb->bottom = NULL;
-      backrb->rowStride = 0;
-      }*/
-
    return buf;
 }