mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-03-24 07:00:42 +01:00
Updated all drivers that used the old _ac_ functions to use the new _vbo_ functions. I know this fixed the fbdev driver, it looks like it might fix some other drivers too.
940 lines
20 KiB
C
940 lines
20 KiB
C
/*
|
|
* 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
|
|
*
|
|
* To improve on this library, maybe support subwindows or overlays,
|
|
* I (sean at depagnier dot com) will do my best to help.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <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/glut.h>
|
|
|
|
#include "internal.h"
|
|
|
|
#define FBMODES "/etc/fb.modes"
|
|
|
|
struct fb_fix_screeninfo FixedInfo;
|
|
struct fb_var_screeninfo VarInfo;
|
|
static struct fb_var_screeninfo 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 */
|
|
GLFBDevContextPtr Context;
|
|
GLFBDevBufferPtr Buffer;
|
|
GLFBDevVisualPtr Visual;
|
|
|
|
int Redisplay;
|
|
int Visible;
|
|
int VisibleSwitch;
|
|
int Active;
|
|
static int Resized;
|
|
/* we have to poll to see if we are visible
|
|
on a framebuffer that is not active */
|
|
int VisiblePoll;
|
|
int Swapping, VTSwitch;
|
|
static int FramebufferIndex;
|
|
|
|
static int 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)
|
|
{
|
|
/* do not handle this signal when cleaning up */
|
|
signal(SIGWINCH, SIG_IGN);
|
|
|
|
if(GameMode)
|
|
glutLeaveGameMode();
|
|
|
|
if(ConsoleFD != -1)
|
|
RestoreVT();
|
|
|
|
/* close mouse */
|
|
CloseMouse();
|
|
|
|
if(Visual)
|
|
glutDestroyWindow(1);
|
|
|
|
/* restore original variable screen info */
|
|
if(FrameBufferFD != -1) {
|
|
OrigVarInfo.xoffset = 0;
|
|
OrigVarInfo.yoffset = 0;
|
|
|
|
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo))
|
|
fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
|
|
strerror(errno));
|
|
|
|
if(FrameBuffer)
|
|
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, nomouse = 0, nokeyboard = 0, usestdin = 0;
|
|
int RequiredWidth = 0, RequiredHeight;
|
|
char *fbdev;
|
|
|
|
stack_t stack;
|
|
struct sigaction sa;
|
|
|
|
/* 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);
|
|
|
|
/* set up SIGSEGV to use alternate stack */
|
|
stack.ss_flags = 0;
|
|
stack.ss_size = SIGSTKSZ;
|
|
if(!(stack.ss_sp = malloc(SIGSTKSZ)))
|
|
sprintf(exiterror, "Failed to allocate alternate stack for SIGSEGV!\n");
|
|
|
|
sigaltstack(&stack, NULL);
|
|
|
|
sa.sa_handler = CrashHandler;
|
|
sa.sa_flags = SA_ONSTACK;
|
|
sigemptyset(&sa.sa_mask);
|
|
sigaction(SIGSEGV, &sa, NULL);
|
|
|
|
signal(SIGINT, CrashHandler);
|
|
signal(SIGTERM, CrashHandler);
|
|
signal(SIGABRT, CrashHandler);
|
|
|
|
if(nomouse == 0)
|
|
InitializeMouse();
|
|
if(nokeyboard == 0)
|
|
InitializeVT(usestdin);
|
|
|
|
fbdev = getenv("FRAMEBUFFER");
|
|
if(fbdev) {
|
|
#ifdef MULTIHEAD
|
|
if(!sscanf(fbdev, "/dev/fb%d", &FramebufferIndex))
|
|
if(!sscanf(fbdev, "/dev/fb/%d", &FramebufferIndex))
|
|
sprintf(exiterror, "Could not determine Framebuffer index!\n");
|
|
#endif
|
|
} else {
|
|
static char fb[128];
|
|
struct fb_con2fbmap confb;
|
|
int fd = open("/dev/fb0", O_RDWR);
|
|
|
|
FramebufferIndex = 0;
|
|
|
|
confb.console = CurrentVT;
|
|
if(ioctl(fd, FBIOGET_CON2FBMAP, &confb) != -1)
|
|
FramebufferIndex = confb.framebuffer;
|
|
sprintf(fb, "/dev/fb%d", FramebufferIndex);
|
|
fbdev = fb;
|
|
close(fd);
|
|
}
|
|
|
|
/* open the framebuffer device */
|
|
FrameBufferFD = open(fbdev, O_RDWR);
|
|
if (FrameBufferFD < 0) {
|
|
sprintf(exiterror, "Error opening %s: %s\n", fbdev, strerror(errno));
|
|
exit(0);
|
|
}
|
|
|
|
/* get the fixed screen info */
|
|
if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
|
|
sprintf(exiterror, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
|
|
strerror(errno));
|
|
exit(0);
|
|
}
|
|
|
|
/* get the variable screen info */
|
|
if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
|
|
sprintf(exiterror, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
|
|
strerror(errno));
|
|
exit(0);
|
|
}
|
|
|
|
/* operate on a copy */
|
|
VarInfo = OrigVarInfo;
|
|
|
|
/* set the depth, resolution, etc */
|
|
if(RequiredWidth)
|
|
if(!ParseFBModes(RequiredWidth, RequiredWidth, RequiredHeight,
|
|
RequiredHeight, 0, MAX_VSYNC)) {
|
|
sprintf(exiterror, "No mode (%dx%d) found in "FBMODES"\n",
|
|
RequiredWidth, RequiredHeight);
|
|
exit(0);
|
|
}
|
|
|
|
Initialized = 1;
|
|
}
|
|
|
|
void glutInitDisplayMode (unsigned int mode)
|
|
{
|
|
DisplayMode = mode;
|
|
}
|
|
|
|
static const char *GetStrVal(const char *p, int *set, int min, int max)
|
|
{
|
|
char *endptr;
|
|
int comp = *p, val;
|
|
|
|
if(p[1] == '=')
|
|
p++;
|
|
|
|
if(*p == '\0')
|
|
return p;
|
|
|
|
val = strtol(p+1, &endptr, 10);
|
|
|
|
if(endptr == p+1)
|
|
return p;
|
|
|
|
switch(comp) {
|
|
case '!':
|
|
if(val == min)
|
|
val = max;
|
|
else
|
|
val = min;
|
|
break;
|
|
case '<':
|
|
val = min;
|
|
break;
|
|
case '>':
|
|
val = max;
|
|
break;
|
|
}
|
|
|
|
if(val < min || val > max) {
|
|
sprintf(exiterror, "display string value out of range\n");
|
|
exit(0);
|
|
}
|
|
|
|
*set = val;
|
|
|
|
return endptr;
|
|
}
|
|
|
|
static void SetAttrib(int val, int attr)
|
|
{
|
|
if(val)
|
|
DisplayMode |= attr;
|
|
else
|
|
DisplayMode &= ~attr;
|
|
}
|
|
|
|
void glutInitDisplayString(const char *string)
|
|
{
|
|
const char *p = string;
|
|
int val;
|
|
while(*p) {
|
|
if(*p == ' ')
|
|
p++;
|
|
else
|
|
if(memcmp(p, "acca", 4) == 0) {
|
|
p = GetStrVal(p+4, &AccumSize, 1, 32);
|
|
SetAttrib(AccumSize, GLUT_ACCUM);
|
|
} else
|
|
if(memcmp(p, "acc", 3) == 0) {
|
|
p = GetStrVal(p+3, &AccumSize, 1, 32);
|
|
SetAttrib(AccumSize, GLUT_ACCUM);
|
|
} else
|
|
if(memcmp(p, "depth", 5) == 0) {
|
|
p = GetStrVal(p+5, &DepthSize, 12, 32);
|
|
SetAttrib(DepthSize, GLUT_DEPTH);
|
|
} else
|
|
if(memcmp(p, "double", 6) == 0) {
|
|
val = 1;
|
|
p = GetStrVal(p+6, &val, 0, 1);
|
|
SetAttrib(val, GLUT_DOUBLE);
|
|
} else
|
|
if(memcmp(p, "index", 5) == 0) {
|
|
val = 1;
|
|
p = GetStrVal(p+5, &val, 0, 1);
|
|
SetAttrib(val, GLUT_INDEX);
|
|
} else
|
|
if(memcmp(p, "stencil", 7) == 0) {
|
|
p = GetStrVal(p+7, &StencilSize, 0, 1);
|
|
SetAttrib(StencilSize, GLUT_STENCIL);
|
|
} else
|
|
if(memcmp(p, "samples", 7) == 0) {
|
|
NumSamples = 1;
|
|
p = GetStrVal(p+7, &NumSamples, 0, 16);
|
|
SetAttrib(NumSamples, GLUT_MULTISAMPLE);
|
|
} else
|
|
if(p = strchr(p, ' '))
|
|
p++;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
void glutInitWindowPosition (int x, int y)
|
|
{
|
|
}
|
|
|
|
void glutInitWindowSize (int width, int height)
|
|
{
|
|
}
|
|
|
|
static void ProcessTimers(void)
|
|
{
|
|
while(GlutTimers && GlutTimers->time <= glutGet(GLUT_ELAPSED_TIME)) {
|
|
struct GlutTimer *timer = GlutTimers;
|
|
GlutTimers = timer->next;
|
|
timer->func(timer->value);
|
|
free(timer);
|
|
}
|
|
}
|
|
|
|
void glutMainLoop(void)
|
|
{
|
|
int idleiters;
|
|
|
|
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(Resized) {
|
|
SetVideoMode();
|
|
CreateBuffer();
|
|
|
|
if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) {
|
|
sprintf(exiterror, "Failure to Make Current\n");
|
|
exit(0);
|
|
}
|
|
|
|
InitializeMenus();
|
|
|
|
if(ReshapeFunc)
|
|
ReshapeFunc(VarInfo.xres, VarInfo.yres);
|
|
|
|
Redisplay = 1;
|
|
Resized = 0;
|
|
}
|
|
|
|
if(Visible && Redisplay) {
|
|
Redisplay = 0;
|
|
EraseCursor();
|
|
DisplayFunc();
|
|
if(!(DisplayMode & GLUT_DOUBLE)) {
|
|
if(ActiveMenu)
|
|
DrawMenus();
|
|
DrawCursor();
|
|
}
|
|
idleiters = 0;
|
|
} else {
|
|
/* we sleep if not receiving redisplays, and
|
|
the main loop is running faster than 2khz */
|
|
|
|
static int lasttime;
|
|
int time = glutGet(GLUT_ELAPSED_TIME);
|
|
if(time > lasttime) {
|
|
if(idleiters >= 2)
|
|
usleep(100);
|
|
|
|
idleiters = 0;
|
|
lasttime = time;
|
|
}
|
|
idleiters++;
|
|
}
|
|
}
|
|
}
|
|
|
|
int ParseFBModes(int minw, int maxw, int minh, int maxh, int minf, int maxf)
|
|
{
|
|
char buf[1024];
|
|
struct fb_var_screeninfo vi = VarInfo;
|
|
|
|
FILE *fbmodes = fopen(FBMODES, "r");
|
|
|
|
if(!fbmodes) {
|
|
sprintf(exiterror, "Warning: could not open "FBMODES"\n");
|
|
return 0;
|
|
}
|
|
|
|
while(fgets(buf, sizeof buf, fbmodes)) {
|
|
char *c;
|
|
int v, bpp, freq;
|
|
|
|
if(!(c = strstr(buf, "geometry")))
|
|
continue;
|
|
v = sscanf(c, "geometry %d %d %d %d %d", &vi.xres, &vi.yres,
|
|
&vi.xres_virtual, &vi.yres_virtual, &bpp);
|
|
if(v != 5)
|
|
continue;
|
|
|
|
if(maxw < minw) {
|
|
if(maxw < vi.xres && minw > vi.xres)
|
|
continue;
|
|
} else
|
|
if(maxw < vi.xres || minw > vi.xres)
|
|
continue;
|
|
|
|
if(maxh < minh) {
|
|
if(maxh < vi.yres && minh > vi.yres)
|
|
continue;
|
|
} else
|
|
if(maxh < vi.yres || minh > vi.yres)
|
|
continue;
|
|
|
|
fgets(buf, sizeof buf, fbmodes);
|
|
if(!(c = strstr(buf, "timings")))
|
|
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;
|
|
|
|
freq = 1E12/vi.pixclock
|
|
/(vi.left_margin + vi.xres + vi.right_margin + vi.hsync_len)
|
|
/(vi.upper_margin + vi.yres + vi.lower_margin + vi.vsync_len);
|
|
|
|
if(maxf < minf) {
|
|
if(maxf < freq && minf > freq)
|
|
continue;
|
|
} else
|
|
if(maxf < freq || minf > freq)
|
|
continue;
|
|
|
|
VarInfo = vi;
|
|
fclose(fbmodes);
|
|
return 1;
|
|
}
|
|
|
|
fclose(fbmodes);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SetVideoMode(void)
|
|
{
|
|
/* set new variable screen info */
|
|
if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
|
|
sprintf(exiterror, "FBIOPUT_VSCREENINFO failed: %s\n", strerror(errno));
|
|
strcat(exiterror, "Perhaps the device does not support the selected mode\n");
|
|
exit(0);
|
|
}
|
|
|
|
/* reload the screen info to update rgb bits */
|
|
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();
|
|
}
|
|
|
|
void CreateBuffer(void)
|
|
{
|
|
int size = VarInfo.xres_virtual * VarInfo.yres_virtual
|
|
* VarInfo.bits_per_pixel / 8;
|
|
|
|
/* mmap the framebuffer into our address space */
|
|
if(FrameBuffer)
|
|
munmap(FrameBuffer, FixedInfo.smem_len);
|
|
FrameBuffer = mmap(0, FixedInfo.smem_len, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, FrameBufferFD, 0);
|
|
if (FrameBuffer == MAP_FAILED) {
|
|
sprintf(exiterror, "error: unable to mmap framebuffer: %s\n",
|
|
strerror(errno));
|
|
exit(0);
|
|
}
|
|
|
|
if(DisplayMode & GLUT_DOUBLE) {
|
|
free(BackBuffer);
|
|
if(!(BackBuffer = malloc(size))) {
|
|
sprintf(exiterror, "Failed to allocate double buffer\n");
|
|
exit(0);
|
|
}
|
|
} else
|
|
BackBuffer = FrameBuffer;
|
|
|
|
if(Buffer)
|
|
glFBDevDestroyBuffer(Buffer);
|
|
|
|
if(!(Buffer = glFBDevCreateBuffer( &FixedInfo, &VarInfo, Visual,
|
|
FrameBuffer, BackBuffer, size))) {
|
|
sprintf(exiterror, "Failure to create Buffer\n");
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
void CreateVisual(void)
|
|
{
|
|
int i, mask = DisplayMode;
|
|
int attribs[20];
|
|
for(i=0; i<sizeof(attribs)/sizeof(*attribs) && mask; i++) {
|
|
if(mask & GLUT_DOUBLE) {
|
|
attribs[i] = GLFBDEV_DOUBLE_BUFFER;
|
|
mask &= ~GLUT_DOUBLE;
|
|
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;
|
|
}
|
|
|
|
if(mask & GLUT_MULTISAMPLE) {
|
|
attribs[i] = GLFBDEV_MULTISAMPLE;
|
|
attribs[++i] = NumSamples;
|
|
mask &= ~GLUT_MULTISAMPLE;
|
|
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);
|
|
}
|
|
}
|
|
|
|
static void SignalWinch(int arg)
|
|
{
|
|
/* we can't change bitdepth without destroying the visual */
|
|
int bits_per_pixel = VarInfo.bits_per_pixel;
|
|
struct fb_bitfield red = VarInfo.red, green = VarInfo.green,
|
|
blue = VarInfo.blue, transp = VarInfo.transp;
|
|
|
|
/* get the variable screen info */
|
|
if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &VarInfo)) {
|
|
sprintf(exiterror, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
|
|
strerror(errno));
|
|
exit(0);
|
|
}
|
|
|
|
/* restore bitdepth and color masks only */
|
|
VarInfo.bits_per_pixel = bits_per_pixel;
|
|
VarInfo.red = red;
|
|
VarInfo.green = green;
|
|
VarInfo.blue = blue;
|
|
VarInfo.transp = transp;
|
|
|
|
Resized = 1;
|
|
}
|
|
|
|
int glutCreateWindow (const char *title)
|
|
{
|
|
if(Initialized == 0) {
|
|
int argc = 0;
|
|
char *argv[] = {NULL};
|
|
glutInit(&argc, argv);
|
|
}
|
|
|
|
if(Context)
|
|
return 0;
|
|
|
|
if(DisplayMode & GLUT_INDEX)
|
|
VarInfo.bits_per_pixel = 8;
|
|
else
|
|
if(VarInfo.bits_per_pixel == 8)
|
|
VarInfo.bits_per_pixel = 32;
|
|
|
|
if (DesiredDepth)
|
|
VarInfo.bits_per_pixel = DesiredDepth;
|
|
|
|
VarInfo.xoffset = 0;
|
|
VarInfo.yoffset = 0;
|
|
VarInfo.nonstd = 0;
|
|
VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
|
|
|
|
SetVideoMode();
|
|
CreateVisual();
|
|
CreateBuffer();
|
|
|
|
if(!(Context = glFBDevCreateContext(Visual, NULL))) {
|
|
sprintf(exiterror, "Failure to create Context\n");
|
|
exit(0);
|
|
}
|
|
|
|
if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) {
|
|
sprintf(exiterror, "Failure to Make Current\n");
|
|
exit(0);
|
|
}
|
|
|
|
InitializeCursor();
|
|
InitializeMenus();
|
|
|
|
glutSetWindowTitle(title);
|
|
|
|
signal(SIGWINCH, SignalWinch);
|
|
|
|
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)
|
|
{
|
|
glFBDevMakeCurrent( NULL, NULL, NULL);
|
|
glFBDevDestroyContext(Context);
|
|
glFBDevDestroyBuffer(Buffer);
|
|
glFBDevDestroyVisual(Visual);
|
|
|
|
Visual = NULL;
|
|
}
|
|
|
|
void glutPostRedisplay(void)
|
|
{
|
|
Redisplay = 1;
|
|
}
|
|
|
|
void glutPostWindowRedisplay(int win)
|
|
{
|
|
Redisplay = 1;
|
|
}
|
|
|
|
void glutSwapBuffers(void)
|
|
{
|
|
glFlush();
|
|
|
|
if(!(DisplayMode & GLUT_DOUBLE))
|
|
return;
|
|
|
|
if(ActiveMenu)
|
|
DrawMenus();
|
|
DrawCursor();
|
|
|
|
if(Visible) {
|
|
Swapping = 1;
|
|
glFBDevSwapBuffers(Buffer);
|
|
Swapping = 0;
|
|
}
|
|
|
|
/* if there was a vt switch while swapping, switch now */
|
|
if(VTSwitch) {
|
|
if(ioctl(ConsoleFD, VT_ACTIVATE, VTSwitch) < 0)
|
|
sprintf(exiterror, "Error switching console\n");
|
|
VTSwitch = 0;
|
|
}
|
|
}
|
|
|
|
void glutPositionWindow(int x, int y)
|
|
{
|
|
}
|
|
|
|
void glutReshapeWindow(int width, int height)
|
|
{
|
|
if(GameMode)
|
|
return;
|
|
|
|
if(!ParseFBModes(width, width, height, height, 0, MAX_VSYNC))
|
|
return;
|
|
|
|
signal(SIGWINCH, SIG_IGN);
|
|
|
|
SetVideoMode();
|
|
signal(SIGWINCH, SignalWinch);
|
|
Resized = 1;
|
|
}
|
|
|
|
void glutFullScreen(void)
|
|
{
|
|
}
|
|
|
|
void glutPopWindow(void)
|
|
{
|
|
}
|
|
|
|
void glutPushWindow(void)
|
|
{
|
|
}
|
|
|
|
void glutShowWindow(void)
|
|
{
|
|
Visible = 1;
|
|
}
|
|
|
|
void glutHideWindow(void)
|
|
{
|
|
Visible = 0;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
RestoreColorMap();
|
|
|
|
Redisplay = 1;
|
|
VisibleSwitch = 1;
|
|
Visible = 1;
|
|
}
|
|
|
|
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)
|
|
{
|
|
/* escape code to set title in screen */
|
|
if(getenv("TERM") && memcmp(getenv("TERM"), "screen", 6) == 0)
|
|
printf("\033k%s\033\\", name);
|
|
}
|
|
|
|
void glutSetIconTitle(const char *name)
|
|
{
|
|
}
|