2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r17434...
[blender.git] / source / blender / gpu / intern / gpu_draw.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2005 Blender Foundation.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): Brecht Van Lommel.
29  *
30  * ***** END GPL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34
35 #include "GL/glew.h"
36
37 #include "DNA_image_types.h"
38 #include "DNA_lamp_types.h"
39 #include "DNA_material_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_node_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_userdef_types.h"
45 #include "DNA_view3d_types.h"
46
47 #include "MEM_guardedalloc.h"
48
49 #include "IMB_imbuf.h"
50 #include "IMB_imbuf_types.h"
51
52 #include "BKE_bmfont.h"
53 #include "BKE_global.h"
54 #include "BKE_image.h"
55 #include "BKE_main.h"
56 #include "BKE_material.h"
57 #include "BKE_node.h"
58 #include "BKE_object.h"
59 #include "BKE_utildefines.h"
60
61 #include "GPU_extensions.h"
62 #include "GPU_material.h"
63 #include "GPU_draw.h"
64
65 /* These are some obscure rendering functions shared between the
66  * game engine and the blender, in this module to avoid duplicaten
67  * and abstract them away from the rest a bit */
68
69 /* Text Rendering */
70
71 static void gpu_mcol(unsigned int ucol)
72 {
73         /* mcol order is swapped */
74         char *cp= (char *)&ucol;
75         glColor3ub(cp[3], cp[2], cp[1]);
76 }
77
78 void GPU_render_text(MTFace *tface, int mode,
79         const char *textstr, int textlen, unsigned int *col,
80         float *v1, float *v2, float *v3, float *v4, int glattrib)
81 {
82         if (mode & TF_BMFONT) {
83                 Image* ima;
84                 int characters, index, character;
85                 float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
86
87                 characters = textlen;
88
89                 ima = (Image*)tface->tpage;
90                 if (ima == NULL)
91                         characters = 0;
92
93                 // color has been set
94                 if (tface->mode & TF_OBCOL)
95                         col= NULL;
96                 else if (!col)
97                         glColor3f(1.0f, 1.0f, 1.0f);
98
99                 glPushMatrix();
100                 for (index = 0; index < characters; index++) {
101                         float uv[4][2];
102
103                         // lets calculate offset stuff
104                         character = textstr[index];
105                         
106                         // space starts at offset 1
107                         // character = character - ' ' + 1;
108                         matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, &centery,
109                                 &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
110
111                         uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx;
112                         uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy;
113                         uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx;
114                         uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy;
115                         uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx;
116                         uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy;
117                         
118                         glBegin(GL_POLYGON);
119                         if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]);
120                         else glTexCoord2fv(uv[0]);
121                         if(col) gpu_mcol(col[0]);
122                         glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
123                         
124                         if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[1]);
125                         else glTexCoord2fv(uv[1]);
126                         if(col) gpu_mcol(col[1]);
127                         glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
128
129                         if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[2]);
130                         else glTexCoord2fv(uv[2]);
131                         if(col) gpu_mcol(col[2]);
132                         glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
133
134                         if(v4) {
135                                 uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx;
136                                 uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy;
137
138                                 if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]);
139                                 else glTexCoord2fv(uv[3]);
140                                 if(col) gpu_mcol(col[3]);
141                                 glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
142                         }
143                         glEnd();
144
145                         glTranslatef(advance, 0.0, 0.0);
146                 }
147                 glPopMatrix();
148         }
149 }
150
151 /* Checking powers of two for images since opengl 1.x requires it */
152
153 static int is_pow2(int num)
154 {
155         /* (n&(n-1)) zeros the least significant bit of n */
156         return ((num)&(num-1))==0;
157 }
158
159 static int smaller_pow2(int num)
160 {
161         while (!is_pow2(num))
162                 num= num&(num-1);
163
164         return num;     
165 }
166
167 static int is_pow2_limit(int num)
168 {
169         /* take texture clamping into account */
170         if (U.glreslimit != 0 && num > U.glreslimit)
171                 return 0;
172
173         return ((num)&(num-1))==0;
174 }
175
176 static int smaller_pow2_limit(int num)
177 {
178         /* take texture clamping into account */
179         if (U.glreslimit != 0 && num > U.glreslimit)
180                 return U.glreslimit;
181
182         return smaller_pow2(num);
183 }
184
185 /* Current OpenGL state caching for GPU_set_tpage */
186
187 static struct GPUTextureState {
188         int curtile, tile;
189         int curtilemode, tilemode;
190         int curtileXRep, tileXRep;
191         int curtileYRep, tileYRep;
192         Image *ima, *curima;
193
194         int domipmap, linearmipmap;
195
196         int alphamode;
197         MTFace *lasttface;
198 } GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, NULL};
199
200 /* Mipmap settings */
201
202 void GPU_set_mipmap(int mipmap)
203 {
204         if (GTS.domipmap != (mipmap != 0)) {
205                 GPU_free_images();
206                 GTS.domipmap = mipmap != 0;
207         }
208 }
209
210 void GPU_set_linear_mipmap(int linear)
211 {
212         if (GTS.linearmipmap != (linear != 0)) {
213                 GPU_free_images();
214                 GTS.linearmipmap = linear != 0;
215         }
216 }
217
218 static int gpu_get_mipmap(void)
219 {
220         return GTS.domipmap && (!(G.f & G_TEXTUREPAINT));
221 }
222
223 static GLenum gpu_get_mipmap_filter(int mag)
224 {
225         /* linearmipmap is off by default *when mipmapping is off,
226          * use unfiltered display */
227         if(mag) {
228                 if(GTS.linearmipmap || GTS.domipmap)
229                         return GL_LINEAR;
230                 else
231                         return GL_NEAREST;
232         }
233         else {
234                 if(GTS.linearmipmap)
235                         return GL_LINEAR_MIPMAP_LINEAR;
236                 else if(GTS.domipmap)
237                         return GL_LINEAR_MIPMAP_NEAREST;
238                 else
239                         return GL_NEAREST;
240         }
241 }
242
243 /* Set OpenGL state for an MTFace */
244
245 static void gpu_make_repbind(Image *ima)
246 {
247         ImBuf *ibuf;
248         
249         ibuf = BKE_image_get_ibuf(ima, NULL);
250         if(ibuf==NULL)
251                 return;
252
253         if(ima->repbind) {
254                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
255                 MEM_freeN(ima->repbind);
256                 ima->repbind= 0;
257                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
258         }
259
260         ima->totbind= ima->xrep*ima->yrep;
261
262         if(ima->totbind>1)
263                 ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
264 }
265
266 static void gpu_clear_tpage()
267 {
268         if(GTS.lasttface==0)
269                 return;
270         
271         GTS.lasttface= 0;
272         GTS.curtile= 0;
273         GTS.curima= 0;
274         if(GTS.curtilemode!=0) {
275                 glMatrixMode(GL_TEXTURE);
276                 glLoadIdentity();
277                 glMatrixMode(GL_MODELVIEW);
278         }
279         GTS.curtilemode= 0;
280         GTS.curtileXRep=0;
281         GTS.curtileYRep=0;
282         GTS.alphamode= -1;
283         
284         glDisable(GL_BLEND);
285         glDisable(GL_TEXTURE_2D);
286         glDisable(GL_TEXTURE_GEN_S);
287         glDisable(GL_TEXTURE_GEN_T);
288         glDisable(GL_ALPHA_TEST);
289 }
290
291 static void gpu_set_blend_mode(GPUBlendMode blendmode)
292 {
293         if(blendmode == GPU_BLEND_SOLID) {
294                 glDisable(GL_BLEND);
295                 glDisable(GL_ALPHA_TEST);
296                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
297         }
298         else if(blendmode==GPU_BLEND_ADD) {
299                 glEnable(GL_BLEND);
300                 glBlendFunc(GL_ONE, GL_ONE);
301                 glDisable(GL_ALPHA_TEST);
302         }
303         else if(blendmode==GPU_BLEND_ALPHA) {
304                 glEnable(GL_BLEND);
305                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
306                 
307                 /* if U.glalphaclip == 1.0, some cards go bonkers...
308                  * turn off alpha test in this case */
309
310                 /* added after 2.45 to clip alpha */
311                 if(U.glalphaclip == 1.0) {
312                         glDisable(GL_ALPHA_TEST);
313                 }
314                 else {
315                         glEnable(GL_ALPHA_TEST);
316                         glAlphaFunc(GL_GREATER, U.glalphaclip);
317                 }
318         }
319         else if(blendmode==GPU_BLEND_CLIP) {
320                 glDisable(GL_BLEND); 
321                 glEnable(GL_ALPHA_TEST);
322                 glAlphaFunc(GL_GREATER, 0.5f);
323         }
324 }
325
326 static void gpu_verify_alpha_mode(MTFace *tface)
327 {
328         /* verify alpha blending modes */
329         if(GTS.alphamode == tface->transp)
330                 return;
331
332         gpu_set_blend_mode(tface->transp);
333         GTS.alphamode= tface->transp;
334 }
335
336 static void gpu_verify_reflection(Image *ima)
337 {
338         if (ima && (ima->flag & IMA_REFLECT)) {
339                 /* enable reflection mapping */
340                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
341                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
342
343                 glEnable(GL_TEXTURE_GEN_S);
344                 glEnable(GL_TEXTURE_GEN_T);
345         }
346         else {
347                 /* disable reflection mapping */
348                 glDisable(GL_TEXTURE_GEN_S);
349                 glDisable(GL_TEXTURE_GEN_T);
350         }
351 }
352
353 int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare)
354 {
355         ImBuf *ibuf = NULL;
356         unsigned int *bind = NULL;
357         int rectw, recth, tpx=0, tpy=0, y;
358         unsigned int *rectrow, *tilerectrow;
359         unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL;
360         short texwindx, texwindy, texwinsx, texwinsy;
361
362         /* initialize tile mode and number of repeats */
363         GTS.ima = ima;
364         GTS.tilemode= (tfmode & TF_TILES) || (ima && (ima->tpageflag & IMA_TWINANIM));
365         GTS.tileXRep = 0;
366         GTS.tileYRep = 0;
367
368         /* setting current tile according to frame */
369         if(ima && (ima->tpageflag & IMA_TWINANIM))
370                 GTS.tile= ima->lastframe;
371         else
372                 GTS.tile= tftile;
373
374         GTS.tile = MAX2(0, GTS.tile);
375
376         if(ima) {
377                 GTS.tileXRep = ima->xrep;
378                 GTS.tileYRep = ima->yrep;
379         }
380
381         /* if same image & tile, we're done */
382         if(compare && ima == GTS.curima && GTS.curtile == GTS.tile &&
383            GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep &&
384            GTS.curtileYRep == GTS.tileYRep)
385                 return (ima!=0);
386
387         /* if tiling mode or repeat changed, change texture matrix to fit */
388         if(GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep ||
389            GTS.curtileYRep != GTS.tileYRep) {
390
391                 glMatrixMode(GL_TEXTURE);
392                 glLoadIdentity();
393
394                 if((tfmode & TF_TILES) && ima!=NULL)
395                         glScalef(ima->xrep, ima->yrep, 1.0);
396
397                 glMatrixMode(GL_MODELVIEW);
398         }
399
400         /* check if we have a valid image */
401         if(ima==NULL || ima->ok==0)
402                 return 0;
403
404         /* check if we have a valid image buffer */
405         ibuf= BKE_image_get_ibuf(ima, NULL);
406
407         if(ibuf==NULL)
408                 return 0;
409
410         /* ensure we have a char buffer and not only float */
411         if ((ibuf->rect==NULL) && ibuf->rect_float)
412                 IMB_rect_from_float(ibuf);
413
414         if(GTS.tilemode) {
415                 /* tiled mode */
416                 if(ima->repbind==0) gpu_make_repbind(ima);
417                 if(GTS.tile>=ima->totbind) GTS.tile= 0;
418                 
419                 /* this happens when you change repeat buttons */
420                 if(ima->repbind) bind= &ima->repbind[GTS.tile];
421                 else bind= &ima->bindcode;
422                 
423                 if(*bind==0) {
424                         
425                         texwindx= ibuf->x/ima->xrep;
426                         texwindy= ibuf->y/ima->yrep;
427                         
428                         if(GTS.tile>=ima->xrep*ima->yrep)
429                                 GTS.tile= ima->xrep*ima->yrep-1;
430         
431                         texwinsy= GTS.tile / ima->xrep;
432                         texwinsx= GTS.tile - texwinsy*ima->xrep;
433         
434                         texwinsx*= texwindx;
435                         texwinsy*= texwindy;
436         
437                         tpx= texwindx;
438                         tpy= texwindy;
439
440                         rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
441                 }
442         }
443         else {
444                 /* regular image mode */
445                 bind= &ima->bindcode;
446                 
447                 if(*bind==0) {
448                         tpx= ibuf->x;
449                         tpy= ibuf->y;
450                         rect= ibuf->rect;
451                 }
452         }
453
454         if(*bind != 0) {
455                 /* enable opengl drawing with textures */
456                 glBindTexture(GL_TEXTURE_2D, *bind);
457                 return *bind;
458         }
459
460         rectw = tpx;
461         recth = tpy;
462
463         /* for tiles, copy only part of image into buffer */
464         if (GTS.tilemode) {
465                 tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
466
467                 for (y=0; y<recth; y++) {
468                         rectrow= &rect[y*ibuf->x];
469                         tilerectrow= &tilerect[y*rectw];
470                                 
471                         memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
472                 }
473                         
474                 rect= tilerect;
475         }
476
477         /* scale if not a power of two */
478         if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) {
479                 rectw= smaller_pow2_limit(rectw);
480                 recth= smaller_pow2_limit(recth);
481                 
482                 scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
483                 gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
484                 rect= scalerect;
485         }
486
487         /* create image */
488         glGenTextures(1, (GLuint *)bind);
489         glBindTexture( GL_TEXTURE_2D, *bind);
490
491         if (!gpu_get_mipmap()) {
492                 glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
493                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
494                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
495         }
496         else {
497                 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
498                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
499                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
500
501                 ima->tpageflag |= IMA_MIPMAP_COMPLETE;
502         }
503
504         /* set to modulate with vertex color */
505         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
506                 
507         /* clean up */
508         if (tilerect)
509                 MEM_freeN(tilerect);
510         if (scalerect)
511                 MEM_freeN(scalerect);
512
513         return *bind;
514 }
515
516 static void gpu_verify_repeat(Image *ima)
517 {
518         /* set either clamp or repeat in X/Y */
519         if (ima->tpageflag & IMA_CLAMP_U)
520            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
521         else
522                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
523
524         if (ima->tpageflag & IMA_CLAMP_V)
525                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
526         else
527                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
528 }
529
530 int GPU_set_tpage(MTFace *tface)
531 {
532         Image *ima;
533         
534         /* check if we need to clear the state */
535         if(tface==0) {
536                 gpu_clear_tpage();
537                 return 0;
538         }
539
540         ima= tface->tpage;
541         GTS.lasttface= tface;
542
543         gpu_verify_alpha_mode(tface);
544         gpu_verify_reflection(ima);
545
546         if(GPU_verify_image(ima, tface->tile, tface->mode, 1)) {
547                 GTS.curtile= GTS.tile;
548                 GTS.curima= GTS.ima;
549                 GTS.curtilemode= GTS.tilemode;
550                 GTS.curtileXRep = GTS.tileXRep;
551                 GTS.curtileYRep = GTS.tileYRep;
552
553                 glEnable(GL_TEXTURE_2D);
554         }
555         else {
556                 glDisable(GL_TEXTURE_2D);
557                 
558                 GTS.curtile= 0;
559                 GTS.curima= 0;
560                 GTS.curtilemode= 0;
561                 GTS.curtileXRep = 0;
562                 GTS.curtileYRep = 0;
563
564                 return 0;
565         }
566         
567         gpu_verify_repeat(ima);
568         
569         /* Did this get lost in the image recode? */
570         /* tag_image_time(ima);*/
571
572         return 1;
573 }
574
575 /* these two functions are called on entering and exiting texture paint mode,
576    temporary disabling/enabling mipmapping on all images for quick texture
577    updates with glTexSubImage2D. images that didn't change don't have to be
578    re-uploaded to OpenGL */
579 void GPU_paint_set_mipmap(int mipmap)
580 {
581         Image* ima;
582         
583         if(!GTS.domipmap)
584                 return;
585
586         if(mipmap) {
587                 for(ima=G.main->image.first; ima; ima=ima->id.next) {
588                         if(ima->bindcode) {
589                                 if(ima->tpageflag & IMA_MIPMAP_COMPLETE) {
590                                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
591                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
592                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
593                                 }
594                                 else
595                                         GPU_free_image(ima);
596                         }
597                 }
598
599         }
600         else {
601                 for(ima=G.main->image.first; ima; ima=ima->id.next) {
602                         if(ima->bindcode) {
603                                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
604                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
605                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
606                         }
607                 }
608         }
609 }
610
611 void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
612 {
613         ImBuf *ibuf;
614         
615         ibuf = BKE_image_get_ibuf(ima, NULL);
616         
617         if (ima->repbind || gpu_get_mipmap() || !ima->bindcode || !ibuf ||
618                 (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) ||
619                 (w == 0) || (h == 0)) {
620                 /* these cases require full reload still */
621                 GPU_free_image(ima);
622         }
623         else {
624                 /* for the special case, we can do a partial update
625                  * which is much quicker for painting */
626                 GLint row_length, skip_pixels, skip_rows;
627
628                 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
629                 glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
630                 glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
631
632                 if ((ibuf->rect==NULL) && ibuf->rect_float)
633                         IMB_rect_from_float(ibuf);
634
635                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
636
637                 glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
638                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
639                 glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
640
641                 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
642                         GL_UNSIGNED_BYTE, ibuf->rect);
643
644                 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
645                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
646                 glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
647
648                 if(ima->tpageflag & IMA_MIPMAP_COMPLETE)
649                         ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
650         }
651 }
652
653 void GPU_update_images_framechange(void)
654 {
655         Image *ima;
656         
657         for(ima=G.main->image.first; ima; ima=ima->id.next) {
658                 if(ima->tpageflag & IMA_TWINANIM) {
659                         if(ima->twend >= ima->xrep*ima->yrep)
660                                 ima->twend= ima->xrep*ima->yrep-1;
661                 
662                         /* check: is bindcode not in the array? free. (to do) */
663                         
664                         ima->lastframe++;
665                         if(ima->lastframe > ima->twend)
666                                 ima->lastframe= ima->twsta;
667                 }
668         }
669 }
670
671 int GPU_update_image_time(Image *ima, double time)
672 {
673         int     inc = 0;
674         float   diff;
675         int     newframe;
676
677         if (!ima)
678                 return 0;
679
680         if (ima->lastupdate<0)
681                 ima->lastupdate = 0;
682
683         if (ima->lastupdate>time)
684                 ima->lastupdate=(float)time;
685
686         if(ima->tpageflag & IMA_TWINANIM) {
687                 if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
688                 
689                 /* check: is the bindcode not in the array? Then free. (still to do) */
690                 
691                 diff = (float)(time-ima->lastupdate);
692                 inc = (int)(diff*(float)ima->animspeed);
693
694                 ima->lastupdate+=((float)inc/(float)ima->animspeed);
695
696                 newframe = ima->lastframe+inc;
697
698                 if(newframe > (int)ima->twend) {
699                         if(ima->twend-ima->twsta != 0)
700                                 newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
701                         else
702                                 newframe = ima->twsta;
703                 }
704
705                 ima->lastframe = newframe;
706         }
707
708         return inc;
709 }
710
711 void GPU_free_image(Image *ima)
712 {
713         /* free regular image binding */
714         if(ima->bindcode) {
715                 glDeleteTextures(1, (GLuint *)&ima->bindcode);
716                 ima->bindcode= 0;
717                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
718         }
719
720         /* free glsl image binding */
721         if(ima->gputexture) {
722                 GPU_texture_free(ima->gputexture);
723                 ima->gputexture= NULL;
724         }
725
726         /* free repeated image binding */
727         if(ima->repbind) {
728                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
729         
730                 MEM_freeN(ima->repbind);
731                 ima->repbind= NULL;
732                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
733         }
734 }
735
736 void GPU_free_images(void)
737 {
738         Image* ima;
739
740         if(G.main)
741                 for(ima=G.main->image.first; ima; ima=ima->id.next)
742                         GPU_free_image(ima);
743 }
744
745 /* OpenGL Materials */
746
747 /* materials start counting at # one.... */
748 #define MAXMATBUF (MAXMAT+1)
749
750 /* OpenGL state caching for materials */
751
752 static struct GPUMaterialState {
753         float matbuf[MAXMATBUF][2][4];
754         int totmat;
755
756         Material *gmatbuf[MAXMATBUF];
757         Material *gboundmat;
758         Object *gob;
759         Scene *gscene;
760
761         GPUBlendMode blendmode[MAXMATBUF];
762         int alphapass;
763
764         int lastmatnr, lastretval;
765         GPUBlendMode lastblendmode;
766 } GMS;
767
768 Material *gpu_active_node_material(Material *ma)
769 {
770         if(ma && ma->use_nodes && ma->nodetree) {
771                 bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
772
773                 if(node)
774                         return (Material *)node->id;
775                 else
776                         return NULL;
777         }
778
779         return ma;
780 }
781
782 void GPU_set_object_materials(Scene *scene, Object *ob, int glsl, int *do_alpha_pass)
783 {
784         extern Material defmaterial; /* from material.c */
785         Material *ma;
786         GPUMaterial *gpumat;
787         GPUBlendMode blendmode;
788         int a;
789         
790         /* initialize state */
791         memset(&GMS, 0, sizeof(GMS));
792         GMS.lastmatnr = -1;
793         GMS.lastretval = -1;
794         GMS.lastblendmode = GPU_BLEND_SOLID;
795
796         GMS.gob = ob;
797         GMS.gscene = scene;
798         GMS.totmat= ob->totcol;
799
800         GMS.alphapass = (G.vd && G.vd->transp);
801         if(do_alpha_pass)
802                 *do_alpha_pass = 0;
803
804         /* no materials assigned? */
805         if(ob->totcol==0) {
806                 GMS.matbuf[0][0][0]= defmaterial.r;
807                 GMS.matbuf[0][0][1]= defmaterial.g;
808                 GMS.matbuf[0][0][2]= defmaterial.b;
809                 GMS.matbuf[0][0][3]= 1.0;
810
811                 GMS.matbuf[0][1][0]= defmaterial.specr;
812                 GMS.matbuf[0][1][1]= defmaterial.specg;
813                 GMS.matbuf[0][1][2]= defmaterial.specb;
814                 GMS.matbuf[0][1][3]= 1.0;
815                 
816                 /* do material 1 too, for displists! */
817                 QUATCOPY(GMS.matbuf[1][0], GMS.matbuf[0][0]);
818                 QUATCOPY(GMS.matbuf[1][1], GMS.matbuf[0][1]);
819
820                 if(glsl) {
821                         GMS.gmatbuf[0]= &defmaterial;
822                         GPU_material_from_blender(GMS.gscene, &defmaterial);
823                 }
824
825                 GMS.blendmode[0]= GPU_BLEND_SOLID;
826         }
827         
828         /* setup materials */
829         for(a=1; a<=ob->totcol; a++) {
830                 /* find a suitable material */
831                 ma= give_current_material(ob, a);
832                 if(!glsl) ma= gpu_active_node_material(ma);
833                 if(ma==NULL) ma= &defmaterial;
834
835                 /* this shouldn't happen .. */
836                 if(a>=MAXMATBUF)
837                         continue;
838
839                 /* create glsl material if requested */
840                 gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
841
842                 if(gpumat) {
843                         /* do glsl only if creating it succeed, else fallback */
844                         GMS.gmatbuf[a]= ma;
845                         blendmode = GPU_material_blend_mode(gpumat, ob->col);
846                 }
847                 else {
848                         /* fixed function opengl materials */
849                         if (ma->mode & MA_SHLESS) {
850                                 GMS.matbuf[a][0][0]= ma->r;
851                                 GMS.matbuf[a][0][1]= ma->g;
852                                 GMS.matbuf[a][0][2]= ma->b;
853                         } else {
854                                 GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
855                                 GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
856                                 GMS.matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
857
858                                 GMS.matbuf[a][1][0]= ma->spec*ma->specr;
859                                 GMS.matbuf[a][1][1]= ma->spec*ma->specg;
860                                 GMS.matbuf[a][1][2]= ma->spec*ma->specb;
861                                 GMS.matbuf[a][1][3]= 1.0;
862                         }
863
864                         blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
865                         if(do_alpha_pass && GMS.alphapass)
866                                 GMS.matbuf[a][0][3]= ma->alpha;
867                         else
868                                 GMS.matbuf[a][0][3]= 1.0f;
869                 }
870
871                 /* setting do_alpha_pass = 1 indicates this object needs to be
872                  * drawn in a second alpha pass for improved blending */
873                 if(do_alpha_pass) {
874                         GMS.blendmode[a]= blendmode;
875                         if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass)
876                                 *do_alpha_pass= 1;
877                 }
878         }
879
880         /* let's start with a clean state */
881         GPU_disable_material();
882 }
883
884 int GPU_enable_material(int nr, void *attribs)
885 {
886         GPUVertexAttribs *gattribs = attribs;
887         GPUMaterial *gpumat;
888         GPUBlendMode blendmode;
889
890         /* prevent index to use un-initialized array items */
891         if(nr>GMS.totmat)
892                 nr= GMS.totmat;
893
894         if(gattribs)
895                 memset(gattribs, 0, sizeof(*gattribs));
896
897         /* keep current material */
898         if(nr>=MAXMATBUF || nr==GMS.lastmatnr)
899                 return GMS.lastretval;
900
901         /* unbind glsl material */
902         if(GMS.gboundmat) {
903                 if(GMS.alphapass) glDepthMask(0);
904                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
905                 GMS.gboundmat= NULL;
906         }
907
908         /* draw materials with alpha in alpha pass */
909         GMS.lastmatnr = nr;
910         GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
911         if(GMS.alphapass)
912                 GMS.lastretval = !GMS.lastretval;
913
914         if(GMS.lastretval) {
915                 if(gattribs && GMS.gmatbuf[nr]) {
916                         /* bind glsl material and get attributes */
917                         Material *mat = GMS.gmatbuf[nr];
918
919                         gpumat = GPU_material_from_blender(GMS.gscene, mat);
920                         GPU_material_vertex_attributes(gpumat, gattribs);
921                         GPU_material_bind(gpumat, GMS.gob->lay, G.vd->lay, 1.0);
922                         GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, G.vd->viewmat, G.vd->viewinv, GMS.gob->col);
923                         GMS.gboundmat= mat;
924
925                         if(GMS.alphapass) glDepthMask(1);
926                 }
927                 else {
928                         /* or do fixed function opengl material */
929                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr][0]);
930                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr][1]);
931                 }
932
933                 /* set (alpha) blending mode */
934                 blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID;
935                 GPU_set_material_blend_mode(blendmode);
936         }
937
938         return GMS.lastretval;
939 }
940
941 void GPU_set_material_blend_mode(int blendmode)
942 {
943         if(GMS.lastblendmode == blendmode)
944                 return;
945         
946         gpu_set_blend_mode(blendmode);
947         GMS.lastblendmode = blendmode;
948 }
949
950 int GPU_get_material_blend_mode(void)
951 {
952         return GMS.lastblendmode;
953 }
954
955 void GPU_disable_material(void)
956 {
957         GMS.lastmatnr= -1;
958         GMS.lastretval= 1;
959
960         if(GMS.gboundmat) {
961                 if(GMS.alphapass) glDepthMask(0);
962                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
963                 GMS.gboundmat= NULL;
964         }
965
966         GPU_set_material_blend_mode(GPU_BLEND_SOLID);
967 }
968
969 /* Lights */
970
971 int GPU_default_lights(void)
972 {
973         int a, count = 0;
974         
975         /* initialize */
976         if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
977                 U.light[0].flag= 1;
978                 U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
979                 U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
980                 U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
981                 U.light[0].spec[3]= 1.0;
982                 
983                 U.light[1].flag= 0;
984                 U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
985                 U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
986                 U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
987                 U.light[1].spec[3]= 1.0;
988         
989                 U.light[2].flag= 0;
990                 U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
991                 U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
992                 U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
993                 U.light[2].spec[3]= 1.0;
994         }
995
996         glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); 
997         glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); 
998         glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); 
999
1000         glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); 
1001         glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); 
1002         glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); 
1003
1004         glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); 
1005         glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); 
1006         glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); 
1007
1008         for(a=0; a<8; a++) {
1009                 if(a<3) {
1010                         if(U.light[a].flag) {
1011                                 glEnable(GL_LIGHT0+a);
1012                                 count++;
1013                         }
1014                         else
1015                                 glDisable(GL_LIGHT0+a);
1016                         
1017                         // clear stuff from other opengl lamp usage
1018                         glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
1019                         glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
1020                         glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
1021                 }
1022                 else
1023                         glDisable(GL_LIGHT0+a);
1024         }
1025         
1026         glDisable(GL_LIGHTING);
1027
1028         glDisable(GL_COLOR_MATERIAL);
1029
1030         return count;
1031 }
1032
1033 int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4])
1034 {
1035         Base *base;
1036         Lamp *la;
1037         int count;
1038         float position[4], direction[4], energy[4];
1039         
1040         /* disable all lights */
1041         for(count=0; count<8; count++)
1042                 glDisable(GL_LIGHT0+count);
1043         
1044         count= 0;
1045         
1046         for(base=scene->base.first; base; base=base->next) {
1047                 if(base->object->type!=OB_LAMP)
1048                         continue;
1049
1050                 if(!(base->lay & lay) || !(base->lay & ob->lay))
1051                         continue;
1052
1053                 la= base->object->data;
1054                 
1055                 /* setup lamp transform */
1056                 glPushMatrix();
1057                 glLoadMatrixf((float *)viewmat);
1058                 
1059                 where_is_object_simul(base->object);
1060                 
1061                 if(la->type==LA_SUN) {
1062                         /* sun lamp */
1063                         VECCOPY(direction, base->object->obmat[2]);
1064                         direction[3]= 0.0;
1065
1066                         glLightfv(GL_LIGHT0+count, GL_POSITION, direction); 
1067                 }
1068                 else {
1069                         /* other lamps with attenuation */
1070                         VECCOPY(position, base->object->obmat[3]);
1071                         position[3]= 1.0f;
1072
1073                         glLightfv(GL_LIGHT0+count, GL_POSITION, position); 
1074                         glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
1075                         glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
1076                         glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
1077                         
1078                         if(la->type==LA_SPOT) {
1079                                 /* spot lamp */
1080                                 direction[0]= -base->object->obmat[2][0];
1081                                 direction[1]= -base->object->obmat[2][1];
1082                                 direction[2]= -base->object->obmat[2][2];
1083                                 glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction);
1084                                 glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0);
1085                                 glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend);
1086                         }
1087                         else
1088                                 glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
1089                 }
1090                 
1091                 /* setup energy */
1092                 energy[0]= la->energy*la->r;
1093                 energy[1]= la->energy*la->g;
1094                 energy[2]= la->energy*la->b;
1095                 energy[3]= 1.0;
1096
1097                 glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); 
1098                 glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy);
1099                 glEnable(GL_LIGHT0+count);
1100                 
1101                 glPopMatrix();                                  
1102                 
1103                 count++;
1104                 if(count==8)
1105                         break;
1106         }
1107
1108         return count;
1109 }
1110
1111 /* Default OpenGL State */
1112
1113 void GPU_state_init(void)
1114 {
1115         /* also called when doing opengl rendering and in the game engine */
1116         float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
1117         float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
1118         float mat_shininess[] = { 35.0 };
1119         int a, x, y;
1120         GLubyte pat[32*32];
1121         const GLubyte *patc= pat;
1122         
1123         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
1124         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
1125         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1126         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1127
1128         GPU_default_lights();
1129         
1130         /* no local viewer, looks ugly in ortho mode */
1131         /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
1132         
1133         glDepthFunc(GL_LEQUAL);
1134         /* scaling matrices */
1135         glEnable(GL_NORMALIZE);
1136
1137         glShadeModel(GL_FLAT);
1138
1139         glDisable(GL_ALPHA_TEST);
1140         glDisable(GL_BLEND);
1141         glDisable(GL_DEPTH_TEST);
1142         glDisable(GL_FOG);
1143         glDisable(GL_LIGHTING);
1144         glDisable(GL_LOGIC_OP);
1145         glDisable(GL_STENCIL_TEST);
1146         glDisable(GL_TEXTURE_1D);
1147         glDisable(GL_TEXTURE_2D);
1148
1149         /* default on, disable/enable should be local per function */
1150         glEnableClientState(GL_VERTEX_ARRAY);
1151         glEnableClientState(GL_NORMAL_ARRAY);
1152         
1153         glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
1154         glPixelTransferi(GL_RED_SCALE, 1);
1155         glPixelTransferi(GL_RED_BIAS, 0);
1156         glPixelTransferi(GL_GREEN_SCALE, 1);
1157         glPixelTransferi(GL_GREEN_BIAS, 0);
1158         glPixelTransferi(GL_BLUE_SCALE, 1);
1159         glPixelTransferi(GL_BLUE_BIAS, 0);
1160         glPixelTransferi(GL_ALPHA_SCALE, 1);
1161         glPixelTransferi(GL_ALPHA_BIAS, 0);
1162         
1163         glPixelTransferi(GL_DEPTH_BIAS, 0);
1164         glPixelTransferi(GL_DEPTH_SCALE, 1);
1165         glDepthRange(0.0, 1.0);
1166         
1167         a= 0;
1168         for(x=0; x<32; x++) {
1169                 for(y=0; y<4; y++) {
1170                         if( (x) & 1) pat[a++]= 0x88;
1171                         else pat[a++]= 0x22;
1172                 }
1173         }
1174         
1175         glPolygonStipple(patc);
1176
1177         glMatrixMode(GL_TEXTURE);
1178         glLoadIdentity();
1179         glMatrixMode(GL_MODELVIEW);
1180
1181         glFrontFace(GL_CCW);
1182         glCullFace(GL_BACK);
1183         glDisable(GL_CULL_FACE);
1184 }
1185