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