implement setter for texture coord 2 (u,v) vertex attribute so it can be used by...
[freeglut] / src / fg_window.c
1 /*
2  * freeglut_window.c
3  *
4  * Window management methods.
5  *
6  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8  * Creation date: Fri Dec 3 1999
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27
28 #define FREEGLUT_BUILDING_LIB
29 #include <GL/freeglut.h>
30 #include "fg_internal.h"
31 #include "fg_gl2.h"
32
33 /*
34  * TODO BEFORE THE STABLE RELEASE:
35  *
36  *  fgSetupPixelFormat      -- ignores the display mode settings
37  *  fgOpenWindow()          -- check the Win32 version, -iconic handling!
38  *  fgCloseWindow()         -- check the Win32 version
39  *  glutCreateWindow()      -- Check when default position and size is {-1,-1}
40  *  glutCreateSubWindow()   -- Check when default position and size is {-1,-1}
41  *  glutDestroyWindow()     -- check the Win32 version
42  *  glutSetWindow()         -- check the Win32 version
43  *  glutSetWindowTitle()    -- check the Win32 version
44  *  glutSetIconTitle()      -- check the Win32 version
45  *  glutShowWindow()        -- check the Win32 version
46  *  glutHideWindow()        -- check the Win32 version
47  *  glutIconifyWindow()     -- check the Win32 version
48  *  glutPushWindow()        -- check the Win32 version
49  *  glutPopWindow()         -- check the Win32 version
50  */
51
52
53 extern void fgPlatformSetWindow ( SFG_Window *window );
54 extern void fgPlatformOpenWindow( SFG_Window* window, const char* title,
55                                   GLboolean positionUse, int x, int y,
56                                   GLboolean sizeUse, int w, int h,
57                                   GLboolean gameMode, GLboolean isSubWindow );
58 extern void fgPlatformCloseWindow( SFG_Window* window );
59 extern void fgPlatformGlutShowWindow( void );
60 extern void fgPlatformGlutHideWindow( void );
61 extern void fgPlatformGlutIconifyWindow( void );
62 extern void fgPlatformGlutSetWindowTitle( const char* title );
63 extern void fgPlatformGlutSetIconTitle( const char* title );
64 extern void fgPlatformGlutPositionWindow( int x, int y );
65 extern void fgPlatformGlutPushWindow( void );
66 extern void fgPlatformGlutPopWindow( void );
67 extern void fgPlatformGlutFullScreen( SFG_Window *win );
68 extern void fgPlatformGlutLeaveFullScreen( SFG_Window *win );
69 extern void fgPlatformGlutFullScreenToggle( SFG_Window *win );
70
71
72 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
73
74 int fghIsLegacyContextRequested( void )
75 {
76     return fgState.MajorVersion < 2 || (fgState.MajorVersion == 2 && fgState.MinorVersion <= 1);
77 }
78
79 int fghNumberOfAuxBuffersRequested( void )
80 {
81   if ( fgState.DisplayMode & GLUT_AUX4 ) {
82     return 4;
83   }
84   if ( fgState.DisplayMode & GLUT_AUX3 ) {
85     return 3;
86   }
87   if ( fgState.DisplayMode & GLUT_AUX2 ) {
88     return 2;
89   }
90   if ( fgState.DisplayMode & GLUT_AUX1 ) { /* NOTE: Same as GLUT_AUX! */
91     return fgState.AuxiliaryBufferNumber;
92   }
93   return 0;
94 }
95
96 int fghMapBit( int mask, int from, int to )
97 {
98   return ( mask & from ) ? to : 0;
99
100 }
101
102 void fghContextCreationError( void )
103 {
104     fgError( "Unable to create OpenGL %d.%d context (flags %x, profile %x)",
105              fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags,
106              fgState.ContextProfile );
107 }
108
109
110 /* -- SYSTEM-DEPENDENT PRIVATE FUNCTIONS ------------------------------------ */
111
112 /*
113  * Sets the OpenGL context and the fgStructure "Current Window" pointer to
114  * the window structure passed in.
115  */
116 void fgSetWindow ( SFG_Window *window )
117 {
118         fgPlatformSetWindow ( window );
119
120     fgStructure.CurrentWindow = window;
121 }
122
123 /*
124  * Opens a window. Requires a SFG_Window object created and attached
125  * to the freeglut structure. OpenGL context is created here.
126  */
127 void fgOpenWindow( SFG_Window* window, const char* title,
128                    GLboolean positionUse, int x, int y,
129                    GLboolean sizeUse, int w, int h,
130                    GLboolean gameMode, GLboolean isSubWindow )
131 {
132         fgPlatformOpenWindow( window, title,
133                    positionUse, x, y,
134                    sizeUse, w, h,
135                    gameMode, isSubWindow );
136
137     fgSetWindow( window );
138
139     window->Window.DoubleBuffered =
140         ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
141
142 #ifndef EGL_VERSION_1_0  /* No glDrawBuffer/glReadBuffer in GLES */
143     if ( ! window->Window.DoubleBuffered )
144     {
145         glDrawBuffer ( GL_FRONT );
146         glReadBuffer ( GL_FRONT );
147     }
148 #endif
149     window->Window.attribute_v_coord = -1;
150     window->Window.attribute_v_normal = -1;
151     window->Window.attribute_v_texture = -1;
152
153     fgInitGL2();
154
155     window->State.NeedToInitContext = GL_TRUE;
156 }
157
158 /*
159  * Closes a window, destroying the frame and OpenGL context
160  */
161 void fgCloseWindow( SFG_Window* window )
162 {
163     /* if we're in gamemode and we're closing the gamemode window,
164      * call glutLeaveGameMode first to make sure the gamemode is
165      * properly closed before closing the window
166      */
167     if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==window->ID)
168         glutLeaveGameMode();
169
170         fgPlatformCloseWindow ( window );
171 }
172
173
174 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
175
176 /*
177  * Creates a new top-level freeglut window
178  */
179 int FGAPIENTRY glutCreateWindow( const char* title )
180 {
181     /* XXX GLUT does not exit; it simply calls "glutInit" quietly if the
182      * XXX application has not already done so.  The "freeglut" community
183      * XXX decided not to go this route (freeglut-developer e-mail from
184      * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer]
185      * XXX Desired 'freeglut' behaviour when there is no current window"
186      */
187     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" );
188
189     return fgCreateWindow( NULL, title, fgState.Position.Use,
190                            fgState.Position.X, fgState.Position.Y,
191                            fgState.Size.Use, fgState.Size.X, fgState.Size.Y,
192                            GL_FALSE, GL_FALSE )->ID;
193 }
194
195 /*
196  * This function creates a sub window.
197  */
198 int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
199 {
200     int ret = 0;
201     SFG_Window* window = NULL;
202     SFG_Window* parent = NULL;
203
204     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" );
205     parent = fgWindowByID( parentID );
206     freeglut_return_val_if_fail( parent != NULL, 0 );
207     if ( x < 0 )
208     {
209         x = parent->State.Width + x ;
210         if ( w >= 0 ) x -= w ;
211     }
212
213     if ( w < 0 ) w = parent->State.Width - x + w ;
214     if ( w < 0 )
215     {
216         x += w ;
217         w = -w ;
218     }
219
220     if ( y < 0 )
221     {
222         y = parent->State.Height + y ;
223         if ( h >= 0 ) y -= h ;
224     }
225
226     if ( h < 0 ) h = parent->State.Height - y + h ;
227     if ( h < 0 )
228     {
229         y += h ;
230         h = -h ;
231     }
232
233     window = fgCreateWindow( parent, "", GL_TRUE, x, y, GL_TRUE, w, h, GL_FALSE, GL_FALSE );
234     ret = window->ID;
235
236     return ret;
237 }
238
239 /*
240  * Destroys a window and all of its subwindows
241  */
242 void FGAPIENTRY glutDestroyWindow( int windowID )
243 {
244     SFG_Window* window;
245     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDestroyWindow" );
246     window = fgWindowByID( windowID );
247     freeglut_return_if_fail( window != NULL );
248     {
249         fgExecutionState ExecState = fgState.ExecState;
250         fgAddToWindowDestroyList( window );
251         fgState.ExecState = ExecState;
252     }
253 }
254
255 /*
256  * This function selects the specified window as the current window
257  */
258 void FGAPIENTRY glutSetWindow( int ID )
259 {
260     SFG_Window* window = NULL;
261
262     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindow" );
263     if( fgStructure.CurrentWindow != NULL )
264         if( fgStructure.CurrentWindow->ID == ID )
265             return;
266
267     window = fgWindowByID( ID );
268     if( window == NULL )
269     {
270         fgWarning( "glutSetWindow(): window ID %d not found!", ID );
271         return;
272     }
273
274     fgSetWindow( window );
275 }
276
277 /*
278  * This function returns the ID number of the current window, 0 if none exists
279  */
280 int FGAPIENTRY glutGetWindow( void )
281 {
282     SFG_Window *win = fgStructure.CurrentWindow;
283     /*
284      * Since GLUT did not throw an error if this function was called without a prior call to
285      * "glutInit", this function shouldn't do so here.  Instead let us return a zero.
286      * See Feature Request "[ 1307049 ] glutInit check".
287      */
288     if ( ! fgState.Initialised )
289         return 0;
290
291     while ( win && win->IsMenu )
292         win = win->Parent;
293     return win ? win->ID : 0;
294 }
295
296 /*
297  * This function makes the current window visible
298  */
299 void FGAPIENTRY glutShowWindow( void )
300 {
301     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
302     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
303
304         fgPlatformGlutShowWindow ();
305
306     fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
307 }
308
309 /*
310  * This function hides the current window
311  */
312 void FGAPIENTRY glutHideWindow( void )
313 {
314     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
315     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
316
317         fgPlatformGlutHideWindow ();
318
319     fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
320 }
321
322 /*
323  * Iconify the current window (top-level windows only)
324  */
325 void FGAPIENTRY glutIconifyWindow( void )
326 {
327     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
328     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
329
330         fgPlatformGlutIconifyWindow ();
331
332     fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
333 }
334
335 /*
336  * Set the current window's title
337  */
338 void FGAPIENTRY glutSetWindowTitle( const char* title )
339 {
340     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowTitle" );
341     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
342     if( ! fgStructure.CurrentWindow->Parent )
343     {
344                 fgPlatformGlutSetWindowTitle ( title );
345     }
346 }
347
348 /*
349  * Set the current window's iconified title
350  */
351 void FGAPIENTRY glutSetIconTitle( const char* title )
352 {
353     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetIconTitle" );
354     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetIconTitle" );
355
356     if( ! fgStructure.CurrentWindow->Parent )
357     {
358                 fgPlatformGlutSetIconTitle ( title );
359     }
360 }
361
362 /*
363  * Change the current window's size
364  */
365 void FGAPIENTRY glutReshapeWindow( int width, int height )
366 {
367     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" );
368     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" );
369
370     if (glutGet(GLUT_FULL_SCREEN))
371     {
372       /*  Leave full screen state before resizing. */
373       glutLeaveFullScreen();
374     }
375
376     fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
377     fgStructure.CurrentWindow->State.Width  = width ;
378     fgStructure.CurrentWindow->State.Height = height;
379 }
380
381 /*
382  * Change the current window's position
383  */
384 void FGAPIENTRY glutPositionWindow( int x, int y )
385 {
386     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" );
387     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" );
388
389     if (glutGet(GLUT_FULL_SCREEN))
390     {
391       /*  Leave full screen state before moving. */
392       glutLeaveFullScreen();
393     }
394
395         fgPlatformGlutPositionWindow ( x, y );
396 }
397
398 /*
399  * Lowers the current window (by Z order change)
400  */
401 void FGAPIENTRY glutPushWindow( void )
402 {
403     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
404     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
405
406         fgPlatformGlutPushWindow ();
407 }
408
409 /*
410  * Raises the current window (by Z order change)
411  */
412 void FGAPIENTRY glutPopWindow( void )
413 {
414     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
415     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
416
417         fgPlatformGlutPopWindow ();
418 }
419
420 /*
421  * Resize the current window so that it fits the whole screen
422  */
423 void FGAPIENTRY glutFullScreen( void )
424 {
425     SFG_Window *win;
426
427     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
428     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
429
430     win = fgStructure.CurrentWindow;
431
432     if (win->Parent)
433     {
434         /* Child windows cannot be made fullscreen, consistent with GLUT's behavior
435          * Also, what would it mean for a child window to be fullscreen, given that it
436          * is confined to its parent?
437          */
438         fgWarning("glutFullScreen called on a child window, ignoring...");
439         return;
440     }
441     else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID && win->State.IsFullscreen)
442     {
443         /* Ignore fullscreen call on GameMode window, those are always fullscreen already
444          * only exception is during first entering GameMode
445          */
446         return;
447     }
448
449         fgPlatformGlutFullScreen ( win );
450 }
451
452 /*
453  * If we are fullscreen, resize the current window back to its original size
454  */
455 void FGAPIENTRY glutLeaveFullScreen( void )
456 {
457     SFG_Window *win;
458
459     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
460     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
461
462     win = fgStructure.CurrentWindow;
463
464         fgPlatformGlutLeaveFullScreen ( win );
465 }
466
467 /*
468  * Toggle the window's full screen state.
469  */
470 void FGAPIENTRY glutFullScreenToggle( void )
471 {
472     SFG_Window *win;
473
474     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
475     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
476
477     win = fgStructure.CurrentWindow;
478
479         fgPlatformGlutFullScreenToggle ( win );
480 }
481
482 /*
483  * A.Donev: Set and retrieve the window's user data
484  */
485 void* FGAPIENTRY glutGetWindowData( void )
486 {
487     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetWindowData" );
488     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutGetWindowData" );
489     return fgStructure.CurrentWindow->UserData;
490 }
491
492 void FGAPIENTRY glutSetWindowData(void* data)
493 {
494     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetWindowData" );
495     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowData" );
496     fgStructure.CurrentWindow->UserData = data;
497 }
498
499 /*** END OF FILE ***/