Browse Source

Modularized code into multiple files.

Added gamemode stubs, iconify support, joystick stubs.

Fixed color index mode, added 8 bit alpha blending, enabled cmaps even
with 15, 16, 24, and 32 depths as some fbdev drivers need this.

Fixed compiling with -ansi

Using SIGIO for keyboard input, so that vt switching is enabled even
if the program is locked.

Fixed numerous small bugs.
tags/texmem_0_2_20060912
Sean D'Epagnier 19 years ago
parent
commit
288d4b6ebe

+ 10
- 2
src/glut/fbdev/Makefile View File

@@ -13,7 +13,16 @@ GLUT_TINY = 1
INCLUDES = -I$(TOP)/include -I$(GLX_SHARED)

CORE_SOURCES = \
glut_fbdev.c
fbdev.c \
colormap.c \
cursor.c \
menu.c \
overlay.c \
ext.c \
state.c \
input.c \
callback.c \
gamemode.c

GLX_SHARED_SOURCES = \
$(GLX_SHARED)/glut_8x13.c \
@@ -58,7 +67,6 @@ $(TOP)/$(LIB_DIR)/$(GLUT_LIB_NAME): depend $(OBJECTS)
$(GLUT_LIB_DEPS) -install $(TOP)/$(LIB_DIR) \
$(MKLIB_OPTIONS) $(OBJECTS)


# Run 'make -f Makefile.solo dep' to update the dependencies if you change
# what's included by any source file.
depend: $(SOURCES)

+ 172
- 0
src/glut/fbdev/callback.c View File

@@ -0,0 +1,172 @@
/*
* 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
*/

#include <GL/glut.h>

#include "internal.h"

void (*DisplayFunc)(void) = NULL;
void (*ReshapeFunc)(int width, int height) = NULL;
void (*KeyboardFunc)(unsigned char key, int x, int y) = NULL;
void (*KeyboardUpFunc)(unsigned char key, int x, int y) = NULL;
void (*MouseFunc)(int key, int state, int x, int y) = NULL;
void (*MotionFunc)(int x, int y) = NULL;
void (*PassiveMotionFunc)(int x, int y) = NULL;
void (*VisibilityFunc)(int state) = NULL;
void (*SpecialFunc)(int key, int x, int y) = NULL;
void (*SpecialUpFunc)(int key, int x, int y) = NULL;
void (*IdleFunc)(void) = NULL;
void (*MenuStatusFunc)(int state, int x, int y) = NULL;
void (*MenuStateFunc)(int state) = NULL;

void glutDisplayFunc(void (*func)(void))
{
DisplayFunc = func;
}

void glutOverlayDisplayFunc(void (*func)(void))
{
}

void glutWindowStatusFunc(void (*func)(int state))
{
}

void glutReshapeFunc(void (*func)(int width, int height))
{
ReshapeFunc = func;
}

void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))
{
KeyboardFunc = func;
}

void glutKeyboardUpFunc(void (*func)(unsigned char key, int x, int y))
{
KeyboardUpFunc = func;
}

void glutMouseFunc(void (*func)(int button, int state, int x, int y))
{
MouseEnabled = 1;
MouseFunc = func;
}

void glutMotionFunc(void (*func)(int x, int y))
{
MouseEnabled = 1;
MotionFunc = func;
}

void glutPassiveMotionFunc(void (*func)(int x, int y))
{
MouseEnabled = 1;
PassiveMotionFunc = func;
}

void glutJoystickFunc(void (*func)(unsigned int buttonMask,
int x, int y, int z), int pollInterval)
{
}

void glutVisibilityFunc(void (*func)(int state))
{
VisibilityFunc = func;
}

void glutEntryFunc(void (*func)(int state))
{
}

void glutSpecialFunc(void (*func)(int key, int x, int y))
{
SpecialFunc = func;
}

void glutSpecialUpFunc(void (*func)(int key, int x, int y))
{
SpecialUpFunc = func;
}

void glutSpaceballMotionFunc(void (*func)(int x, int y, int z))
{
}

void glutSpaceballRotateFunc(void (*func)(int x, int y, int z))
{
}

void glutSpaceballButtonFunc(void (*func)(int button, int state))
{
}

void glutButtonBoxFunc(void (*func)(int button, int state))
{
}

void glutDialsFunc(void (*func)(int dial, int value))
{
}

void glutTabletMotionFunc(void (*func)(int x, int y))
{
}

void glutTabletButtonFunc(void (*func)(int button, int state,
int x, int y))
{
}

void glutMenuStatusFunc(void (*func)(int status, int x, int y))
{
MenuStatusFunc = func;
}

void glutMenuStateFunc(void (*func)(int status))
{
MenuStateFunc = func;
}

void glutIdleFunc(void (*func)(void))
{
IdleFunc = func;
}

void glutTimerFunc(unsigned int msecs,
void (*func)(int value), int value)
{
struct GlutTimer **head = &GlutTimers, *timer = malloc(sizeof *timer);
timer->time = glutGet(GLUT_ELAPSED_TIME) + msecs;
timer->func = func;
timer->value = value;

while(*head && (*head)->time < timer->time)
head = &(*head)->next;

timer->next = *head;
*head = timer;
}

+ 173
- 0
src/glut/fbdev/colormap.c View File

@@ -0,0 +1,173 @@
/*
* 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
*/

#include <stdlib.h>

#include <linux/fb.h>

#include <GL/gl.h>
#include <GL/glfbdev.h>
#include <GL/glut.h>

#include "internal.h"

#define TOCMAP(x)(unsigned short)((x<0?0:x>1?1:x)*(GLfloat) ((1<<16) - 1))
#define TORMAP(x)(unsigned short)((x<0?0:x>1?1:x)*(GLfloat)(REVERSECMAPSIZE-1))
#define FROMCMAP(x) (GLfloat)x / (GLfloat)((1<<16) - 1)

static struct fb_cmap ColorMap;

unsigned short RedColorMap[256], GreenColorMap[256], BlueColorMap[256];

unsigned char ReverseColorMap[REVERSECMAPSIZE]
[REVERSECMAPSIZE]
[REVERSECMAPSIZE];

static void FindReverseMap(int r, int g, int b)
{
static int count;
int i, shift = 16 - REVERSECMAPSIZELOG;
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));
if(val < minv) {
minv = val;
mini = i;
}
}
ReverseColorMap[r][g][b] = mini;
}

static void FillItemReverseColorMap(int r, int g, int b)
{
FindReverseMap(r, g, b);
if(r > 0)
FindReverseMap(r-1, g, b);
if(r < REVERSECMAPSIZE - 1)
FindReverseMap(r+1, g, b);
if(g > 0)
FindReverseMap(r, g-1, b);
if(g < REVERSECMAPSIZE - 1)
FindReverseMap(r, g+1, b);
if(b > 0)
FindReverseMap(r, g, b-1);
if(b < REVERSECMAPSIZE - 1)
FindReverseMap(r, g, b+1);
}

static void FillReverseColorMap(void)
{
int r, g, b;
for(r = 0; r < REVERSECMAPSIZE; r++)
for(g = 0; g < REVERSECMAPSIZE; g++)
for(b = 0; b < REVERSECMAPSIZE; b++)
FindReverseMap(r, g, b);
}

void RestoreColorMap(void)
{
if (ioctl(FrameBufferFD, FBIOPUTCMAP, (void *) &ColorMap) < 0)
sprintf(exiterror, "ioctl(FBIOPUTCMAP) failed!\n");
}

void LoadColorMap(void)
{
/* we're assuming 256 entries here */
int i;

ColorMap.start = 0;
ColorMap.len = 256;
ColorMap.red = RedColorMap;
ColorMap.green = GreenColorMap;
ColorMap.blue = BlueColorMap;
ColorMap.transp = NULL;

if (ioctl(FrameBufferFD, FBIOGETCMAP, (void *) &ColorMap) < 0)
sprintf(exiterror, "ioctl(FBIOGETCMAP) failed!\n");

switch(VarInfo.bits_per_pixel) {
case 15:
for(i=0; i<32; i++)
RedColorMap[i] = GreenColorMap[i] = BlueColorMap[i] = i*65535/31;
break;
case 16:
for(i=0; i<32; i++)
RedColorMap[i] = BlueColorMap[i] = i*65535/31;
for(i=0; i<64; i++)
GreenColorMap[i] = i*65535/63;
break;
case 24:
case 32:
for(i=0; i<256; i++)
RedColorMap[i] = GreenColorMap[i] = BlueColorMap[i] = i*257;
break;
}

RestoreColorMap();

if(DisplayMode & GLUT_INDEX)
FillReverseColorMap();
}

void glutSetColor(int cell, GLfloat red, GLfloat green, GLfloat blue)
{
if(cell < 0 || cell >= 256)
return;

RedColorMap[cell] = TOCMAP(red);
GreenColorMap[cell] = TOCMAP(green);
BlueColorMap[cell] = TOCMAP(blue);
RestoreColorMap();

FillItemReverseColorMap(TORMAP(red), TORMAP(green), TORMAP(blue));
}

