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
@@ -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) |
@@ -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; | |||
} |
@@ -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) | |||
{ | |||
} |
@@ -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(); | |||
} |
@@ -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); | |||
} |
@@ -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) | |||
{ | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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 |
@@ -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; | |||
} |
@@ -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) | |||
{ | |||
} |
@@ -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; | |||
} |