/** * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** * vervanging voor een aantal fie's zoals swinopen, winset, (zie onder) * dit alles omdat GL en X te traag zijn * feb: Opengl en toch maar naar X! */ #include #ifdef WIN32 #include "BLI_winstuff.h" #endif #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" #include "BLI_gsqueue.h" #include "DNA_screen_types.h" #include "BKE_global.h" #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "mydevice.h" #include "blendef.h" #include "winlay.h" typedef struct { unsigned short event; short val; char ascii; } QEvent; typedef struct { struct bWindow *next, *prev; int id, pad; int xmin, xmax, ymin, ymax; float viewmat[4][4], winmat[4][4]; GSQueue *qevents; } bWindow; /* globals */ static Window *winlay_mainwindow; static int curswin=0; static bWindow *swinarray[MAXWIN]= {0}; static bWindow mainwindow, renderwindow; static int mainwin_color_depth; void mywindow_init_mainwin(Window *win, int orx, int ory, int sizex, int sizey) { int r, g, b; winlay_mainwindow= win; swinarray[1]= &mainwindow; curswin= 1; mainwindow.xmin= orx; mainwindow.ymin= ory; mainwindow.xmax= orx+sizex-1; mainwindow.ymax= ory+sizey-1; mainwindow.qevents= NULL; myortho2(-0.5, (float)sizex-0.5, -0.5, (float)sizey-0.5); glLoadIdentity(); glGetFloatv(GL_PROJECTION_MATRIX, (float *)mainwindow.winmat); glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mainwindow.viewmat); glGetIntegerv(GL_RED_BITS, &r); glGetIntegerv(GL_GREEN_BITS, &g); glGetIntegerv(GL_BLUE_BITS, &b); mainwin_color_depth= r + g + b; } /* XXXXXXXXXXXXXXXX very hacky, not allowed to release * again after 2.24 */ void mywindow_build_and_set_renderwin(void) { glGetFloatv(GL_PROJECTION_MATRIX, (float *)renderwindow.winmat); glGetFloatv(GL_MODELVIEW_MATRIX, (float *)renderwindow.viewmat); swinarray[2]= &renderwindow; renderwindow.qevents= NULL; curswin= 2; } /* ------------------------------------------------------------------------- */ /* XXXXX, remove later */ static bWindow *bwin_from_winid(int winid) { bWindow *bwin= swinarray[winid]; if (!bwin) { printf("bwin_from_winid: Internal error, bad winid: %d\n", winid); } return bwin; } int bwin_qtest(int winid) { return !BLI_gsqueue_is_empty(bwin_from_winid(winid)->qevents); } unsigned short bwin_qread(int winid, short *val_r, char *ascii_r) { if (bwin_qtest(winid)) { QEvent evt; BLI_gsqueue_pop(bwin_from_winid(winid)->qevents, &evt); *val_r= evt.val; *ascii_r= evt.ascii; return evt.event; } else { *val_r= 0; return 0; } } void bwin_qadd(int winid, unsigned short event, short val, char ascii) { QEvent evt; evt.event= event; evt.val= val; evt.ascii= ascii; BLI_gsqueue_push(bwin_from_winid(winid)->qevents, &evt); } /* ------------------------------------------------------------------------- */ void bwin_get_rect(int winid, rcti *rect_r) { bWindow *win= bwin_from_winid(winid); rect_r->xmin= win->xmin; rect_r->ymin= win->ymin; rect_r->xmax= win->xmax; rect_r->ymax= win->ymax; } void bwin_getsize(int win, int *x, int *y) { if(win<4) { if (win==1) { window_get_size(winlay_mainwindow, x, y); } else { printf("bwin_getsize: Internal error, bad winid: %d\n", win); *x= *y= 0; } } else { bWindow *bwin= swinarray[win]; if (bwin) { *x= bwin->xmax-bwin->xmin+1; *y= bwin->ymax-bwin->ymin+1; } } } void bwin_getsuborigin(int win, int *x, int *y) { if(win<4) { *x= *y= 0; } else { bWindow *bwin= swinarray[win]; if (bwin) { *x= bwin->xmin; *y= bwin->ymin; } } } void bwin_getsinglematrix(int winid, float mat[][4]) { bWindow *win; float matview[4][4], matproj[4][4]; win= swinarray[winid]; if(win==0) { glGetFloatv(GL_PROJECTION_MATRIX, (float *)matproj); glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matview); Mat4MulMat4(mat, matview, matproj); } else { Mat4MulMat4(mat, win->viewmat, win->winmat); } } /* ------------------------------------------------------------------------- */ void bwin_load_viewmatrix(int winid, float mat[][4]) { bWindow *win= bwin_from_winid(winid); glLoadMatrixf(mat); Mat4CpyMat4(win->viewmat, mat); } void bwin_load_winmatrix(int winid, float mat[][4]) { bWindow *win= bwin_from_winid(winid); glLoadMatrixf(mat); Mat4CpyMat4(win->winmat, mat); } void bwin_get_viewmatrix(int winid, float mat[][4]) { bWindow *win= bwin_from_winid(winid); Mat4CpyMat4(mat, win->viewmat); } void bwin_get_winmatrix(int winid, float mat[][4]) { bWindow *win= bwin_from_winid(winid); Mat4CpyMat4(mat, win->winmat); } void bwin_multmatrix(int winid, float mat[][4]) { bWindow *win= bwin_from_winid(winid); glMultMatrixf((float*) mat); glGetFloatv(GL_MODELVIEW_MATRIX, (float *)win->viewmat); } void bwin_clear_viewmat(int swin) { bWindow *win; win= swinarray[swin]; if(win==0) return; memset(win->viewmat, 0, sizeof(win->viewmat)); win->viewmat[0][0]= 1.0; win->viewmat[1][1]= 1.0; win->viewmat[2][2]= 1.0; win->viewmat[3][3]= 1.0; } void myloadmatrix(float mat[][4]) { if (glaGetOneInteger(GL_MATRIX_MODE)==GL_MODELVIEW) { bwin_load_viewmatrix(curswin, mat); } else { bwin_load_winmatrix(curswin, mat); } } void mygetmatrix(float mat[][4]) { if (glaGetOneInteger(GL_MATRIX_MODE)==GL_MODELVIEW) { bwin_get_viewmatrix(curswin, mat); } else { bwin_get_winmatrix(curswin, mat); } } void mymultmatrix(float mat[][4]) { bwin_multmatrix(curswin, mat); } void mygetsingmatrix(float mat[][4]) { bwin_getsinglematrix(curswin, mat); } int mywinget(void) { return curswin; } void mywinset(int wid) { bWindow *win; win= swinarray[wid]; if(win==0) { printf("mywinset %d: doesn't exist\n", wid); return; } if (wid == 1) { /* main window */ glViewport(0, 0, ( win->xmax-win->xmin)+1, ( win->ymax-win->ymin)+1); glScissor(0, 0, ( win->xmax-win->xmin)+1, ( win->ymax-win->ymin)+1); } else { int width= (win->xmax - win->xmin)+1; int height= (win->ymax - win->ymin)+1; /* CRITICAL, this clamping ensures that * the viewport never goes outside the screen * edges (assuming the x, y coords aren't * outside). This causes a hardware lock * on Matrox cards if it happens. * * Really Blender should never _ever_ try * to do such a thing, but just to be safe * clamp it anyway (or fix the bScreen * scaling routine, and be damn sure you * fixed it). - zr */ if (win->xmin + width>G.curscreen->sizex) width= G.curscreen->sizex - win->xmin; if (win->ymin + height>G.curscreen->sizey) height= G.curscreen->sizey - win->ymin; glViewport(win->xmin, win->ymin, width, height); glScissor(win->xmin, win->ymin, width, height); } glMatrixMode(GL_PROJECTION); glLoadMatrixf(&win->winmat[0][0]); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(&win->viewmat[0][0]); glFinish(); curswin= wid; } int myswinopen(int parentid, int xmin, int xmax, int ymin, int ymax) { bWindow *win= NULL; int freewinid; for (freewinid= 4; freewinidid= freewinid; swinarray[win->id]= win; win->xmin= xmin; win->ymin= ymin; win->xmax= xmax; win->ymax= ymax; win->qevents= BLI_gsqueue_new(sizeof(QEvent)); Mat4One(win->viewmat); Mat4One(win->winmat); mywinset(win->id); return win->id; } } void mywinclose(int winid) { if (winid<4) { if (winid==1) { window_destroy(winlay_mainwindow); winlay_mainwindow= NULL; } else { printf("mwinclose: Internal error, bad winid: %d\n", winid); } } else { bWindow *win= swinarray[winid]; if (win) { BLI_gsqueue_free(win->qevents); MEM_freeN(win); } else { printf("mwinclose: Internal error, bad winid: %d\n", winid); } } swinarray[winid]= 0; if (curswin==winid) curswin= 0; } void mywinposition(int winid, int xmin, int xmax, int ymin, int ymax) /* let op: andere syntax */ { bWindow *win= bwin_from_winid(winid); win->xmin= xmin; win->ymin= ymin; win->xmax= xmax; win->ymax= ymax; } void bwin_ortho(int winid, float x1, float x2, float y1, float y2, float n, float f) { bWindow *bwin= bwin_from_winid(winid); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(x1, x2, y1, y2, n, f); glGetFloatv(GL_PROJECTION_MATRIX, (float *)bwin->winmat); glMatrixMode(GL_MODELVIEW); } void bwin_ortho2(int win, float x1, float x2, float y1, float y2) { bwin_ortho(win, x1, x2, y1, y2, -1, 1); } void bwin_frustum(int winid, float x1, float x2, float y1, float y2, float n, float f) { bWindow *win= bwin_from_winid(winid); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(x1, x2, y1, y2, n, f); glGetFloatv(GL_PROJECTION_MATRIX, (float *)win->winmat); glMatrixMode(GL_MODELVIEW); } void myortho(float x1, float x2, float y1, float y2, float n, float f) { bwin_ortho(curswin, x1, x2, y1, y2, n, f); } void myortho2(float x1, float x2, float y1, float y2) { bwin_ortho(curswin, x1, x2, y1, y2, -1, 1); } void mywindow(float x1, float x2, float y1, float y2, float n, float f) { bwin_frustum(curswin, x1, x2, y1, y2, n, f); } unsigned int index_to_framebuffer(int index) { unsigned int i= index; switch(mainwin_color_depth) { case 8: i= ((i & 48)<<18) + ((i & 12)<<12) + ((i & 3)<<6); i |= 0x3F3F3F; break; case 12: i= ((i & 0xF00)<<12) + ((i & 0xF0)<<8) + ((i & 0xF)<<4); /* sometimes dithering subtracts! */ i |= 0x0F0F0F; break; case 15: case 16: i= ((i & 0x7C00)<<9) + ((i & 0x3E0)<<6) + ((i & 0x1F)<<3); i |= 0x070707; break; default: i= ((i & 0x3F000)<<6) + ((i & 0xFC0)<<4) + ((i & 0x3F)<<2); i |= 0x030303; break; } return i; } int framebuffer_to_index(unsigned int col) { if (col==0) return 0; switch(mainwin_color_depth) { case 8: return ((col & 0xC00000)>>18) + ((col & 0xC000)>>12) + ((col & 0xC0)>>6); case 12: return ((col & 0xF00000)>>12) + ((col & 0xF000)>>8) + ((col & 0xF0)>>4); case 15: case 16: return ((col & 0xF80000)>>9) + ((col & 0xF800)>>6) + ((col & 0xF8)>>3); default: return ((col & 0xFC0000)>>6) + ((col & 0xFC00)>>4) + ((col & 0xFC)>>2); } } /* ********** END MY WINDOW ************** */ #ifdef WIN32 static int is_a_really_crappy_nvidia_card(void) { static int well_is_it= -1; /* Do you understand the implication? Do you? */ if (well_is_it==-1) well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); return well_is_it; } #endif void myswapbuffers(void) { ScrArea *sa; sa= G.curscreen->areabase.first; while(sa) { if(sa->win_swap==WIN_BACK_OK) sa->win_swap= WIN_FRONT_OK; if(sa->head_swap==WIN_BACK_OK) sa->head_swap= WIN_FRONT_OK; sa= sa->next; } /* HACK, some windows drivers feel they should honor the scissor * test when swapping buffers, disable the test while swapping * on WIN32. (namely Matrox and NVidia's new drivers around Oct 1 2001) * - zr */ #ifdef WIN32 /* HACK, in some NVidia driver release some kind of * fancy optimiziation (I presume) was put in which for * some reason causes parts of the buffer not to be * swapped. One way to defeat it is the following wierd * code (which we only do for nvidia cards). This should * be removed if NVidia fixes their drivers. - zr */ if (is_a_really_crappy_nvidia_card()) { glDrawBuffer(GL_FRONT); glBegin(GL_LINES); glEnd(); glDrawBuffer(GL_BACK); } glDisable(GL_SCISSOR_TEST); window_swap_buffers(winlay_mainwindow); glEnable(GL_SCISSOR_TEST); #else window_swap_buffers(winlay_mainwindow); #endif } /* *********************** PATTERNS ENZO ***************** */ void setlinestyle(int nr) { if(nr==0) { glDisable(GL_LINE_STIPPLE); } else { glEnable(GL_LINE_STIPPLE); glLineStipple(nr, 0xAAAA); } } /*******************/ /*******************/ /* Menu utilities */ static int *frontbuffer_save= NULL; static int ov_x, ov_y, ov_sx, ov_sy; void my_put_frontbuffer_image(void) { if (frontbuffer_save) { glRasterPos2f( (float)ov_x -0.5, (float)ov_y - 0.5 ); glDrawPixels(ov_sx, ov_sy, GL_RGBA, GL_UNSIGNED_BYTE, frontbuffer_save); MEM_freeN(frontbuffer_save); frontbuffer_save= NULL; } } void my_get_frontbuffer_image(int x, int y, int sx, int sy) { if(frontbuffer_save) return; ov_x= x; ov_y= y; ov_sx= sx; ov_sy= sy; if(sx>1 && sy>1) { frontbuffer_save= MEM_mallocN(sx*sy*4, "temp_frontbuffer_image"); glReadPixels(x, y, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, frontbuffer_save); } #ifdef WIN32 /* ander coordinatensysteem! */ y= (G.curscreen->sizey-y); if(curswin>3) { y -= curarea->winrct.ymin; } #endif } int mywin_inmenu(void) { return frontbuffer_save?1:0; } void mywin_getmenu_rect(int *x, int *y, int *sx, int *sy) { *x= ov_x; *sx= ov_sx; *sy= ov_sy; #if defined(WIN32) || defined (__BeOS) *y= ov_y; #else *y= (G.curscreen->sizey - ov_y) - ov_sy; #endif }