GLfloat glutGetColor(int cell, int component)
{
if(!(DisplayMode & GLUT_INDEX))
return -1.0;

if(cell < 0 || cell > 256)
return -1.0;

switch(component) {
case GLUT_RED:
return FROMCMAP(RedColorMap[cell]);
case GLUT_GREEN:
return FROMCMAP(GreenColorMap[cell]);
case GLUT_BLUE:
return FROMCMAP(BlueColorMap[cell]);
}
return -1.0;
}

void glutCopyColormap(int win)
{
}

+ 260
- 0
src/glut/fbdev/cursor.c View File

@@ -0,0 +1,260 @@
/*
* 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
*/

/* these routines are written to access graphics memory directly, not using mesa
to render the cursor, this is faster, and */

#include <stdlib.h>
#include <inttypes.h>

#include <linux/fb.h>

#include <GL/glut.h>

#include "internal.h"
#include "cursors.h"

int CurrentCursor = GLUT_CURSOR_LEFT_ARROW;

static int LastMouseX, LastMouseY;
static unsigned char *MouseBuffer;

void InitializeCursor(void)
{
if((MouseBuffer = malloc(CURSOR_WIDTH * CURSOR_HEIGHT
* VarInfo.bits_per_pixel / 8)) == NULL) {
sprintf(exiterror, "malloc failure\n");
exit(0);
}

MouseX = VarInfo.xres / 2;
MouseY = VarInfo.yres / 2;
}

void EraseCursor(void)
{
int off = LastMouseY * FixedInfo.line_length
+ LastMouseX * VarInfo.bits_per_pixel / 8;
int stride = CURSOR_WIDTH * VarInfo.bits_per_pixel / 8;
int i;

unsigned char *src = MouseBuffer;

for(i = 0; i<CURSOR_HEIGHT; i++) {
memcpy(BackBuffer + off, src, stride);
src += stride;
off += FixedInfo.line_length;
}
}

static void SaveCursor(int x, int y)
{
int bypp, off, stride, i;
unsigned char *src = MouseBuffer;

if(x < 0)
LastMouseX = 0;
else
if(x > (int)VarInfo.xres - CURSOR_WIDTH)
LastMouseX = VarInfo.xres - CURSOR_WIDTH;
else
LastMouseX = x;

if(y < 0)
LastMouseY = 0;
else
if(y > (int)VarInfo.yres - CURSOR_HEIGHT)
LastMouseY = VarInfo.yres - CURSOR_HEIGHT;
else
LastMouseY = y;

bypp = VarInfo.bits_per_pixel / 8;
off = LastMouseY * FixedInfo.line_length + LastMouseX * bypp;
stride = CURSOR_WIDTH * bypp;
for(i = 0; i<CURSOR_HEIGHT; i++) {
memcpy(src, BackBuffer + off, stride);
src += stride;
off += FixedInfo.line_length;
}
}

void DrawCursor(void)
{
int i, j, px, py, xoff, xlen, yoff, ylen, bypp, cstride, dstride;
unsigned char *c;
const unsigned char *d;

if(CurrentCursor < 0 || CurrentCursor >= NUM_CURSORS)
return;

px = MouseX - CursorsXOffset[CurrentCursor];
py = MouseY - CursorsYOffset[CurrentCursor];

SaveCursor(px, py);

xoff = 0;
if(px < 0)
xoff = -px;

xlen = CURSOR_WIDTH;
if(px + CURSOR_WIDTH > VarInfo.xres)
xlen = VarInfo.xres - px;

yoff = 0;
if(py < 0)
yoff = -py;

ylen = CURSOR_HEIGHT;
if(py + CURSOR_HEIGHT > VarInfo.yres)
ylen = VarInfo.yres - py;

bypp = VarInfo.bits_per_pixel / 8;

c = BackBuffer + FixedInfo.line_length * (py + yoff) + (px + xoff) * bypp;
cstride = FixedInfo.line_length - bypp * (xlen - xoff);

d = Cursors[CurrentCursor] + (CURSOR_WIDTH * yoff + xoff)*4;
dstride = (CURSOR_WIDTH - xlen + xoff) * 4;

switch(bypp) {
case 1:
{
const int shift = 8 - REVERSECMAPSIZELOG;
for(i = yoff; i < ylen; i++) {
for(j = xoff; j < xlen; j++) {
if(d[3] < 220)
*c = ReverseColorMap
[(d[0]+(((int)(RedColorMap[c[0]]>>8)*d[3])>>8))>>shift]
[(d[1]+(((int)(GreenColorMap[c[0]]>>8)*d[3])>>8))>>shift]
[(d[2]+(((int)(BlueColorMap[c[0]]>>8)*d[3])>>8))>>shift];
c++;
d+=4;
}
d += dstride;
c += cstride;
}
} break;
case 2:
{
uint16_t *e = (void*)c;
cstride /= 2;
for(i = yoff; i < ylen; i++) {
for(j = xoff; j < xlen; j++) {
e[0] = ((((d[0] + (((int)(((e[0] >> 8) & 0xf8)
| ((c[0] >> 11) & 0x7)) * d[3]) >> 8)) & 0xf8) << 8)
| (((d[1] + (((int)(((e[0] >> 3) & 0xfc)
| ((e[0] >> 5) & 0x3)) * d[3]) >> 8)) & 0xfc) << 3)
| ((d[2] + (((int)(((e[0] << 3) & 0xf8)
| (e[0] & 0x7)) * d[3]) >> 8)) >> 3));
e++;
d+=4;
}
d += dstride;
e += cstride;
}
} break;
case 3:
case 4:
for(i = yoff; i < ylen; i++) {
for(j = xoff; j < xlen; j++) {
c[0] = d[0] + (((int)c[0] * d[3]) >> 8);
c[1] = d[1] + (((int)c[1] * d[3]) >> 8);
c[2] = d[2] + (((int)c[2] * d[3]) >> 8);
c+=bypp;
d+=4;
}
d += dstride;
c += cstride;
} break;
}
}

#define MIN(x, y) x < y ? x : y
void SwapCursor(void)
{
int px = MouseX - CursorsXOffset[CurrentCursor];
int py = MouseY - CursorsYOffset[CurrentCursor];

int minx = MIN(px, LastMouseX);
int sizex = abs(px - LastMouseX);

int miny = MIN(py, LastMouseY);
int sizey = abs(py - LastMouseY);

DrawCursor();
/* now update the portion of the screen that has changed */

if(DisplayMode & GLUT_DOUBLE && (sizex || sizey)) {
int off, stride, i;
if(minx < 0)
minx = 0;
if(miny < 0)
miny = 0;
if(minx + sizex > VarInfo.xres)
sizex = VarInfo.xres - minx;
if(miny + sizey > VarInfo.yres)
sizey = VarInfo.yres - miny;
off = FixedInfo.line_length * miny
+ minx * VarInfo.bits_per_pixel / 8;
stride = (sizex + CURSOR_WIDTH) * VarInfo.bits_per_pixel / 8;

for(i = 0; i< sizey + CURSOR_HEIGHT; i++) {
memcpy(FrameBuffer+off, BackBuffer+off, stride);
off += FixedInfo.line_length;
}
}
}

void glutWarpPointer(int x, int y)
{
if(x < 0)
x = 0;
if(x >= VarInfo.xres)
x = VarInfo.xres - 1;
MouseX = x;

if(y < 0)
y = 0;
if(y >= VarInfo.yres)
y = VarInfo.yres - 1;
MouseY = y;

EraseCursor();
SwapCursor();
}

void glutSetCursor(int cursor)
{
if(cursor == GLUT_CURSOR_FULL_CROSSHAIR)
cursor = GLUT_CURSOR_CROSSHAIR;
CurrentCursor = cursor;
MouseEnabled = 1;
EraseCursor();
SwapCursor();
}

+ 7082
- 7082
src/glut/fbdev/cursors.h
File diff suppressed because it is too large
View File


+ 153
- 0
src/glut/fbdev/ext.c View File

@@ -0,0 +1,153 @@
/*
* 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
*/

#include <GL/gl.h>
#include <GL/glfbdev.h>
#include <GL/glut.h>

#include "internal.h"

void glutReportErrors(void)
{
GLenum error;

while ((error = glGetError()) != GL_NO_ERROR)
sprintf(exiterror, "GL error: %s", gluErrorString(error));
}

