Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): 2007 Blender Foundation (refactor) 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 * 00025 * 00026 * Subwindow opengl handling. 00027 * BTW: subwindows open/close in X11 are way too slow, tried it, and choose for my own system... (ton) 00028 * 00029 */ 00030 00036 #include <string.h> 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "DNA_windowmanager_types.h" 00041 #include "DNA_screen_types.h" 00042 00043 #include "BLI_blenlib.h" 00044 #include "BLI_math.h" 00045 #include "BLI_utildefines.h" 00046 00047 00048 #include "BKE_context.h" 00049 #include "BKE_global.h" 00050 00051 #include "BIF_gl.h" 00052 00053 #include "GPU_extensions.h" 00054 00055 #include "WM_api.h" 00056 #include "wm_subwindow.h" 00057 #include "wm_window.h" 00058 00059 /* wmSubWindow stored in wmWindow... but not exposed outside this C file */ 00060 /* it seems a bit redundant (area regions can store it too, but we keep it 00061 because we can store all kind of future opengl fanciness here */ 00062 00063 /* we use indices and array because: 00064 - index has safety, no pointers from this C file hanging around 00065 - fast lookups of indices with array, list would give overhead 00066 - old code used it this way... 00067 - keep option open to have 2 screens using same window 00068 */ 00069 00070 typedef struct wmSubWindow { 00071 struct wmSubWindow *next, *prev; 00072 00073 rcti winrct; 00074 int swinid; 00075 } wmSubWindow; 00076 00077 00078 /* ******************* open, free, set, get data ******************** */ 00079 00080 /* not subwindow itself */ 00081 static void wm_subwindow_free(wmSubWindow *UNUSED(swin)) 00082 { 00083 /* future fancy stuff */ 00084 } 00085 00086 void wm_subwindows_free(wmWindow *win) 00087 { 00088 wmSubWindow *swin; 00089 00090 for(swin= win->subwindows.first; swin; swin= swin->next) 00091 wm_subwindow_free(swin); 00092 00093 BLI_freelistN(&win->subwindows); 00094 } 00095 00096 00097 int wm_subwindow_get(wmWindow *win) 00098 { 00099 if(win->curswin) 00100 return win->curswin->swinid; 00101 return 0; 00102 } 00103 00104 static wmSubWindow *swin_from_swinid(wmWindow *win, int swinid) 00105 { 00106 wmSubWindow *swin; 00107 00108 for(swin= win->subwindows.first; swin; swin= swin->next) 00109 if(swin->swinid==swinid) 00110 break; 00111 return swin; 00112 } 00113 00114 void wm_subwindow_getsize(wmWindow *win, int swinid, int *x, int *y) 00115 { 00116 wmSubWindow *swin= swin_from_swinid(win, swinid); 00117 00118 if(swin) { 00119 *x= swin->winrct.xmax - swin->winrct.xmin + 1; 00120 *y= swin->winrct.ymax - swin->winrct.ymin + 1; 00121 } 00122 } 00123 00124 void wm_subwindow_getorigin(wmWindow *win, int swinid, int *x, int *y) 00125 { 00126 wmSubWindow *swin= swin_from_swinid(win, swinid); 00127 00128 if(swin) { 00129 *x= swin->winrct.xmin; 00130 *y= swin->winrct.ymin; 00131 } 00132 } 00133 00134 void wm_subwindow_getmatrix(wmWindow *win, int swinid, float mat[][4]) 00135 { 00136 wmSubWindow *swin= swin_from_swinid(win, swinid); 00137 00138 if(swin) { 00139 /* used by UI, should find a better way to get the matrix there */ 00140 if(swinid == win->screen->mainwin) { 00141 int width, height; 00142 00143 wm_subwindow_getsize(win, swin->swinid, &width, &height); 00144 orthographic_m4(mat, -0.375f, (float)width-0.375f, -0.375f, (float)height-0.375f, -100, 100); 00145 } 00146 else 00147 glGetFloatv(GL_PROJECTION_MATRIX, (float*)mat); 00148 } 00149 } 00150 00151 /* always sets pixel-precise 2D window/view matrices */ 00152 /* coords is in whole pixels. xmin = 15, xmax= 16: means window is 2 pix big */ 00153 int wm_subwindow_open(wmWindow *win, rcti *winrct) 00154 { 00155 wmSubWindow *swin; 00156 int width, height; 00157 int freewinid= 1; 00158 00159 for(swin= win->subwindows.first; swin; swin= swin->next) 00160 if(freewinid <= swin->swinid) 00161 freewinid= swin->swinid+1; 00162 00163 win->curswin= swin= MEM_callocN(sizeof(wmSubWindow), "swinopen"); 00164 BLI_addtail(&win->subwindows, swin); 00165 00166 if(G.f & G_DEBUG) printf("swin %d added\n", freewinid); 00167 swin->swinid= freewinid; 00168 swin->winrct= *winrct; 00169 00170 /* and we appy it all right away */ 00171 wmSubWindowSet(win, swin->swinid); 00172 00173 /* extra service */ 00174 wm_subwindow_getsize(win, swin->swinid, &width, &height); 00175 wmOrtho2(-0.375f, (float)width-0.375f, -0.375f, (float)height-0.375f); 00176 glLoadIdentity(); 00177 00178 return swin->swinid; 00179 } 00180 00181 00182 void wm_subwindow_close(wmWindow *win, int swinid) 00183 { 00184 wmSubWindow *swin= swin_from_swinid(win, swinid); 00185 00186 if (swin) { 00187 if (swin==win->curswin) 00188 win->curswin= NULL; 00189 wm_subwindow_free(swin); 00190 BLI_remlink(&win->subwindows, swin); 00191 MEM_freeN(swin); 00192 } 00193 else { 00194 printf("wm_subwindow_close: Internal error, bad winid: %d\n", swinid); 00195 } 00196 00197 } 00198 00199 /* pixels go from 0-99 for a 100 pixel window */ 00200 void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct) 00201 { 00202 wmSubWindow *swin= swin_from_swinid(win, swinid); 00203 00204 if(swin) { 00205 int width, height; 00206 00207 swin->winrct= *winrct; 00208 00209 /* CRITICAL, this clamping ensures that 00210 * the viewport never goes outside the screen 00211 * edges (assuming the x, y coords aren't 00212 * outside). This caused a hardware lock 00213 * on Matrox cards if it happens. 00214 * 00215 * Really Blender should never _ever_ try 00216 * to do such a thing, but just to be safe 00217 * clamp it anyway (or fix the bScreen 00218 * scaling routine, and be damn sure you 00219 * fixed it). - zr (2001!) 00220 */ 00221 00222 if (swin->winrct.xmax > win->sizex) 00223 swin->winrct.xmax= win->sizex; 00224 if (swin->winrct.ymax > win->sizey) 00225 swin->winrct.ymax= win->sizey; 00226 00227 /* extra service */ 00228 wmSubWindowSet(win, swinid); 00229 wm_subwindow_getsize(win, swinid, &width, &height); 00230 wmOrtho2(-0.375f, (float)width-0.375f, -0.375f, (float)height-0.375f); 00231 } 00232 else { 00233 printf("wm_subwindow_position: Internal error, bad winid: %d\n", swinid); 00234 } 00235 } 00236 00237 /* ---------------- WM versions of OpenGL calls, using glBlah() syntax ------------------------ */ 00238 /* ----------------- exported in WM_api.h ------------------------------------------------------ */ 00239 00240 /* internal state, no threaded opengl! XXX */ 00241 static wmWindow *_curwindow= NULL; 00242 static wmSubWindow *_curswin= NULL; 00243 00244 void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct) 00245 { 00246 int width, height; 00247 _curswin= swin_from_swinid(win, swinid); 00248 00249 if(_curswin==NULL) { 00250 printf("wmSubWindowSet %d: doesn't exist\n", swinid); 00251 return; 00252 } 00253 00254 win->curswin= _curswin; 00255 _curwindow= win; 00256 00257 width= _curswin->winrct.xmax - _curswin->winrct.xmin + 1; 00258 height= _curswin->winrct.ymax - _curswin->winrct.ymin + 1; 00259 glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height); 00260 00261 if(srct) { 00262 width= srct->xmax - srct->xmin + 1; 00263 height= srct->ymax - srct->ymin + 1; 00264 glScissor(srct->xmin, srct->ymin, width, height); 00265 } 00266 else 00267 glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height); 00268 00269 wmOrtho2(-0.375f, (float)width-0.375f, -0.375f, (float)height-0.375f); 00270 glLoadIdentity(); 00271 00272 glFlush(); 00273 } 00274 00275 00276 /* enable the WM versions of opengl calls */ 00277 void wmSubWindowSet(wmWindow *win, int swinid) 00278 { 00279 wmSubWindowScissorSet(win, swinid, NULL); 00280 } 00281 00282 void wmFrustum(float x1, float x2, float y1, float y2, float n, float f) 00283 { 00284 glMatrixMode(GL_PROJECTION); 00285 glLoadIdentity(); 00286 glFrustum(x1, x2, y1, y2, n, f); 00287 glMatrixMode(GL_MODELVIEW); 00288 } 00289 00290 void wmOrtho(float x1, float x2, float y1, float y2, float n, float f) 00291 { 00292 glMatrixMode(GL_PROJECTION); 00293 glLoadIdentity(); 00294 00295 glOrtho(x1, x2, y1, y2, n, f); 00296 00297 glMatrixMode(GL_MODELVIEW); 00298 } 00299 00300 void wmOrtho2(float x1, float x2, float y1, float y2) 00301 { 00302 /* prevent opengl from generating errors */ 00303 if(x1==x2) x2+=1.0f; 00304 if(y1==y2) y2+=1.0f; 00305 00306 wmOrtho(x1, x2, y1, y2, -100, 100); 00307 } 00308 00309 /* *************************** Framebuffer color depth, for selection codes ********************** */ 00310 00311 #ifdef __APPLE__ 00312 00313 /* apple seems to round colors to below and up on some configs */ 00314 00315 unsigned int index_to_framebuffer(int index) 00316 { 00317 unsigned int i= index; 00318 00319 switch(GPU_color_depth()) { 00320 case 12: 00321 i= ((i & 0xF00)<<12) + ((i & 0xF0)<<8) + ((i & 0xF)<<4); 00322 /* sometimes dithering subtracts! */ 00323 i |= 0x070707; 00324 break; 00325 case 15: 00326 case 16: 00327 i= ((i & 0x7C00)<<9) + ((i & 0x3E0)<<6) + ((i & 0x1F)<<3); 00328 i |= 0x030303; 00329 break; 00330 case 24: 00331 break; 00332 default: // 18 bits... 00333 i= ((i & 0x3F000)<<6) + ((i & 0xFC0)<<4) + ((i & 0x3F)<<2); 00334 i |= 0x010101; 00335 break; 00336 } 00337 00338 return i; 00339 } 00340 00341 #else 00342 00343 /* this is the old method as being in use for ages.... seems to work? colors are rounded to lower values */ 00344 00345 unsigned int index_to_framebuffer(int index) 00346 { 00347 unsigned int i= index; 00348 00349 switch(GPU_color_depth()) { 00350 case 8: 00351 i= ((i & 48)<<18) + ((i & 12)<<12) + ((i & 3)<<6); 00352 i |= 0x3F3F3F; 00353 break; 00354 case 12: 00355 i= ((i & 0xF00)<<12) + ((i & 0xF0)<<8) + ((i & 0xF)<<4); 00356 /* sometimes dithering subtracts! */ 00357 i |= 0x0F0F0F; 00358 break; 00359 case 15: 00360 case 16: 00361 i= ((i & 0x7C00)<<9) + ((i & 0x3E0)<<6) + ((i & 0x1F)<<3); 00362 i |= 0x070707; 00363 break; 00364 case 24: 00365 break; 00366 default: // 18 bits... 00367 i= ((i & 0x3F000)<<6) + ((i & 0xFC0)<<4) + ((i & 0x3F)<<2); 00368 i |= 0x030303; 00369 break; 00370 } 00371 00372 return i; 00373 } 00374 00375 #endif 00376 00377 void WM_set_framebuffer_index_color(int index) 00378 { 00379 const int col= index_to_framebuffer(index); 00380 cpack(col); 00381 } 00382 00383 int WM_framebuffer_to_index(unsigned int col) 00384 { 00385 if (col==0) return 0; 00386 00387 switch(GPU_color_depth()) { 00388 case 8: 00389 return ((col & 0xC00000)>>18) + ((col & 0xC000)>>12) + ((col & 0xC0)>>6); 00390 case 12: 00391 return ((col & 0xF00000)>>12) + ((col & 0xF000)>>8) + ((col & 0xF0)>>4); 00392 case 15: 00393 case 16: 00394 return ((col & 0xF80000)>>9) + ((col & 0xF800)>>6) + ((col & 0xF8)>>3); 00395 case 24: 00396 return col & 0xFFFFFF; 00397 default: // 18 bits... 00398 return ((col & 0xFC0000)>>6) + ((col & 0xFC00)>>4) + ((col & 0xFC)>>2); 00399 } 00400 } 00401 00402 00403 /* ********** END MY WINDOW ************** */ 00404