implement arb_vertex_program in hw for r200. Code contains still some hacks, generic...
[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->EnableEvents( new->window, DWET_KEYDOWN | DWET_KEYUP |
159 DWET_BUTTONDOWN | DWET_BUTTONUP |
160 DWET_ENTER | DWET_LEAVE |
161 DWET_MOTION | DWET_SIZE );
162
163
164 new->req.flags |= WINDOW_REQUEST_SHOW;
165 }
166
167 new->reshape = GL_TRUE;
168 new->visibility = GL_TRUE;
169 new->redisplay = GL_TRUE;
170
171 if (g_stack) {
172 new->prev = g_stack->prev;
173 g_stack->prev->next = new;
174 g_stack->prev = new;
175 }
176 else {
177 new->prev = new;
178 g_stack = new;
179 }
180
181 return new;
182 }
183
184
185 __GlutWindow*
186 __glutFindWindow( DFBWindowID id )
187 {
188 __GlutWindow *cur;
189
190 for (cur = g_stack; cur; cur = cur->next) {
191 if (cur->wid == id)
192 return cur;
193 }
194
195 __glutFatalError( "Window %d not found", id );
196
197 return NULL;
198 }
199
200
201 void
202 __glutSetWindow( __GlutWindow *window )
203 {
204 if (g_current) {
205 if (g_current == window)
206 return;
207 g_current->gl->Unlock( g_current->gl );
208 }
209
210 if (window)
211 window->gl->Lock( window->gl );
212 g_current = window;
213 }
214
215
216 void
217 __glutHandleWindows( void )
218 {
219 __GlutWindow *cur = g_stack;
220
221 while (cur) {
222 __GlutWindow *next = cur->next;
223
224 if (cur->window && cur->req.flags) {
225 if (cur == g_current)
226 cur->gl->Unlock( cur->gl );
227
228 if (cur->req.flags & WINDOW_REQUEST_DESTROY) {
229 __glutDestroyWindow( cur );
230 cur = next;
231 continue;
232 }
233
234 if (cur->req.flags & WINDOW_REQUEST_POSITION) {
235 cur->window->MoveTo( cur->window,
236 cur->req.x, cur->req.y );
237 }
238
239 if (cur->req.flags & WINDOW_REQUEST_RESIZE) {
240 cur->window->Resize( cur->window,
241 cur->req.w, cur->req.h );
242 cur->reshape = GL_TRUE;
243 cur->redisplay = GL_TRUE;
244 }
245
246 if (cur->req.flags & WINDOW_REQUEST_RESTACK) {
247 while (cur->req.z > 0) {
248 if (cur->req.z >= +1000) {
249 cur->window->RaiseToTop( cur->window );
250 cur->req.z = 0;
251 break;
252 }
253
254 cur->window->Raise( cur->window );
255 cur->req.z--;
256 }
257
258 while (cur->req.z < 0) {
259 if (cur->req.z <= -1000) {
260 cur->window->LowerToBottom( cur->window );
261 cur->req.z = 0;
262 break;
263 }
264
265 cur->window->Lower( cur->window );
266 cur->req.z++;
267 }
268 }
269
270 if (cur->req.flags & WINDOW_REQUEST_SHOW) {
271 cur->window->SetOpacity( cur->window, 0xff );
272 cur->visible = GL_TRUE;
273 cur->visibility = GL_TRUE;
274 }
275 else if (cur->req.flags & WINDOW_REQUEST_HIDE) {
276 cur->window->SetOpacity( cur->window, 0x00 );
277 cur->visible = GL_FALSE;
278 cur->visibility = GL_TRUE;
279 }
280
281 cur->req.flags = 0;
282
283 if (cur == g_current)
284 cur->gl->Lock( cur->gl );
285 }
286
287 if (cur->reshape && reshape_func) {
288 int w, h;
289 g_idle = GL_FALSE;
290 cur->surface->GetSize( cur->surface, &w, &h );
291 __glutSetWindow( cur );
292 reshape_func( w, h );
293 }
294
295 if (cur->visibility && visibility_func) {
296 g_idle = GL_FALSE;
297 __glutSetWindow( cur );
298 visibility_func( cur->visible ? GLUT_VISIBLE : GLUT_NOT_VISIBLE );
299 }
300
301 if (cur->redisplay && display_func) {
302 g_idle = GL_FALSE;
303 __glutSetWindow( cur );
304 display_func();
305 }
306
307 cur->reshape = GL_FALSE;
308 cur->visibility = GL_FALSE;
309 cur->redisplay = GL_FALSE;
310
311 cur = next;
312 }
313 }
314
315
316 void
317 __glutDestroyWindow( __GlutWindow *window )
318 {
319 __GlutWindow *next = window->next;
320 __GlutWindow *prev = window->prev;
321
322 __glutAssert( window != NULL );
323
324 if (window == g_current)
325 g_current = NULL;
326 if (window == g_game)
327 g_game = NULL;
328
329 window->gl->Unlock( window->gl );
330 window->gl->Release( window->gl );
331 window->surface->Release( window->surface );
332
333 if (window->window) {
334 window->window->Destroy( window->window );
335 window->window->Release( window->window );
336 }
337 else {
338 #if DIRECTFB_VERSION_CODE >= VERSION_CODE(0,9,26)
339 if (joystick)
340 joystick->DetachEventBuffer( joystick, events );
341 if (mouse)
342 mouse->DetachEventBuffer( mouse, events );
343 if (keyboard)
344 keyboard->DetachEventBuffer( keyboard, events );
345 #endif
346 events->Reset( events );
347 }
348
349 free( window );
350
351 if (next)
352 next->prev = prev;
353 else
354 g_stack->prev = prev;
355
356 if (window == g_stack)
357 g_stack = next;
358 else
359 prev->next = next;
360 }
361
362
363 void
364 __glutDestroyWindows( void )
365 {
366 __GlutWindow *cur = g_stack;
367
368 while (cur) {
369 __GlutWindow *next = cur->next;
370 __glutDestroyWindow( cur );
371 cur = next;
372 }
373 }
374
375
376 int GLUTAPIENTRY
377 glutCreateWindow( const char *title )
378 {
379 __GlutWindow *window;
380
381 if (getenv( "__GLUT_GAME_MODE" ))
382 return glutEnterGameMode();
383
384 glutInit( NULL, NULL );
385
386 window = __glutCreateWindow( GL_FALSE );
387 if (!window)
388 return 0;
389
390 __glutSetWindow( window );
391 glutSetCursor( GLUT_CURSOR_INHERIT );
392
393 return window->id;
394 }
395
396
397 int GLUTAPIENTRY
398 glutCreateSubWindow( int win, int x, int y, int width, int height )
399 {
400 return GL_FALSE;
401 }
402
403
404 void GLUTAPIENTRY
405 glutDestroyWindow( int win )
406 {
407 __GlutWindow *cur;
408
409 for (cur = g_stack; cur; cur = cur->next) {
410 if (cur->id == win) {
411 if (cur->window)
412 cur->window->Destroy( cur->window );
413
414 cur->req.flags |= WINDOW_REQUEST_DESTROY;
415 break;
416 }
417 }
418 }
419
420
421 void GLUTAPIENTRY
422 glutPostRedisplay( void )
423 {
424 if (g_current)
425 g_current->redisplay = GL_TRUE;
426 }
427
428
429 void GLUTAPIENTRY
430 glutPostWindowRedisplay( int win )
431 {
432 __GlutWindow *cur;
433
434 for (cur = g_stack; cur; cur = cur->next) {
435 if (cur->id == win) {
436 cur->redisplay = GL_TRUE;
437 break;
438 }
439 }
440 }
441
442
443 void GLUTAPIENTRY
444 glutSwapBuffers( void )
445 {
446 if (g_current) {
447 g_current->gl->Unlock( g_current->gl );
448 g_current->surface->Flip( g_current->surface, NULL, 0 );
449 g_current->gl->Lock( g_current->gl );
450 }
451 }
452
453
454 int GLUTAPIENTRY
455 glutGetWindow( void )
456 {
457 return (g_current) ? g_current->id : 0;
458 }
459
460
461 void GLUTAPIENTRY
462 glutSetWindow( int win )
463 {
464 __GlutWindow *cur;
465
466 if (g_current && g_current->id == win)
467 return;
468
469 for (cur = g_stack; cur; cur = cur->next) {
470 if (cur->id == win) {
471 __glutSetWindow( cur );
472 break;
473 }
474 }
475 }
476
477
478 void GLUTAPIENTRY
479 glutSetWindowTitle( const char *title )
480 {
481 }
482
483
484 void GLUTAPIENTRY
485 glutSetIconTitle( const char *title )
486 {
487 }
488
489
490 void GLUTAPIENTRY
491 glutFullScreen( void )
492 {
493 if (g_current && !g_game) {
494 DFBDisplayLayerConfig config;
495
496 primary->GetConfiguration( primary, &config );
497
498 g_current->req.flags |= WINDOW_REQUEST_POSITION |
499 WINDOW_REQUEST_RESIZE |
500 WINDOW_REQUEST_RESTACK;
501 g_current->req.x = 0;
502 g_current->req.y = 0;
503 g_current->req.w = config.width;
504 g_current->req.h = config.height;
505 g_current->req.z = 1000;
506 }
507 }
508
509
510 void GLUTAPIENTRY
511 glutPositionWindow( int x, int y )
512 {
513 if (g_current && !g_game) {
514 g_current->req.flags |= WINDOW_REQUEST_POSITION;
515 g_current->req.x = x;
516 g_current->req.y = y;
517 }
518 }
519
520
521 void GLUTAPIENTRY
522 glutReshapeWindow( int width, int height )
523 {
524 if (g_current && !g_game) {
525 g_current->req.flags |= WINDOW_REQUEST_RESIZE;
526 g_current->req.w = width;
527 g_current->req.h = height;
528 }
529 }
530
531
532 void GLUTAPIENTRY
533 glutPopWindow( void )
534 {
535 if (g_current && !g_game) {
536 g_current->req.flags |= WINDOW_REQUEST_RESTACK;
537 g_current->req.z--;
538 }
539 }
540
541
542 void GLUTAPIENTRY
543 glutPushWindow( void )
544 {
545 if (g_current && !g_game) {
546 g_current->req.flags |= WINDOW_REQUEST_RESTACK;
547 g_current->req.z++;
548 }
549 }
550
551
552 void GLUTAPIENTRY
553 glutIconifyWindow( void )
554 {
555 }
556
557
558 void GLUTAPIENTRY
559 glutShowWindow( void )
560 {
561 if (g_current && !g_game) {
562 g_current->req.flags |= WINDOW_REQUEST_SHOW;
563 g_current->req.flags &= ~WINDOW_REQUEST_HIDE;
564 }
565 }
566
567
568 void GLUTAPIENTRY
569 glutHideWindow( void )
570 {
571 if (g_current && !g_game) {
572 g_current->req.flags |= WINDOW_REQUEST_HIDE;
573 g_current->req.flags &= ~WINDOW_REQUEST_SHOW;
574 }
575 }
576