static struct {
const char *name;
const GLUTproc address;
} glut_functions[] = {
{ "glutInit", (const GLUTproc) glutInit },
{ "glutInitDisplayMode", (const GLUTproc) glutInitDisplayMode },
{ "glutInitWindowPosition", (const GLUTproc) glutInitWindowPosition },
{ "glutInitWindowSize", (const GLUTproc) glutInitWindowSize },
{ "glutMainLoop", (const GLUTproc) glutMainLoop },
{ "glutCreateWindow", (const GLUTproc) glutCreateWindow },
{ "glutCreateSubWindow", (const GLUTproc) glutCreateSubWindow },
{ "glutDestroyWindow", (const GLUTproc) glutDestroyWindow },
{ "glutPostRedisplay", (const GLUTproc) glutPostRedisplay },
{ "glutSwapBuffers", (const GLUTproc) glutSwapBuffers },
{ "glutGetWindow", (const GLUTproc) glutGetWindow },
{ "glutSetWindow", (const GLUTproc) glutSetWindow },
{ "glutSetWindowTitle", (const GLUTproc) glutSetWindowTitle },
{ "glutSetIconTitle", (const GLUTproc) glutSetIconTitle },
{ "glutPositionWindow", (const GLUTproc) glutPositionWindow },
{ "glutReshapeWindow", (const GLUTproc) glutReshapeWindow },
{ "glutPopWindow", (const GLUTproc) glutPopWindow },
{ "glutPushWindow", (const GLUTproc) glutPushWindow },
{ "glutIconifyWindow", (const GLUTproc) glutIconifyWindow },
{ "glutShowWindow", (const GLUTproc) glutShowWindow },
{ "glutHideWindow", (const GLUTproc) glutHideWindow },
{ "glutFullScreen", (const GLUTproc) glutFullScreen },
{ "glutSetCursor", (const GLUTproc) glutSetCursor },
{ "glutWarpPointer", (const GLUTproc) glutWarpPointer },
{ "glutEstablishOverlay", (const GLUTproc) glutEstablishOverlay },
{ "glutRemoveOverlay", (const GLUTproc) glutRemoveOverlay },
{ "glutUseLayer", (const GLUTproc) glutUseLayer },
{ "glutPostOverlayRedisplay", (const GLUTproc) glutPostOverlayRedisplay },
{ "glutShowOverlay", (const GLUTproc) glutShowOverlay },
{ "glutHideOverlay", (const GLUTproc) glutHideOverlay },
{ "glutCreateMenu", (const GLUTproc) glutCreateMenu },
{ "glutDestroyMenu", (const GLUTproc) glutDestroyMenu },
{ "glutGetMenu", (const GLUTproc) glutGetMenu },
{ "glutSetMenu", (const GLUTproc) glutSetMenu },
{ "glutAddMenuEntry", (const GLUTproc) glutAddMenuEntry },
{ "glutAddSubMenu", (const GLUTproc) glutAddSubMenu },
{ "glutChangeToMenuEntry", (const GLUTproc) glutChangeToMenuEntry },
{ "glutChangeToSubMenu", (const GLUTproc) glutChangeToSubMenu },
{ "glutRemoveMenuItem", (const GLUTproc) glutRemoveMenuItem },
{ "glutAttachMenu", (const GLUTproc) glutAttachMenu },
{ "glutDetachMenu", (const GLUTproc) glutDetachMenu },
{ "glutDisplayFunc", (const GLUTproc) glutDisplayFunc },
{ "glutReshapeFunc", (const GLUTproc) glutReshapeFunc },
{ "glutKeyboardFunc", (const GLUTproc) glutKeyboardFunc },
{ "glutMouseFunc", (const GLUTproc) glutMouseFunc },
{ "glutMotionFunc", (const GLUTproc) glutMotionFunc },
{ "glutPassiveMotionFunc", (const GLUTproc) glutPassiveMotionFunc },
{ "glutEntryFunc", (const GLUTproc) glutEntryFunc },
{ "glutVisibilityFunc", (const GLUTproc) glutVisibilityFunc },
{ "glutIdleFunc", (const GLUTproc) glutIdleFunc },
{ "glutTimerFunc", (const GLUTproc) glutTimerFunc },
{ "glutMenuStateFunc", (const GLUTproc) glutMenuStateFunc },
{ "glutSpecialFunc", (const GLUTproc) glutSpecialFunc },
{ "glutSpaceballRotateFunc", (const GLUTproc) glutSpaceballRotateFunc },
{ "glutButtonBoxFunc", (const GLUTproc) glutButtonBoxFunc },
{ "glutDialsFunc", (const GLUTproc) glutDialsFunc },
{ "glutTabletMotionFunc", (const GLUTproc) glutTabletMotionFunc },
{ "glutTabletButtonFunc", (const GLUTproc) glutTabletButtonFunc },
{ "glutMenuStatusFunc", (const GLUTproc) glutMenuStatusFunc },
{ "glutOverlayDisplayFunc", (const GLUTproc) glutOverlayDisplayFunc },
{ "glutSetColor", (const GLUTproc) glutSetColor },
{ "glutGetColor", (const GLUTproc) glutGetColor },
{ "glutCopyColormap", (const GLUTproc) glutCopyColormap },
{ "glutGet", (const GLUTproc) glutGet },
{ "glutDeviceGet", (const GLUTproc) glutDeviceGet },
{ "glutExtensionSupported", (const GLUTproc) glutExtensionSupported },
{ "glutGetModifiers", (const GLUTproc) glutGetModifiers },
{ "glutLayerGet", (const GLUTproc) glutLayerGet },
{ "glutGetProcAddress", (const GLUTproc) glutGetProcAddress },
{ "glutBitmapCharacter", (const GLUTproc) glutBitmapCharacter },
{ "glutBitmapWidth", (const GLUTproc) glutBitmapWidth },
{ "glutStrokeCharacter", (const GLUTproc) glutStrokeCharacter },
{ "glutStrokeWidth", (const GLUTproc) glutStrokeWidth },
{ "glutBitmapLength", (const GLUTproc) glutBitmapLength },
{ "glutStrokeLength", (const GLUTproc) glutStrokeLength },
{ "glutWireSphere", (const GLUTproc) glutWireSphere },
{ "glutSolidSphere", (const GLUTproc) glutSolidSphere },
{ "glutWireCone", (const GLUTproc) glutWireCone },
{ "glutSolidCone", (const GLUTproc) glutSolidCone },
{ "glutWireCube", (const GLUTproc) glutWireCube },
{ "glutSolidCube", (const GLUTproc) glutSolidCube },
{ "glutWireTorus", (const GLUTproc) glutWireTorus },
{ "glutSolidTorus", (const GLUTproc) glutSolidTorus },
{ "glutWireDodecahedron", (const GLUTproc) glutWireDodecahedron },
{ "glutSolidDodecahedron", (const GLUTproc) glutSolidDodecahedron },
{ "glutWireTeapot", (const GLUTproc) glutWireTeapot },
{ "glutSolidTeapot", (const GLUTproc) glutSolidTeapot },
{ "glutWireOctahedron", (const GLUTproc) glutWireOctahedron },
{ "glutSolidOctahedron", (const GLUTproc) glutSolidOctahedron },
{ "glutWireTetrahedron", (const GLUTproc) glutWireTetrahedron },
{ "glutSolidTetrahedron", (const GLUTproc) glutSolidTetrahedron },
{ "glutWireIcosahedron", (const GLUTproc) glutWireIcosahedron },
{ "glutSolidIcosahedron", (const GLUTproc) glutSolidIcosahedron },
{ "glutReportErrors", (const GLUTproc) glutReportErrors },
{ NULL, NULL }
};

GLUTproc glutGetProcAddress(const char *procName)
{
/* Try GLUT functions first */
int i;
for (i = 0; glut_functions[i].name; i++) {
if (strcmp(glut_functions[i].name, procName) == 0)
return glut_functions[i].address;
}

/* Try core GL functions */
return (GLUTproc) glFBDevGetProcAddress(procName);
}

+ 698
- 0
src/glut/fbdev/fbdev.c View File

@@ -0,0 +1,698 @@
/*
* 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
*/

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>

#include <sys/mman.h>
#include <sys/time.h>
#include <sys/kd.h>

#include <linux/fb.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;

static int DesiredDepth = 0;

int FrameBufferFD = -1;
unsigned char *FrameBuffer;
unsigned char *BackBuffer = NULL;
int DisplayMode;

struct GlutTimer *GlutTimers = NULL;

struct timeval StartTime;

/* per window data */
static GLFBDevContextPtr Context;
static GLFBDevBufferPtr Buffer;
static GLFBDevVisualPtr Visual;

int Redisplay;
int Visible;
int VisibleSwitch;
int Active;
/* we have to poll to see if we are visible
on a framebuffer that is not active */
int VisiblePoll;
static int FramebufferIndex;

static int RequiredWidth;
static int RequiredHeight;
static int InitialWidthHint;
static int InitialHeightHint;

static int Initialized;

char exiterror[256];

/* test if the active console is attached to the same framebuffer */
void TestVisible(void) {
struct fb_con2fbmap confb;
struct vt_stat st;
int ret;
ioctl(ConsoleFD, VT_GETSTATE, &st);
confb.console = st.v_active;

ret = ioctl(FrameBufferFD, FBIOGET_CON2FBMAP, &confb);

if(ret == -1 || confb.framebuffer == FramebufferIndex) {
VisibleSwitch = 1;
Visible = 0;
VisiblePoll = 0;
}
}

