The colormap code is now simpler, 15bpp works where it did not before.
[mesa.git] / src / glut / fbdev / fbdev.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 * Copyright (C) 1995-2006 Brian Paul
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22 * Library for glut using mesa fbdev driver
23 *
24 * Written by Sean D'Epagnier (c) 2006
25 *
26 * To improve on this library, maybe support subwindows or overlays,
27 * I (sean at depagnier dot com) will do my best to help.
28 */
29
30 #include <errno.h>
31 #include <signal.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <inttypes.h>
38
39 #include <sys/mman.h>
40 #include <sys/time.h>
41 #include <sys/kd.h>
42
43 #include <linux/fb.h>
44 #include <linux/vt.h>
45
46 #include <GL/gl.h>
47 #include <GL/glut.h>
48
49 #include "internal.h"
50
51 #define FBMODES "/etc/fb.modes"
52
53 struct fb_fix_screeninfo FixedInfo;
54 struct fb_var_screeninfo VarInfo;
55 static struct fb_var_screeninfo OrigVarInfo;
56
57 static int DesiredDepth = 0;
58
59 int FrameBufferFD = -1;
60 unsigned char *FrameBuffer;
61 unsigned char *BackBuffer = NULL;
62 int DisplayMode;
63
64 struct GlutTimer *GlutTimers = NULL;
65
66 struct timeval StartTime;
67
68 /* per window data */
69 GLFBDevContextPtr Context;
70 GLFBDevBufferPtr Buffer;
71 GLFBDevVisualPtr Visual;
72
73 int Redisplay;
74 int Visible;
75 int VisibleSwitch;
76 int Active;
77 /* we have to poll to see if we are visible
78 on a framebuffer that is not active */
79 int VisiblePoll;
80 int Swapping, VTSwitch;
81 static int FramebufferIndex;
82
83 static int Initialized;
84
85 char exiterror[256];
86
87 /* test if the active console is attached to the same framebuffer */
88 void TestVisible(void) {
89 struct fb_con2fbmap confb;
90 struct vt_stat st;
91 int ret;
92 ioctl(ConsoleFD, VT_GETSTATE, &st);
93 confb.console = st.v_active;
94
95 ret = ioctl(FrameBufferFD, FBIOGET_CON2FBMAP, &confb);
96
97 if(ret == -1 || confb.framebuffer == FramebufferIndex) {
98 VisibleSwitch = 1;
99 Visible = 0;
100 VisiblePoll = 0;
101 }
102 }
103
104 static void Cleanup(void)
105 {
106 if(GameMode)
107 glutLeaveGameMode();
108
109 if(ConsoleFD != -1)
110 RestoreVT();
111
112 /* close mouse */
113 CloseMouse();
114
115 if(Visual)
116 glutDestroyWindow(1);
117
118 /* restore original variable screen info */
119 if(FrameBufferFD != -1) {
120 OrigVarInfo.xoffset = 0;
121 OrigVarInfo.yoffset = 0;
122
123 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo))
124 fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
125 strerror(errno));
126
127 munmap(FrameBuffer, FixedInfo.smem_len);
128 close(FrameBufferFD);
129 }
130
131 /* free allocated back buffer */
132 if(DisplayMode & GLUT_DOUBLE)
133 free(BackBuffer);
134
135 /* free menu items */
136 FreeMenus();
137
138 if(exiterror[0])
139 fprintf(stderr, "[glfbdev glut] %s", exiterror);
140 }
141
142 static void CrashHandler(int sig)
143 {
144 sprintf(exiterror, "Caught signal %d, cleaning up\n", sig);
145 exit(0);
146 }
147
148 static void removeArgs(int *argcp, char **argv, int num)
149 {
150 int i;
151 for (i = 0; argv[i+num]; i++)
152 argv[i] = argv[i+num];
153
154 argv[i] = NULL;
155 *argcp -= num;
156 }
157
158 #define REQPARAM(PARAM) \
159 if (i >= *argcp - 1) { \
160 fprintf(stderr, PARAM" requires a parameter\n"); \
161 exit(0); \
162 }
163
164 void glutInit (int *argcp, char **argv)
165 {
166 int i, nomouse = 0, nokeyboard = 0, usestdin = 0;
167 int RequiredWidth = 0, RequiredHeight;
168 char *fbdev;
169
170 /* parse out args */
171 for (i = 1; i < *argcp;) {
172 if (!strcmp(argv[i], "-geometry")) {
173 REQPARAM("geometry");
174 if(sscanf(argv[i+1], "%dx%d", &RequiredWidth,
175 &RequiredHeight) != 2) {
176 fprintf(stderr,"Please specify geometry as widthxheight\n");
177 exit(0);
178 }
179 removeArgs(argcp, &argv[i], 2);
180 } else
181 if (!strcmp(argv[i], "-bpp")) {
182 REQPARAM("bpp");
183 if(sscanf(argv[i+1], "%d", &DesiredDepth) != 1) {
184 fprintf(stderr, "Please specify a parameter for bpp\n");
185 exit(0);
186 }
187 removeArgs(argcp, &argv[i], 2);
188 } else
189 if (!strcmp(argv[i], "-vt")) {
190 REQPARAM("vt");
191 if(sscanf(argv[i+1], "%d", &CurrentVT) != 1) {
192 fprintf(stderr, "Please specify a parameter for vt\n");
193 exit(0);
194 }
195 removeArgs(argcp, &argv[i], 2);
196 } else
197 if (!strcmp(argv[i], "-mousespeed")) {
198 REQPARAM("mousespeed");
199 if(sscanf(argv[i+1], "%lf", &MouseSpeed) != 1) {
200 fprintf(stderr, "Please specify a mouse speed, eg: 2.5\n");
201 exit(0);
202 }
203 removeArgs(argcp, &argv[i], 2);
204 } else
205 if (!strcmp(argv[i], "-nomouse")) {
206 nomouse = 1;
207 removeArgs(argcp, &argv[i], 1);
208 } else
209 if (!strcmp(argv[i], "-nokeyboard")) {
210 nokeyboard = 1;
211 removeArgs(argcp, &argv[i], 1);
212 } else
213 if (!strcmp(argv[i], "-stdin")) {
214 usestdin = 1;
215 removeArgs(argcp, &argv[i], 1);
216 } else
217 if (!strcmp(argv[i], "-gpmmouse")) {
218 #ifdef HAVE_GPM
219 GpmMouse = 1;
220 #else
221 fprintf(stderr, "gpm support not compiled\n");
222 exit(0);
223 #endif
224 removeArgs(argcp, &argv[i], 1);
225 } else
226 if (!strcmp(argv[i], "--")) {
227 removeArgs(argcp, &argv[i], 1);
228 break;
229 } else
230 i++;
231 }
232
233 gettimeofday(&StartTime, 0);
234 atexit(Cleanup);
235
236 signal(SIGSEGV, CrashHandler);
237 signal(SIGINT, CrashHandler);
238 signal(SIGTERM, CrashHandler);
239
240 if(nomouse == 0)
241 InitializeMouse();
242 if(nokeyboard == 0)
243 InitializeVT(usestdin);
244
245 fbdev = getenv("FRAMEBUFFER");
246 if(fbdev) {
247 #ifdef MULTIHEAD
248 if(!sscanf(fbdev, "/dev/fb%d", &FramebufferIndex))
249 if(!sscanf(fbdev, "/dev/fb/%d", &FramebufferIndex))
250 sprintf(exiterror, "Could not determine Framebuffer index!\n");
251 #endif
252 } else {
253 static char fb[128];
254 struct fb_con2fbmap confb;
255 int fd = open("/dev/fb0", O_RDWR);
256
257 FramebufferIndex = 0;
258
259 confb.console = CurrentVT;
260 if(ioctl(fd, FBIOGET_CON2FBMAP, &confb) != -1)
261 FramebufferIndex = confb.framebuffer;
262 sprintf(fb, "/dev/fb%d", FramebufferIndex);
263 fbdev = fb;
264 close(fd);
265 }
266
267 /* open the framebuffer device */
268 FrameBufferFD = open(fbdev, O_RDWR);
269 if (FrameBufferFD < 0) {
270 sprintf(exiterror, "Error opening %s: %s\n", fbdev, strerror(errno));
271 exit(0);
272 }
273
274 /* Get the fixed screen info */
275 if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
276 sprintf(exiterror, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
277 strerror(errno));
278 exit(0);
279 }
280
281 /* get the variable screen info */
282 if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo)) {
283 sprintf(exiterror, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
284 strerror(errno));
285 exit(0);
286 }
287
288 /* operate on a copy */
289 VarInfo = OrigVarInfo;
290
291 /* set the depth, resolution, etc */
292 if(RequiredWidth)
293 if(!ParseFBModes(RequiredWidth, RequiredWidth, RequiredHeight,
294 RequiredHeight, 0, MAX_VSYNC)) {
295 sprintf(exiterror, "No mode (%dx%d) found in "FBMODES"\n",
296 RequiredWidth, RequiredHeight);
297 exit(0);
298 }
299
300 Initialized = 1;
301 }
302
303 void glutInitDisplayMode (unsigned int mode)
304 {
305 DisplayMode = mode;
306 }
307
308 static const char *GetStrVal(const char *p, int *set, int min, int max)
309 {
310 char *endptr;
311 int comp = *p, val;
312
313 if(p[1] == '=')
314 p++;
315
316 if(*p == '\0')
317 return p;
318
319 val = strtol(p+1, &endptr, 10);
320
321 if(endptr == p+1)
322 return p;
323
324 switch(comp) {
325 case '!':
326 if(val == min)
327 val = max;
328 else
329 val = min;
330 break;
331 case '<':
332 val = min;
333 break;
334 case '>':
335 val = max;
336 break;
337 }
338
339 if(val < min || val > max) {
340 sprintf(exiterror, "display string value out of range\n");
341 exit(0);
342 }
343
344 *set = val;
345
346 return endptr;
347 }
348
349 static void SetAttrib(int val, int attr)
350 {
351 if(val)
352 DisplayMode |= attr;
353 else
354 DisplayMode &= ~attr;
355 }
356
357 void glutInitDisplayString(const char *string)
358 {
359 const char *p = string;
360 int val;
361 while(*p) {
362 if(*p == ' ')
363 p++;
364 else
365 if(memcmp(p, "acca", 4) == 0) {
366 p = GetStrVal(p+4, &AccumSize, 1, 32);
367 SetAttrib(AccumSize, GLUT_ACCUM);
368 } else
369 if(memcmp(p, "acc", 3) == 0) {
370 p = GetStrVal(p+3, &AccumSize, 1, 32);
371 SetAttrib(AccumSize, GLUT_ACCUM);
372 } else
373 if(memcmp(p, "depth", 5) == 0) {
374 p = GetStrVal(p+5, &DepthSize, 12, 32);
375 SetAttrib(DepthSize, GLUT_DEPTH);
376 } else
377 if(memcmp(p, "double", 6) == 0) {
378 val = 1;
379 p = GetStrVal(p+6, &val, 0, 1);
380 SetAttrib(val, GLUT_DOUBLE);
381 } else
382 if(memcmp(p, "index", 5) == 0) {
383 val = 1;
384 p = GetStrVal(p+5, &val, 0, 1);
385 SetAttrib(val, GLUT_INDEX);
386 } else
387 if(memcmp(p, "stencil", 7) == 0) {
388 p = GetStrVal(p+7, &StencilSize, 0, 1);
389 SetAttrib(StencilSize, GLUT_STENCIL);
390 } else
391 if(memcmp(p, "samples", 7) == 0) {
392 NumSamples = 1;
393 p = GetStrVal(p+7, &NumSamples, 0, 16);
394 SetAttrib(NumSamples, GLUT_MULTISAMPLE);
395 } else
396 if(p = strchr(p, ' '))
397 p++;
398 else
399 break;
400 }
401 }
402
403 void glutInitWindowPosition (int x, int y)
404 {
405 }
406
407 void glutInitWindowSize (int width, int height)
408 {
409 }
410
411 static void ProcessTimers(void)
412 {
413 if(GlutTimers && GlutTimers->time < glutGet(GLUT_ELAPSED_TIME)) {
414 struct GlutTimer *timer = GlutTimers;
415 timer->func(timer->value);
416 GlutTimers = timer->next;
417 free(timer);
418 }
419 }
420
421 void glutMainLoop(void)
422 {
423 if(ReshapeFunc)
424 ReshapeFunc(VarInfo.xres, VarInfo.yres);
425
426 if(!DisplayFunc) {
427 sprintf(exiterror, "Fatal Error: No Display Function registered\n");
428 exit(0);
429 }
430
431 for(;;) {
432 ProcessTimers();
433
434 if(Active)
435 ReceiveInput();
436 else
437 if(VisiblePoll)
438 TestVisible();
439 else
440 usleep(1);
441
442 if(IdleFunc)
443 IdleFunc();
444
445 if(VisibleSwitch) {
446 VisibleSwitch = 0;
447 if(VisibilityFunc)
448 VisibilityFunc(Visible ? GLUT_VISIBLE : GLUT_NOT_VISIBLE);
449 }
450
451 if(Visible && Redisplay) {
452 Redisplay = 0;
453 if(MouseEnabled)
454 EraseCursor();
455 DisplayFunc();
456 if(!(DisplayMode & GLUT_DOUBLE)) {
457 if(ActiveMenu)
458 DrawMenus();
459 if(MouseEnabled)
460 DrawCursor();
461 }
462 }
463 }
464 }
465
466 int ParseFBModes(int minw, int maxw, int minh, int maxh, int minf, int maxf)
467 {
468 char buf[1024];
469 struct fb_var_screeninfo vi = VarInfo;
470
471 FILE *fbmodes = fopen(FBMODES, "r");
472
473 if(!fbmodes) {
474 sprintf(exiterror, "Warning: could not open "FBMODES"\n");
475 return 0;
476 }
477
478 while(fgets(buf, sizeof buf, fbmodes)) {
479 char *c;
480 int v, bpp, freq;
481
482 if(!(c = strstr(buf, "geometry")))
483 continue;
484 v = sscanf(c, "geometry %d %d %d %d %d", &vi.xres, &vi.yres,
485 &vi.xres_virtual, &vi.yres_virtual, &bpp);
486 if(v != 5)
487 continue;
488
489 if(maxw < minw) {
490 if(maxw < vi.xres && minw > vi.xres)
491 continue;
492 } else
493 if(maxw < vi.xres || minw > vi.xres)
494 continue;
495
496 if(maxh < minh) {
497 if(maxh < vi.yres && minh > vi.yres)
498 continue;
499 } else
500 if(maxh < vi.yres || minh > vi.yres)
501 continue;
502
503 fgets(buf, sizeof buf, fbmodes);
504 if(!(c = strstr(buf, "timings")))
505 continue;
506
507 v = sscanf(c, "timings %d %d %d %d %d %d %d", &vi.pixclock,
508 &vi.left_margin, &vi.right_margin, &vi.upper_margin,
509 &vi.lower_margin, &vi.hsync_len, &vi.vsync_len);
510
511 if(v != 7)
512 continue;
513
514 freq = 1E12/vi.pixclock
515 /(vi.left_margin + vi.xres + vi.right_margin + vi.hsync_len)
516 /(vi.upper_margin + vi.yres + vi.lower_margin + vi.vsync_len);
517
518 if(maxf < minf) {
519 if(maxf < freq && minf > freq)
520 continue;
521 } else
522 if(maxf < freq || minf > freq)
523 continue;
524
525 VarInfo = vi;
526 fclose(fbmodes);
527 return 1;
528 }
529
530 fclose(fbmodes);
531
532 return 0;
533 }
534
535 /* ---------- Window Management ----------*/
536 void SetVideoMode(void)
537 {
538 /* set new variable screen info */
539 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
540 sprintf(exiterror, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
541 strerror(errno));
542 exit(0);
543 }
544
545 /* reload the screen info to update offsets */
546 if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &VarInfo)) {
547 sprintf(exiterror, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
548 strerror(errno));
549 exit(0);
550 }
551
552 /* reload the fixed info to update color mode */
553 if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo)) {
554 sprintf(exiterror, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
555 strerror(errno));
556 exit(0);
557 }
558
559 if (DesiredDepth && DesiredDepth != VarInfo.bits_per_pixel) {
560 sprintf(exiterror, "error: Could not set set %d bpp\n", DesiredDepth);
561 exit(0);
562 }
563
564 if(DisplayMode & GLUT_INDEX && FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
565 sprintf(exiterror, "error: Could not set 8 bit color mode\n");
566 exit(0);
567 }
568
569 /* initialize colormap */
570 LoadColorMap();
571 }
572
573 void CreateBuffer()
574 {
575 int size = VarInfo.xres_virtual * VarInfo.yres_virtual
576 * VarInfo.bits_per_pixel / 8;
577
578 /* mmap the framebuffer into our address space */
579 if(FrameBuffer)
580 munmap(FrameBuffer, FixedInfo.smem_len);
581 FrameBuffer = mmap(0, FixedInfo.smem_len, PROT_READ | PROT_WRITE,
582 MAP_SHARED, FrameBufferFD, 0);
583 if (FrameBuffer == MAP_FAILED) {
584 sprintf(exiterror, "error: unable to mmap framebuffer: %s\n",
585 strerror(errno));
586 exit(0);
587 }
588
589 if(DisplayMode & GLUT_DOUBLE) {
590 free(BackBuffer);
591 if(!(BackBuffer = malloc(size))) {
592 sprintf(exiterror, "Failed to allocate double buffer\n");
593 exit(0);
594 }
595 } else
596 BackBuffer = FrameBuffer;
597
598 if(Buffer)
599 glFBDevDestroyBuffer(Buffer);
600
601 if(!(Buffer = glFBDevCreateBuffer( &FixedInfo, &VarInfo, Visual,
602 FrameBuffer, BackBuffer, size))) {
603 sprintf(exiterror, "Failure to create Buffer\n");
604 exit(0);
605 }
606 }
607
608 void CreateVisual(void)
609 {
610 int i, mask = DisplayMode;
611 int attribs[20];
612 for(i=0; i<sizeof(attribs)/sizeof(*attribs) && mask; i++) {
613 if(mask & GLUT_DOUBLE) {
614 attribs[i] = GLFBDEV_DOUBLE_BUFFER;
615 mask &= ~GLUT_DOUBLE;
616 continue;
617 }
618
619 if(mask & GLUT_INDEX) {
620 attribs[i] = GLFBDEV_COLOR_INDEX;
621 mask &= ~GLUT_INDEX;
622 continue;
623 }
624
625 if(mask & GLUT_DEPTH) {
626 attribs[i] = GLFBDEV_DEPTH_SIZE;
627 attribs[++i] = DepthSize;
628 mask &= ~GLUT_DEPTH;
629 continue;
630 }
631
632 if(mask & GLUT_STENCIL) {
633 attribs[i] = GLFBDEV_STENCIL_SIZE;
634 attribs[++i] = StencilSize;
635 mask &= ~GLUT_STENCIL;
636 continue;
637 }
638
639 if(mask & GLUT_ACCUM) {
640 attribs[i] = GLFBDEV_ACCUM_SIZE;
641 attribs[++i] = AccumSize;
642 mask &= ~GLUT_ACCUM;
643 continue;
644 }
645
646 if(mask & GLUT_ALPHA)
647 if(!(DisplayMode & GLUT_INDEX)) {
648 mask &= ~GLUT_ALPHA;
649 i--;
650 continue;
651 }
652
653 if(mask & GLUT_MULTISAMPLE) {
654 attribs[i] = GLFBDEV_MULTISAMPLE;
655 attribs[++i] = NumSamples;
656 mask &= ~GLUT_MULTISAMPLE;
657 continue;
658 }
659
660 sprintf(exiterror, "Invalid mode from glutInitDisplayMode\n");
661 exit(0);
662 }
663
664 attribs[i] = GLFBDEV_NONE;
665
666 if(!(Visual = glFBDevCreateVisual( &FixedInfo, &VarInfo, attribs ))) {
667 sprintf(exiterror, "Failure to create Visual\n");
668 exit(0);
669 }
670 }
671
672 int glutCreateWindow (const char *title)
673 {
674 if(Initialized == 0) {
675 int argc = 0;
676 char *argv[] = {NULL};
677 glutInit(&argc, argv);
678 }
679
680 if(Context)
681 return 0;
682
683 if(DisplayMode & GLUT_INDEX)
684 VarInfo.bits_per_pixel = 8;
685 else
686 if(VarInfo.bits_per_pixel == 8)
687 VarInfo.bits_per_pixel = 32;
688
689 if (DesiredDepth)
690 VarInfo.bits_per_pixel = DesiredDepth;
691
692 VarInfo.xoffset = 0;
693 VarInfo.yoffset = 0;
694 VarInfo.nonstd = 0;
695 VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
696
697 SetVideoMode();
698 CreateVisual();
699 CreateBuffer();
700
701 if(!(Context = glFBDevCreateContext(Visual, NULL))) {
702 sprintf(exiterror, "Failure to create Context\n");
703 exit(0);
704 }
705
706 if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) {
707 sprintf(exiterror, "Failure to Make Current\n");
708 exit(0);
709 }
710
711 InitializeCursor();
712 InitializeMenus();
713
714 glutSetWindowTitle(title);
715
716 Visible = 1;
717 VisibleSwitch = 1;
718 Redisplay = 1;
719 return 1;
720 }
721
722 int glutCreateSubWindow(int win, int x, int y, int width, int height)
723 {
724 return 0;
725 }
726
727 void glutSetWindow(int win)
728 {
729 }
730
731 int glutGetWindow(void)
732 {
733 return 1;
734 }
735
736 void glutDestroyWindow(int win)
737 {
738 glFBDevMakeCurrent( NULL, NULL, NULL);
739 glFBDevDestroyContext(Context);
740 glFBDevDestroyBuffer(Buffer);
741 glFBDevDestroyVisual(Visual);
742 Visual = NULL;
743 }
744
745 void glutPostRedisplay(void)
746 {
747 Redisplay = 1;
748 }
749
750 void glutPostWindowRedisplay(int win)
751 {
752 Redisplay = 1;
753 }
754
755 void glutSwapBuffers(void)
756 {
757 glFlush();
758
759 if(ActiveMenu)
760 DrawMenus();
761 if(MouseEnabled)
762 DrawCursor();
763
764 if(DisplayMode & GLUT_DOUBLE && Visible) {
765 Swapping = 1;
766 glFBDevSwapBuffers(Buffer);
767 Swapping = 0;
768 }
769
770 /* if there was a vt switch while swapping, switch now */
771 if(VTSwitch) {
772 if(ioctl(ConsoleFD, VT_ACTIVATE, VTSwitch) < 0)
773 sprintf(exiterror, "Error switching console\n");
774 VTSwitch = 0;
775 }
776 }
777
778 void glutPositionWindow(int x, int y)
779 {
780 }
781
782 void glutReshapeWindow(int width, int height)
783 {
784 if(GameMode)
785 return;
786
787 if(!ParseFBModes(width, width, height, height, 0, MAX_VSYNC))
788 return;
789
790 SetVideoMode();
791 CreateBuffer();
792
793 if(!glFBDevMakeCurrent( Context, Buffer, Buffer )) {
794 sprintf(exiterror, "Failure to Make Current\n");
795 exit(0);
796 }
797
798 InitializeMenus();
799
800 if(ReshapeFunc)
801 ReshapeFunc(VarInfo.xres, VarInfo.yres);
802 Redisplay = 1;
803 }
804
805 void glutFullScreen(void)
806 {
807 }
808
809 void glutPopWindow(void)
810 {
811 }
812
813 void glutPushWindow(void)
814 {
815 }
816
817 void glutShowWindow(void)
818 {
819 Visible = 1;
820 }
821
822 void glutHideWindow(void)
823 {
824 Visible = 0;
825 }
826
827 static void UnIconifyWindow(int sig)
828 {
829 if(ConsoleFD == 0)
830 InitializeVT(1);
831 else
832 if(ConsoleFD > 0)
833 InitializeVT(0);
834 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &VarInfo)) {
835 sprintf(exiterror, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
836 strerror(errno));
837 exit(0);
838 }
839 Redisplay = 1;
840 VisibleSwitch = 1;
841 Visible = 1;
842 }
843
844 void glutIconifyWindow(void)
845 {
846 RestoreVT();
847 signal(SIGCONT, UnIconifyWindow);
848 if (ioctl(FrameBufferFD, FBIOPUT_VSCREENINFO, &OrigVarInfo))
849 fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
850 strerror(errno));
851 raise(SIGSTOP);
852 }
853
854 void glutSetWindowTitle(const char *name)
855 {
856 /* escape code to set title in screen */
857 if(getenv("TERM") && memcmp(getenv("TERM"), "screen", 6) == 0)
858 printf("\033k%s\033\\", name);
859 }
860
861 void glutSetIconTitle(const char *name)
862 {
863 }