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