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