static void Cleanup(void)
{
if(ConsoleFD != -1)
RestoreVT();

/* close mouse */
CloseMouse();

glFBDevMakeCurrent( NULL, NULL, NULL);

glFBDevDestroyContext(Context);
glFBDevDestroyBuffer(Buffer);
glFBDevDestroyVisual(Visual);

/* restore original variable screen info */
if(FrameBufferFD != -1) {
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo))
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
strerror(errno));

munmap(FrameBuffer, FixedInfo.smem_len);
close(FrameBufferFD);
}

/* free allocated back buffer */
if(DisplayMode & GLUT_DOUBLE)
free(BackBuffer);

/* free menu items */
FreeMenus();

if(exiterror[0])
fprintf(stderr, "[glfbdev glut] %s", exiterror);
}

static void CrashHandler(int sig)
{
sprintf(exiterror, "Caught signal %d, cleaning up\n", sig);
exit(0);
}

static void removeArgs(int *argcp, char **argv, int num)
{
int i;
for (i = 0; argv[i+num]; i++)
argv[i] = argv[i+num];

argv[i] = NULL;
*argcp -= num;
}

#define REQPARAM(PARAM) \
if (i >= *argcp - 1) { \
fprintf(stderr, PARAM" requires a parameter\n"); \
exit(0); \
}

void glutInit (int *argcp, char **argv)
{
int i;
int nomouse = 0;
int nokeyboard = 0;
int usestdin = 0;

/* parse out args */
for (i = 1; i < *argcp;) {
if (!strcmp(argv[i], "-geometry")) {
REQPARAM("geometry");
if(sscanf(argv[i+1], "%dx%d", &RequiredWidth,
&RequiredHeight) != 2) {
fprintf(stderr,"Please specify geometry as widthxheight\n");
exit(0);
}
removeArgs(argcp, &argv[i], 2);
} else
if (!strcmp(argv[i], "-bpp")) {
REQPARAM("bpp");
if(sscanf(argv[i+1], "%d", &DesiredDepth) != 1) {
fprintf(stderr, "Please specify a parameter for bpp\n");
exit(0);
}
removeArgs(argcp, &argv[i], 2);
} else
if (!strcmp(argv[i], "-vt")) {
REQPARAM("vt");
if(sscanf(argv[i+1], "%d", &CurrentVT) != 1) {
fprintf(stderr, "Please specify a parameter for vt\n");
exit(0);
}
removeArgs(argcp, &argv[i], 2);
} else
if (!strcmp(argv[i], "-mousespeed")) {
REQPARAM("mousespeed");
if(sscanf(argv[i+1], "%lf", &MouseSpeed) != 1) {
fprintf(stderr, "Please specify a mouse speed, eg: 2.5\n");
exit(0);
}
removeArgs(argcp, &argv[i], 2);
} else
if (!strcmp(argv[i], "-nomouse")) {
nomouse = 1;
removeArgs(argcp, &argv[i], 1);
} else
if (!strcmp(argv[i], "-nokeyboard")) {
nokeyboard = 1;
removeArgs(argcp, &argv[i], 1);
} else
if (!strcmp(argv[i], "-stdin")) {
usestdin = 1;
removeArgs(argcp, &argv[i], 1);
} else
if (!strcmp(argv[i], "-gpmmouse")) {
#ifdef HAVE_GPM
GpmMouse = 1;
#else
fprintf(stderr, "gpm support not compiled\n");
exit(0);
#endif
removeArgs(argcp, &argv[i], 1);
} else
if (!strcmp(argv[i], "--")) {
removeArgs(argcp, &argv[i], 1);
break;
} else
i++;
}

gettimeofday(&StartTime, 0);
atexit(Cleanup);

signal(SIGSEGV, CrashHandler);
signal(SIGINT, CrashHandler);
signal(SIGTERM, CrashHandler);

if(nomouse == 0)
InitializeMouse();
if(nokeyboard == 0)
InitializeVT(usestdin);

Initialized = 1;
}

void glutInitDisplayMode (unsigned int mode)
{
DisplayMode = mode;
}

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)) {
struct GlutTimer *timer = GlutTimers;
timer->func(timer->value);
GlutTimers = timer->next;
free(timer);
}
}

void glutMainLoop(void)
{
if(ReshapeFunc)
ReshapeFunc(VarInfo.xres, VarInfo.yres);

if(!DisplayFunc) {
sprintf(exiterror, "Fatal Error: No Display Function registered\n");
exit(0);
}

for(;;) {
ProcessTimers();

if(Active)
ReceiveInput();
else
if(VisiblePoll)
TestVisible();

if(IdleFunc)
IdleFunc();

if(VisibleSwitch) {
VisibleSwitch = 0;
if(VisibilityFunc)
VisibilityFunc(Visible ? GLUT_VISIBLE : GLUT_NOT_VISIBLE);
}

if(Visible && Redisplay) {
Redisplay = 0;
if(MouseEnabled)
EraseCursor();
DisplayFunc();
if(!(DisplayMode & GLUT_DOUBLE)) {
if(ActiveMenu)
DrawMenus();
if(MouseEnabled)
DrawCursor();
}
}
}
}

static void ParseFBModes(void)
{
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;
}

if(InitialWidthHint == 0 && InitialHeightHint == 0
&& RequiredWidth == 0)
return; /* use current mode */

while(fgets(buf, sizeof buf, fbmodes)) {
char *c;
int v;

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);
if(v != 5)
continue;

/* now we have to decide what is best */
if(RequiredWidth) {
if(RequiredWidth != vi.xres || RequiredHeight != vi.yres)
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)
continue;
}

fgets(buf, sizeof buf, fbmodes);
if(!(c = strstr(buf, "timings")))
continue;

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;
}
}

fclose(fbmodes);

if(RequiredWidth) {
sprintf(exiterror, "No mode (%dx%d) found in "FBMODES"\n",
RequiredWidth, RequiredHeight);
exit(0);
}
}

/* ---------- Window Management ----------*/
int glutCreateWindow (const char *title)
{
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",
strerror(errno));
exit(0);
}

/* reload the screen info to update offsets */
if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &VarInfo)) {
sprintf(exiterror, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
strerror(errno));
exit(0);
}

/* reload the fixed info to update color mode */
if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
sprintf(exiterror, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
strerror(errno));
exit(0);
}

if (DesiredDepth && DesiredDepth != VarInfo.bits_per_pixel) {
sprintf(exiterror, "error: Could not set set %d bpp\n", DesiredDepth);
exit(0);
}

if(DisplayMode & GLUT_INDEX && FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
sprintf(exiterror, "error: Could not set 8 bit color mode\n");
exit(0);
}

/* initialize colormap */
LoadColorMap();

/* mmap the framebuffer into our address space */
FrameBuffer = mmap(0, FixedInfo.smem_len, PROT_READ | PROT_WRITE,
MAP_SHARED, FrameBufferFD, 0);
if (FrameBuffer == MAP_FAILED) {
sprintf(exiterror, "error: unable to mmap framebuffer: %s\n",
strerror(errno));
exit(0);
}

mask = DisplayMode;
for(i=0; i<8 && mask; i++) {
if(mask & GLUT_DOUBLE) {
attribs[i] = GLFBDEV_DOUBLE_BUFFER;
mask &= ~GLUT_DOUBLE;
continue;
}

if(mask & GLUT_INDEX) {
attribs[i] = GLFBDEV_COLOR_INDEX;
mask &= ~GLUT_INDEX;
continue;
}

if(mask & GLUT_DEPTH) {
attribs[i] = GLFBDEV_DEPTH_SIZE;
attribs[++i] = DepthSize;
mask &= ~GLUT_DEPTH;
continue;
}

if(mask & GLUT_STENCIL) {
attribs[i] = GLFBDEV_STENCIL_SIZE;
attribs[++i] = StencilSize;
mask &= ~GLUT_STENCIL;
continue;
}

if(mask & GLUT_ACCUM) {
attribs[i] = GLFBDEV_ACCUM_SIZE;
attribs[++i] = AccumSize;
mask &= ~GLUT_ACCUM;
continue;
}

if(mask & GLUT_ALPHA)
if(!(DisplayMode & GLUT_INDEX)) {
mask &= ~GLUT_ALPHA;
i--;
continue;
}
sprintf(exiterror, "Invalid mode from glutInitDisplayMode\n");
exit(0);
}

attribs[i] = GLFBDEV_NONE;
if(!(Visual = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs ))) {
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);
}

if(!(Context = glFBDevCreateContext(Visual, NULL))) {
sprintf(exiterror, "Failure to create Context\n");
exit(0);
}

if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) {
sprintf(exiterror, "Failure to Make Current\n");
exit(0);
}

InitializeCursor();
InitializeMenus();

