mesa: include mtypes.h
[mesa.git] / src / glut / directfb / window.c
1 /*
2 * Copyright (C) 2006 Claudio Ciccani <klan@users.sf.net>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "internal.h"
26
27
28 /*****************************************************************************/
29
30 static __GlutWindow *g_stack = NULL;
31
32 /*****************************************************************************/
33
34
35 __GlutWindow*
36 __glutCreateWindow( GLboolean fullscreen )
37 {
38 __GlutWindow *new;
39 DFBResult ret;
40 static int curid = 1;
41
42 new = calloc( 1, sizeof(__GlutWindow) );
43 if (!new)
44 __glutFatalError( "out of memory" );
45
46 new->id = curid++;
47
48 if (fullscreen) {
49 DFBDisplayLayerConfig config;
50 DFBDisplayLayerConfigFlags fail = 0;
51
52 config.flags = DLCONF_WIDTH | DLCONF_HEIGHT |
53 DLCONF_BUFFERMODE;
54 config.width = g_width;
55 config.height = g_height;
56
57 if (g_display_mode & GLUT_DOUBLE)
58 config.buffermode = DLBM_BACKVIDEO;
59 else
60 config.buffermode = DLBM_FRONTONLY;
61
62 if (g_bpp) {
63 config.flags |= DLCONF_PIXELFORMAT;
64
65 switch (g_bpp) {
66 case 8:
67 config.pixelformat = DSPF_RGB332;
68 break;
69 case 15:
70 config.pixelformat = DSPF_ARGB1555;
71 break;
72 case 16:
73 config.pixelformat = DSPF_RGB16;
74 break;
75 case 24:
76 case 32:
77 config.pixelformat = DSPF_RGB32;
78 break;
79 default:
80 config.flags &= ~DLCONF_PIXELFORMAT;
81 break;
82 }
83 }
84
85 primary->TestConfiguration( primary, &config, &fail );
86 config.flags &= ~fail;
87 primary->SetConfiguration( primary, &config );
88
89 ret = primary->GetSurface( primary, &new->surface );
90 if (ret) {
91 DirectFBError( "IDirectFBDisplayLayer::GetSurface()", ret );
92 free( new );
93 return NULL;
94 }
95
96 ret = new->surface->GetGL( new->surface, &new->gl );
97 if (ret) {
98 DirectFBError( "IDirectFBSurface::GetGL()", ret );
99 new->surface->Release( new->surface );
100 free( new );
101 return NULL;
102 }
103
104 events->Reset( events );
105 if (keyboard)
106 keyboard->AttachEventBuffer( keyboard, events );
107 if (mouse)
108 mouse->AttachEventBuffer( mouse, events );
109 if (joystick)
110 joystick->AttachEventBuffer( joystick, events );
111
112 new->visible = GL_TRUE;
113 }
114 else {
115 DFBWindowDescription dsc;
116
117 dsc.flags = DWDESC_CAPS | DWDESC_POSX | DWDESC_POSY |
118 DWDESC_WIDTH | DWDESC_HEIGHT;
119 dsc.caps = DWCAPS_NONE;
120 dsc.posx = g_xpos;
121 dsc.posy = g_ypos;
122 dsc.width = g_width;
123 dsc.height = g_height;
124
125 if (g_display_mode & GLUT_DOUBLE)
126 dsc.caps |= DWCAPS_DOUBLEBUFFER;
127 if (g_display_mode & GLUT_ALPHA)
128 dsc.caps |= DWCAPS_ALPHACHANNEL;
129
130 ret = primary->CreateWindow( primary, &dsc, &new->window );
131 if (ret) {
132 DirectFBError( "IDirectFBDisplayLayer::CreateWindow()", ret );
133 free( new );
134 return NULL;
135 }
136
137 new->window->GetID( new->window, &new->wid );
138
139 ret = new->window->GetSurface( new->window, &new->surface );
140 if (ret) {
141 DirectFBError( "IDirectFBWindow::GetSurface()", ret );
142 new->window->Release( new->window );
143 free( new );
144 return NULL;
145 }
146
147 ret = new->surface->GetGL( new->surface, &new->gl );
148 if (ret) {
149 DirectFBError( "IDirectFBSurface::GetGl()", ret );
150 new->surface->Release( new->surface );
151 new->window->Release( new->window );
152 free( new );
153 return NULL;
154 }
155
156 new->window->AttachEventBuffer( new->window, events );
157 /* enable only handled events */
158 new->window->DisableEvents( new->window, DWET_ALL );
159 new->window->EnableEvents( new->window, DWET_KEYDOWN | DWET_KEYUP |
160 DWET_BUTTONDOWN | DWET_BUTTONUP |
161 DWET_ENTER | DWET_LEAVE |
162 DWET_MOTION | DWET_SIZE );
163
164
165 new->req.flags |= WINDOW_REQUEST_SHOW;
166 }
167
168 new->reshape = GL_TRUE;
169 new->visibility = GL_TRUE;
170 new->redisplay = GL_TRUE;
171
172 if (g_stack) {
173 new->prev = g_stack->prev;
174 g_stack->prev->next = new;
175 g_stack->prev = new;
176 }
177 else {
178 new->prev = new;
179 g_stack = new;
180 }
181
182 return new;
183 }
184
185
186 __GlutWindow*
187 __glutFindWindow( DFBWindowID id )
188 {
189 __GlutWindow *cur;
190
191 for (cur = g_stack; cur; cur = cur->next) {
192 if (cur->wid == id)
193 return cur;
194 }
195
196 __glutFatalError( "Window %d not found", id );
197
198 return NULL;
199 }
200
201
202 void
203 __glutSetWindow( __GlutWindow *window )
204 {
205 if (g_current) {
206 if (g_current == window)
207 return;
208 g_current->gl->Unlock( g_current->gl );
209 }
210
211 if (window)
212 window->gl->Lock( window->gl );
213 g_current = window;
214 }
215
216
217 void
218 __glutHandleWindows( void )
219 {
220 __GlutWindow *cur = g_stack;
221
222 while (cur) {
223 __GlutWindow *next = cur->next;
224
225 if (cur->window && cur->req.flags) {
226 if (cur == g_current)
227 cur->gl->Unlock( cur->gl );
228
229 if (cur->req.flags & WINDOW_REQUEST_DESTROY) {
230 __glutDestroyWindow( cur );
231 cur = next;
232 continue;
233 }
234
235 if (cur->req.flags & WINDOW_REQUEST_POSITION) {
236 cur->window->MoveTo( cur->window,
237 cur->req.x, cur->req.y );
238 }
239
240 if (cur->req.flags & WINDOW_REQUEST_RESIZE) {
241 cur->window->Resize( cur->window,
242 cur->req.w, cur->req.h );
243 cur->reshape = GL_TRUE;
244 cur->redisplay = GL_TRUE;
245 }
246
247 if (cur->req.flags & WINDOW_REQUEST_RESTACK) {
248 while (cur->req.z > 0) {
249 if (cur->req.z >= +1000) {
250 cur->window->RaiseToTop( cur->window );
251 cur->req.z = 0;
252 break;
253 }
254
255 cur->window->Raise( cur->window );
256 cur->req.z--;
257 }
258
259 while (cur->req.z < 0) {
260 if (cur->req.z <= -1000) {
261 cur->window->LowerToBottom( cur->window );
262 cur->req.z = 0;
263 break;
264 }
265
266 cur->window->Lower( cur->window );
267 cur->req.z++;
268 }
269 }
270
271 if (cur->req.flags & WINDOW_REQUEST_SHOW) {
272 cur->window->SetOpacity( cur->window, 0xff );
273 cur->visible = GL_TRUE;
274 cur->visibility = GL_TRUE;
275 }
276 else if (cur->req.flags & WINDOW_REQUEST_HIDE) {
277 cur->window->SetOpacity( cur->window, 0x00 );
278 cur->visible = GL_FALSE;
279 cur->visibility = GL_TRUE;
280 }
281
282 cur->req.flags = 0;
283
284 if (cur == g_current)
285 cur->gl->Lock( cur->gl );
286 }
287
288 if (cur->reshape && reshape_func) {
289 int w, h;
290 g_idle = GL_FALSE;
291 cur->surface->GetSize( cur->surface, &w, &h );
292 __glutSetWindow( cur );
293 reshape_func( w, h );
294 }
295
296 if (cur->visibility && visibility_func) {
297 g_idle = GL_FALSE;
298 __glutSetWindow( cur );
299 visibility_func( cur->visible ? GLUT_VISIBLE : GLUT_NOT_VISIBLE );
300 }
301
302 if (cur->redisplay && display_func) {
303 g_idle = GL_FALSE;
304 __glutSetWindow( cur );
305 display_func();
306 }
307
308 cur->reshape = GL_FALSE;
309 cur->visibility = GL_FALSE;
310 cur->redisplay = GL_FALSE;
311
312 cur = next;
313 }
314 }
315
316
317 void
318 __glutDestroyWindow( __GlutWindow *window )
319 {
320 __GlutWindow *next = window->next;
321 __GlutWindow *prev = window->prev;
322
323 __glutAssert( window != NULL );
324
325 if (window == g_current)
326 g_current = NULL;
327 if (window == g_game)
328 g_game = NULL;
329
330 window->gl->Unlock( window->gl );
331 window->gl->Release( window->gl );
332 window->surface->Release( window->surface );
333
334 if (window->window) {
335 #if DIRECTFB_VERSION_CODE >= VERSION_CODE(0,9,26)
336 window->window->DetachEventBuffer( window->window, events );
337 #else
338 window->window->Destroy( window->window );
339 #endif
340 window->window->Release( window->window );
341 }
342 else {
343 #if DIRECTFB_VERSION_CODE >= VERSION_CODE(0,9,26)
344 if (joystick)
345 joystick->DetachEventBuffer( joystick, events );
346 if (mouse)
347 mouse->DetachEventBuffer( mouse, events );
348 if (keyboard)
349 keyboard->DetachEventBuffer( keyboard, events );
350 #endif
351 events->Reset( events );
352 }
353
354 free( window );
355
356 if (next)
357 next->prev = prev;
358 else
359 g_stack->prev = prev;
360
361 if (window == g_stack)
362 g_stack = next;
363 else
364 prev->next = next;
365 }
366
367
368 void
369 __glutDestroyWindows( void )
370 {
371 __GlutWindow *cur = g_stack;
372
373 while (cur) {
374 __GlutWindow *next = cur->next;
375 __glutDestroyWindow( cur );
376 cur = next;
377 }
378 }
379
380
381 int GLUTAPIENTRY
382 glutCreateWindow( const char *title )
383 {
384 __GlutWindow *window;
385
386 if (getenv( "__GLUT_GAME_MODE" ))
387 return glutEnterGameMode();
388
389 glutInit( NULL, NULL );
390
391 window = __glutCreateWindow( GL_FALSE );
392 if (!window)
393 return 0;
394
395 __glutSetWindow( window );
396 glutSetCursor( GLUT_CURSOR_INHERIT );
397
398 return window->id;
399 }
400
401
402 int GLUTAPIENTRY
403 glutCreateSubWindow( int win, int x, int y, int width, int height )
404 {
405 return GL_FALSE;
406 }
407
408
409 void GLUTAPIENTRY
410 glutDestroyWindow( int win )
411 {
412 __GlutWindow *cur;
413
414 for (cur = g_stack; cur; cur = cur->next) {
415 if (cur->id == win) {
416 if (cur->window)
417 cur->window->Destroy( cur->window );
418
419 cur->req.flags |= WINDOW_REQUEST_DESTROY;
420 break;
421 }
422 }
423 }
424
425
426 void GLUTAPIENTRY
427 glutPostRedisplay( void )
428 {
429 if (g_current)
430 g_current->redisplay = GL_TRUE;
431 }
432
433
434 void GLUTAPIENTRY
435 glutPostWindowRedisplay( int win )
436 {
437 __GlutWindow *cur;
438
439 for (cur = g_stack; cur; cur = cur->next) {
440 if (cur->id == win) {
441 cur->redisplay = GL_TRUE;
442 break;
443 }
444 }
445 }
446
447
448 void GLUTAPIENTRY
449 glutSwapBuffers( void )
450 {
451 if (g_current) {
452 g_current->gl->Unlock( g_current->gl );
453 g_current->surface->Flip( g_current->surface, NULL, 0 );
454 g_current->gl->Lock( g_current->gl );
455 }
456 }
457
458
459 int GLUTAPIENTRY
460 glutGetWindow( void )
461 {
462 return (g_current) ? g_current->id : 0;
463 }
464
465
466 void GLUTAPIENTRY
467 glutSetWindow( int win )
468 {
469 __GlutWindow *cur;
470
471 if (g_current && g_current->id == win)
472 return;
473
474 for (cur = g_stack; cur; cur = cur->next) {
475 if (cur->id == win) {
476 __glutSetWindow( cur );
477 break;
478 }
479 }
480 }
481
482
483 void GLUTAPIENTRY
484 glutSetWindowTitle( const char *title )
485 {
486 }
487
488
489 void GLUTAPIENTRY
490 glutSetIconTitle( const char *title )
491 {
492 }
493
494
495 void GLUTAPIENTRY
496 glutFullScreen( void )
497 {
498 if (g_current && !g_game) {
499 DFBDisplayLayerConfig config;
500
501 primary->GetConfiguration( primary, &config );
502
503 g_current->req.flags |= WINDOW_REQUEST_POSITION |
504 WINDOW_REQUEST_RESIZE |
505 WINDOW_REQUEST_RESTACK;
506 g_current->req.x = 0;
507 g_current->req.y = 0;
508 g_current->req.w = config.width;
509 g_current->req.h = config.height;
510 g_current->req.z = 1000;
511 }
512 }
513
514
515 void GLUTAPIENTRY
516 glutPositionWindow( int x, int y )
517 {
518 if (g_current && !g_game) {
519 g_current->req.flags |= WINDOW_REQUEST_POSITION;
520 g_current->req.x = x;
521 g_current->req.y = y;
522 }
523 }
524
525
526 void GLUTAPIENTRY
527 glutReshapeWindow( int width, int height )
528 {
529 if (g_current && !g_game) {
530 g_current->req.flags |= WINDOW_REQUEST_RESIZE;
531 g_current->req.w = width;
532 g_current->req.h = height;
533 }
534 }
535
536
537 void GLUTAPIENTRY
538 glutPopWindow( void )
539 {
540 if (g_current && !g_game) {
541 g_current->req.flags |= WINDOW_REQUEST_RESTACK;
542 g_current->req.z--;
543 }
544 }
545
546
547 void GLUTAPIENTRY
548 glutPushWindow( void )
549 {
550 if (g_current && !g_game) {
551 g_current->req.flags |= WINDOW_REQUEST_RESTACK;
552 g_current->req.z++;
553 }
554 }
555
556
557 void GLUTAPIENTRY
558 glutIconifyWindow( void )
559 {
560 }
561
562
563 void GLUTAPIENTRY
564 glutShowWindow( void )
565 {
566 if (g_current && !g_game) {
567 g_current->req.flags |= WINDOW_REQUEST_SHOW;
568 g_current->req.flags &= ~WINDOW_REQUEST_HIDE;
569 }
570 }
571
572
573 void GLUTAPIENTRY
574 glutHideWindow( void )
575 {
576 if (g_current && !g_game) {
577 g_current->req.flags |= WINDOW_REQUEST_HIDE;
578 g_current->req.flags &= ~WINDOW_REQUEST_SHOW;
579 }
580 }
581