prevent crash in gpu_draw.c, so tilemode might not have GLSL/GPU features
[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()
224 {
225         /* linearmipmap is off by default
226          * when mipmapping is off, use unfiltered display */
227         return GTS.linearmipmap? GL_LINEAR_MIPMAP_LINEAR :
228                                 (GTS.domipmap ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST);
229 }
230
231 /* Set OpenGL state for an MTFace */
232
233 static void gpu_make_repbind(Image *ima)
234 {
235         ImBuf *ibuf;
236         
237         ibuf = BKE_image_get_ibuf(ima, NULL);
238         if(ibuf==NULL)
239                 return;
240
241         if(ima->repbind) {
242                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
243                 MEM_freeN(ima->repbind);
244                 ima->repbind= 0;
245                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
246         }
247
248         ima->totbind= ima->xrep*ima->yrep;
249
250         if(ima->totbind>1)
251                 ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
252 }
253
254 static void gpu_clear_tpage()
255 {
256         if(GTS.lasttface==0)
257                 return;
258         
259         GTS.lasttface= 0;
260         GTS.curtile= 0;
261         GTS.curima= 0;
262         if(GTS.curtilemode!=0) {
263                 glMatrixMode(GL_TEXTURE);
264                 glLoadIdentity();
265                 glMatrixMode(GL_MODELVIEW);
266         }
267         GTS.curtilemode= 0;
268         GTS.curtileXRep=0;
269         GTS.curtileYRep=0;
270         GTS.alphamode= -1;
271         
272         glDisable(GL_BLEND);
273         glDisable(GL_TEXTURE_2D);
274         glDisable(GL_TEXTURE_GEN_S);
275         glDisable(GL_TEXTURE_GEN_T);
276         glDisable(GL_ALPHA_TEST);
277 }
278
279 static void gpu_set_blend_mode(GPUBlendMode blendmode)
280 {
281         if(blendmode == GPU_BLEND_SOLID) {
282                 glDisable(GL_BLEND);
283                 glDisable(GL_ALPHA_TEST);
284                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
285         }
286         else if(blendmode==GPU_BLEND_ADD) {
287                 glEnable(GL_BLEND);
288                 glBlendFunc(GL_ONE, GL_ONE);
289                 glDisable(GL_ALPHA_TEST);
290         }
291         else if(blendmode==GPU_BLEND_ALPHA) {
292                 glEnable(GL_BLEND);
293                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
294                 
295                 /* if U.glalphaclip == 1.0, some cards go bonkers...
296                  * turn off alpha test in this case */
297
298                 /* added after 2.45 to clip alpha */
299                 if(U.glalphaclip == 1.0) {
300                         glDisable(GL_ALPHA_TEST);
301                 }
302                 else {
303                         glEnable(GL_ALPHA_TEST);
304                         glAlphaFunc(GL_GREATER, U.glalphaclip);
305                 }
306         }
307         else if(blendmode==GPU_BLEND_CLIP) {
308                 glDisable(GL_BLEND); 
309                 glEnable(GL_ALPHA_TEST);
310                 glAlphaFunc(GL_GREATER, 0.5f);
311         }
312 }
313
314 static void gpu_verify_alpha_mode(MTFace *tface)
315 {
316         /* verify alpha blending modes */
317         if(GTS.alphamode == tface->transp)
318                 return;
319
320         gpu_set_blend_mode(tface->transp);
321         GTS.alphamode= tface->transp;
322 }
323
324 static void gpu_verify_reflection(Image *ima)
325 {
326         if (ima && (ima->flag & IMA_REFLECT)) {
327                 /* enable reflection mapping */
328                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
329                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
330
331                 glEnable(GL_TEXTURE_GEN_S);
332                 glEnable(GL_TEXTURE_GEN_T);
333         }
334         else {
335                 /* disable reflection mapping */
336                 glDisable(GL_TEXTURE_GEN_S);
337                 glDisable(GL_TEXTURE_GEN_T);
338         }
339 }
340
341 int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare)
342 {
343         ImBuf *ibuf = NULL;
344         unsigned int *bind = NULL;
345         int rectw, recth, tpx=0, tpy=0, y;
346         unsigned int *rectrow, *tilerectrow;
347         unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL;
348         short texwindx, texwindy, texwinsx, texwinsy;
349
350         /* initialize tile mode and number of repeats */
351         GTS.ima = ima;
352         GTS.tilemode= (tfmode & TF_TILES) || (ima && (ima->tpageflag & IMA_TWINANIM));
353         GTS.tileXRep = 0;
354         GTS.tileYRep = 0;
355
356         /* setting current tile according to frame */
357         if(ima && (ima->tpageflag & IMA_TWINANIM))
358                 GTS.tile= ima->lastframe;
359         else
360                 GTS.tile= tftile;
361
362         if(ima) {
363                 GTS.tileXRep = ima->xrep;
364                 GTS.tileYRep = ima->yrep;
365         }
366
367         /* if same image & tile, we're done */
368         if(compare && ima == GTS.curima && GTS.curtile == GTS.tile &&
369            GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep &&
370            GTS.curtileYRep == GTS.tileYRep)
371                 return (ima!=0);
372
373         /* if tiling mode or repeat changed, change texture matrix to fit */
374         if(GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep ||
375            GTS.curtileYRep != GTS.tileYRep) {
376
377                 glMatrixMode(GL_TEXTURE);
378                 glLoadIdentity();
379
380                 if((tfmode & TF_TILES) && ima!=NULL)
381                         glScalef(ima->xrep, ima->yrep, 1.0);
382
383                 glMatrixMode(GL_MODELVIEW);
384         }
385
386         /* check if we have a valid image */
387         if(ima==NULL || ima->ok==0)
388                 return 0;
389
390         /* check if we have a valid image buffer */
391         ibuf= BKE_image_get_ibuf(ima, NULL);
392
393         if(ibuf==NULL)
394                 return 0;
395
396         /* ensure we have a char buffer and not only float */
397         if ((ibuf->rect==NULL) && ibuf->rect_float)
398                 IMB_rect_from_float(ibuf);
399
400         if(GTS.tilemode) {
401                 /* tiled mode */
402                 if(ima->repbind==0) gpu_make_repbind(ima);
403                 if(GTS.tile>=ima->totbind) GTS.tile= 0;
404                 
405                 /* this happens when you change repeat buttons */
406                 if(ima->repbind) bind= &ima->repbind[GTS.tile];
407                 else bind= &ima->bindcode;
408                 
409                 if(*bind==0) {
410                         
411                         texwindx= ibuf->x/ima->xrep;
412                         texwindy= ibuf->y/ima->yrep;
413                         
414                         if(GTS.tile>=ima->xrep*ima->yrep)
415                                 GTS.tile= ima->xrep*ima->yrep-1;
416         
417                         texwinsy= GTS.tile / ima->xrep;
418                         texwinsx= GTS.tile - texwinsy*ima->xrep;
419         
420                         texwinsx*= texwindx;
421                         texwinsy*= texwindy;
422         
423                         tpx= texwindx;
424                         tpy= texwindy;
425
426                         rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
427                 }
428         }
429         else {
430                 /* regular image mode */
431                 bind= &ima->bindcode;
432                 
433                 if(*bind==0) {
434                         tpx= ibuf->x;
435                         tpy= ibuf->y;
436                         rect= ibuf->rect;
437                 }
438         }
439
440         if(*bind != 0) {
441                 /* enable opengl drawing with textures */
442                 glBindTexture(GL_TEXTURE_2D, *bind);
443                 return *bind;
444         }
445
446         rectw = tpx;
447         recth = tpy;
448
449         /* for tiles, copy only part of image into buffer */
450         if (GTS.tilemode) {
451                 return 0; //disabled for now, it causes crashes
452                 //see http://projects.blender.org/tracker/index.php?func=detail&aid=17819&group_id=9&atid=125
453
454                 tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
455
456                 for (y=0; y<recth; y++) {
457                         rectrow= &rect[y*ibuf->x];
458                         tilerectrow= &tilerect[y*rectw];
459                                 
460                         memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
461                 }
462                         
463                 rect= tilerect;
464         }
465
466         /* scale if not a power of two */
467         if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) {
468                 rectw= smaller_pow2_limit(rectw);
469                 recth= smaller_pow2_limit(recth);
470                 
471                 scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
472                 gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
473                 rect= scalerect;
474         }
475
476         /* create image */
477         glGenTextures(1, (GLuint *)bind);
478         glBindTexture( GL_TEXTURE_2D, *bind);
479
480         if (!gpu_get_mipmap()) {
481                 glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
482                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
483                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter());
484         }
485         else {
486                 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
487                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter());
488                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter());
489
490                 ima->tpageflag |= IMA_MIPMAP_COMPLETE;
491         }
492
493         /* set to modulate with vertex color */
494         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
495                 
496         /* clean up */
497         if (tilerect)
498                 MEM_freeN(tilerect);
499         if (scalerect)
500                 MEM_freeN(scalerect);
501
502         return *bind;
503 }
504
505 static void gpu_verify_repeat(Image *ima)
506 {
507         /* set either clamp or repeat in X/Y */
508         if (ima->tpageflag & IMA_CLAMP_U)
509            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
510         else
511                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
512
513         if (ima->tpageflag & IMA_CLAMP_V)
514                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
515         else
516                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
517 }
518
519 int GPU_set_tpage(MTFace *tface)
520 {
521         Image *ima;
522         
523         /* check if we need to clear the state */
524         if(tface==0) {
525                 gpu_clear_tpage();
526                 return 0;
527         }
528
529         ima= tface->tpage;
530         GTS.lasttface= tface;
531
532         gpu_verify_alpha_mode(tface);
533         gpu_verify_reflection(ima);
534
535         if(GPU_verify_image(ima, tface->tile, tface->mode, 1)) {
536                 GTS.curtile= GTS.tile;
537                 GTS.curima= GTS.ima;
538                 GTS.curtilemode= GTS.tilemode;
539                 GTS.curtileXRep = GTS.tileXRep;
540                 GTS.curtileYRep = GTS.tileYRep;
541
542                 glEnable(GL_TEXTURE_2D);
543         }
544         else {
545                 glDisable(GL_TEXTURE_2D);
546                 
547                 GTS.curtile= 0;
548                 GTS.curima= 0;
549                 GTS.curtilemode= 0;
550                 GTS.curtileXRep = 0;
551                 GTS.curtileYRep = 0;
552
553                 return 0;
554         }
555         
556         gpu_verify_repeat(ima);
557         
558         /* Did this get lost in the image recode? */
559         /* tag_image_time(ima);*/
560
561         return 1;
562 }
563
564 /* these two functions are called on entering and exiting texture paint mode,
565    temporary disabling/enabling mipmapping on all images for quick texture
566    updates with glTexSubImage2D. images that didn't change don't have to be
567    re-uploaded to OpenGL */
568 void GPU_paint_set_mipmap(int mipmap)
569 {
570         Image* ima;
571         
572         if(!GTS.domipmap)
573                 return;
574
575         if(mipmap) {
576                 for(ima=G.main->image.first; ima; ima=ima->id.next) {
577                         if(ima->bindcode) {
578                                 if(ima->tpageflag & IMA_MIPMAP_COMPLETE) {
579                                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
580                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter());
581                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter());
582                                 }
583                                 else
584                                         GPU_free_image(ima);
585                         }
586                 }
587
588         }
589         else {
590                 for(ima=G.main->image.first; ima; ima=ima->id.next) {
591                         if(ima->bindcode) {
592                                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
593                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
594                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter());
595                         }
596                 }
597         }
598 }
599
600 void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
601 {
602         ImBuf *ibuf;
603         
604         ibuf = BKE_image_get_ibuf(ima, NULL);
605         
606         if (ima->repbind || gpu_get_mipmap() || !ima->bindcode || !ibuf ||
607                 (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) ||
608                 (w == 0) || (h == 0)) {
609                 /* these cases require full reload still */
610                 GPU_free_image(ima);
611         }
612         else {
613                 /* for the special case, we can do a partial update
614                  * which is much quicker for painting */
615                 GLint row_length, skip_pixels, skip_rows;
616
617                 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
618                 glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
619                 glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
620
621                 if ((ibuf->rect==NULL) && ibuf->rect_float)
622                         IMB_rect_from_float(ibuf);
623
624                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
625
626                 glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
627                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
628                 glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
629
630                 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
631                         GL_UNSIGNED_BYTE, ibuf->rect);
632
633                 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
634                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
635                 glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
636
637                 if(ima->tpageflag & IMA_MIPMAP_COMPLETE)
638                         ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
639         }
640 }
641
642 void GPU_update_images_framechange(void)
643 {
644         Image *ima;
645         
646         for(ima=G.main->image.first; ima; ima=ima->id.next) {
647                 if(ima->tpageflag & IMA_TWINANIM) {
648                         if(ima->twend >= ima->xrep*ima->yrep)
649                                 ima->twend= ima->xrep*ima->yrep-1;
650                 
651                         /* check: is bindcode not in the array? free. (to do) */
652                         
653                         ima->lastframe++;
654                         if(ima->lastframe > ima->twend)
655                                 ima->lastframe= ima->twsta;
656                 }
657         }
658 }
659
660 int GPU_update_image_time(Image *ima, double time)
661 {
662         int     inc = 0;
663         float   diff;
664         int     newframe;
665
666         if (!ima)
667                 return 0;
668
669         if (ima->lastupdate<0)
670                 ima->lastupdate = 0;
671
672         if (ima->lastupdate>time)
673                 ima->lastupdate=(float)time;
674
675         if(ima->tpageflag & IMA_TWINANIM) {
676                 if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
677                 
678                 /* check: is the bindcode not in the array? Then free. (still to do) */
679                 
680                 diff = (float)(time-ima->lastupdate);
681                 inc = (int)(diff*(float)ima->animspeed);
682
683                 ima->lastupdate+=((float)inc/(float)ima->animspeed);
684
685                 newframe = ima->lastframe+inc;
686
687                 if(newframe > (int)ima->twend) {
688                         if(ima->twend-ima->twsta != 0)
689                                 newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
690                         else
691                                 newframe = ima->twsta;
692                 }
693
694                 ima->lastframe = newframe;
695         }
696
697         return inc;
698 }
699
700 void GPU_free_image(Image *ima)
701 {
702         /* free regular image binding */
703         if(ima->bindcode) {
704                 glDeleteTextures(1, (GLuint *)&ima->bindcode);
705                 ima->bindcode= 0;
706                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
707         }
708
709         /* free glsl image binding */
710         if(ima->gputexture) {
711                 GPU_texture_free(ima->gputexture);
712                 ima->gputexture= NULL;
713         }
714
715         /* free repeated image binding */
716         if(ima->repbind) {
717                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
718         
719                 MEM_freeN(ima->repbind);
720                 ima->repbind= NULL;
721                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
722         }
723 }
724
725 void GPU_free_images(void)
726 {
727         Image* ima;
728
729         if(G.main)
730                 for(ima=G.main->image.first; ima; ima=ima->id.next)
731                         GPU_free_image(ima);
732 }
733
734 /* OpenGL Materials */
735
736 /* materials start counting at # one.... */
737 #define MAXMATBUF (MAXMAT+1)
738
739 /* OpenGL state caching for materials */
740
741 static struct GPUMaterialState {
742         float matbuf[MAXMATBUF][2][4];
743         int totmat;
744
745         Material *gmatbuf[MAXMATBUF];
746         Material *gboundmat;
747         Object *gob;
748         Scene *gscene;
749
750         GPUBlendMode blendmode[MAXMATBUF];
751         int alphapass;
752
753         int lastmatnr, lastretval;
754         GPUBlendMode lastblendmode;
755 } GMS;
756
757 Material *gpu_active_node_material(Material *ma)
758 {
759         if(ma && ma->use_nodes && ma->nodetree) {
760                 bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
761
762                 if(node)
763                         return (Material *)node->id;
764                 else
765                         return NULL;
766         }
767
768         return ma;
769 }
770
771 void GPU_set_object_materials(Scene *scene, Object *ob, int glsl, int *do_alpha_pass)
772 {
773         extern Material defmaterial; /* from material.c */
774         Material *ma;
775         GPUMaterial *gpumat;
776         GPUBlendMode blendmode;
777         int a;
778         
779         /* initialize state */
780         memset(&GMS, 0, sizeof(GMS));
781         GMS.lastmatnr = -1;
782         GMS.lastretval = -1;
783         GMS.lastblendmode = GPU_BLEND_SOLID;
784
785         GMS.gob = ob;
786         GMS.gscene = scene;
787         GMS.totmat= ob->totcol;
788
789         GMS.alphapass = (G.vd && G.vd->transp);
790         if(do_alpha_pass)
791                 *do_alpha_pass = 0;
792
793         /* no materials assigned? */
794         if(ob->totcol==0) {
795                 GMS.matbuf[0][0][0]= defmaterial.r;
796                 GMS.matbuf[0][0][1]= defmaterial.g;
797                 GMS.matbuf[0][0][2]= defmaterial.b;
798                 GMS.matbuf[0][0][3]= 1.0;
799
800                 GMS.matbuf[0][1][0]= defmaterial.specr;
801                 GMS.matbuf[0][1][1]= defmaterial.specg;
802                 GMS.matbuf[0][1][2]= defmaterial.specb;
803                 GMS.matbuf[0][1][3]= 1.0;
804                 
805                 /* do material 1 too, for displists! */
806                 QUATCOPY(GMS.matbuf[1][0], GMS.matbuf[0][0]);
807                 QUATCOPY(GMS.matbuf[1][1], GMS.matbuf[0][1]);
808
809                 if(glsl) {
810                         GMS.gmatbuf[0]= &defmaterial;
811                         GPU_material_from_blender(GMS.gscene, &defmaterial);
812                 }
813
814                 GMS.blendmode[0]= GPU_BLEND_SOLID;
815         }
816         
817         /* setup materials */
818         for(a=1; a<=ob->totcol; a++) {
819                 /* find a suitable material */
820                 ma= give_current_material(ob, a);
821                 if(!glsl) ma= gpu_active_node_material(ma);
822                 if(ma==NULL) ma= &defmaterial;
823
824                 /* this shouldn't happen .. */
825                 if(a>=MAXMATBUF)
826                         continue;
827
828                 /* create glsl material if requested */
829                 gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
830
831                 if(gpumat) {
832                         /* do glsl only if creating it succeed, else fallback */
833                         GMS.gmatbuf[a]= ma;
834                         blendmode = GPU_material_blend_mode(gpumat, ob->col);
835                 }
836                 else {
837                         /* fixed function opengl materials */
838                         if (ma->mode & MA_SHLESS) {
839                                 GMS.matbuf[a][0][0]= ma->r;
840                                 GMS.matbuf[a][0][1]= ma->g;
841                                 GMS.matbuf[a][0][2]= ma->b;
842                         } else {
843                                 GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r;
844                                 GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g;
845                                 GMS.matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b;
846
847                                 GMS.matbuf[a][1][0]= ma->spec*ma->specr;
848                                 GMS.matbuf[a][1][1]= ma->spec*ma->specg;
849                                 GMS.matbuf[a][1][2]= ma->spec*ma->specb;
850                                 GMS.matbuf[a][1][3]= 1.0;
851                         }
852
853                         blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
854                         if(do_alpha_pass && GMS.alphapass)
855                                 GMS.matbuf[a][0][3]= ma->alpha;
856                         else
857                                 GMS.matbuf[a][0][3]= 1.0f;
858                 }
859
860                 /* setting do_alpha_pass = 1 indicates this object needs to be
861                  * drawn in a second alpha pass for improved blending */
862                 if(do_alpha_pass) {
863                         GMS.blendmode[a]= blendmode;
864                         if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass)
865                                 *do_alpha_pass= 1;
866                 }
867         }
868
869         /* let's start with a clean state */
870         GPU_disable_material();
871 }
872
873 int GPU_enable_material(int nr, void *attribs)
874 {
875         GPUVertexAttribs *gattribs = attribs;
876         GPUMaterial *gpumat;
877         GPUBlendMode blendmode;
878
879         /* prevent index to use un-initialized array items */
880         if(nr>GMS.totmat)
881                 nr= GMS.totmat;
882
883         if(gattribs)
884                 memset(gattribs, 0, sizeof(*gattribs));
885
886         /* keep current material */
887         if(nr>=MAXMATBUF || nr==GMS.lastmatnr)
888                 return GMS.lastretval;
889
890         /* unbind glsl material */
891         if(GMS.gboundmat) {
892                 if(GMS.alphapass) glDepthMask(0);
893                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
894                 GMS.gboundmat= NULL;
895         }
896
897         /* draw materials with alpha in alpha pass */
898         GMS.lastmatnr = nr;
899         GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
900         if(GMS.alphapass)
901                 GMS.lastretval = !GMS.lastretval;
902
903         if(GMS.lastretval) {
904                 if(gattribs && GMS.gmatbuf[nr]) {
905                         /* bind glsl material and get attributes */
906                         Material *mat = GMS.gmatbuf[nr];
907
908                         gpumat = GPU_material_from_blender(GMS.gscene, mat);
909                         GPU_material_vertex_attributes(gpumat, gattribs);
910                         GPU_material_bind(gpumat, GMS.gob->lay, G.vd->lay, 1.0);
911                         GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, G.vd->viewmat, G.vd->viewinv, GMS.gob->col);
912                         GMS.gboundmat= mat;
913
914                         if(GMS.alphapass) glDepthMask(1);
915                 }
916                 else {
917                         /* or do fixed function opengl material */
918                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr][0]);
919                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr][1]);
920                 }
921
922                 /* set (alpha) blending mode */
923                 blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID;
924                 GPU_set_material_blend_mode(blendmode);
925         }
926
927         return GMS.lastretval;
928 }
929
930 void GPU_set_material_blend_mode(int blendmode)
931 {
932         if(GMS.lastblendmode == blendmode)
933                 return;
934         
935         gpu_set_blend_mode(blendmode);
936         GMS.lastblendmode = blendmode;
937 }
938
939 int GPU_get_material_blend_mode(void)
940 {
941         return GMS.lastblendmode;
942 }
943
944 void GPU_disable_material(void)
945 {
946         GMS.lastmatnr= -1;
947         GMS.lastretval= 1;
948
949         if(GMS.gboundmat) {
950                 if(GMS.alphapass) glDepthMask(0);
951                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
952                 GMS.gboundmat= NULL;
953         }
954
955         GPU_set_material_blend_mode(GPU_BLEND_SOLID);
956 }
957
958 /* Lights */
959
960 int GPU_default_lights(void)
961 {
962         int a, count = 0;
963         
964         /* initialize */
965         if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
966                 U.light[0].flag= 1;
967                 U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
968                 U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
969                 U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
970                 U.light[0].spec[3]= 1.0;
971                 
972                 U.light[1].flag= 0;
973                 U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
974                 U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
975                 U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
976                 U.light[1].spec[3]= 1.0;
977         
978                 U.light[2].flag= 0;
979                 U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
980                 U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
981                 U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
982                 U.light[2].spec[3]= 1.0;
983         }
984
985         glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); 
986         glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); 
987         glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); 
988
989         glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); 
990         glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); 
991         glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); 
992
993         glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); 
994         glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); 
995         glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); 
996
997         for(a=0; a<8; a++) {
998                 if(a<3) {
999                         if(U.light[a].flag) {
1000                                 glEnable(GL_LIGHT0+a);
1001                                 count++;
1002                         }
1003                         else
1004                                 glDisable(GL_LIGHT0+a);
1005                         
1006                         // clear stuff from other opengl lamp usage
1007                         glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
1008                         glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
1009                         glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
1010                 }
1011                 else
1012                         glDisable(GL_LIGHT0+a);
1013         }
1014         
1015         glDisable(GL_LIGHTING);
1016
1017         glDisable(GL_COLOR_MATERIAL);
1018
1019         return count;
1020 }
1021
1022 int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4])
1023 {
1024         Base *base;
1025         Lamp *la;
1026         int count;
1027         float position[4], direction[4], energy[4];
1028         
1029         /* disable all lights */
1030         for(count=0; count<8; count++)
1031                 glDisable(GL_LIGHT0+count);
1032         
1033         count= 0;
1034         
1035         for(base=scene->base.first; base; base=base->next) {
1036                 if(base->object->type!=OB_LAMP)
1037                         continue;
1038
1039                 if(!(base->lay & lay) || !(base->lay & ob->lay))
1040                         continue;
1041
1042                 la= base->object->data;
1043                 
1044                 /* setup lamp transform */
1045                 glPushMatrix();
1046                 glLoadMatrixf((float *)viewmat);
1047                 
1048                 where_is_object_simul(base->object);
1049                 
1050                 if(la->type==LA_SUN) {
1051                         /* sun lamp */
1052                         VECCOPY(direction, base->object->obmat[2]);
1053                         direction[3]= 0.0;
1054
1055                         glLightfv(GL_LIGHT0+count, GL_POSITION, direction); 
1056                 }
1057                 else {
1058                         /* other lamps with attenuation */
1059                         VECCOPY(position, base->object->obmat[3]);
1060                         position[3]= 1.0f;
1061
1062                         glLightfv(GL_LIGHT0+count, GL_POSITION, position); 
1063                         glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
1064                         glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
1065                         glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
1066                         
1067                         if(la->type==LA_SPOT) {
1068                                 /* spot lamp */
1069                                 direction[0]= -base->object->obmat[2][0];
1070                                 direction[1]= -base->object->obmat[2][1];
1071                                 direction[2]= -base->object->obmat[2][2];
1072                                 glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction);
1073                                 glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0);
1074                                 glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend);
1075                         }
1076                         else
1077                                 glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
1078                 }
1079                 
1080                 /* setup energy */
1081                 energy[0]= la->energy*la->r;
1082                 energy[1]= la->energy*la->g;
1083                 energy[2]= la->energy*la->b;
1084                 energy[3]= 1.0;
1085
1086                 glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); 
1087                 glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy);
1088                 glEnable(GL_LIGHT0+count);
1089                 
1090                 glPopMatrix();                                  
1091                 
1092                 count++;
1093                 if(count==8)
1094                         break;
1095         }
1096
1097         return count;
1098 }
1099
1100 /* Default OpenGL State */
1101
1102 void GPU_state_init(void)
1103 {
1104         /* also called when doing opengl rendering and in the game engine */
1105         float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
1106         float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
1107         float mat_shininess[] = { 35.0 };
1108         int a, x, y;
1109         GLubyte pat[32*32];
1110         const GLubyte *patc= pat;
1111         
1112         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
1113         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
1114         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
1115         glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess);
1116
1117         GPU_default_lights();
1118         
1119         /* no local viewer, looks ugly in ortho mode */
1120         /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
1121         
1122         glDepthFunc(GL_LEQUAL);
1123         /* scaling matrices */
1124         glEnable(GL_NORMALIZE);
1125
1126         glShadeModel(GL_FLAT);
1127
1128         glDisable(GL_ALPHA_TEST);
1129         glDisable(GL_BLEND);
1130         glDisable(GL_DEPTH_TEST);
1131         glDisable(GL_FOG);
1132         glDisable(GL_LIGHTING);
1133         glDisable(GL_LOGIC_OP);
1134         glDisable(GL_STENCIL_TEST);
1135         glDisable(GL_TEXTURE_1D);
1136         glDisable(GL_TEXTURE_2D);
1137
1138         /* default on, disable/enable should be local per function */
1139         glEnableClientState(GL_VERTEX_ARRAY);
1140         glEnableClientState(GL_NORMAL_ARRAY);
1141         
1142         glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
1143         glPixelTransferi(GL_RED_SCALE, 1);
1144         glPixelTransferi(GL_RED_BIAS, 0);
1145         glPixelTransferi(GL_GREEN_SCALE, 1);
1146         glPixelTransferi(GL_GREEN_BIAS, 0);
1147         glPixelTransferi(GL_BLUE_SCALE, 1);
1148         glPixelTransferi(GL_BLUE_BIAS, 0);
1149         glPixelTransferi(GL_ALPHA_SCALE, 1);
1150         glPixelTransferi(GL_ALPHA_BIAS, 0);
1151         
1152         glPixelTransferi(GL_DEPTH_BIAS, 0);
1153         glPixelTransferi(GL_DEPTH_SCALE, 1);
1154         glDepthRange(0.0, 1.0);
1155         
1156         a= 0;
1157         for(x=0; x<32; x++) {
1158                 for(y=0; y<4; y++) {
1159                         if( (x) & 1) pat[a++]= 0x88;
1160                         else pat[a++]= 0x22;
1161                 }
1162         }
1163         
1164         glPolygonStipple(patc);
1165
1166         glMatrixMode(GL_TEXTURE);
1167         glLoadIdentity();
1168         glMatrixMode(GL_MODELVIEW);
1169
1170         glFrontFace(GL_CCW);
1171         glCullFace(GL_BACK);
1172         glDisable(GL_CULL_FACE);
1173 }
1174