Visible = 1;
VisibleSwitch = 1;
Redisplay = 1;
return 1;
}

int glutCreateSubWindow(int win, int x, int y, int width, int height)
{
return 0;
}

void glutSetWindow(int win)
{
}

int glutGetWindow(void)
{
return 1;
}

void glutDestroyWindow(int win)
{
}

void glutPostRedisplay(void)
{
Redisplay = 1;
}

void glutPostWindowRedisplay(int win)
{
Redisplay = 1;
}

void glutSwapBuffers(void)
{
glFlush();

if(Visible && DisplayMode & GLUT_DOUBLE) {
if(ActiveMenu)
DrawMenus();
if(MouseEnabled)
DrawCursor();
glFBDevSwapBuffers(Buffer);
}
}

void glutPositionWindow(int x, int y)
{
}

void glutReshapeWindow(int width, int height)
{
}

void glutFullScreen(void)
{
}

void glutPopWindow(void)
{
}

void glutPushWindow(void)
{
}

void glutShowWindow(void)
{
}

void glutHideWindow(void)
{
}

static void UnIconifyWindow(int sig)
{
if(ConsoleFD == 0)
InitializeVT(1);
else
if(ConsoleFD > 0)
InitializeVT(0);
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
sprintf(exiterror, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
strerror(errno));
exit(0);
}
}

void glutIconifyWindow(void)
{
RestoreVT();
signal(SIGCONT, UnIconifyWindow);
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo))
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
strerror(errno));
raise(SIGSTOP);
}

void glutSetWindowTitle(const char *name)
{
}

void glutSetIconTitle(const char *name)
{
}

+ 78
- 0
src/glut/fbdev/gamemode.c View File

@@ -0,0 +1,78 @@
/*
* 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: game mode will not be fully implemented until
glutReshapeWindow is fully implemented */

#include <stdlib.h>

#include <linux/fb.h>

#include <GL/glut.h>

#include "internal.h"

void glutGameModeString(const char *string)
{
}

int glutEnterGameMode(void)
{
if(ActiveMenu)
return 0;
return 1;
}

void glutLeaveGameMode(void)
{
}

int glutGameModeGet(GLenum mode) {
switch(mode) {
case GLUT_GAME_MODE_ACTIVE:
return 1;
case GLUT_GAME_MODE_POSSIBLE:
return 1;
case GLUT_GAME_MODE_WIDTH:
return VarInfo.xres;
case GLUT_GAME_MODE_HEIGHT:
return VarInfo.yres;
case GLUT_GAME_MODE_PIXEL_DEPTH:
return VarInfo.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;
}
}

+ 715
- 0
src/glut/fbdev/input.c View File

@@ -0,0 +1,715 @@
/*
* 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
*/

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <inttypes.h>

#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/kd.h>

#include <linux/keyboard.h>
#include <linux/fb.h>
#include <linux/vt.h>

#include <GL/glut.h>

#include "internal.h"

#define MOUSEDEV "/dev/gpmdata"

#ifdef HAVE_GPM
#include <gpm.h>
int GpmMouse;
#endif

int CurrentVT;
int ConsoleFD = -1;

int KeyboardModifiers;

int MouseX, MouseY;
int NumMouseButtons;

double MouseSpeed = 0;

int KeyRepeatMode = GLUT_KEY_REPEAT_DEFAULT;

/* only display the mouse if there is a registered callback for it */
int MouseEnabled = 0;

static int OldKDMode = -1;
static int OldMode;
static struct vt_mode OldVTMode;
static struct termios OldTermios;

static int KeyboardLedState;

static int MouseFD;

static int kbdpipe[2];

#define MODIFIER(mod) \
KeyboardModifiers = release ? KeyboardModifiers & ~mod \
: KeyboardModifiers | mod;

/* signal handler attached to SIGIO on keyboard input, vt
switching and modifiers is handled in the signal handler
other keypresses read from a pipe that leaves the handler
if a program locks up the glut loop, you can still switch
vts and kill it without Alt-SysRq hack */
static void KeyboardHandler(int sig)
{
int release, labelval;
unsigned char code;
struct kbentry entry;

if(read(ConsoleFD, &code, 1) != 1)
return;

release = code & 0x80;
entry.kb_index = code & 0x7F;
entry.kb_table = 0;
if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
exit(0);
}

labelval = entry.kb_value;

switch(labelval) {
case K_SHIFT:
case K_SHIFTL:
MODIFIER(GLUT_ACTIVE_SHIFT);
return;
case K_CTRL:
MODIFIER(GLUT_ACTIVE_CTRL);
return;
case K_ALT:
case K_ALTGR:
MODIFIER(GLUT_ACTIVE_ALT);
return;
}

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");
return;
}
write(kbdpipe[1], &code, 1);
}

static void LedModifier(int led, int release)
{
static int releaseflag = K_CAPS | K_NUM | K_HOLD;
if(release)
releaseflag |= led;
else
if(releaseflag & led) {
KeyboardLedState ^= led;
releaseflag &= ~led;
}
ioctl(ConsoleFD, KDSKBLED, KeyboardLedState);
ioctl(ConsoleFD, KDSETLED, 0x80);
}

#define READKEY read(kbdpipe[0], &code, 1)
static int ReadKey(void)
{
int release, labelval;
unsigned char code;
int specialkey = 0;
struct kbentry entry;

if(READKEY != 1)
return 0;
if(code == 0)
return 0;

/* stdin input escape code based */
if(ConsoleFD == 0) {
KeyboardModifiers = 0;
altset:
if(code == 27 && READKEY == 1) {
switch(code) {
case 79: /* function key */
READKEY;
if(code == 50) {
READKEY;
shiftfunc:
KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
specialkey = GLUT_KEY_F1 + code - 53;
READKEY;
} else {
READKEY;
specialkey = GLUT_KEY_F1 + code - 80;
}
break;
case 91:
READKEY;
switch(code) {
case 68:
specialkey = GLUT_KEY_LEFT; break;
case 65:
specialkey = GLUT_KEY_UP; break;
case 67:
specialkey = GLUT_KEY_RIGHT; break;
case 66:
specialkey = GLUT_KEY_DOWN; break;
case 53:
specialkey = GLUT_KEY_PAGE_UP; READKEY; break;
case 54:
specialkey = GLUT_KEY_PAGE_DOWN; READKEY; break;
case 49:
specialkey = GLUT_KEY_HOME; READKEY; break;
case 52:
specialkey = GLUT_KEY_END; READKEY; break;
case 50:
READKEY;
if(code != 126)
goto shiftfunc;
specialkey = GLUT_KEY_INSERT;
break;
case 51:
code = '\b'; goto stdkey;
case 91:
READKEY;
specialkey = GLUT_KEY_F1 + code - 65;
break;
default:
return 0;
}
break;
default:
KeyboardModifiers |= GLUT_ACTIVE_ALT;
goto altset;
}
}
stdkey:
if(specialkey) {
if(SpecialFunc)
SpecialFunc(specialkey, MouseX, MouseY);
} else {
if(code >= 1 && code <= 26) {
KeyboardModifiers |= GLUT_ACTIVE_CTRL;
code += 'a' - 1;
}
if((code >= 43 && code <= 34) || (code == 60)
|| (code >= 62 && code <= 90) || (code == 94)
|| (code == 95) || (code >= 123 && code <= 126))
KeyboardModifiers |= GLUT_ACTIVE_SHIFT;

if(KeyboardFunc)
KeyboardFunc(code, MouseX, MouseY);
}
return 1;
}

/* linux kbd reading */
release = code & 0x80;
code &= 0x7F;

if(KeyRepeatMode == GLUT_KEY_REPEAT_OFF) {
static char keystates[128];
if(release)
keystates[code] = 0;
else {
if(keystates[code])
return 1;
keystates[code] = 1;
}
}
entry.kb_index = code;
entry.kb_table = 0;

if(KeyboardModifiers & GLUT_ACTIVE_SHIFT)
entry.kb_table |= K_SHIFTTAB;
if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
exit(0);
}

labelval = entry.kb_value;

switch(labelval) {
case K_CAPS:
LedModifier(LED_CAP, release);
return 0;
case K_NUM:
LedModifier(LED_NUM, release);
return 0;
case K_HOLD: /* scroll lock suspends glut */
LedModifier(LED_SCR, release);
while(KeyboardLedState & LED_SCR) {
usleep(10000);
ReadKey();
}
return 0;
}

/* we could queue keypresses here */
if(KeyboardLedState & LED_SCR)
return 0;

