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