<h1>4. Using fbdevglut</h1>
Almost all of the programs in the progs directory use glut, and they compile with fbdevglut.
-Currently glBlendFunc is not working with glFBDev.
+
<p>
To compile the redbook sample programs:
<pre>
#define GLFBDEV_STENCIL_SIZE 103
#define GLFBDEV_ACCUM_SIZE 104
#define GLFBDEV_LEVEL 105
+#define GLFBDEV_MULTISAMPLE 106
#define GLFBDEV_NONE 0
/* For glFBDevGetString */
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)
state.c \
input.c \
callback.c \
- gamemode.c
+ gamemode.c \
+ vidresize.c
GLX_SHARED_SOURCES = \
$(GLX_SHARED)/glut_8x13.c \
#include <linux/fb.h>
#include <GL/gl.h>
-#include <GL/glfbdev.h>
#include <GL/glut.h>
#include "internal.h"
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;
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);
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;
*/
#include <GL/gl.h>
-#include <GL/glfbdev.h>
#include <GL/glut.h>
#include "internal.h"
* 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>
#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;
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;
/* 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];
static void Cleanup(void)
{
+ if(GameMode)
+ glutLeaveGameMode();
+
if(ConsoleFD != -1)
RestoreVT();
if(exiterror[0])
fprintf(stderr, "[glfbdev glut] %s", exiterror);
-}
+ }
static void CrashHandler(int sig)
{
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;) {
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;
}
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)) {
else
if(VisiblePoll)
TestVisible();
+ else
+ usleep(1);
if(IdleFunc)
IdleFunc();
-
+
if(VisibleSwitch) {
VisibleSwitch = 0;
if(VisibilityFunc)
}
}
-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;
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")))
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",
/* 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) {
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;
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);
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);
InitializeCursor();
InitializeMenus();
+ glutSetWindowTitle(title);
+
Visible = 1;
VisibleSwitch = 1;
Redisplay = 1;
{
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;
}
}
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)
void glutShowWindow(void)
{
+ Visible = 1;
}
void glutHideWindow(void)
{
+ Visible = 0;
}
static void UnIconifyWindow(int sig)
strerror(errno));
exit(0);
}
+ Redisplay = 1;
+ VisibleSwitch = 1;
+ Visible = 1;
}
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)
* 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>
#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);
}
}
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);
PassiveMotionFunc(MouseX, MouseY);
EraseCursor();
+
if(ActiveMenu)
Redisplay = 1;
else
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;
}
/* 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) {
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)
#include <sys/time.h>
#include <linux/fb.h>
+#include <GL/glfbdev.h>
#define MULTIHEAD /* enable multihead hacks,
it allows the program to continue drawing
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;
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
extern unsigned char ReverseColorMap[REVERSECMAPSIZE]
[REVERSECMAPSIZE]
[REVERSECMAPSIZE];
+void LoadOldColorMap(void);
void LoadColorMap(void);
void UnloadColorMap(void);
void RestoreColorMap(void);
void CloseMenu(void);
/* --- state --- */
-extern int AccumSize, DepthSize, StencilSize;
+extern int AccumSize, DepthSize, StencilSize, NumSamples;
extern struct timeval StartTime;
extern int KeyboardModifiers;
extern struct GlutTimer *GlutTimers;
+/* ------- Game Mode -------- */
+extern int GameMode;
+
#pragma GCC visibility pop
int CurrentMenu;
static double MenuProjection[16];
-static double MenuModelview[16];
static int AttachedMenus[3];
static int NumMenus = 1;
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();
}
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);
}
{
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;
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);
glDisable(GL_TEXTURE_2D);
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_AND_REVERSE);
-
+
if(DrawMenu(ActiveMenu, x, &y))
Menus[ActiveMenu].selected = -1;
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;
}
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)
{
return 256;
return 0;
case GLUT_WINDOW_NUM_SAMPLES:
- return 0;
+ return NumSamples;
case GLUT_WINDOW_STEREO:
return 0;
case GLUT_WINDOW_CURSOR:
return -1;
}
-int glutVideoResizeGet(GLenum param)
-{
- switch(param) {
- case GLUT_VIDEO_RESIZE_POSSIBLE:
- return 0;
-
- }
- return -1;
-}
-
int glutGetModifiers(void){
return KeyboardModifiers;
}
--- /dev/null
+/*
+ * 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)
+{
+}
case GLFBDEV_VENDOR:
return "Mesa Project";
case GLFBDEV_VERSION:
- return "1.0.0";
+ return "1.0.1";
default:
return NULL;
}
case GLFBDEV_LEVEL:
/* ignored for now */
break;
+ case GLFBDEV_MULTISAMPLE:
+ numSamples = attrib[1];
+ attrib++;
+ break;
default:
/* unexpected token */
_mesa_free(vis);
}
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;
}
return rb;
}
-
GLFBDevBufferPtr
glFBDevCreateBuffer( const struct fb_fix_screeninfo *fixInfo,
const struct fb_var_screeninfo *varInfo,
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 ||
&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);
}
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;
}