if(labelval >= K_F1 && labelval <= K_F12)
specialkey = GLUT_KEY_F1 + labelval - K_F1;
else
switch(labelval) {
case K_LEFT:
specialkey = GLUT_KEY_LEFT; break;
case K_UP:
specialkey = GLUT_KEY_UP; break;
case K_RIGHT:
specialkey = GLUT_KEY_RIGHT; break;
case K_DOWN:
specialkey = GLUT_KEY_DOWN; break;
case K_PGUP:
specialkey = GLUT_KEY_PAGE_UP; break;
case K_PGDN:
specialkey = GLUT_KEY_PAGE_DOWN; break;
case K_FIND:
specialkey = GLUT_KEY_HOME; break;
case K_SELECT:
specialkey = GLUT_KEY_END; break;
case K_INSERT:
specialkey = GLUT_KEY_INSERT; break;
case K_REMOVE:
labelval = '\b'; break;
case K_ENTER:
labelval = '\n'; break;
}

/* dispatch callback */
if(specialkey) {
if(release) {
if(SpecialUpFunc)
SpecialUpFunc(specialkey, MouseX, MouseY);
} else
if(SpecialFunc)
SpecialFunc(specialkey, MouseX, MouseY);
} else {
char c = labelval;

if(KeyboardLedState & LED_CAP) {
if(c >= 'A' && c <= 'Z')
c += 'a' - 'A';
else
if(c >= 'a' && c <= 'z')
c += 'A' - 'a';
}
if(release) {
if(KeyboardUpFunc)
KeyboardUpFunc(c, MouseX, MouseY);
} else
if(KeyboardFunc)
KeyboardFunc(c, MouseX, MouseY);
}
return 1;
}

void glutIgnoreKeyRepeat(int ignore)
{
KeyRepeatMode = ignore ? GLUT_KEY_REPEAT_OFF : GLUT_KEY_REPEAT_ON;
}

void glutSetKeyRepeat(int repeatMode)
{
KeyRepeatMode = repeatMode;
}

void glutForceJoystickFunc(void)
{
}

static void HandleMousePress(int button, int pressed)
{
if(TryMenu(button, pressed))
return;
if(MouseFunc)
MouseFunc(button, pressed ? GLUT_DOWN : GLUT_UP, MouseX, MouseY);
}

static int ReadMouse(void)
{
int l, r, m;
static int ll, lm, lr;
signed char dx, dy;

#ifdef HAVE_GPM
if(GpmMouse) {
Gpm_Event event;
struct pollfd pfd;
pfd.fd = gpm_fd;
pfd.events = POLLIN;
if(poll(&pfd, 1, 1) != 1)
return 0;
if(Gpm_GetEvent(&event) != 1)
return 0;
l = event.buttons & GPM_B_LEFT;
m = event.buttons & GPM_B_MIDDLE;
r = event.buttons & GPM_B_RIGHT;

/* gpm is weird in that it gives a button number when the button
is released, with type set to GPM_UP, this is only a problem
if it is the last button released */
if(event.type & GPM_UP)
if(event.buttons == GPM_B_LEFT || event.buttons == GPM_B_MIDDLE ||
event.buttons == GPM_B_RIGHT || event.buttons == GPM_B_FOURTH)
l = m = r = 0;

dx = event.dx;
dy = event.dy;
} else
#endif
{
char data[4];

if(MouseFD == -1)
return 0;

if(fcntl(MouseFD, F_SETFL, O_NONBLOCK) == -1) {
close(MouseFD);
MouseFD = -1;
return 0;
}

if(read(MouseFD, data, 4) != 4)
return 0;
l = ((data[0] & 0x20) >> 3);
m = ((data[3] & 0x10) >> 3);
r = ((data[0] & 0x10) >> 4);

dx = (((data[0] & 0x03) << 6) | (data[1] & 0x3F));
dy = (((data[0] & 0x0C) << 4) | (data[2] & 0x3F));
}

MouseX += dx * MouseSpeed;
if(MouseX < 0)
MouseX = 0;
else
if(MouseX >= VarInfo.xres)
MouseX = VarInfo.xres - 1;

MouseY += dy * MouseSpeed;
if(MouseY < 0)
MouseY = 0;
else
if(MouseY >= VarInfo.yres)
MouseY = VarInfo.yres - 1;

if(l != ll)
HandleMousePress(GLUT_LEFT_BUTTON, l);
if(m != lm)
HandleMousePress(GLUT_MIDDLE_BUTTON, m);
if(r != lr)
HandleMousePress(GLUT_RIGHT_BUTTON, r);

ll = l, lm = m, lr = r;

if(dx || dy) {
if(l || m || r) {
if(MotionFunc)
MotionFunc(MouseX, MouseY);
} else
if(PassiveMotionFunc)
PassiveMotionFunc(MouseX, MouseY);

EraseCursor();
if(ActiveMenu)
Redisplay = 1;
else
SwapCursor();
}

return 1;
}

void ReceiveInput(void)
{
if(ConsoleFD != -1)
while(ReadKey());
if(MouseEnabled)
while(ReadMouse());
}

static void VTSwitchHandler(int sig)
{
struct vt_stat st;
switch(sig) {
case SIGUSR1:
ioctl(ConsoleFD, VT_RELDISP, 1);
Active = 0;
#ifdef MULTIHEAD
VisiblePoll = 1;
TestVisible();
#else
VisibleSwitch = 1;
Visible = 0;
#endif
break;
case SIGUSR2:
ioctl(ConsoleFD, VT_GETSTATE, &st);
if(st.v_active)
ioctl(ConsoleFD, VT_RELDISP, VT_ACKACQ);

/* this is a hack to turn the cursor off */
ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo);

RestoreColorMap();

Active = 1;
Visible = 1;
VisibleSwitch = 1;

Redisplay = 1;

break;
}
}

void InitializeVT(int usestdin)
{
struct termios tio;
struct vt_mode vt;
char console[128];

/* terminos settings for straight-through mode */
if (tcgetattr(0, &OldTermios) < 0) {
sprintf(exiterror, "tcgetattr failed\n");
exit(0);
}

tio = OldTermios;
tio.c_lflag &= ~(ICANON | ECHO | ISIG);
tio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
tio.c_iflag |= IGNBRK;

tio.c_cc[VMIN] = 0;
tio.c_cc[VTIME] = 0;

if (tcsetattr(0, TCSANOW, &tio) < 0) {
sprintf(exiterror, "tcsetattr failed\n");
exit(0);
}

if(fcntl(0, F_SETFL, O_NONBLOCK | O_ASYNC) < 0) {
sprintf(exiterror, "Failed to set keyboard to non-blocking\n");
exit(0);
}

Active = 1;

if(usestdin) {
ConsoleFD = 0;
return;
}

/* detect the current vt if it was not specified */
if(CurrentVT == 0) {
int fd = open("/dev/tty", O_RDWR | O_NDELAY, 0);
struct vt_stat st;
if(fd == -1) {
sprintf(exiterror, "Failed to open /dev/tty\n");
exit(0);
}
if(ioctl(fd, VT_GETSTATE, &st) == -1) {
fprintf(stderr, "Could not detect current vt, specify with -vt\n");
fprintf(stderr, "Defaulting to stdin input\n");
ConsoleFD = 0;
close(fd);
return;
} else
CurrentVT = st.v_active;

close(fd);
}
/* open the console tty */
sprintf(console, "/dev/tty%d", CurrentVT);
ConsoleFD = open(console, O_RDWR | O_NDELAY, 0);
if (ConsoleFD < 0) {
sprintf(exiterror, "error couldn't open %s,"
" defaulting to stdin \n", console);
ConsoleFD = 0;
return;
}

signal(SIGUSR1, VTSwitchHandler);
signal(SIGUSR2, VTSwitchHandler);

if (ioctl(ConsoleFD, VT_GETMODE, &OldVTMode) < 0) {
sprintf(exiterror,"Failed to grab %s, defaulting to stdin\n", console);
close(ConsoleFD);
ConsoleFD = 0;
return;
}

vt = OldVTMode;

vt.mode = VT_PROCESS;
vt.waitv = 0;
vt.relsig = SIGUSR1;
vt.acqsig = SIGUSR2;
if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
sprintf(exiterror, "error: ioctl(VT_SETMODE) failed: %s\n",
strerror(errno));
close(ConsoleFD);
ConsoleFD = 0;
exit(1);
}

if (ioctl(ConsoleFD, KDGKBMODE, &OldKDMode) < 0) {
sprintf(exiterror, "Warning: ioctl KDGKBMODE failed!\n");
OldKDMode = K_XLATE;
}

/* 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) {
sprintf(exiterror, "Failed to set keyboard to non-blocking\n");
exit(0);
}

fcntl(0, F_SETOWN, getpid());

if(ioctl(ConsoleFD, KDGETMODE, &OldMode) < 0)
sprintf(exiterror, "Warning: Failed to get terminal mode\n");

#ifdef HAVE_GPM
if(!GpmMouse)
#endif
if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0)
sprintf(exiterror,"Warning: Failed to set terminal to graphics\n");


if (ioctl(ConsoleFD, KDSKBMODE, K_MEDIUMRAW) < 0) {
sprintf(exiterror, "ioctl KDSKBMODE failed!\n");
tcsetattr(0, TCSANOW, &OldTermios);
exit(0);
}

if( ioctl(ConsoleFD, KDGKBLED, &KeyboardLedState) < 0) {
sprintf(exiterror, "ioctl KDGKBLED failed!\n");
exit(0);
}
}

void RestoreVT(void)
{
if(ConsoleFD >= 0)
if (tcsetattr(0, TCSANOW, &OldTermios) < 0)
fprintf(stderr, "tcsetattr failed\n");

if(ConsoleFD > 0) {
/* restore keyboard state */
if (ioctl(ConsoleFD, VT_SETMODE, &OldVTMode) < 0)
fprintf(stderr, "Failed to set vtmode\n");

