2 * Mesa 3-D graphics library
4 * Copyright (C) 1995-2006 Brian Paul
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.
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.
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.
22 * Library for glut using mesa fbdev driver
24 * Written by Sean D'Epagnier (c) 2006
38 #include <sys/ioctl.h>
40 #include <sys/types.h>
43 #include <sys/types.h>
47 #include <linux/keyboard.h>
51 #include <GL/glfbdev.h>
56 #include "../../mesa/main/config.h"
58 #define MULTIHEAD /* enable multihead hacks,
59 it allows the program to continue drawing
60 without reading input when a second fbdev
61 has keyboard focus it can cause
62 screen corruption that requires C-l to fix */
64 #define FBMODES "/etc/fb.modes"
73 #define MOUSEDEV "/dev/gpmdata"
76 static int ConsoleFD
= - 1;
78 /* save settings to restore on exit */
79 static int OldKDMode
= -1;
81 struct vt_mode OldVTMode
;
82 struct termios OldTermios
;
84 static struct fb_fix_screeninfo FixedInfo
;
85 static struct fb_var_screeninfo VarInfo
, OrigVarInfo
;
86 struct fb_cmap ColorMap
;
88 static int DesiredDepth
= 0;
90 static int FrameBufferFD
= -1;
91 static caddr_t FrameBuffer
= (caddr_t
) -1;
92 static caddr_t BackBuffer
= NULL
;
93 static int DisplayMode
;
95 static int AccumSize
= 16; /* per channel size of accumulation buffer */
96 static int DepthSize
= DEFAULT_SOFTWARE_DEPTH_BITS
;
97 static int StencilSize
= STENCIL_BITS
;
99 #define MENU_FONT_WIDTH 9
100 #define MENU_FONT_HEIGHT 15
101 #define MENU_FONT GLUT_BITMAP_9_BY_15
102 #define SUBMENU_OFFSET 20
104 static int AttachedMenus
[3];
105 static int ActiveMenu
;
106 static int SelectedMenu
;
107 static int CurrentMenu
;
108 static int NumMenus
= 1;
127 struct GlutTimer
*next
;
130 struct GlutTimer
*GlutTimers
= NULL
;
132 static struct timeval StartTime
;
134 static int KeyboardModifiers
;
135 static int KeyboardLedState
;
138 static int NumMouseButtons
;
141 static double MouseSpeed
= 0;
142 static int CurrentCursor
= GLUT_CURSOR_LEFT_ARROW
;
143 /* only display the mouse if there is a registered callback for it */
144 static int MouseEnabled
= 0;
146 /* per window data */
147 static GLFBDevContextPtr Context
;
148 static GLFBDevBufferPtr Buffer
;
149 static GLFBDevVisualPtr Visual
;
150 static void (*DisplayFunc
)(void) = NULL
;
151 static void (*ReshapeFunc
)(int width
, int height
) = NULL
;
152 static void (*KeyboardFunc
)(unsigned char key
, int x
, int y
) = NULL
;
153 static void (*MouseFunc
)(int key
, int state
, int x
, int y
) = NULL
;
154 static void (*MotionFunc
)(int x
, int y
) = NULL
;
155 static void (*PassiveMotionFunc
)(int x
, int y
) = NULL
;
156 static void (*VisibilityFunc
)(int state
) = NULL
;
157 static void (*SpecialFunc
)(int key
, int x
, int y
) = NULL
;
158 static void (*IdleFunc
)(void) = NULL
;
159 static void (*MenuStatusFunc
)(int state
, int x
, int y
) = NULL
;
160 static void (*MenuStateFunc
)(int state
) = NULL
;
162 static int Redisplay
;
164 static int VisibleSwitch
;
166 /* we have to poll to see if we are visible
167 on a framebuffer that is not active */
168 static int VisiblePoll
;
169 static int FramebufferIndex
;
171 static int RequiredWidth
;
172 static int RequiredHeight
;
173 static int InitialWidthHint
;
174 static int InitialHeightHint
;
176 static char exiterror
[256];
178 /* --------- Initialization ------------*/
179 /* test if the active console is attached to the same framebuffer */
180 static void TestVisible(void) {
181 struct fb_con2fbmap confb
;
184 ioctl(ConsoleFD
, VT_GETSTATE
, &st
);
185 confb
.console
= st
.v_active
;
187 ret
= ioctl(FrameBufferFD
, FBIOGET_CON2FBMAP
, &confb
);
189 if(ret
== -1 || confb
.framebuffer
== FramebufferIndex
) {
196 static void VTSwitchHandler(int sig
)
201 ioctl(ConsoleFD
, VT_RELDISP
, 1);
212 ioctl(ConsoleFD
, VT_GETSTATE
, &st
);
214 ioctl(ConsoleFD
, VT_RELDISP
, VT_ACKACQ
);
216 /* this is a hack to turn the cursor off */
217 ioctl(FrameBufferFD
, FBIOPUT_VSCREENINFO
, &VarInfo
);
219 /* restore color map */
220 if(DisplayMode
& GLUT_INDEX
) {
224 if (ioctl(FrameBufferFD
, FBIOPUTCMAP
, (void *) &ColorMap
) < 0)
225 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed!\n");
238 static void Cleanup(void)
241 if (tcsetattr(0, TCSANOW
, &OldTermios
) < 0)
242 fprintf(stderr
, "tcsetattr failed\n");
245 /* restore keyboard state */
246 if (ioctl(ConsoleFD
, VT_SETMODE
, &OldVTMode
) < 0)
247 fprintf(stderr
, "Failed to set vtmode\n");
249 if (ioctl(ConsoleFD
, KDSKBMODE
, OldKDMode
) < 0)
250 fprintf(stderr
, "ioctl KDSKBMODE failed!\n");
252 if(ioctl(ConsoleFD
, KDSETMODE
, OldMode
) < 0)
253 fprintf(stderr
, "ioctl KDSETMODE failed!\n");
268 glFBDevMakeCurrent( NULL
, NULL
, NULL
);
270 glFBDevDestroyContext(Context
);
271 glFBDevDestroyBuffer(Buffer
);
272 glFBDevDestroyVisual(Visual
);
276 /* restore original variable screen info */
277 if(FrameBufferFD
!= -1) {
278 if (ioctl(FrameBufferFD
, FBIOPUT_VSCREENINFO
, &OrigVarInfo
))
279 fprintf(stderr
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
282 munmap(FrameBuffer
, FixedInfo
.smem_len
);
283 close(FrameBufferFD
);
286 /* free allocated back buffer */
287 if(DisplayMode
& GLUT_DOUBLE
)
290 /* free menu items */
293 for(i
= 1; i
<NumMenus
; i
++) {
294 for(i
= 1; i
<Menus
[i
].NumItems
; i
++)
295 free(Menus
[i
].Items
[j
].name
);
296 free(Menus
[i
].Items
);
301 fprintf(stderr
, "[glfbdev glut] %s", exiterror
);
304 static void CrashHandler(int sig
)
306 sprintf(exiterror
, "Caught signal %d, cleaning up\n", sig
);
310 static void InitializeVT(int usestdin
)
312 /* terminos settings for straight-through mode */
313 if (tcgetattr(0, &OldTermios
) < 0) {
314 sprintf(exiterror
, "tcgetattr failed\n");
318 struct termios tio
= OldTermios
;
320 tio
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
);
321 tio
.c_iflag
&= ~(ISTRIP
| IGNCR
| ICRNL
| INLCR
| IXOFF
| IXON
);
322 tio
.c_iflag
|= IGNBRK
;
326 if (tcsetattr(0, TCSANOW
, &tio
) < 0) {
327 sprintf(exiterror
, "tcsetattr failed\n");
331 if(fcntl(0, F_SETFL
, O_NONBLOCK
) < 0) {
332 sprintf(exiterror
, "Failed to set keyboard to non-blocking\n");
343 /* detect the current vt if it was not specified */
345 int fd
= open("/dev/tty", O_RDWR
| O_NDELAY
, 0);
348 sprintf(exiterror
, "Failed to open /dev/tty\n");
351 if(ioctl(fd
, VT_GETSTATE
, &st
) == -1) {
352 fprintf(stderr
, "Could not detect current vt, specify with -vt\n");
353 fprintf(stderr
, "Defaulting to stdin input\n");
358 CurrentVT
= st
.v_active
;
363 /* open the console tty */
365 sprintf(console
, "/dev/tty%d", CurrentVT
);
366 ConsoleFD
= open(console
, O_RDWR
| O_NDELAY
, 0);
368 sprintf(exiterror
, "error couldn't open %s,"
369 " defaulting to stdin \n", console
);
374 signal(SIGUSR1
, VTSwitchHandler
);
375 signal(SIGUSR2
, VTSwitchHandler
);
379 if (ioctl(ConsoleFD
, VT_GETMODE
, &OldVTMode
) < 0) {
380 sprintf(exiterror
,"Failed to grab %s, defaulting to stdin\n", console
);
388 vt
.mode
= VT_PROCESS
;
392 if (ioctl(ConsoleFD
, VT_SETMODE
, &vt
) < 0) {
393 sprintf(exiterror
, "error: ioctl(VT_SETMODE) failed: %s\n",
400 if (ioctl(ConsoleFD
, KDGKBMODE
, &OldKDMode
) < 0) {
401 fprintf(stderr
, "warning: ioctl KDGKBMODE failed!\n");
405 if(ioctl(ConsoleFD
, KDGETMODE
, &OldMode
) < 0)
406 sprintf(exiterror
, "Warning: Failed to get terminal mode\n");
411 if(ioctl(ConsoleFD
, KDSETMODE
, KD_GRAPHICS
) < 0)
412 sprintf(exiterror
,"Warning: Failed to set terminal to graphics\n");
415 if (ioctl(ConsoleFD
, KDSKBMODE
, K_MEDIUMRAW
) < 0) {
416 sprintf(exiterror
, "ioctl KDSKBMODE failed!\n");
417 tcsetattr(0, TCSANOW
, &OldTermios
);
421 if( ioctl(ConsoleFD
, KDGKBLED
, &KeyboardLedState
) < 0) {
422 sprintf(exiterror
, "ioctl KDGKBLED failed!\n");
427 static void InitializeMouse(void)
433 conn
.eventMask
= ~0; /* Want to know about all the events */
434 conn
.defaultMask
= 0; /* don't handle anything by default */
435 conn
.minMod
= 0; /* want everything */
436 conn
.maxMod
= ~0; /* all modifiers included */
437 if(Gpm_Open(&conn
, 0) == -1) {
438 fprintf(stderr
, "Cannot open gpmctl. Continuing without Mouse\n");
447 const char *mousedev
= getenv("MOUSE");
450 if((MouseFD
= open(mousedev
, O_RDONLY
)) < 0) {
451 fprintf(stderr
,"Cannot open %s.\n"
452 "Continuing without Mouse\n", MOUSEDEV
);
463 static void removeArgs(int *argcp
, char **argv
, int num
)
466 for (i
= 0; argv
[i
+num
]; i
++)
467 argv
[i
] = argv
[i
+num
];
473 #define REQPARAM(PARAM) \
474 if (i >= *argcp - 1) { \
475 fprintf(stderr, PARAM" requires a parameter\n"); \
479 void glutInit (int *argcp
, char **argv
)
487 for (i
= 1; i
< *argcp
;) {
488 if (!strcmp(argv
[i
], "-geometry")) {
489 REQPARAM("geometry");
490 if(sscanf(argv
[i
+1], "%dx%d", &RequiredWidth
,
491 &RequiredHeight
) != 2) {
492 fprintf(stderr
,"Please specify geometry as widthxheight\n");
495 removeArgs(argcp
, &argv
[i
], 2);
497 if (!strcmp(argv
[i
], "-bpp")) {
499 if(sscanf(argv
[i
+1], "%d", &DesiredDepth
) != 1) {
500 fprintf(stderr
, "Please specify a parameter for bpp\n");
504 removeArgs(argcp
, &argv
[i
], 2);
506 if (!strcmp(argv
[i
], "-vt")) {
508 if(sscanf(argv
[i
+1], "%d", &CurrentVT
) != 1) {
509 fprintf(stderr
, "Please specify a parameter for vt\n");
512 removeArgs(argcp
, &argv
[i
], 2);
514 if (!strcmp(argv
[i
], "-mousespeed")) {
515 REQPARAM("mousespeed");
516 if(sscanf(argv
[i
+1], "%lf", &MouseSpeed
) != 1) {
517 fprintf(stderr
, "Please specify a mouse speed, eg: 2.5\n");
520 removeArgs(argcp
, &argv
[i
], 2);
522 if (!strcmp(argv
[i
], "-nomouse")) {
524 removeArgs(argcp
, &argv
[i
], 1);
526 if (!strcmp(argv
[i
], "-nokeyboard")) {
528 removeArgs(argcp
, &argv
[i
], 1);
530 if (!strcmp(argv
[i
], "-stdin")) {
532 removeArgs(argcp
, &argv
[i
], 1);
534 if (!strcmp(argv
[i
], "-gpmmouse")) {
538 fprintf(stderr
, "gpm support was not compiled\n");
541 removeArgs(argcp
, &argv
[i
], 1);
543 if (!strcmp(argv
[i
], "--")) {
544 removeArgs(argcp
, &argv
[i
], 1);
550 gettimeofday(&StartTime
, 0);
553 signal(SIGSEGV
, CrashHandler
);
554 signal(SIGINT
, CrashHandler
);
555 signal(SIGTERM
, CrashHandler
);
560 InitializeVT(usestdin
);
563 void glutInitDisplayMode (unsigned int mode
)
568 void glutInitWindowPosition (int x
, int y
)
572 void glutInitWindowSize (int width
, int height
)
574 InitialWidthHint
= width
;
575 InitialHeightHint
= height
;
578 /* --------- Mouse Rendering ------------*/
580 static int LastMouseX
;
581 static int LastMouseY
;
582 static unsigned char *MouseBuffer
;
584 static void EraseCursor(void)
586 int off
= LastMouseY
* FixedInfo
.line_length
587 + LastMouseX
* VarInfo
.bits_per_pixel
/ 8;
588 int stride
= CURSOR_WIDTH
* VarInfo
.bits_per_pixel
/ 8;
591 unsigned char *src
= MouseBuffer
;
593 for(i
= 0; i
<CURSOR_HEIGHT
; i
++) {
594 memcpy(BackBuffer
+ off
, src
, stride
);
596 off
+= FixedInfo
.line_length
;
600 static void SaveCursor(int x
, int y
)
605 if(x
> (int)VarInfo
.xres
- CURSOR_WIDTH
)
606 LastMouseX
= VarInfo
.xres
- CURSOR_WIDTH
;
613 if(y
> (int)VarInfo
.yres
- CURSOR_HEIGHT
)
614 LastMouseY
= VarInfo
.yres
- CURSOR_HEIGHT
;
618 int off
= LastMouseY
* FixedInfo
.line_length
619 + LastMouseX
* VarInfo
.bits_per_pixel
/ 8;
620 int stride
= CURSOR_WIDTH
* VarInfo
.bits_per_pixel
/ 8;
622 unsigned char *src
= MouseBuffer
;
623 for(i
= 0; i
<CURSOR_HEIGHT
; i
++) {
624 memcpy(src
, BackBuffer
+ off
, stride
);
626 off
+= FixedInfo
.line_length
;
630 static void DrawCursor(void)
632 if(CurrentCursor
< 0 || CurrentCursor
>= NUM_CURSORS
)
635 int px
= MouseX
- CursorsXOffset
[CurrentCursor
];
636 int py
= MouseY
- CursorsYOffset
[CurrentCursor
];
644 int xlen
= CURSOR_WIDTH
;
645 if(px
+ CURSOR_WIDTH
> VarInfo
.xres
)
646 xlen
= VarInfo
.xres
- px
;
652 int ylen
= CURSOR_HEIGHT
;
653 if(py
+ CURSOR_HEIGHT
> VarInfo
.yres
)
654 ylen
= VarInfo
.yres
- py
;
656 int bypp
= VarInfo
.bits_per_pixel
/ 8;
658 unsigned char *c
= BackBuffer
+ FixedInfo
.line_length
* (py
+ yoff
)
659 + (px
+ xoff
) * bypp
;
661 unsigned char *d
= Cursors
[CurrentCursor
] + (CURSOR_WIDTH
* yoff
+ xoff
)*4;
664 int dstride
= (CURSOR_WIDTH
- xlen
+ xoff
) * 4;
665 int cstride
= FixedInfo
.line_length
- bypp
* (xlen
- xoff
);
668 case 1: /* no support for 8bpp mouse yet */
672 uint16_t *e
= (void*)c
;
674 for(i
= yoff
; i
< ylen
; i
++) {
675 for(j
= xoff
; j
< xlen
; j
++) {
676 e
[0] = ((((d
[0] + (((int)(((e
[0] >> 8) & 0xf8)
677 | ((c
[0] >> 11) & 0x7)) * d
[3]) >> 8)) & 0xf8) << 8)
678 | (((d
[1] + (((int)(((e
[0] >> 3) & 0xfc)
679 | ((e
[0] >> 5) & 0x3)) * d
[3]) >> 8)) & 0xfc) << 3)
680 | ((d
[2] + (((int)(((e
[0] << 3) & 0xf8)
681 | (e
[0] & 0x7)) * d
[3]) >> 8)) >> 3));
693 for(i
= yoff
; i
< ylen
; i
++) {
694 for(j
= xoff
; j
< xlen
; j
++) {
695 c
[0] = d
[0] + (((int)c
[0] * d
[3]) >> 8);
696 c
[1] = d
[1] + (((int)c
[1] * d
[3]) >> 8);
697 c
[2] = d
[2] + (((int)c
[2] * d
[3]) >> 8);
708 #define MIN(x, y) x < y ? x : y
709 static void SwapCursor(void)
711 int px
= MouseX
- CursorsXOffset
[CurrentCursor
];
712 int py
= MouseY
- CursorsYOffset
[CurrentCursor
];
714 int minx
= MIN(px
, LastMouseX
);
715 int sizex
= abs(px
- LastMouseX
);
717 int miny
= MIN(py
, LastMouseY
);
718 int sizey
= abs(py
- LastMouseY
);
721 /* now update the portion of the screen that has changed */
723 if(DisplayMode
& GLUT_DOUBLE
&& (sizex
|| sizey
)) {
729 if(minx
+ sizex
> VarInfo
.xres
)
730 sizex
= VarInfo
.xres
- minx
;
731 if(miny
+ sizey
> VarInfo
.yres
)
732 sizey
= VarInfo
.yres
- miny
;
733 int off
= FixedInfo
.line_length
* miny
734 + minx
* VarInfo
.bits_per_pixel
/ 8;
735 int stride
= (sizex
+ CURSOR_WIDTH
) * VarInfo
.bits_per_pixel
/ 8;
737 for(i
= 0; i
< sizey
+ CURSOR_HEIGHT
; i
++) {
738 memcpy(FrameBuffer
+off
, BackBuffer
+off
, stride
);
739 off
+= FixedInfo
.line_length
;
744 /* --------- Menu Rendering ------------*/
745 static double MenuProjection
[16];
746 static double MenuModelview
[16];
748 static void InitMenuMatrices(void)
750 glMatrixMode(GL_PROJECTION
);
752 gluOrtho2D(0.0,VarInfo
.xres
,VarInfo
.yres
,0.0);
753 glMatrixMode(GL_MODELVIEW
);
755 glViewport(0,0,VarInfo
.xres
,VarInfo
.yres
);
756 glGetDoublev(GL_PROJECTION_MATRIX
, MenuProjection
);
757 glGetDoublev(GL_MODELVIEW_MATRIX
, MenuModelview
);
760 static int DrawMenu(int menu
, int x
, int *y
)
764 for(i
=0; i
< Menus
[menu
].NumItems
; i
++) {
765 char *s
= Menus
[menu
].Items
[i
].name
;
767 if(MouseY
>= *y
&& MouseY
< *y
+ MENU_FONT_HEIGHT
&&
768 MouseX
>= x
&& MouseX
< x
+ Menus
[menu
].width
) {
772 Menus
[menu
].selected
= i
;
777 *y
+= MENU_FONT_HEIGHT
;
778 glRasterPos2i(x
, *y
);
780 glutBitmapCharacter(MENU_FONT
, *s
);
782 if(Menus
[menu
].selected
== i
)
783 if(Menus
[menu
].Items
[i
].submenu
)
784 if(DrawMenu(Menus
[menu
].Items
[i
].submenu
, x
785 + SUBMENU_OFFSET
, y
)) {
787 Menus
[menu
].selected
= -1;
794 static void DrawMenus(void)
796 /* save old settings */
799 glMatrixMode(GL_MODELVIEW
);
801 glLoadMatrixd(MenuModelview
);
802 glMatrixMode(GL_PROJECTION
);
804 glLoadMatrixd(MenuProjection
);
806 glDisable(GL_DEPTH_TEST
);
807 glDisable(GL_ALPHA_TEST
);
808 glDisable(GL_LIGHTING
);
810 glDisable(GL_TEXTURE_2D
);
811 // glEnable(GL_LOGIC_OP);
812 //glEnable(GL_COLOR_LOGIC_OP);
813 // glLogicOp(GL_XOR);
815 int x
= Menus
[ActiveMenu
].x
;
816 int y
= Menus
[ActiveMenu
].y
;
818 if(DrawMenu(ActiveMenu
, x
, &y
))
819 Menus
[ActiveMenu
].selected
= -1;
821 /* restore settings */
824 glMatrixMode(GL_MODELVIEW
);
830 /* --------- Event Processing ------------*/
831 #define MODIFIER(mod) \
832 KeyboardModifiers = release ? KeyboardModifiers & ~mod \
833 : KeyboardModifiers | mod;
835 #define READKEY read(ConsoleFD, &code, 1)
837 static void LedModifier(int led
, int release
)
839 static int releaseflag
= K_CAPS
| K_NUM
;
843 if(releaseflag
& led
) {
844 KeyboardLedState
^= led
;
847 ioctl(ConsoleFD
, KDSKBLED
, KeyboardLedState
);
848 ioctl(ConsoleFD
, KDSETLED
, 0x80);
851 static int ReadKey(void)
862 /* stdin input escape code based */
864 KeyboardModifiers
= 0;
866 if(code
== 27 && READKEY
== 1) {
868 case 79: /* function key */
873 KeyboardModifiers
|= GLUT_ACTIVE_SHIFT
;
874 specialkey
= GLUT_KEY_F1
+ code
- 53;
878 specialkey
= GLUT_KEY_F1
+ code
- 80;
885 specialkey
= GLUT_KEY_LEFT
; break;
887 specialkey
= GLUT_KEY_UP
; break;
889 specialkey
= GLUT_KEY_RIGHT
; break;
891 specialkey
= GLUT_KEY_DOWN
; break;
893 specialkey
= GLUT_KEY_PAGE_UP
; READKEY
; break;
895 specialkey
= GLUT_KEY_PAGE_DOWN
; READKEY
; break;
897 specialkey
= GLUT_KEY_HOME
; READKEY
; break;
899 specialkey
= GLUT_KEY_END
; READKEY
; break;
904 specialkey
= GLUT_KEY_INSERT
;
907 code
= '\b'; goto stdkey
;
910 specialkey
= GLUT_KEY_F1
+ code
- 65;
917 KeyboardModifiers
|= GLUT_ACTIVE_ALT
;
924 SpecialFunc(specialkey
, MouseX
, MouseY
);
926 if(code
>= 1 && code
<= 26) {
927 KeyboardModifiers
|= GLUT_ACTIVE_CTRL
;
930 if((code
>= 43 && code
<= 34) || (code
== 60)
931 || (code
>= 62 && code
<= 90) || (code
== 94)
932 || (code
== 95) || (code
>= 123 && code
<= 126))
933 KeyboardModifiers
|= GLUT_ACTIVE_SHIFT
;
936 KeyboardFunc(code
, MouseX
, MouseY
);
941 /* linux kbd reading */
942 struct kbentry entry
;
944 if(KeyboardModifiers
& GLUT_ACTIVE_SHIFT
)
945 entry
.kb_table
|= K_SHIFTTAB
;
947 int release
= code
& 0x80;
950 entry
.kb_index
= code
;
952 if (ioctl(ConsoleFD
, KDGKBENT
, &entry
) < 0) {
953 sprintf(exiterror
, "ioctl(KDGKBENT) failed.\n");
957 int labelval
= entry
.kb_value
;
962 MODIFIER(GLUT_ACTIVE_SHIFT
);
965 MODIFIER(GLUT_ACTIVE_CTRL
);
969 MODIFIER(GLUT_ACTIVE_ALT
);
973 if(!release
&& labelval
>= K_F1
&& labelval
<= K_F12
)
974 if(KeyboardModifiers
& GLUT_ACTIVE_ALT
) {
975 /* VT switch, we must do it */
976 if(ioctl(ConsoleFD
, VT_ACTIVATE
, labelval
- K_F1
+ 1) < 0)
977 sprintf(exiterror
, "Error switching console\n");
983 LedModifier(LED_CAP
, release
);
986 LedModifier(LED_NUM
, release
);
988 case K_HOLD
: /* scroll lock suspends glut */
989 LedModifier(LED_SCR
, release
);
990 while(KeyboardLedState
& LED_SCR
) {
997 /* we could queue keypresses here */
998 if(KeyboardLedState
& LED_SCR
)
1004 if(labelval
>= K_F1
&& labelval
<= K_F12
)
1005 specialkey
= GLUT_KEY_F1
+ labelval
- K_F1
;
1009 specialkey
= GLUT_KEY_LEFT
; break;
1011 specialkey
= GLUT_KEY_UP
; break;
1013 specialkey
= GLUT_KEY_RIGHT
; break;
1015 specialkey
= GLUT_KEY_DOWN
; break;
1017 specialkey
= GLUT_KEY_PAGE_UP
; break;
1019 specialkey
= GLUT_KEY_PAGE_DOWN
; break;
1021 specialkey
= GLUT_KEY_HOME
; break;
1023 specialkey
= GLUT_KEY_END
; break;
1025 specialkey
= GLUT_KEY_INSERT
; break;
1027 labelval
= '\b'; break;
1029 labelval
= '\n'; break;
1034 SpecialFunc(specialkey
, MouseX
, MouseY
);
1038 if(KeyboardLedState
& LED_CAP
) {
1039 if(c
>= 'A' && c
<= 'Z')
1042 if(c
>= 'a' && c
<= 'z')
1045 KeyboardFunc(c
, MouseX
, MouseY
);
1050 static void HandleMousePress(int button
, int pressed
)
1052 if(ActiveMenu
&& !pressed
) {
1054 MenuStatusFunc(GLUT_MENU_NOT_IN_USE
, MouseX
, MouseY
);
1056 MenuStateFunc(GLUT_MENU_NOT_IN_USE
);
1057 if(SelectedMenu
> 0) {
1058 int selected
= Menus
[SelectedMenu
].selected
;
1060 if(Menus
[SelectedMenu
].Items
[selected
].submenu
== 0)
1061 Menus
[SelectedMenu
].func(Menus
[SelectedMenu
].Items
1069 if(AttachedMenus
[button
] && pressed
) {
1070 ActiveMenu
= AttachedMenus
[button
];
1072 MenuStatusFunc(GLUT_MENU_IN_USE
, MouseX
, MouseY
);
1074 MenuStateFunc(GLUT_MENU_IN_USE
);
1075 Menus
[ActiveMenu
].x
= MouseX
- Menus
[ActiveMenu
].width
/2;
1076 Menus
[ActiveMenu
].y
= MouseY
- Menus
[ActiveMenu
].NumItems
*MENU_FONT_HEIGHT
/2;
1077 Menus
[ActiveMenu
].selected
= -1;
1083 MouseFunc(button
, pressed
? GLUT_DOWN
: GLUT_UP
, MouseX
, MouseY
);
1086 static int ReadMouse(void)
1089 static int ll
, lm
, lr
;
1097 pfd
.events
= POLLIN
;
1098 if(poll(&pfd
, 1, 1) != 1)
1101 if(Gpm_GetEvent(&event
) != 1)
1104 l
= event
.buttons
& GPM_B_LEFT
;
1105 m
= event
.buttons
& GPM_B_MIDDLE
;
1106 r
= event
.buttons
& GPM_B_RIGHT
;
1108 /* gpm is weird in that it gives a button number when the button
1109 is released, with type set to GPM_UP, this is only a problem
1110 if it is the last button released */
1112 if(event
.type
& GPM_UP
)
1113 if(event
.buttons
== GPM_B_LEFT
|| event
.buttons
== GPM_B_MIDDLE
||
1114 event
.buttons
== GPM_B_RIGHT
|| event
.buttons
== GPM_B_FOURTH
)
1125 if(fcntl(MouseFD
, F_SETFL
, O_NONBLOCK
) == -1) {
1132 if(read(MouseFD
, data
, 4) != 4)
1135 l
= ((data
[0] & 0x20) >> 3);
1136 m
= ((data
[3] & 0x10) >> 3);
1137 r
= ((data
[0] & 0x10) >> 4);
1139 dx
= (((data
[0] & 0x03) << 6) | (data
[1] & 0x3F));
1140 dy
= (((data
[0] & 0x0C) << 4) | (data
[2] & 0x3F));
1143 MouseX
+= dx
* MouseSpeed
;
1147 if(MouseX
>= VarInfo
.xres
)
1148 MouseX
= VarInfo
.xres
- 1;
1150 MouseY
+= dy
* MouseSpeed
;
1154 if(MouseY
>= VarInfo
.yres
)
1155 MouseY
= VarInfo
.yres
- 1;
1158 HandleMousePress(GLUT_LEFT_BUTTON
, l
);
1160 HandleMousePress(GLUT_MIDDLE_BUTTON
, m
);
1162 HandleMousePress(GLUT_RIGHT_BUTTON
, r
);
1164 ll
= l
, lm
= m
, lr
= r
;
1169 MotionFunc(MouseX
, MouseY
);
1171 if(PassiveMotionFunc
)
1172 PassiveMotionFunc(MouseX
, MouseY
);
1184 static void RecieveEvents(void)
1192 static void ProcessTimers(void)
1194 if(GlutTimers
&& GlutTimers
->time
< glutGet(GLUT_ELAPSED_TIME
)) {
1195 struct GlutTimer
*timer
= GlutTimers
;
1196 timer
->func(timer
->value
);
1197 GlutTimers
= timer
->next
;
1202 void glutMainLoop(void)
1205 ReshapeFunc(VarInfo
.xres
, VarInfo
.yres
);
1208 sprintf(exiterror
, "Fatal Error: No Display Function registered\n");
1227 VisibilityFunc(Visible
? GLUT_VISIBLE
: GLUT_NOT_VISIBLE
);
1230 if(Visible
&& Redisplay
) {
1235 if(!(DisplayMode
& GLUT_DOUBLE
)) {
1245 /* ---------- Window Management ----------*/
1246 static void ParseFBModes(void)
1249 struct fb_var_screeninfo vi
= VarInfo
;
1251 FILE *fbmodes
= fopen(FBMODES
, "r");
1254 sprintf(exiterror
, "Warning: could not open "
1255 FBMODES
" using current mode\n");
1259 if(InitialWidthHint
== 0 && InitialHeightHint
== 0
1260 && RequiredWidth
== 0)
1261 return; /* use current mode */
1263 while(fgets(buf
, sizeof buf
, fbmodes
)) {
1267 if(!(c
= strstr(buf
, "geometry")))
1269 v
= sscanf(c
, "geometry %d %d %d %d %d", &vi
.xres
, &vi
.yres
,
1270 &vi
.xres_virtual
, &vi
.yres_virtual
, &vi
.bits_per_pixel
);
1274 /* now we have to decide what is best */
1276 if(RequiredWidth
!= vi
.xres
|| RequiredHeight
!= vi
.yres
)
1279 if(VarInfo
.xres
< vi
.xres
&& VarInfo
.xres
< InitialWidthHint
)
1281 if(VarInfo
.xres
> vi
.xres
&& vi
.xres
> InitialWidthHint
)
1284 if(VarInfo
.yres
< vi
.yres
&& VarInfo
.yres
< InitialHeightHint
)
1286 if(VarInfo
.yres
> vi
.yres
&& vi
.yres
> InitialHeightHint
)
1293 fgets(buf
, sizeof buf
, fbmodes
);
1294 if(!(c
= strstr(buf
, "timings")))
1297 v
= sscanf(c
, "timings %d %d %d %d %d %d %d", &vi
.pixclock
,
1298 &vi
.left_margin
, &vi
.right_margin
, &vi
.upper_margin
,
1299 &vi
.lower_margin
, &vi
.hsync_len
, &vi
.vsync_len
);
1303 VarInfo
= vi
; /* finally found a better mode */
1313 sprintf(exiterror
, "No mode (%dx%d) found in "FBMODES
"\n",
1314 RequiredWidth
, RequiredHeight
);
1319 int glutCreateWindow (const char *title
)
1321 if(ConsoleFD
== -1) {
1323 char *argv
[] = {NULL
};
1324 glutInit(&argc
, argv
);
1330 char *fbdev
= getenv("FRAMEBUFFER");
1333 if(!sscanf(fbdev
, "/dev/fb%d", &FramebufferIndex
))
1334 if(!sscanf(fbdev
, "/dev/fb/%d", &FramebufferIndex
))
1335 sprintf(exiterror
, "Could not determine Framebuffer index!\n");
1338 static char fb
[128];
1339 FramebufferIndex
= 0;
1340 struct fb_con2fbmap confb
;
1341 int fd
= open("/dev/fb0", O_RDWR
);
1342 confb
.console
= CurrentVT
;
1343 if(ioctl(fd
, FBIOGET_CON2FBMAP
, &confb
) != -1)
1344 FramebufferIndex
= confb
.framebuffer
;
1345 sprintf(fb
, "/dev/fb%d", FramebufferIndex
);
1350 /* open the framebuffer device */
1351 FrameBufferFD
= open(fbdev
, O_RDWR
);
1352 if (FrameBufferFD
< 0) {
1353 sprintf(exiterror
, "Error opening %s: %s\n", fbdev
, strerror(errno
));
1357 /* Get the fixed screen info */
1358 if (ioctl(FrameBufferFD
, FBIOGET_FSCREENINFO
, &FixedInfo
)) {
1359 sprintf(exiterror
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
1364 /* get the variable screen info */
1365 if (ioctl(FrameBufferFD
, FBIOGET_VSCREENINFO
, &OrigVarInfo
)) {
1366 sprintf(exiterror
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
1371 /* operate on a copy */
1372 VarInfo
= OrigVarInfo
;
1374 /* set the depth, resolution, etc */
1377 if(DisplayMode
& GLUT_INDEX
)
1378 VarInfo
.bits_per_pixel
= 8;
1380 if(VarInfo
.bits_per_pixel
== 8)
1381 VarInfo
.bits_per_pixel
= 32;
1384 VarInfo
.bits_per_pixel
= DesiredDepth
;
1386 VarInfo
.xoffset
= 0;
1387 VarInfo
.yoffset
= 0;
1389 VarInfo
.vmode
&= ~FB_VMODE_YWRAP
; /* turn off scrolling */
1391 /* set new variable screen info */
1392 if (ioctl(FrameBufferFD
, FBIOPUT_VSCREENINFO
, &VarInfo
)) {
1393 sprintf(exiterror
, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
1398 /* reload the screen info to update offsets */
1399 if (ioctl(FrameBufferFD
, FBIOGET_VSCREENINFO
, &VarInfo
)) {
1400 sprintf(exiterror
, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
1405 /* reload the fixed info to update color mode */
1406 if (ioctl(FrameBufferFD
, FBIOGET_FSCREENINFO
, &FixedInfo
)) {
1407 sprintf(exiterror
, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
1412 if(DisplayMode
& GLUT_INDEX
) {
1413 /* initialize colormap */
1414 if (FixedInfo
.visual
!= FB_VISUAL_DIRECTCOLOR
) {
1415 static unsigned short red
[256], green
[256], blue
[256];
1416 /* we're assuming 256 entries here */
1421 ColorMap
.green
= green
;
1422 ColorMap
.blue
= blue
;
1423 ColorMap
.transp
= NULL
;
1425 if (ioctl(FrameBufferFD
, FBIOGETCMAP
, (void *) &ColorMap
) < 0)
1426 sprintf(exiterror
, "ioctl(FBIOGETCMAP) failed!\n");
1429 sprintf(exiterror
, "error: Could not set 8 bit color mode\n");
1434 /* mmap the framebuffer into our address space */
1435 FrameBuffer
= mmap(0, FixedInfo
.smem_len
, PROT_READ
| PROT_WRITE
,
1436 MAP_SHARED
, FrameBufferFD
, 0);
1437 if (FrameBuffer
== MAP_FAILED
) {
1438 sprintf(exiterror
, "error: unable to mmap framebuffer: %s\n",
1446 int mask
= DisplayMode
;
1447 for(i
=0; i
<8 && mask
; i
++) {
1448 if(mask
& GLUT_DOUBLE
) {
1449 attribs
[i
] = GLFBDEV_DOUBLE_BUFFER
;
1450 mask
&= ~GLUT_DOUBLE
;
1454 if(mask
& GLUT_INDEX
) {
1455 attribs
[i
] = GLFBDEV_COLOR_INDEX
;
1456 mask
&= ~GLUT_INDEX
;
1460 if(mask
& GLUT_DEPTH
) {
1461 attribs
[i
] = GLFBDEV_DEPTH_SIZE
;
1462 attribs
[++i
] = DepthSize
;
1463 mask
&= ~GLUT_DEPTH
;
1467 if(mask
& GLUT_STENCIL
) {
1468 attribs
[i
] = GLFBDEV_STENCIL_SIZE
;
1469 attribs
[++i
] = StencilSize
;
1470 mask
&= ~GLUT_STENCIL
;
1474 if(mask
& GLUT_ACCUM
) {
1475 attribs
[i
] = GLFBDEV_ACCUM_SIZE
;
1476 attribs
[++i
] = AccumSize
;
1477 mask
&= ~GLUT_ACCUM
;
1481 if(mask
& GLUT_ALPHA
)
1482 if(!(DisplayMode
& GLUT_INDEX
)) {
1483 mask
&= ~GLUT_ALPHA
;
1488 sprintf(exiterror
, "Invalid mode from glutInitDisplayMode\n");
1492 attribs
[i
] = GLFBDEV_NONE
;
1494 if(!(Visual
= glFBDevCreateVisual( &FixedInfo
, &VarInfo
, attribs
))) {
1495 sprintf(exiterror
, "Failure to create Visual\n");
1499 int size
= VarInfo
.xres_virtual
* VarInfo
.yres_virtual
1500 * VarInfo
.bits_per_pixel
/ 8;
1501 if(DisplayMode
& GLUT_DOUBLE
) {
1502 if(!(BackBuffer
= malloc(size
))) {
1503 sprintf(exiterror
, "Failed to allocate double buffer\n");
1507 BackBuffer
= FrameBuffer
;
1509 if(!(Buffer
= glFBDevCreateBuffer( &FixedInfo
, &VarInfo
, Visual
,
1510 FrameBuffer
, BackBuffer
, size
))) {
1511 sprintf(exiterror
, "Failure to create Buffer\n");
1515 if(!(Context
= glFBDevCreateContext(Visual
, NULL
))) {
1516 sprintf(exiterror
, "Failure to create Context\n");
1520 if(!glFBDevMakeCurrent( Context
, Buffer
, Buffer
)) {
1521 sprintf(exiterror
, "Failure to Make Current\n");
1530 if((MouseBuffer
= malloc(CURSOR_WIDTH
* CURSOR_HEIGHT
1531 * VarInfo
.bits_per_pixel
/ 8)) == NULL
) {
1532 sprintf(exiterror
, "malloc failure\n");
1536 MouseX
= VarInfo
.xres
/ 2;
1537 MouseY
= VarInfo
.yres
/ 2;
1544 int glutCreateSubWindow(int win
, int x
, int y
, int width
, int height
)
1549 void glutSetWindow(int win
)
1553 int glutGetWindow(void)
1558 void glutDestroyWindow(int win
)
1562 void glutPostRedisplay(void)
1567 void glutSwapBuffers(void)
1571 if(DisplayMode
& GLUT_DOUBLE
) {
1576 glFBDevSwapBuffers(Buffer
);
1580 void glutPositionWindow(int x
, int y
)
1584 void glutReshapeWindow(int width
, int height
)
1588 void glutFullScreen(void)
1592 void glutPopWindow(void)
1596 void glutPushWindow(void)
1600 void glutShowWindow(void)
1604 void glutHideWindow(void)
1608 void glutIconifyWindow(void)
1612 void glutSetWindowTitle(const char *name
)
1616 void glutSetIconTitle(const char *name
)
1620 void glutSetCursor(int cursor
)
1622 if(cursor
== GLUT_CURSOR_FULL_CROSSHAIR
)
1623 cursor
= GLUT_CURSOR_CROSSHAIR
;
1624 CurrentCursor
= cursor
;
1630 /* --------- Overlays ------------*/
1631 void glutEstablishOverlay(void)
1636 void glutUseLayer(GLenum layer
)
1640 void glutRemoveOverlay(void)
1644 void glutPostOverlayRedisplay(void)
1648 void glutShowOverlay(void)
1652 void glutHideOverlay(void)
1656 /* --------- Menus ------------*/
1657 int glutCreateMenu(void (*func
)(int value
))
1660 CurrentMenu
= NumMenus
;
1662 Menus
= realloc(Menus
, sizeof(*Menus
) * NumMenus
);
1663 Menus
[CurrentMenu
].NumItems
= 0;
1664 Menus
[CurrentMenu
].Items
= NULL
;
1665 Menus
[CurrentMenu
].func
= func
;
1666 Menus
[CurrentMenu
].width
= 0;
1670 void glutSetMenu(int menu
)
1675 int glutGetMenu(void)
1680 void glutDestroyMenu(int menu
)
1682 if(menu
== CurrentMenu
)
1686 static void NameMenuEntry(int entry
, const char *name
)
1688 int cm
= CurrentMenu
;
1689 if(!(Menus
[cm
].Items
[entry
-1].name
= realloc(Menus
[cm
].Items
[entry
-1].name
,
1690 strlen(name
) + 1))) {
1691 sprintf(exiterror
, "realloc failed in NameMenuEntry\n");
1694 strcpy(Menus
[cm
].Items
[entry
-1].name
, name
);
1695 if(strlen(name
) * MENU_FONT_WIDTH
> Menus
[cm
].width
)
1696 Menus
[cm
].width
= strlen(name
) * MENU_FONT_WIDTH
;
1699 static int AddMenuItem(const char *name
)
1701 int cm
= CurrentMenu
;
1702 int item
= Menus
[cm
].NumItems
++;
1703 if(!(Menus
[cm
].Items
= realloc(Menus
[cm
].Items
,
1704 Menus
[cm
].NumItems
* sizeof(*Menus
[0].Items
)))) {
1705 sprintf(exiterror
, "realloc failed in AddMenuItem\n");
1708 Menus
[cm
].Items
[item
].name
= NULL
;
1709 NameMenuEntry(item
+1, name
);
1713 void glutAddMenuEntry(const char *name
, int value
)
1715 int item
= AddMenuItem(name
);
1716 Menus
[CurrentMenu
].Items
[item
].value
= value
;
1717 Menus
[CurrentMenu
].Items
[item
].submenu
= 0;
1720 void glutAddSubMenu(const char *name
, int menu
)
1722 int item
= AddMenuItem(name
);
1723 if(menu
== CurrentMenu
) {
1724 sprintf(exiterror
, "Recursive menus not supported\n");
1727 Menus
[CurrentMenu
].Items
[item
].submenu
= menu
;
1730 void glutChangeToMenuEntry(int entry
, const char *name
, int value
)
1732 NameMenuEntry(entry
, name
);
1733 Menus
[CurrentMenu
].Items
[entry
-1].value
= value
;
1734 Menus
[CurrentMenu
].Items
[entry
-1].submenu
= 0;
1737 void glutChangeToSubMenu(int entry
, const char *name
, int menu
)
1739 NameMenuEntry(entry
, name
);
1740 Menus
[CurrentMenu
].Items
[entry
-1].submenu
= menu
;
1743 void glutRemoveMenuItem(int entry
)
1745 memmove(Menus
[CurrentMenu
].Items
+ entry
- 1,
1746 Menus
[CurrentMenu
].Items
+ entry
,
1747 sizeof(*Menus
[0].Items
) * (Menus
[CurrentMenu
].NumItems
- entry
));
1748 Menus
[CurrentMenu
].NumItems
--;
1751 void glutAttachMenu(int button
)
1753 AttachedMenus
[button
] = CurrentMenu
;
1756 void glutDetachMenu(int button
)
1758 AttachedMenus
[button
] = 0;
1761 /* --------- Callbacks ------------ */
1762 void glutDisplayFunc(void (*func
)(void))
1767 void glutOverlayDisplayFunc(void (*func
)(void))
1771 void glutReshapeFunc(void (*func
)(int width
, int height
))
1776 void glutKeyboardFunc(void (*func
)(unsigned char key
, int x
, int y
))
1778 KeyboardFunc
= func
;
1781 void glutMouseFunc(void (*func
)(int button
, int state
, int x
, int y
))
1787 void glutMotionFunc(void (*func
)(int x
, int y
))
1793 void glutPassiveMotionFunc(void (*func
)(int x
, int y
))
1796 PassiveMotionFunc
= func
;
1799 void glutVisibilityFunc(void (*func
)(int state
))
1801 VisibilityFunc
= func
;
1804 void glutEntryFunc(void (*func
)(int state
))
1808 void glutSpecialFunc(void (*func
)(int key
, int x
, int y
))
1813 void glutSpaceballMotionFunc(void (*func
)(int x
, int y
, int z
))
1817 void glutSpaceballRotateFunc(void (*func
)(int x
, int y
, int z
))
1821 void glutButtonBoxFunc(void (*func
)(int button
, int state
))
1825 void glutDialsFunc(void (*func
)(int dial
, int value
))
1829 void glutTabletMotionFunc(void (*func
)(int x
, int y
))
1833 void glutTabletButtonFunc(void (*func
)(int button
, int state
,
1838 void glutMenuStatusFunc(void (*func
)(int status
, int x
, int y
))
1840 MenuStatusFunc
= func
;
1843 void glutMenuStateFunc(void (*func
)(int status
))
1845 MenuStateFunc
= func
;
1848 void glutIdleFunc(void (*func
)(void))
1853 void glutTimerFunc(unsigned int msecs
,
1854 void (*func
)(int value
), int value
)
1856 struct GlutTimer
*timer
= malloc(sizeof *timer
);
1857 timer
->time
= glutGet(GLUT_ELAPSED_TIME
) + msecs
;
1859 timer
->value
= value
;
1861 struct GlutTimer
**head
= &GlutTimers
;
1862 while(*head
&& (*head
)->time
< timer
->time
)
1863 head
= &(*head
)->next
;
1865 timer
->next
= *head
;
1869 /* --------- Color Map ------------*/
1870 #define TOCMAP(x) (unsigned short)((x<0?0:x>1?1:x) * (GLfloat) (2<<16))
1871 #define FROMCMAP(x) (GLfloat)x / (GLfloat)(2<<16)
1873 void glutSetColor(int cell
, GLfloat red
, GLfloat green
, GLfloat blue
)
1875 if(cell
>=0 && cell
< 256) {
1877 ColorMap
.red
[cell
] = TOCMAP(red
);
1878 ColorMap
.green
[cell
] = TOCMAP(green
);
1879 ColorMap
.blue
[cell
] = TOCMAP(blue
);
1881 ColorMap
.start
= cell
;
1884 if (ioctl(FrameBufferFD
, FBIOPUTCMAP
, (void *) &ColorMap
) < 0)
1885 fprintf(stderr
, "ioctl(FBIOPUTCMAP) failed [%d]\n", cell
);
1889 GLfloat
glutGetColor(int cell
, int component
)
1891 if(!(DisplayMode
& GLUT_INDEX
))
1894 if(cell
< 0 || cell
> 256)
1899 return FROMCMAP(ColorMap
.red
[cell
]);
1901 return FROMCMAP(ColorMap
.green
[cell
]);
1903 return FROMCMAP(ColorMap
.blue
[cell
]);
1908 void glutCopyColormap(int win
)
1912 /* --------- State ------------*/
1913 void glutWarpPointer(int x
, int y
)
1917 if(x
>= VarInfo
.xres
)
1918 x
= VarInfo
.xres
- 1;
1923 if(y
>= VarInfo
.yres
)
1924 y
= VarInfo
.yres
- 1;
1931 int glutGet(GLenum state
)
1938 case GLUT_INIT_WINDOW_WIDTH
:
1939 case GLUT_WINDOW_WIDTH
:
1940 case GLUT_SCREEN_WIDTH
:
1941 return VarInfo
.xres
;
1942 case GLUT_INIT_WINDOW_HEIGHT
:
1943 case GLUT_WINDOW_HEIGHT
:
1944 case GLUT_SCREEN_HEIGHT
:
1945 return VarInfo
.yres
;
1946 case GLUT_WINDOW_BUFFER_SIZE
:
1947 return VarInfo
.bits_per_pixel
;
1948 case GLUT_WINDOW_STENCIL_SIZE
:
1950 case GLUT_WINDOW_DEPTH_SIZE
:
1952 case GLUT_WINDOW_RED_SIZE
:
1953 return VarInfo
.red
.length
;
1954 case GLUT_WINDOW_GREEN_SIZE
:
1955 return VarInfo
.green
.length
;
1956 case GLUT_WINDOW_BLUE_SIZE
:
1957 return VarInfo
.green
.length
;
1958 case GLUT_WINDOW_ALPHA_SIZE
:
1959 return VarInfo
.transp
.length
;
1960 case GLUT_WINDOW_ACCUM_RED_SIZE
:
1961 case GLUT_WINDOW_ACCUM_GREEN_SIZE
:
1962 case GLUT_WINDOW_ACCUM_BLUE_SIZE
:
1963 case GLUT_WINDOW_ACCUM_ALPHA_SIZE
:
1965 case GLUT_WINDOW_DOUBLEBUFFER
:
1966 if(DisplayMode
& GLUT_DOUBLE
)
1969 case GLUT_WINDOW_RGBA
:
1970 if(DisplayMode
& GLUT_INDEX
)
1973 case GLUT_WINDOW_PARENT
:
1975 case GLUT_WINDOW_NUM_CHILDREN
:
1977 case GLUT_WINDOW_COLORMAP_SIZE
:
1978 if(DisplayMode
& GLUT_INDEX
)
1981 case GLUT_WINDOW_NUM_SAMPLES
:
1983 case GLUT_WINDOW_STEREO
:
1985 case GLUT_WINDOW_CURSOR
:
1986 return CurrentCursor
;
1987 case GLUT_SCREEN_WIDTH_MM
:
1988 return VarInfo
.width
;
1989 case GLUT_SCREEN_HEIGHT_MM
:
1990 return VarInfo
.height
;
1991 case GLUT_MENU_NUM_ITEMS
:
1993 return Menus
[CurrentMenu
].NumItems
;
1995 case GLUT_DISPLAY_MODE_POSSIBLE
:
1996 if((DisplayMode
& GLUT_MULTISAMPLE
)
1997 || (DisplayMode
& GLUT_STEREO
)
1998 || (DisplayMode
& GLUT_LUMINANCE
)
1999 || (DisplayMode
& GLUT_ALPHA
) && (DisplayMode
& GLUT_INDEX
))
2002 case GLUT_INIT_DISPLAY_MODE
:
2004 case GLUT_INIT_WINDOW_X
:
2005 case GLUT_INIT_WINDOW_Y
:
2007 case GLUT_ELAPSED_TIME
:
2009 static struct timeval tv
;
2010 gettimeofday(&tv
, 0);
2011 return 1000 * (tv
.tv_sec
- StartTime
.tv_sec
)
2012 + (tv
.tv_usec
- StartTime
.tv_usec
) / 1000;
2017 int glutLayerGet(GLenum info
)
2020 case GLUT_OVERLAY_POSSIBLE
:
2022 case GLUT_LAYER_IN_USE
:
2024 case GLUT_HAS_OVERLAY
:
2026 case GLUT_TRANSPARENT_INDEX
:
2028 case GLUT_NORMAL_DAMAGED
:
2030 case GLUT_OVERLAY_DAMAGED
:
2036 int glutDeviceGet(GLenum info
)
2039 case GLUT_HAS_KEYBOARD
:
2041 case GLUT_HAS_MOUSE
:
2042 case GLUT_NUM_MOUSE_BUTTONS
:
2043 return NumMouseButtons
;
2044 case GLUT_HAS_SPACEBALL
:
2045 case GLUT_HAS_DIAL_AND_BUTTON_BOX
:
2046 case GLUT_HAS_TABLET
:
2048 case GLUT_NUM_SPACEBALL_BUTTONS
:
2049 case GLUT_NUM_BUTTON_BOX_BUTTONS
:
2050 case GLUT_NUM_DIALS
:
2051 case GLUT_NUM_TABLET_BUTTONS
:
2057 int glutGetModifiers(void){
2058 return KeyboardModifiers
;
2061 /* ------------- extensions ------------ */
2062 int glutExtensionSupported(const char *extension
)
2064 const char *exts
= (const char *) glGetString(GL_EXTENSIONS
);
2065 const char *start
= exts
;
2066 int len
= strlen(extension
);
2069 const char *p
= strstr(exts
, extension
);
2072 if((p
== start
|| p
[-1] == ' ') && (p
[len
] == ' ' || p
[len
] == 0))
2079 void glutReportErrors(void)
2083 while ((error
= glGetError()) != GL_NO_ERROR
)
2084 fprintf(stderr
, "GL error: %s", gluErrorString(error
));
2089 const GLUTproc address
;
2090 } glut_functions
[] = {
2091 { "glutInit", (const GLUTproc
) glutInit
},
2092 { "glutInitDisplayMode", (const GLUTproc
) glutInitDisplayMode
},
2093 { "glutInitWindowPosition", (const GLUTproc
) glutInitWindowPosition
},
2094 { "glutInitWindowSize", (const GLUTproc
) glutInitWindowSize
},
2095 { "glutMainLoop", (const GLUTproc
) glutMainLoop
},
2096 { "glutCreateWindow", (const GLUTproc
) glutCreateWindow
},
2097 { "glutCreateSubWindow", (const GLUTproc
) glutCreateSubWindow
},
2098 { "glutDestroyWindow", (const GLUTproc
) glutDestroyWindow
},
2099 { "glutPostRedisplay", (const GLUTproc
) glutPostRedisplay
},
2100 { "glutSwapBuffers", (const GLUTproc
) glutSwapBuffers
},
2101 { "glutGetWindow", (const GLUTproc
) glutGetWindow
},
2102 { "glutSetWindow", (const GLUTproc
) glutSetWindow
},
2103 { "glutSetWindowTitle", (const GLUTproc
) glutSetWindowTitle
},
2104 { "glutSetIconTitle", (const GLUTproc
) glutSetIconTitle
},
2105 { "glutPositionWindow", (const GLUTproc
) glutPositionWindow
},
2106 { "glutReshapeWindow", (const GLUTproc
) glutReshapeWindow
},
2107 { "glutPopWindow", (const GLUTproc
) glutPopWindow
},
2108 { "glutPushWindow", (const GLUTproc
) glutPushWindow
},
2109 { "glutIconifyWindow", (const GLUTproc
) glutIconifyWindow
},
2110 { "glutShowWindow", (const GLUTproc
) glutShowWindow
},
2111 { "glutHideWindow", (const GLUTproc
) glutHideWindow
},
2112 { "glutFullScreen", (const GLUTproc
) glutFullScreen
},
2113 { "glutSetCursor", (const GLUTproc
) glutSetCursor
},
2114 { "glutWarpPointer", (const GLUTproc
) glutWarpPointer
},
2115 { "glutEstablishOverlay", (const GLUTproc
) glutEstablishOverlay
},
2116 { "glutRemoveOverlay", (const GLUTproc
) glutRemoveOverlay
},
2117 { "glutUseLayer", (const GLUTproc
) glutUseLayer
},
2118 { "glutPostOverlayRedisplay", (const GLUTproc
) glutPostOverlayRedisplay
},
2119 { "glutShowOverlay", (const GLUTproc
) glutShowOverlay
},
2120 { "glutHideOverlay", (const GLUTproc
) glutHideOverlay
},
2121 { "glutCreateMenu", (const GLUTproc
) glutCreateMenu
},
2122 { "glutDestroyMenu", (const GLUTproc
) glutDestroyMenu
},
2123 { "glutGetMenu", (const GLUTproc
) glutGetMenu
},
2124 { "glutSetMenu", (const GLUTproc
) glutSetMenu
},
2125 { "glutAddMenuEntry", (const GLUTproc
) glutAddMenuEntry
},
2126 { "glutAddSubMenu", (const GLUTproc
) glutAddSubMenu
},
2127 { "glutChangeToMenuEntry", (const GLUTproc
) glutChangeToMenuEntry
},
2128 { "glutChangeToSubMenu", (const GLUTproc
) glutChangeToSubMenu
},
2129 { "glutRemoveMenuItem", (const GLUTproc
) glutRemoveMenuItem
},
2130 { "glutAttachMenu", (const GLUTproc
) glutAttachMenu
},
2131 { "glutDetachMenu", (const GLUTproc
) glutDetachMenu
},
2132 { "glutDisplayFunc", (const GLUTproc
) glutDisplayFunc
},
2133 { "glutReshapeFunc", (const GLUTproc
) glutReshapeFunc
},
2134 { "glutKeyboardFunc", (const GLUTproc
) glutKeyboardFunc
},
2135 { "glutMouseFunc", (const GLUTproc
) glutMouseFunc
},
2136 { "glutMotionFunc", (const GLUTproc
) glutMotionFunc
},
2137 { "glutPassiveMotionFunc", (const GLUTproc
) glutPassiveMotionFunc
},
2138 { "glutEntryFunc", (const GLUTproc
) glutEntryFunc
},
2139 { "glutVisibilityFunc", (const GLUTproc
) glutVisibilityFunc
},
2140 { "glutIdleFunc", (const GLUTproc
) glutIdleFunc
},
2141 { "glutTimerFunc", (const GLUTproc
) glutTimerFunc
},
2142 { "glutMenuStateFunc", (const GLUTproc
) glutMenuStateFunc
},
2143 { "glutSpecialFunc", (const GLUTproc
) glutSpecialFunc
},
2144 { "glutSpaceballRotateFunc", (const GLUTproc
) glutSpaceballRotateFunc
},
2145 { "glutButtonBoxFunc", (const GLUTproc
) glutButtonBoxFunc
},
2146 { "glutDialsFunc", (const GLUTproc
) glutDialsFunc
},
2147 { "glutTabletMotionFunc", (const GLUTproc
) glutTabletMotionFunc
},
2148 { "glutTabletButtonFunc", (const GLUTproc
) glutTabletButtonFunc
},
2149 { "glutMenuStatusFunc", (const GLUTproc
) glutMenuStatusFunc
},
2150 { "glutOverlayDisplayFunc", (const GLUTproc
) glutOverlayDisplayFunc
},
2151 { "glutSetColor", (const GLUTproc
) glutSetColor
},
2152 { "glutGetColor", (const GLUTproc
) glutGetColor
},
2153 { "glutCopyColormap", (const GLUTproc
) glutCopyColormap
},
2154 { "glutGet", (const GLUTproc
) glutGet
},
2155 { "glutDeviceGet", (const GLUTproc
) glutDeviceGet
},
2156 { "glutExtensionSupported", (const GLUTproc
) glutExtensionSupported
},
2157 { "glutGetModifiers", (const GLUTproc
) glutGetModifiers
},
2158 { "glutLayerGet", (const GLUTproc
) glutLayerGet
},
2159 { "glutGetProcAddress", (const GLUTproc
) glutGetProcAddress
},
2160 { "glutBitmapCharacter", (const GLUTproc
) glutBitmapCharacter
},
2161 { "glutBitmapWidth", (const GLUTproc
) glutBitmapWidth
},
2162 { "glutStrokeCharacter", (const GLUTproc
) glutStrokeCharacter
},
2163 { "glutStrokeWidth", (const GLUTproc
) glutStrokeWidth
},
2164 { "glutBitmapLength", (const GLUTproc
) glutBitmapLength
},
2165 { "glutStrokeLength", (const GLUTproc
) glutStrokeLength
},
2166 { "glutWireSphere", (const GLUTproc
) glutWireSphere
},
2167 { "glutSolidSphere", (const GLUTproc
) glutSolidSphere
},
2168 { "glutWireCone", (const GLUTproc
) glutWireCone
},
2169 { "glutSolidCone", (const GLUTproc
) glutSolidCone
},
2170 { "glutWireCube", (const GLUTproc
) glutWireCube
},
2171 { "glutSolidCube", (const GLUTproc
) glutSolidCube
},
2172 { "glutWireTorus", (const GLUTproc
) glutWireTorus
},
2173 { "glutSolidTorus", (const GLUTproc
) glutSolidTorus
},
2174 { "glutWireDodecahedron", (const GLUTproc
) glutWireDodecahedron
},
2175 { "glutSolidDodecahedron", (const GLUTproc
) glutSolidDodecahedron
},
2176 { "glutWireTeapot", (const GLUTproc
) glutWireTeapot
},
2177 { "glutSolidTeapot", (const GLUTproc
) glutSolidTeapot
},
2178 { "glutWireOctahedron", (const GLUTproc
) glutWireOctahedron
},
2179 { "glutSolidOctahedron", (const GLUTproc
) glutSolidOctahedron
},
2180 { "glutWireTetrahedron", (const GLUTproc
) glutWireTetrahedron
},
2181 { "glutSolidTetrahedron", (const GLUTproc
) glutSolidTetrahedron
},
2182 { "glutWireIcosahedron", (const GLUTproc
) glutWireIcosahedron
},
2183 { "glutSolidIcosahedron", (const GLUTproc
) glutSolidIcosahedron
},
2184 { "glutReportErrors", (const GLUTproc
) glutReportErrors
},
2188 GLUTproc
glutGetProcAddress(const char *procName
)
2190 /* Try GLUT functions first */
2192 for (i
= 0; glut_functions
[i
].name
; i
++) {
2193 if (strcmp(glut_functions
[i
].name
, procName
) == 0)
2194 return glut_functions
[i
].address
;
2197 /* Try core GL functions */
2198 return (GLUTproc
) glFBDevGetProcAddress(procName
);