Blender V2.61 - r43446

glutil.c

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