if (ioctl(ConsoleFD, KDSKBMODE, OldKDMode) < 0)
fprintf(stderr, "ioctl KDSKBMODE failed!\n");

/* 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");

if(ioctl(ConsoleFD, KDSETMODE, OldMode) < 0)
fprintf(stderr, "ioctl KDSETMODE failed!\n");

close(ConsoleFD);
}
}

void InitializeMouse(void)
{
#ifdef HAVE_GPM
if(GpmMouse) {
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");
return;
}
if(!MouseSpeed)
MouseSpeed = 5;
} else
#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;
}

void CloseMouse(void)
{
#ifdef HAVE_GPM
if(GpmMouse) {
if(NumMouseButtons)
Gpm_Close();
} else
#endif
if(MouseFD >= 0)
close(MouseFD);
}

+ 159
- 0
src/glut/fbdev/internal.h View File

@@ -0,0 +1,159 @@
/*
* 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
*/

#include <sys/time.h>
#include <linux/fb.h>

#define MULTIHEAD /* enable multihead hacks,
it allows the program to continue drawing
without reading input when a second fbdev
has keyboard focus it can cause
screen corruption that requires C-l to fix */
#define HAVE_GPM

/* this causes these symbols to not be exported */
#pragma GCC visibility push(hidden)

extern int Redisplay;
extern int Visible;
extern int VisibleSwitch;
extern int Active;
extern int VisiblePoll;

void TestVisible(void);

extern int FrameBufferFD;
extern unsigned char *FrameBuffer;
extern unsigned char *BackBuffer;
extern int DisplayMode;

extern char exiterror[256];

extern struct fb_fix_screeninfo FixedInfo;
extern struct fb_var_screeninfo VarInfo, OrigVarInfo;

/* --- colormap --- */
#define REVERSECMAPSIZELOG 3
#define REVERSECMAPSIZE (1<<REVERSECMAPSIZELOG)

extern unsigned short RedColorMap[256],
GreenColorMap[256],
BlueColorMap[256];
extern unsigned char ReverseColorMap[REVERSECMAPSIZE]
[REVERSECMAPSIZE]
[REVERSECMAPSIZE];
void LoadColorMap(void);
void UnloadColorMap(void);
void RestoreColorMap(void);

/* --- mouse --- */
extern int MouseX, MouseY;
extern int CurrentCursor;
extern int MouseEnabled;
extern int NumMouseButtons;

void InitializeCursor(void);
void EraseCursor(void);
void DrawCursor(void);
void SwapCursor(void);

/* --- menus --- */
struct GlutMenu {
int NumItems;
int x, y;
int width;
int selected;
struct {
int value;
int submenu;
char *name;
} *Items;
void (*func)(int);
};

extern struct GlutMenu *Menus;

extern int ActiveMenu;
extern int CurrentMenu;

void InitializeMenus(void);
void FreeMenus(void);
void DrawMenus(void);

int TryMenu(int, int);
void OpenMenu(void);
void CloseMenu(void);

/* --- state --- */
extern int AccumSize, DepthSize, StencilSize;
extern struct timeval StartTime;
extern int KeyboardModifiers;

/* --- input --- */
#ifdef HAVE_GPM
extern int GpmMouse;
#endif

extern int CurrentVT;
extern int ConsoleFD;

extern double MouseSpeed;

extern int KeyRepeatMode;

void InitializeVT(int);
void RestoreVT(void);
void CloseMouse(void);
void InitializeMouse(void);

void ReceiveInput(void);

/* --- callback --- */
extern void (*DisplayFunc)(void);
extern void (*ReshapeFunc)(int width, int height);
extern void (*KeyboardFunc)(unsigned char key, int x, int y);
extern void (*KeyboardUpFunc)(unsigned char key, int x, int y);
extern void (*MouseFunc)(int key, int state, int x, int y);
extern void (*MotionFunc)(int x, int y);
extern void (*PassiveMotionFunc)(int x, int y);
extern void (*VisibilityFunc)(int state);
extern void (*SpecialFunc)(int key, int x, int y);
extern void (*SpecialUpFunc)(int key, int x, int y);
extern void (*IdleFunc)(void);
extern void (*MenuStatusFunc)(int state, int x, int y);
extern void (*MenuStateFunc)(int state);

/* --- timers --- */
struct GlutTimer {
int time;
void (*func)(int);
int value;
struct GlutTimer *next;
};

extern struct GlutTimer *GlutTimers;

#pragma GCC visibility pop

+ 299
- 0
src/glut/fbdev/menu.c View File

@@ -0,0 +1,299 @@
/*
* 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
*/

#include <stdlib.h>

#include <linux/fb.h>

#include <GL/glut.h>

#include "internal.h"

#define MENU_FONT_WIDTH 9
#define MENU_FONT_HEIGHT 15
#define MENU_FONT GLUT_BITMAP_9_BY_15
#define SUBMENU_OFFSET 20

struct GlutMenu *Menus;
int ActiveMenu;
int CurrentMenu;

static double MenuProjection[16];
static double MenuModelview[16];

static int AttachedMenus[3];
static int NumMenus = 1;
static int SelectedMenu;

void InitializeMenus(void)
{
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
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();
}

void FreeMenus(void)
{
int i, j;
for(i = 1; i<NumMenus; i++) {
for(j = 1; i<Menus[i].NumItems; j++)
free(Menus[i].Items[j].name);
free(Menus[i].Items);
}
free(Menus);
}

int TryMenu(int button, int pressed)
{
if(ActiveMenu && !pressed) {
ActiveMenu = 0;
CloseMenu();
Redisplay = 1;
return 1;
}

if(AttachedMenus[button] && pressed) {
ActiveMenu = AttachedMenus[button];
OpenMenu();
Redisplay = 1;
return 1;
}
return 0;
}

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;
if(MouseY >= *y && MouseY < *y + MENU_FONT_HEIGHT &&
MouseX >= x && MouseX < x + Menus[menu].width) {
a = 1;
SelectedMenu = menu;
ret = 0;
Menus[menu].selected = i;
glColor3f(1,0,0);
} else
glColor3f(1,1,1);

*y += MENU_FONT_HEIGHT;
glRasterPos2i(x, *y);
for(; *s; s++)
glutBitmapCharacter(MENU_FONT, *s);

if(Menus[menu].selected == i)
if(Menus[menu].Items[i].submenu)
if(DrawMenu(Menus[menu].Items[i].submenu, x
+ SUBMENU_OFFSET, y)) {
if(!a)
Menus[menu].selected = -1;
} else
ret = 0;
}
return ret;
}

void DrawMenus(void)
{
int x = Menus[ActiveMenu].x;
int y = Menus[ActiveMenu].y;

/* save old settings */
glPushAttrib(-1);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixd(MenuModelview);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixd(MenuProjection);

glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glDisable(GL_TEXTURE_2D);
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_AND_REVERSE);
if(DrawMenu(ActiveMenu, x, &y))
Menus[ActiveMenu].selected = -1;
/* restore settings */
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();

glPopAttrib();
}

void OpenMenu(void)
{
if(MenuStatusFunc)
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].selected = -1;
}

void CloseMenu(void)
{
if(MenuStatusFunc)
MenuStatusFunc(GLUT_MENU_NOT_IN_USE, MouseX, MouseY);
if(MenuStateFunc)
MenuStateFunc(GLUT_MENU_NOT_IN_USE);
if(SelectedMenu > 0) {
int selected = Menus[SelectedMenu].selected;
if(selected >= 0)
if(Menus[SelectedMenu].Items[selected].submenu == 0)
Menus[SelectedMenu].func(Menus[SelectedMenu].Items
[selected].value);
}

}

/* glut menu functions */

int glutCreateMenu(void (*func)(int value))
{
MouseEnabled = 1;
CurrentMenu = NumMenus;
NumMenus++;
Menus = realloc(Menus, sizeof(*Menus) * NumMenus);
Menus[CurrentMenu].NumItems = 0;
Menus[CurrentMenu].Items = NULL;
Menus[CurrentMenu].func = func;
Menus[CurrentMenu].width = 0;
return CurrentMenu;
}

void glutSetMenu(int menu)
{
CurrentMenu = menu;
}

int glutGetMenu(void)
{
return CurrentMenu;
}

void glutDestroyMenu(int menu)
{
if(menu == CurrentMenu)
CurrentMenu = 0;
}

