|
Blender
V2.59
|
00001 /* 00002 * $Id: glutil.c 38978 2011-08-03 09:28:16Z 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): Blender Foundation 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdio.h> 00034 #include <string.h> 00035 00036 #include "MEM_guardedalloc.h" 00037 00038 #include "DNA_vec_types.h" 00039 00040 #include "BLI_utildefines.h" 00041 00042 #include "BKE_colortools.h" 00043 00044 #include "BLI_math.h" 00045 #include "BLI_threads.h" 00046 00047 #include "BIF_gl.h" 00048 #include "BIF_glutil.h" 00049 00050 #ifndef GL_CLAMP_TO_EDGE 00051 #define GL_CLAMP_TO_EDGE 0x812F 00052 #endif 00053 00054 00055 /* ******************************************** */ 00056 00057 /* defined in BIF_gl.h */ 00058 GLubyte stipple_halftone[128] = { 00059 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00060 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00061 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00062 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00063 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00064 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00065 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00066 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00067 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00068 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00069 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00070 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00071 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00072 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00073 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 00074 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55}; 00075 00076 00077 /* repeat this pattern 00078 X000X000 00079 00000000 00080 00X000X0 00081 00000000 */ 00082 00083 00084 GLubyte stipple_quarttone[128] = { 00085 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00086 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00087 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00088 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00089 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00090 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00091 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0, 00092 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0}; 00093 00094 00095 GLubyte stipple_diag_stripes_pos[128] = { 00096 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00097 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00098 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00099 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, 00100 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00101 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00102 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00103 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, 00104 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00105 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00106 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00107 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, 00108 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00109 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00110 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00111 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f}; 00112 00113 00114 GLubyte stipple_diag_stripes_neg[128] = { 00115 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00116 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00117 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00118 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, 00119 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00120 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00121 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00122 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, 00123 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, 00124 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, 00125 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, 00126 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, 00127 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, 00128 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, 00129 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, 00130 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80}; 00131 00132 00133 void fdrawbezier(float vec[4][3]) 00134 { 00135 float dist; 00136 float curve_res = 24, spline_step = 0.0f; 00137 00138 dist= 0.5f*ABS(vec[0][0] - vec[3][0]); 00139 00140 /* check direction later, for top sockets */ 00141 vec[1][0]= vec[0][0]+dist; 00142 vec[1][1]= vec[0][1]; 00143 00144 vec[2][0]= vec[3][0]-dist; 00145 vec[2][1]= vec[3][1]; 00146 /* we can reuse the dist variable here to increment the GL curve eval amount*/ 00147 dist = 1.0f/curve_res; 00148 00149 cpack(0x0); 00150 glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]); 00151 glBegin(GL_LINE_STRIP); 00152 while (spline_step < 1.000001f) { 00153 /*if(do_shaded) 00154 UI_ThemeColorBlend(th_col1, th_col2, spline_step);*/ 00155 glEvalCoord1f(spline_step); 00156 spline_step += dist; 00157 } 00158 glEnd(); 00159 } 00160 00161 void fdrawline(float x1, float y1, float x2, float y2) 00162 { 00163 float v[2]; 00164 00165 glBegin(GL_LINE_STRIP); 00166 v[0] = x1; v[1] = y1; 00167 glVertex2fv(v); 00168 v[0] = x2; v[1] = y2; 00169 glVertex2fv(v); 00170 glEnd(); 00171 } 00172 00173 void fdrawbox(float x1, float y1, float x2, float y2) 00174 { 00175 float v[2]; 00176 00177 glBegin(GL_LINE_STRIP); 00178 00179 v[0] = x1; v[1] = y1; 00180 glVertex2fv(v); 00181 v[0] = x1; v[1] = y2; 00182 glVertex2fv(v); 00183 v[0] = x2; v[1] = y2; 00184 glVertex2fv(v); 00185 v[0] = x2; v[1] = y1; 00186 glVertex2fv(v); 00187 v[0] = x1; v[1] = y1; 00188 glVertex2fv(v); 00189 00190 glEnd(); 00191 } 00192 00193 void sdrawline(short x1, short y1, short x2, short y2) 00194 { 00195 short v[2]; 00196 00197 glBegin(GL_LINE_STRIP); 00198 v[0] = x1; v[1] = y1; 00199 glVertex2sv(v); 00200 v[0] = x2; v[1] = y2; 00201 glVertex2sv(v); 00202 glEnd(); 00203 } 00204 00205 /* 00206 00207 x1,y2 00208 | \ 00209 | \ 00210 | \ 00211 x1,y1-- x2,y1 00212 00213 */ 00214 00215 static void sdrawtripoints(short x1, short y1, short x2, short y2) 00216 { 00217 short v[2]; 00218 v[0]= x1; v[1]= y1; 00219 glVertex2sv(v); 00220 v[0]= x1; v[1]= y2; 00221 glVertex2sv(v); 00222 v[0]= x2; v[1]= y1; 00223 glVertex2sv(v); 00224 } 00225 00226 void sdrawtri(short x1, short y1, short x2, short y2) 00227 { 00228 glBegin(GL_LINE_STRIP); 00229 sdrawtripoints(x1, y1, x2, y2); 00230 glEnd(); 00231 } 00232 00233 void sdrawtrifill(short x1, short y1, short x2, short y2) 00234 { 00235 glBegin(GL_TRIANGLES); 00236 sdrawtripoints(x1, y1, x2, y2); 00237 glEnd(); 00238 } 00239 00240 void sdrawbox(short x1, short y1, short x2, short y2) 00241 { 00242 short v[2]; 00243 00244 glBegin(GL_LINE_STRIP); 00245 00246 v[0] = x1; v[1] = y1; 00247 glVertex2sv(v); 00248 v[0] = x1; v[1] = y2; 00249 glVertex2sv(v); 00250 v[0] = x2; v[1] = y2; 00251 glVertex2sv(v); 00252 v[0] = x2; v[1] = y1; 00253 glVertex2sv(v); 00254 v[0] = x1; v[1] = y1; 00255 glVertex2sv(v); 00256 00257 glEnd(); 00258 } 00259 00260 00261 /* ******************************************** */ 00262 00263 void setlinestyle(int nr) 00264 { 00265 if(nr==0) { 00266 glDisable(GL_LINE_STIPPLE); 00267 } 00268 else { 00269 00270 glEnable(GL_LINE_STIPPLE); 00271 glLineStipple(nr, 0xAAAA); 00272 } 00273 } 00274 00275 /* Invert line handling */ 00276 00277 #define glToggle(mode, onoff) (((onoff)?glEnable:glDisable)(mode)) 00278 00279 void set_inverted_drawing(int enable) 00280 { 00281 glLogicOp(enable?GL_INVERT:GL_COPY); 00282 00283 /* Use GL_BLEND_EQUATION_EXT on sgi (if we have it), 00284 * apparently GL_COLOR_LOGIC_OP doesn't work on O2? 00285 * Is this an sgi bug or our bug? 00286 */ 00287 #if defined(__sgi) && defined(GL_BLEND_EQUATION_EXT) 00288 glBlendEquationEXT(enable?GL_LOGIC_OP:GL_FUNC_ADD_EXT); 00289 glToggle(GL_BLEND, enable); 00290 #else 00291 glToggle(GL_COLOR_LOGIC_OP, enable); 00292 #endif 00293 00294 glToggle(GL_DITHER, !enable); 00295 } 00296 00297 void sdrawXORline(int x0, int y0, int x1, int y1) 00298 { 00299 if(x0==x1 && y0==y1) return; 00300 00301 set_inverted_drawing(1); 00302 00303 glBegin(GL_LINES); 00304 glVertex2i(x0, y0); 00305 glVertex2i(x1, y1); 00306 glEnd(); 00307 00308 set_inverted_drawing(0); 00309 } 00310 00311 void sdrawXORline4(int nr, int x0, int y0, int x1, int y1) 00312 { 00313 static short old[4][2][2]; 00314 static char flags[4]= {0, 0, 0, 0}; 00315 00316 /* with builtin memory, max 4 lines */ 00317 00318 set_inverted_drawing(1); 00319 00320 glBegin(GL_LINES); 00321 if(nr== -1) { /* flush */ 00322 for (nr=0; nr<4; nr++) { 00323 if (flags[nr]) { 00324 glVertex2sv(old[nr][0]); 00325 glVertex2sv(old[nr][1]); 00326 flags[nr]= 0; 00327 } 00328 } 00329 } else { 00330 if(nr>=0 && nr<4) { 00331 if(flags[nr]) { 00332 glVertex2sv(old[nr][0]); 00333 glVertex2sv(old[nr][1]); 00334 } 00335 00336 old[nr][0][0]= x0; 00337 old[nr][0][1]= y0; 00338 old[nr][1][0]= x1; 00339 old[nr][1][1]= y1; 00340 00341 flags[nr]= 1; 00342 } 00343 00344 glVertex2i(x0, y0); 00345 glVertex2i(x1, y1); 00346 } 00347 glEnd(); 00348 00349 set_inverted_drawing(0); 00350 } 00351 00352 void fdrawXORellipse(float xofs, float yofs, float hw, float hh) 00353 { 00354 if(hw==0) return; 00355 00356 set_inverted_drawing(1); 00357 00358 glPushMatrix(); 00359 glTranslatef(xofs, yofs, 0.0); 00360 glScalef(1,hh/hw,1); 00361 glutil_draw_lined_arc(0.0, M_PI*2.0, hw, 20); 00362 glPopMatrix(); 00363 00364 set_inverted_drawing(0); 00365 } 00366 void fdrawXORcirc(float xofs, float yofs, float rad) 00367 { 00368 set_inverted_drawing(1); 00369 00370 glPushMatrix(); 00371 glTranslatef(xofs, yofs, 0.0); 00372 glutil_draw_lined_arc(0.0, M_PI*2.0, rad, 20); 00373 glPopMatrix(); 00374 00375 set_inverted_drawing(0); 00376 } 00377 00378 void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments) { 00379 int i; 00380 00381 glBegin(GL_TRIANGLE_FAN); 00382 glVertex2f(0.0, 0.0); 00383 for (i=0; i<nsegments; i++) { 00384 float t= (float) i/(nsegments-1); 00385 float cur= start + t*angle; 00386 00387 glVertex2f(cosf(cur)*radius, sinf(cur)*radius); 00388 } 00389 glEnd(); 00390 } 00391 00392 void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments) { 00393 int i; 00394 00395 glBegin(GL_LINE_STRIP); 00396 for (i=0; i<nsegments; i++) { 00397 float t= (float) i/(nsegments-1); 00398 float cur= start + t*angle; 00399 00400 glVertex2f(cosf(cur)*radius, sinf(cur)*radius); 00401 } 00402 glEnd(); 00403 } 00404 00405 int glaGetOneInteger(int param) 00406 { 00407 GLint i; 00408 glGetIntegerv(param, &i); 00409 return i; 00410 } 00411 00412 float glaGetOneFloat(int param) 00413 { 00414 GLfloat v; 00415 glGetFloatv(param, &v); 00416 return v; 00417 } 00418 00419 void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y) 00420 { 00421 GLubyte dummy= 0; 00422 00423 /* As long as known good coordinates are correct 00424 * this is guarenteed to generate an ok raster 00425 * position (ignoring potential (real) overflow 00426 * issues). 00427 */ 00428 glRasterPos2f(known_good_x, known_good_y); 00429 00430 /* Now shift the raster position to where we wanted 00431 * it in the first place using the glBitmap trick. 00432 */ 00433 glBitmap(0, 0, 0, 0, x - known_good_x, y - known_good_y, &dummy); 00434 } 00435 00436 static int get_cached_work_texture(int *w_r, int *h_r) 00437 { 00438 static GLint texid= -1; 00439 static int tex_w= 256; 00440 static int tex_h= 256; 00441 00442 if (texid==-1) { 00443 GLint ltexid= glaGetOneInteger(GL_TEXTURE_2D); 00444 unsigned char *tbuf; 00445 00446 glGenTextures(1, (GLuint *)&texid); 00447 00448 glBindTexture(GL_TEXTURE_2D, texid); 00449 00450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00452 00453 tbuf= MEM_callocN(tex_w*tex_h*4, "tbuf"); 00454 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tbuf); 00455 MEM_freeN(tbuf); 00456 00457 glBindTexture(GL_TEXTURE_2D, ltexid); 00458 } 00459 00460 *w_r= tex_w; 00461 *h_r= tex_h; 00462 return texid; 00463 } 00464 00465 void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY) 00466 { 00467 unsigned char *uc_rect= (unsigned char*) rect; 00468 float *f_rect= (float *)rect; 00469 float xzoom= glaGetOneFloat(GL_ZOOM_X), yzoom= glaGetOneFloat(GL_ZOOM_Y); 00470 int ltexid= glaGetOneInteger(GL_TEXTURE_2D); 00471 int lrowlength= glaGetOneInteger(GL_UNPACK_ROW_LENGTH); 00472 int subpart_x, subpart_y, tex_w, tex_h; 00473 int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; 00474 int texid= get_cached_work_texture(&tex_w, &tex_h); 00475 00476 /* Specify the color outside this function, and tex will modulate it. 00477 * This is useful for changing alpha without using glPixelTransferf() 00478 */ 00479 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 00480 glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w); 00481 glBindTexture(GL_TEXTURE_2D, texid); 00482 00483 /* don't want nasty border artifacts */ 00484 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 00485 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 00486 00487 #ifdef __APPLE__ 00488 /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */ 00489 glPixelZoom(1.f, 1.f); 00490 #endif 00491 00492 /* setup seamless 2=on, 0=off */ 00493 seamless= ((tex_w<img_w || tex_h<img_h) && tex_w>2 && tex_h>2)? 2: 0; 00494 00495 offset_x= tex_w - seamless; 00496 offset_y= tex_h - seamless; 00497 00498 nsubparts_x= (img_w + (offset_x - 1))/(offset_x); 00499 nsubparts_y= (img_h + (offset_y - 1))/(offset_y); 00500 00501 for (subpart_y=0; subpart_y<nsubparts_y; subpart_y++) { 00502 for (subpart_x=0; subpart_x<nsubparts_x; subpart_x++) { 00503 int remainder_x= img_w-subpart_x*offset_x; 00504 int remainder_y= img_h-subpart_y*offset_y; 00505 int subpart_w= (remainder_x<tex_w)? remainder_x: tex_w; 00506 int subpart_h= (remainder_y<tex_h)? remainder_y: tex_h; 00507 int offset_left= (seamless && subpart_x!=0)? 1: 0; 00508 int offset_bot= (seamless && subpart_y!=0)? 1: 0; 00509 int offset_right= (seamless && remainder_x>tex_w)? 1: 0; 00510 int offset_top= (seamless && remainder_y>tex_h)? 1: 0; 00511 float rast_x= x+subpart_x*offset_x*xzoom; 00512 float rast_y= y+subpart_y*offset_y*yzoom; 00513 00514 /* check if we already got these because we always get 2 more when doing seamless*/ 00515 if(subpart_w<=seamless || subpart_h<=seamless) 00516 continue; 00517 00518 if(format==GL_FLOAT) { 00519 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y*offset_y*img_w*4 + subpart_x*offset_x*4]); 00520 00521 /* add an extra border of pixels so linear looks ok at edges of full image. */ 00522 if(subpart_w<tex_w) 00523 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y*offset_y*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00524 if(subpart_h<tex_h) 00525 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + subpart_x*offset_x*4]); 00526 if(subpart_w<tex_w && subpart_h<tex_h) 00527 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00528 } 00529 else { 00530 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y*offset_y*img_w*4 + subpart_x*offset_x*4]); 00531 00532 if(subpart_w<tex_w) 00533 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y*offset_y*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00534 if(subpart_h<tex_h) 00535 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + subpart_x*offset_x*4]); 00536 if(subpart_w<tex_w && subpart_h<tex_h) 00537 glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y*offset_y+subpart_h-1)*img_w*4 + (subpart_x*offset_x+subpart_w-1)*4]); 00538 } 00539 00540 glEnable(GL_TEXTURE_2D); 00541 glBegin(GL_QUADS); 00542 glTexCoord2f((float)(0 + offset_left)/tex_w, (float)(0 + offset_bot)/tex_h); 00543 glVertex2f(rast_x + (float)offset_left*xzoom, rast_y + (float)offset_bot*xzoom); 00544 00545 glTexCoord2f((float)(subpart_w - offset_right)/tex_w, (float)(0 + offset_bot)/tex_h); 00546 glVertex2f(rast_x + (float)(subpart_w - offset_right)*xzoom*scaleX, rast_y + (float)offset_bot*xzoom); 00547 00548 glTexCoord2f((float)(subpart_w - offset_right)/tex_w, (float)(subpart_h - offset_top)/tex_h); 00549 glVertex2f(rast_x + (float)(subpart_w - offset_right)*xzoom*scaleX, rast_y + (float)(subpart_h - offset_top)*yzoom*scaleY); 00550 00551 glTexCoord2f((float)(0 + offset_left)/tex_w, (float)(subpart_h - offset_top)/tex_h); 00552 glVertex2f(rast_x + (float)offset_left*xzoom, rast_y + (float)(subpart_h - offset_top)*yzoom*scaleY); 00553 glEnd(); 00554 glDisable(GL_TEXTURE_2D); 00555 } 00556 } 00557 00558 glBindTexture(GL_TEXTURE_2D, ltexid); 00559 glPixelStorei(GL_UNPACK_ROW_LENGTH, lrowlength); 00560 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 00561 00562 #ifdef __APPLE__ 00563 /* workaround for os x 10.5/10.6 driver bug (above) */ 00564 glPixelZoom(xzoom, yzoom); 00565 #endif 00566 } 00567 00568 void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect) 00569 { 00570 glaDrawPixelsTexScaled(x, y, img_w, img_h, format, rect, 1.0f, 1.0f); 00571 } 00572 00573 /* row_w is unused but kept for completeness */ 00574 void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int UNUSED(row_w), float *rectf, int do_gamma_correct) 00575 { 00576 unsigned char *rect32; 00577 00578 /* copy imgw-imgh to a temporal 32 bits rect */ 00579 if(img_w<1 || img_h<1) return; 00580 00581 rect32= MEM_mallocN(img_w*img_h*sizeof(int), "temp 32 bits"); 00582 00583 if (do_gamma_correct) { 00584 floatbuf_to_srgb_byte(rectf, rect32, 0, img_w, 0, img_h, img_w); 00585 } else { 00586 floatbuf_to_byte(rectf, rect32, 0, img_w, 0, img_h, img_w); 00587 } 00588 00589 glaDrawPixelsSafe(fx, fy, img_w, img_h, img_w, GL_RGBA, GL_UNSIGNED_BYTE, rect32); 00590 00591 MEM_freeN(rect32); 00592 } 00593 00594 void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect) 00595 { 00596 float xzoom= glaGetOneFloat(GL_ZOOM_X); 00597 float yzoom= glaGetOneFloat(GL_ZOOM_Y); 00598 00599 /* The pixel space coordinate of the intersection of 00600 * the [zoomed] image with the origin. 00601 */ 00602 float ix= -x/xzoom; 00603 float iy= -y/yzoom; 00604 00605 /* The maximum pixel amounts the image can be cropped 00606 * at the lower left without exceeding the origin. 00607 */ 00608 int off_x= floor(MAX2(ix, 0)); 00609 int off_y= floor(MAX2(iy, 0)); 00610 00611 /* The zoomed space coordinate of the raster position 00612 * (starting at the lower left most unclipped pixel). 00613 */ 00614 float rast_x= x + off_x*xzoom; 00615 float rast_y= y + off_y*yzoom; 00616 00617 GLfloat scissor[4]; 00618 int draw_w, draw_h; 00619 00620 /* Determine the smallest number of pixels we need to draw 00621 * before the image would go off the upper right corner. 00622 * 00623 * It may seem this is just an optimization but some graphics 00624 * cards (ATI) freak out if there is a large zoom factor and 00625 * a large number of pixels off the screen (probably at some 00626 * level the number of image pixels to draw is getting multiplied 00627 * by the zoom and then clamped). Making sure we draw the 00628 * fewest pixels possible keeps everyone mostly happy (still 00629 * fails if we zoom in on one really huge pixel so that it 00630 * covers the entire screen). 00631 */ 00632 glGetFloatv(GL_SCISSOR_BOX, scissor); 00633 draw_w = MIN2(img_w-off_x, ceil((scissor[2]-rast_x)/xzoom)); 00634 draw_h = MIN2(img_h-off_y, ceil((scissor[3]-rast_y)/yzoom)); 00635 00636 if (draw_w>0 && draw_h>0) { 00637 int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); 00638 00639 /* Don't use safe RasterPos (slower) if we can avoid it. */ 00640 if (rast_x>=0 && rast_y>=0) { 00641 glRasterPos2f(rast_x, rast_y); 00642 } else { 00643 glaRasterPosSafe2f(rast_x, rast_y, 0, 0); 00644 } 00645 00646 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w); 00647 if(format==GL_LUMINANCE || format==GL_RED) { 00648 if(type==GL_FLOAT) { 00649 float *f_rect= (float *)rect; 00650 glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x)); 00651 } 00652 else if(type==GL_INT || type==GL_UNSIGNED_INT) { 00653 int *i_rect= (int *)rect; 00654 glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y*row_w + off_x)); 00655 } 00656 } 00657 else { /* RGBA */ 00658 if(type==GL_FLOAT) { 00659 float *f_rect= (float *)rect; 00660 glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y*row_w + off_x)*4); 00661 } 00662 else if(type==GL_UNSIGNED_BYTE) { 00663 unsigned char *uc_rect= (unsigned char *) rect; 00664 glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y*row_w + off_x)*4); 00665 } 00666 } 00667 00668 glPixelStorei(GL_UNPACK_ROW_LENGTH, old_row_length); 00669 } 00670 } 00671 00672 /* 2D Drawing Assistance */ 00673 00674 void glaDefine2DArea(rcti *screen_rect) 00675 { 00676 int sc_w= screen_rect->xmax - screen_rect->xmin + 1; 00677 int sc_h= screen_rect->ymax - screen_rect->ymin + 1; 00678 00679 glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); 00680 glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); 00681 00682 /* The 0.375 magic number is to shift the matrix so that 00683 * both raster and vertex integer coordinates fall at pixel 00684 * centers properly. For a longer discussion see the OpenGL 00685 * Programming Guide, Appendix H, Correctness Tips. 00686 */ 00687 00688 glMatrixMode(GL_PROJECTION); 00689 glLoadIdentity(); 00690 glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1); 00691 glTranslatef(0.375, 0.375, 0.0); 00692 00693 glMatrixMode(GL_MODELVIEW); 00694 glLoadIdentity(); 00695 } 00696 00697 struct gla2DDrawInfo { 00698 int orig_vp[4], orig_sc[4]; 00699 float orig_projmat[16], orig_viewmat[16]; 00700 00701 rcti screen_rect; 00702 rctf world_rect; 00703 00704 float wo_to_sc[2]; 00705 }; 00706 00707 void gla2DGetMap(gla2DDrawInfo *di, rctf *rect) 00708 { 00709 *rect= di->world_rect; 00710 } 00711 00712 void gla2DSetMap(gla2DDrawInfo *di, rctf *rect) 00713 { 00714 int sc_w, sc_h; 00715 float wo_w, wo_h; 00716 00717 di->world_rect= *rect; 00718 00719 sc_w= (di->screen_rect.xmax-di->screen_rect.xmin); 00720 sc_h= (di->screen_rect.ymax-di->screen_rect.ymin); 00721 wo_w= (di->world_rect.xmax-di->world_rect.xmin); 00722 wo_h= (di->world_rect.ymax-di->world_rect.ymin); 00723 00724 di->wo_to_sc[0]= sc_w/wo_w; 00725 di->wo_to_sc[1]= sc_h/wo_h; 00726 } 00727 00728 00729 gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) 00730 { 00731 gla2DDrawInfo *di= MEM_mallocN(sizeof(*di), "gla2DDrawInfo"); 00732 int sc_w, sc_h; 00733 float wo_w, wo_h; 00734 00735 glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp); 00736 glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc); 00737 glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat); 00738 glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat); 00739 00740 di->screen_rect= *screen_rect; 00741 if (world_rect) { 00742 di->world_rect= *world_rect; 00743 } else { 00744 di->world_rect.xmin= di->screen_rect.xmin; 00745 di->world_rect.ymin= di->screen_rect.ymin; 00746 di->world_rect.xmax= di->screen_rect.xmax; 00747 di->world_rect.ymax= di->screen_rect.ymax; 00748 } 00749 00750 sc_w= (di->screen_rect.xmax-di->screen_rect.xmin); 00751 sc_h= (di->screen_rect.ymax-di->screen_rect.ymin); 00752 wo_w= (di->world_rect.xmax-di->world_rect.xmin); 00753 wo_h= (di->world_rect.ymax-di->world_rect.ymin); 00754 00755 di->wo_to_sc[0]= sc_w/wo_w; 00756 di->wo_to_sc[1]= sc_h/wo_h; 00757 00758 glaDefine2DArea(&di->screen_rect); 00759 00760 return di; 00761 } 00762 00763 void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r) 00764 { 00765 *sc_x_r= (wo_x - di->world_rect.xmin)*di->wo_to_sc[0]; 00766 *sc_y_r= (wo_y - di->world_rect.ymin)*di->wo_to_sc[1]; 00767 } 00768 void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]) 00769 { 00770 screen_r[0]= (world[0] - di->world_rect.xmin)*di->wo_to_sc[0]; 00771 screen_r[1]= (world[1] - di->world_rect.ymin)*di->wo_to_sc[1]; 00772 } 00773 00774 void glaEnd2DDraw(gla2DDrawInfo *di) 00775 { 00776 glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); 00777 glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); 00778 glMatrixMode(GL_PROJECTION); 00779 glLoadMatrixf(di->orig_projmat); 00780 glMatrixMode(GL_MODELVIEW); 00781 glLoadMatrixf(di->orig_viewmat); 00782 00783 MEM_freeN(di); 00784 } 00785 00786 /* **************** glPoint hack ************************ */ 00787 00788 static int curmode=0; 00789 static int pointhack=0; 00790 static GLubyte Squaredot[16] = { 0xff,0xff,0xff,0xff, 00791 0xff,0xff,0xff,0xff, 00792 0xff,0xff,0xff,0xff, 00793 0xff,0xff,0xff,0xff}; 00794 00795 void bglBegin(int mode) 00796 { 00797 curmode= mode; 00798 00799 if(mode==GL_POINTS) { 00800 float value[4]; 00801 glGetFloatv(GL_POINT_SIZE_RANGE, value); 00802 if(value[1] < 2.0f) { 00803 glGetFloatv(GL_POINT_SIZE, value); 00804 pointhack= floor(value[0] + 0.5f); 00805 if(pointhack>4) pointhack= 4; 00806 } 00807 else glBegin(mode); 00808 } 00809 } 00810 00811 int bglPointHack(void) { 00812 float value[4]; 00813 int pointhack_px; 00814 glGetFloatv(GL_POINT_SIZE_RANGE, value); 00815 if(value[1] < 2.0f) { 00816 glGetFloatv(GL_POINT_SIZE, value); 00817 pointhack_px= floorf(value[0]+0.5f); 00818 if(pointhack_px>4) pointhack_px= 4; 00819 return pointhack_px; 00820 } 00821 return 0; 00822 } 00823 00824 void bglVertex3fv(float *vec) 00825 { 00826 switch(curmode) { 00827 case GL_POINTS: 00828 if(pointhack) { 00829 glRasterPos3fv(vec); 00830 glBitmap(pointhack, pointhack, (float)pointhack/2.0f, (float)pointhack/2.0f, 0.0, 0.0, Squaredot); 00831 } 00832 else glVertex3fv(vec); 00833 break; 00834 } 00835 } 00836 00837 void bglVertex3f(float x, float y, float z) 00838 { 00839 switch(curmode) { 00840 case GL_POINTS: 00841 if(pointhack) { 00842 glRasterPos3f(x, y, z); 00843 glBitmap(pointhack, pointhack, (float)pointhack/2.0f, (float)pointhack/2.0f, 0.0, 0.0, Squaredot); 00844 } 00845 else glVertex3f(x, y, z); 00846 break; 00847 } 00848 } 00849 00850 void bglVertex2fv(float *vec) 00851 { 00852 switch(curmode) { 00853 case GL_POINTS: 00854 if(pointhack) { 00855 glRasterPos2fv(vec); 00856 glBitmap(pointhack, pointhack, (float)pointhack/2, pointhack/2, 0.0, 0.0, Squaredot); 00857 } 00858 else glVertex2fv(vec); 00859 break; 00860 } 00861 } 00862 00863 00864 void bglEnd(void) 00865 { 00866 if(pointhack) pointhack= 0; 00867 else glEnd(); 00868 00869 } 00870 00871 /* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */ 00872 void bgl_get_mats(bglMats *mats) 00873 { 00874 const double badvalue= 1.0e-6; 00875 00876 glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview); 00877 glGetDoublev(GL_PROJECTION_MATRIX, mats->projection); 00878 glGetIntegerv(GL_VIEWPORT, (GLint *)mats->viewport); 00879 00880 /* Very strange code here - it seems that certain bad values in the 00881 modelview matrix can cause gluUnProject to give bad results. */ 00882 if(mats->modelview[0] < badvalue && 00883 mats->modelview[0] > -badvalue) 00884 mats->modelview[0]= 0; 00885 if(mats->modelview[5] < badvalue && 00886 mats->modelview[5] > -badvalue) 00887 mats->modelview[5]= 0; 00888 00889 /* Set up viewport so that gluUnProject will give correct values */ 00890 mats->viewport[0] = 0; 00891 mats->viewport[1] = 0; 00892 } 00893 00894 /* *************** glPolygonOffset hack ************* */ 00895 00896 /* dist is only for ortho now... */ 00897 void bglPolygonOffset(float viewdist, float dist) 00898 { 00899 static float winmat[16], offset=0.0; 00900 00901 if(dist != 0.0f) { 00902 float offs; 00903 00904 // glEnable(GL_POLYGON_OFFSET_FILL); 00905 // glPolygonOffset(-1.0, -1.0); 00906 00907 /* hack below is to mimic polygon offset */ 00908 glMatrixMode(GL_PROJECTION); 00909 glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat); 00910 00911 /* dist is from camera to center point */ 00912 00913 if(winmat[15]>0.5f) offs= 0.00001f*dist*viewdist; // ortho tweaking 00914 else offs= 0.0005f*dist; // should be clipping value or so... 00915 00916 winmat[14]-= offs; 00917 offset+= offs; 00918 00919 glLoadMatrixf(winmat); 00920 glMatrixMode(GL_MODELVIEW); 00921 } 00922 else { 00923 00924 glMatrixMode(GL_PROJECTION); 00925 winmat[14]+= offset; 00926 offset= 0.0; 00927 glLoadMatrixf(winmat); 00928 glMatrixMode(GL_MODELVIEW); 00929 } 00930 } 00931 00932 void bglFlush(void) 00933 { 00934 glFlush(); 00935 #ifdef __APPLE__ 00936 // if(GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_OFFICIAL)) 00937 // XXX myswapbuffers(); //hack to get mac intel graphics to show frontbuffer 00938 #endif 00939 } 00940