| /* |
| * 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) |
| { |
| } |