updated .c files to include:
[blender.git] / source / blender / src / mywindow.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * vervanging voor een aantal fie's zoals swinopen, winset,  (zie onder)
32  * dit alles omdat GL en X te traag zijn
33  * feb: Opengl en toch maar naar X!
34  */
35
36 #include <string.h>
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #ifdef WIN32
43 #include "BLI_winstuff.h"
44 #endif
45 #include "MEM_guardedalloc.h"
46
47 #include "BLI_blenlib.h"
48 #include "BLI_arithb.h"
49 #include "BLI_editVert.h"
50 #include "BLI_gsqueue.h"
51
52 #include "DNA_screen_types.h"
53
54 #include "BKE_global.h"
55
56 #include "BIF_gl.h"
57 #include "BIF_glutil.h"
58 #include "BIF_mywindow.h"
59 #include "BIF_screen.h"
60
61 #include "mydevice.h"
62 #include "blendef.h"
63
64 #include "winlay.h"
65
66
67 typedef struct {
68         unsigned short event;
69         short val;
70         char ascii;
71 } QEvent;
72
73 typedef struct {
74         struct bWindow *next, *prev;
75         int id, pad;
76         
77         int xmin, xmax, ymin, ymax;
78         float viewmat[4][4], winmat[4][4];
79
80         GSQueue *qevents;
81 } bWindow;
82
83 /* globals */
84 static Window *winlay_mainwindow;
85 static int curswin=0;
86 static bWindow *swinarray[MAXWIN]= {0};
87 static bWindow mainwindow, renderwindow;
88 static int mainwin_color_depth;
89
90 void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey)
91 {
92         int r, g, b;
93         
94         winlay_mainwindow= win;
95         
96         swinarray[1]= &mainwindow;
97         curswin= 1;
98
99         mainwindow.xmin= orx;
100         mainwindow.ymin= ory;
101         mainwindow.xmax= orx+sizex-1;
102         mainwindow.ymax= ory+sizey-1;
103         mainwindow.qevents= NULL;
104
105         myortho2(-0.5, (float)sizex-0.5, -0.5, (float)sizey-0.5);
106         glLoadIdentity();
107                 
108         glGetFloatv(GL_PROJECTION_MATRIX, (float *)mainwindow.winmat);
109         glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mainwindow.viewmat);
110         
111         glGetIntegerv(GL_RED_BITS, &r);
112         glGetIntegerv(GL_GREEN_BITS, &g);
113         glGetIntegerv(GL_BLUE_BITS, &b);
114
115         mainwin_color_depth= r + g + b;
116 }
117
118 /* XXXXXXXXXXXXXXXX very hacky, not allowed to release
119  * again after 2.24
120  */
121 void mywindow_build_and_set_renderwin(void)
122 {
123         glGetFloatv(GL_PROJECTION_MATRIX, (float *)renderwindow.winmat);
124         glGetFloatv(GL_MODELVIEW_MATRIX, (float *)renderwindow.viewmat);
125         
126         swinarray[2]= &renderwindow;
127         renderwindow.qevents= NULL;
128
129         curswin= 2;
130 }
131
132 /* ------------------------------------------------------------------------- */
133
134         /* XXXXX, remove later */
135 static bWindow *bwin_from_winid(int winid)
136 {
137         bWindow *bwin= swinarray[winid];
138         if (!bwin) {
139                 printf("bwin_from_winid: Internal error, bad winid: %d\n", winid);
140         }
141         return bwin;
142 }
143
144 int bwin_qtest(int winid)
145 {
146         return !BLI_gsqueue_is_empty(bwin_from_winid(winid)->qevents);
147 }
148 unsigned short bwin_qread(int winid, short *val_r, char *ascii_r)
149 {
150         if (bwin_qtest(winid)) {
151                 QEvent evt;
152                 BLI_gsqueue_pop(bwin_from_winid(winid)->qevents, &evt);
153                 *val_r= evt.val;
154                 *ascii_r= evt.ascii;
155                 return evt.event;
156         } else {
157                 *val_r= 0;
158                 return 0;
159         }
160 }
161 void bwin_qadd(int winid, unsigned short event, short val, char ascii)
162 {
163         QEvent evt;
164         evt.event= event;
165         evt.val= val;
166         evt.ascii= ascii;
167         BLI_gsqueue_push(bwin_from_winid(winid)->qevents, &evt);
168 }
169
170 /* ------------------------------------------------------------------------- */
171
172 void bwin_get_rect(int winid, rcti *rect_r)
173 {
174         bWindow *win= bwin_from_winid(winid);
175
176         rect_r->xmin= win->xmin;
177         rect_r->ymin= win->ymin;
178         rect_r->xmax= win->xmax;
179         rect_r->ymax= win->ymax;
180 }
181
182 void bwin_getsize(int win, int *x, int *y) 
183 {
184         if(win<4) {
185                 if (win==1) {
186                         window_get_size(winlay_mainwindow, x, y);
187                 } else {
188                         printf("bwin_getsize: Internal error, bad winid: %d\n", win);
189                         *x= *y= 0;
190                 }
191         } else {
192                 bWindow *bwin= swinarray[win];
193                 if (bwin) {
194                         *x= bwin->xmax-bwin->xmin+1;
195                         *y= bwin->ymax-bwin->ymin+1;
196                 }
197         }
198 }
199
200 void bwin_getsuborigin(int win, int *x, int *y)
201 {
202         if(win<4) {
203                 *x= *y= 0;      
204         } else {
205                 bWindow *bwin= swinarray[win];
206                 if (bwin) {
207                         *x= bwin->xmin;
208                         *y= bwin->ymin;
209                 }
210         }
211 }
212
213 void bwin_getsinglematrix(int winid, float mat[][4])
214 {
215         bWindow *win;
216         float matview[4][4], matproj[4][4];
217
218         win= swinarray[winid];
219         if(win==0) {
220                 glGetFloatv(GL_PROJECTION_MATRIX, (float *)matproj);
221                 glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matview);
222                 Mat4MulMat4(mat, matview, matproj);
223         }
224         else {
225                 Mat4MulMat4(mat, win->viewmat, win->winmat);
226         }
227 }
228
229 /* ------------------------------------------------------------------------- */
230
231 void bwin_load_viewmatrix(int winid, float mat[][4])
232 {
233         bWindow *win= bwin_from_winid(winid);
234         
235         glLoadMatrixf(mat);
236         Mat4CpyMat4(win->viewmat, mat);
237 }
238 void bwin_load_winmatrix(int winid, float mat[][4])
239 {
240         bWindow *win= bwin_from_winid(winid);
241
242         glLoadMatrixf(mat);
243         Mat4CpyMat4(win->winmat, mat);
244 }
245
246 void bwin_get_viewmatrix(int winid, float mat[][4])
247 {
248         bWindow *win= bwin_from_winid(winid);
249         Mat4CpyMat4(mat, win->viewmat);
250 }
251 void bwin_get_winmatrix(int winid, float mat[][4])
252 {
253         bWindow *win= bwin_from_winid(winid);
254         Mat4CpyMat4(mat, win->winmat);
255 }
256
257 void bwin_multmatrix(int winid, float mat[][4])
258 {
259         bWindow *win= bwin_from_winid(winid);
260
261         glMultMatrixf((float*) mat);
262         glGetFloatv(GL_MODELVIEW_MATRIX, (float *)win->viewmat);
263 }
264
265 void bwin_clear_viewmat(int swin)
266 {
267         bWindow *win;
268
269         win= swinarray[swin];
270         if(win==0) return;
271
272         memset(win->viewmat, 0, sizeof(win->viewmat));
273         win->viewmat[0][0]= 1.0;
274         win->viewmat[1][1]= 1.0;
275         win->viewmat[2][2]= 1.0;
276         win->viewmat[3][3]= 1.0;
277 }
278
279
280 void myloadmatrix(float mat[][4])
281 {
282         if (glaGetOneInteger(GL_MATRIX_MODE)==GL_MODELVIEW) {
283                 bwin_load_viewmatrix(curswin, mat);
284         } else {
285                 bwin_load_winmatrix(curswin, mat);
286         }
287 }
288
289 void mygetmatrix(float mat[][4])
290 {
291         if (glaGetOneInteger(GL_MATRIX_MODE)==GL_MODELVIEW) {
292                 bwin_get_viewmatrix(curswin, mat);
293         } else {
294                 bwin_get_winmatrix(curswin, mat);
295         }
296 }
297
298 void mymultmatrix(float mat[][4])
299 {
300         bwin_multmatrix(curswin, mat);
301 }
302
303 void mygetsingmatrix(float mat[][4])
304 {
305         bwin_getsinglematrix(curswin, mat);
306 }
307
308 int mywinget(void)
309 {
310         return curswin;
311 }
312
313 void mywinset(int wid)
314 {
315         bWindow *win;
316
317         win= swinarray[wid];
318         if(win==0) {
319                 printf("mywinset %d: doesn't exist\n", wid);
320                 return;
321         }
322
323         if (wid == 1) { /* main window */
324                 glViewport(0,  0, ( win->xmax-win->xmin)+1, ( win->ymax-win->ymin)+1);
325                 glScissor(0,  0, ( win->xmax-win->xmin)+1, ( win->ymax-win->ymin)+1);
326         }
327         else {
328                 int width= (win->xmax - win->xmin)+1;
329                 int height= (win->ymax - win->ymin)+1;
330
331                         /* CRITICAL, this clamping ensures that
332                          * the viewport never goes outside the screen
333                          * edges (assuming the x, y coords aren't
334                          * outside). This causes a hardware lock
335                          * on Matrox cards if it happens.
336                          * 
337                          * Really Blender should never _ever_ try
338                          * to do such a thing, but just to be safe
339                          * clamp it anyway (or fix the bScreen
340                          * scaling routine, and be damn sure you
341                          * fixed it). - zr
342                          */
343                 if (win->xmin + width>G.curscreen->sizex)
344                         width= G.curscreen->sizex - win->xmin;
345                 if (win->ymin + height>G.curscreen->sizey)
346                         height= G.curscreen->sizey - win->ymin;
347                 
348                 glViewport(win->xmin, win->ymin, width, height);
349                 glScissor(win->xmin, win->ymin, width, height);
350         }
351         
352         glMatrixMode(GL_PROJECTION);
353         glLoadMatrixf(&win->winmat[0][0]);
354         glMatrixMode(GL_MODELVIEW);
355         glLoadMatrixf(&win->viewmat[0][0]);
356
357         glFinish();
358         
359         curswin= wid;
360 }
361
362 int myswinopen(int parentid, int xmin, int xmax, int ymin, int ymax)
363 {
364         bWindow *win= NULL;
365         int freewinid;
366         
367         for (freewinid= 4; freewinid<MAXWIN; freewinid++)
368                 if (!swinarray[freewinid])
369                         break;
370         
371         if (freewinid==MAXWIN) {
372                 printf("too many windows\n");
373
374                 return 0;
375         } else {
376                 win= MEM_callocN(sizeof(*win), "winopen");
377
378                 win->id= freewinid;
379                 swinarray[win->id]= win;
380
381                 win->xmin= xmin;
382                 win->ymin= ymin;
383                 win->xmax= xmax;
384                 win->ymax= ymax;
385         
386                 win->qevents= BLI_gsqueue_new(sizeof(QEvent));
387
388                 Mat4One(win->viewmat);
389                 Mat4One(win->winmat);
390         
391                 mywinset(win->id);
392
393                 return win->id;
394         }
395 }
396
397 void mywinclose(int winid)
398 {
399         if (winid<4) {
400                 if (winid==1) {
401                         window_destroy(winlay_mainwindow);
402                         winlay_mainwindow= NULL;
403                 } else {
404                         printf("mwinclose: Internal error, bad winid: %d\n", winid);
405                 }
406         } else {
407                 bWindow *win= swinarray[winid];
408
409                 if (win) {
410                         BLI_gsqueue_free(win->qevents);
411                         MEM_freeN(win);
412                 } else {
413                         printf("mwinclose: Internal error, bad winid: %d\n", winid);
414                 }
415         }
416
417         swinarray[winid]= 0;
418         if (curswin==winid) curswin= 0;
419 }
420
421 void mywinposition(int winid, int xmin, int xmax, int ymin, int ymax) /* let op: andere syntax */
422 {
423         bWindow *win= bwin_from_winid(winid);
424         
425         win->xmin= xmin;
426         win->ymin= ymin;
427         win->xmax= xmax;
428         win->ymax= ymax;
429 }
430
431
432 void bwin_ortho(int winid, float x1, float x2, float y1, float y2, float n, float f)
433 {
434         bWindow *bwin= bwin_from_winid(winid);
435         
436         glMatrixMode(GL_PROJECTION);
437         glLoadIdentity();
438         glOrtho(x1, x2, y1, y2, n, f);
439
440         glGetFloatv(GL_PROJECTION_MATRIX, (float *)bwin->winmat);
441         glMatrixMode(GL_MODELVIEW);
442 }
443
444 void bwin_ortho2(int win, float x1, float x2, float y1, float y2)
445 {
446         bwin_ortho(win, x1, x2, y1, y2, -1, 1);
447 }
448
449 void bwin_frustum(int winid, float x1, float x2, float y1, float y2, float n, float f)
450 {
451         bWindow *win= bwin_from_winid(winid);
452
453         glMatrixMode(GL_PROJECTION);
454         glLoadIdentity();
455         glFrustum(x1, x2, y1, y2, n, f);
456
457         glGetFloatv(GL_PROJECTION_MATRIX, (float *)win->winmat);
458         glMatrixMode(GL_MODELVIEW);
459 }
460
461 void myortho(float x1, float x2, float y1, float y2, float n, float f)
462 {
463         bwin_ortho(curswin, x1, x2, y1, y2, n, f);
464 }
465
466 void myortho2(float x1, float x2, float y1, float y2)
467 {
468         bwin_ortho(curswin, x1, x2, y1, y2, -1, 1);
469 }
470
471 void mywindow(float x1, float x2, float y1, float y2, float n, float f)
472 {
473         bwin_frustum(curswin, x1, x2, y1, y2, n, f);
474 }
475
476 unsigned int index_to_framebuffer(int index)
477 {
478         unsigned int i= index;
479
480         switch(mainwin_color_depth) {
481         case 8:
482                 i= ((i & 48)<<18) + ((i & 12)<<12) + ((i & 3)<<6);
483                 i |= 0x3F3F3F;
484                 break;
485         case 12:
486                 i= ((i & 0xF00)<<12) + ((i & 0xF0)<<8) + ((i & 0xF)<<4);
487                 /* sometimes dithering subtracts! */
488                 i |= 0x0F0F0F;
489                 break;
490         case 15:
491         case 16:
492                 i= ((i & 0x7C00)<<9) + ((i & 0x3E0)<<6) + ((i & 0x1F)<<3);
493                 i |= 0x070707;
494                 break;
495         default:
496                 i= ((i & 0x3F000)<<6) + ((i & 0xFC0)<<4) + ((i & 0x3F)<<2);
497                 i |= 0x030303;
498                 break;
499         }
500         
501         return i;
502 }
503
504 int framebuffer_to_index(unsigned int col)
505 {
506         if (col==0) return 0;
507
508         switch(mainwin_color_depth) {
509         case 8:
510                 return ((col & 0xC00000)>>18) + ((col & 0xC000)>>12) + ((col & 0xC0)>>6);
511         case 12:
512                 return ((col & 0xF00000)>>12) + ((col & 0xF000)>>8) + ((col & 0xF0)>>4);
513         case 15:
514         case 16:
515                 return ((col & 0xF80000)>>9) + ((col & 0xF800)>>6) + ((col & 0xF8)>>3);
516         default:
517                 return ((col & 0xFC0000)>>6) + ((col & 0xFC00)>>4) + ((col & 0xFC)>>2);
518         }               
519 }
520
521
522 /* ********** END MY WINDOW ************** */
523
524 #ifdef WIN32
525 static int is_a_really_crappy_nvidia_card(void) {
526         static int well_is_it= -1;
527
528                 /* Do you understand the implication? Do you? */
529         if (well_is_it==-1)
530                 well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0);
531
532         return well_is_it;
533 }
534 #endif
535
536 void myswapbuffers(void)
537 {
538         ScrArea *sa;
539         
540         sa= G.curscreen->areabase.first;
541         while(sa) {
542                 if(sa->win_swap==WIN_BACK_OK) sa->win_swap= WIN_FRONT_OK;
543                 if(sa->head_swap==WIN_BACK_OK) sa->head_swap= WIN_FRONT_OK;
544                 
545                 sa= sa->next;
546         }
547
548         /* HACK, some windows drivers feel they should honor the scissor
549          * test when swapping buffers, disable the test while swapping
550          * on WIN32. (namely Matrox and NVidia's new drivers around Oct 1 2001)
551          * - zr
552          */
553
554 #ifdef WIN32
555                 /* HACK, in some NVidia driver release some kind of
556                  * fancy optimiziation (I presume) was put in which for
557                  * some reason causes parts of the buffer not to be
558                  * swapped. One way to defeat it is the following wierd
559                  * code (which we only do for nvidia cards). This should
560                  * be removed if NVidia fixes their drivers. - zr
561                  */
562         if (is_a_really_crappy_nvidia_card()) {
563                 glDrawBuffer(GL_FRONT);
564
565                 glBegin(GL_LINES);
566                 glEnd();
567
568                 glDrawBuffer(GL_BACK);
569         }
570
571         glDisable(GL_SCISSOR_TEST);
572         window_swap_buffers(winlay_mainwindow);
573         glEnable(GL_SCISSOR_TEST);
574 #else
575         window_swap_buffers(winlay_mainwindow);
576 #endif
577 }
578
579
580 /* *********************** PATTERNS ENZO ***************** */
581
582 void setlinestyle(int nr)
583 {
584         if(nr==0) {
585                 glDisable(GL_LINE_STIPPLE);
586         }
587         else {
588                 
589                 glEnable(GL_LINE_STIPPLE);
590                 glLineStipple(nr, 0xAAAA);
591         }
592 }
593
594 /*******************/
595 /*******************/
596 /*  Menu utilities */
597
598 static int *frontbuffer_save= NULL;
599 static int ov_x, ov_y, ov_sx, ov_sy;
600
601 void my_put_frontbuffer_image(void)
602 {
603         if (frontbuffer_save) {
604                 glRasterPos2f( (float)ov_x -0.5,  (float)ov_y - 0.5 );
605                 glDrawPixels(ov_sx, ov_sy, GL_RGBA, GL_UNSIGNED_BYTE, frontbuffer_save);
606                 MEM_freeN(frontbuffer_save);
607                 frontbuffer_save= NULL;
608         }
609 }
610
611 void my_get_frontbuffer_image(int x, int y, int sx, int sy)
612 {
613         if(frontbuffer_save) return;
614
615         ov_x= x;
616         ov_y= y;
617         ov_sx= sx;
618         ov_sy= sy;
619         
620         if(sx>1 && sy>1) {
621                 frontbuffer_save= MEM_mallocN(sx*sy*4, "temp_frontbuffer_image");
622                 glReadPixels(x, y, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, frontbuffer_save);
623         }
624
625         #ifdef WIN32
626         /* ander coordinatensysteem! */
627         y= (G.curscreen->sizey-y);
628         
629         if(curswin>3) {
630                 y -= curarea->winrct.ymin;
631         }
632         #endif
633 }
634
635 int mywin_inmenu(void) {
636         return frontbuffer_save?1:0;
637 }
638
639 void mywin_getmenu_rect(int *x, int *y, int *sx, int *sy) {
640         *x= ov_x;
641         *sx= ov_sx;
642         *sy= ov_sy;
643
644 #if defined(WIN32) || defined (__BeOS)
645         *y= ov_y;
646 #else
647         *y= (G.curscreen->sizey - ov_y) - ov_sy;
648 #endif  
649 }