summaryrefslogtreecommitdiffstats
path: root/src/glut/fbdev/fbdev.c
diff options
context:
space:
mode:
authorSean D'Epagnier <[email protected]>2006-08-10 10:21:17 +0000
committerSean D'Epagnier <[email protected]>2006-08-10 10:21:17 +0000
commit7196cddb3a404292858101f9cd1a5061e422d2c1 (patch)
treeaa3f79e21b08d9f114c7b1984e6c86c114081cfe /src/glut/fbdev/fbdev.c
parent54e15d65858c1d1eeea7291059766686cf2e1671 (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/fbdev.c')
-rw-r--r--src/glut/fbdev/fbdev.c465
1 files changed, 312 insertions, 153 deletions
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)