static void NameMenuEntry(int entry, const char *name)
{
int cm = CurrentMenu;
if(!(Menus[cm].Items[entry-1].name = realloc(Menus[cm].Items[entry-1].name,
strlen(name) + 1))) {
sprintf(exiterror, "realloc failed in NameMenuEntry\n");
exit(0);
}
strcpy(Menus[cm].Items[entry-1].name, name);
if(strlen(name) * MENU_FONT_WIDTH > Menus[cm].width)
Menus[cm].width = strlen(name) * MENU_FONT_WIDTH;
}

static int AddMenuItem(const char *name)
{
int cm = CurrentMenu;
int item = Menus[cm].NumItems++;
if(!(Menus[cm].Items = realloc(Menus[cm].Items,
Menus[cm].NumItems * sizeof(*Menus[0].Items)))) {
sprintf(exiterror, "realloc failed in AddMenuItem\n");
exit(0);
}
Menus[cm].Items[item].name = NULL;
NameMenuEntry(item+1, name);
return item;
}

void glutAddMenuEntry(const char *name, int value)
{
int item = AddMenuItem(name);
Menus[CurrentMenu].Items[item].value = value;
Menus[CurrentMenu].Items[item].submenu = 0;
}

void glutAddSubMenu(const char *name, int menu)
{
int item = AddMenuItem(name);
if(menu == CurrentMenu) {
sprintf(exiterror, "Recursive menus not supported\n");
exit(0);
}
Menus[CurrentMenu].Items[item].submenu = menu;
}

void glutChangeToMenuEntry(int entry, const char *name, int value)
{
NameMenuEntry(entry, name);
Menus[CurrentMenu].Items[entry-1].value = value;
Menus[CurrentMenu].Items[entry-1].submenu = 0;
}

void glutChangeToSubMenu(int entry, const char *name, int menu)
{
NameMenuEntry(entry, name);
Menus[CurrentMenu].Items[entry-1].submenu = menu;
}

void glutRemoveMenuItem(int entry)
{
memmove(Menus[CurrentMenu].Items + entry - 1,
Menus[CurrentMenu].Items + entry,
sizeof(*Menus[0].Items) * (Menus[CurrentMenu].NumItems - entry));
Menus[CurrentMenu].NumItems--;
}

void glutAttachMenu(int button)
{
AttachedMenus[button] = CurrentMenu;
}

void glutDetachMenu(int button)
{
AttachedMenus[button] = 0;
}

+ 56
- 0
src/glut/fbdev/overlay.c View File

@@ -0,0 +1,56 @@
/*
* 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
*/

#include <GL/gl.h>

void glutEstablishOverlay(void)
{
exit(0);
}

void glutUseLayer(GLenum layer)
{
}

void glutRemoveOverlay(void)
{
}

void glutPostOverlayRedisplay(void)
{
}

void glutPostWindowOverlayRedisplay(int win)
{
}

void glutShowOverlay(void)
{
}

void glutHideOverlay(void)
{
}

+ 205
- 0
src/glut/fbdev/state.c View File

@@ -0,0 +1,205 @@
/*
* 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
*/

#include <sys/time.h>

#include <linux/fb.h>

#include <GL/glut.h>

#include "../../mesa/main/config.h"

#include "internal.h"

int AccumSize = 16; /* per channel size of accumulation buffer */
int DepthSize = DEFAULT_SOFTWARE_DEPTH_BITS;
int StencilSize = STENCIL_BITS;

int glutGet(GLenum state)
{
switch(state) {
case GLUT_WINDOW_X:
return 0;
case GLUT_WINDOW_Y:
return 0;
case GLUT_INIT_WINDOW_WIDTH:
case GLUT_WINDOW_WIDTH:
case GLUT_SCREEN_WIDTH:
return VarInfo.xres;
case GLUT_INIT_WINDOW_HEIGHT:
case GLUT_WINDOW_HEIGHT:
case GLUT_SCREEN_HEIGHT:
return VarInfo.yres;
case GLUT_WINDOW_BUFFER_SIZE:
return VarInfo.bits_per_pixel;
case GLUT_WINDOW_STENCIL_SIZE:
return StencilSize;
case GLUT_WINDOW_DEPTH_SIZE:
return DepthSize;
case GLUT_WINDOW_RED_SIZE:
return VarInfo.red.length;
case GLUT_WINDOW_GREEN_SIZE:
return VarInfo.green.length;
case GLUT_WINDOW_BLUE_SIZE:
return VarInfo.green.length;
case GLUT_WINDOW_ALPHA_SIZE:
return VarInfo.transp.length;
case GLUT_WINDOW_ACCUM_RED_SIZE:
case GLUT_WINDOW_ACCUM_GREEN_SIZE:
case GLUT_WINDOW_ACCUM_BLUE_SIZE:
case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
return AccumSize;
case GLUT_WINDOW_DOUBLEBUFFER:
if(DisplayMode & GLUT_DOUBLE)
return 1;
return 0;
case GLUT_WINDOW_RGBA:
if(DisplayMode & GLUT_INDEX)
return 0;
return 1;
case GLUT_WINDOW_PARENT:
return 0;
case GLUT_WINDOW_NUM_CHILDREN:
return 0;
case GLUT_WINDOW_COLORMAP_SIZE:
if(DisplayMode & GLUT_INDEX)
return 256;
return 0;
case GLUT_WINDOW_NUM_SAMPLES:
return 0;
case GLUT_WINDOW_STEREO:
return 0;
case GLUT_WINDOW_CURSOR:
return CurrentCursor;
case GLUT_SCREEN_WIDTH_MM:
return VarInfo.width;
case GLUT_SCREEN_HEIGHT_MM:
return VarInfo.height;
case GLUT_MENU_NUM_ITEMS:
if(CurrentMenu)
return Menus[CurrentMenu].NumItems;
return 0;
case GLUT_DISPLAY_MODE_POSSIBLE:
if((DisplayMode & GLUT_MULTISAMPLE)
|| (DisplayMode & GLUT_STEREO)
|| (DisplayMode & GLUT_LUMINANCE)
|| (DisplayMode & GLUT_ALPHA) && (DisplayMode & GLUT_INDEX))
return 0;
return 1;
case GLUT_INIT_DISPLAY_MODE:
return DisplayMode;
case GLUT_INIT_WINDOW_X:
case GLUT_INIT_WINDOW_Y:
return 0;
case GLUT_ELAPSED_TIME:
{
static struct timeval tv;
gettimeofday(&tv, 0);
return 1000 * (tv.tv_sec - StartTime.tv_sec)
+ (tv.tv_usec - StartTime.tv_usec) / 1000;
}
}
return -1;
}

int glutLayerGet(GLenum info)
{
switch(info) {
case GLUT_OVERLAY_POSSIBLE:
return 0;
case GLUT_LAYER_IN_USE:
return GLUT_NORMAL;
case GLUT_HAS_OVERLAY:
return 0;
case GLUT_TRANSPARENT_INDEX:
return -1;
case GLUT_NORMAL_DAMAGED:
return Redisplay;
case GLUT_OVERLAY_DAMAGED:
return -1;
}
return -1;
}

int glutDeviceGet(GLenum info)
{
switch(info) {
case GLUT_HAS_KEYBOARD:
return ConsoleFD != -1 ? 1 : 0;
case GLUT_HAS_MOUSE:
case GLUT_NUM_MOUSE_BUTTONS:
return NumMouseButtons;
case GLUT_HAS_SPACEBALL:
case GLUT_HAS_DIAL_AND_BUTTON_BOX:
case GLUT_HAS_TABLET:
return 0;
case GLUT_NUM_SPACEBALL_BUTTONS:
case GLUT_NUM_BUTTON_BOX_BUTTONS:
case GLUT_NUM_DIALS:
case GLUT_NUM_TABLET_BUTTONS:
return 0;
case GLUT_DEVICE_IGNORE_KEY_REPEAT:
return KeyRepeatMode == GLUT_KEY_REPEAT_OFF;
case GLUT_DEVICE_KEY_REPEAT:
return KeyRepeatMode;
case GLUT_JOYSTICK_POLL_RATE:
case GLUT_HAS_JOYSTICK:
case GLUT_JOYSTICK_BUTTONS:
case GLUT_JOYSTICK_AXES:
return 0;
}
return -1;
}

int glutVideoResizeGet(GLenum param)
{
switch(param) {
case GLUT_VIDEO_RESIZE_POSSIBLE:
return 0;
}
return -1;
}

int glutGetModifiers(void){
return KeyboardModifiers;
}

int glutExtensionSupported(const char *extension)
{
const char *exts = (const char *) glGetString(GL_EXTENSIONS);
const char *start = exts;
int len = strlen(extension);
for(;;) {
const char *p = strstr(exts, extension);
if(!p)
break;
if((p == start || p[-1] == ' ') && (p[len] == ' ' || p[len] == 0))
return 1;
exts = p + len;
}
return 0;
}

Loading…
Cancel
Save