CMake: Disable some features when using MinGW and full cmake config
[blender.git] / source / blender / gpu / intern / gpu_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_draw.c
29  *  \ingroup gpu
30  *
31  * Utility functions for dealing with OpenGL texture & material context,
32  * mipmap generation and light objects.
33  *
34  * These are some obscure rendering functions shared between the
35  * game engine and the blender, in this module to avoid duplication
36  * and abstract them away from the rest a bit.
37  */
38
39 #include <string.h>
40
41 #include "GPU_glew.h"
42 #include "GPU_debug.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_linklist.h"
46 #include "BLI_math.h"
47 #include "BLI_threads.h"
48 #include "BLI_utildefines.h"
49
50 #include "DNA_lamp_types.h"
51 #include "DNA_material_types.h"
52 #include "DNA_mesh_types.h"
53 #include "DNA_meshdata_types.h"
54 #include "DNA_modifier_types.h"
55 #include "DNA_node_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_scene_types.h"
58 #include "DNA_smoke_types.h"
59 #include "DNA_view3d_types.h"
60 #include "DNA_particle_types.h"
61
62 #include "MEM_guardedalloc.h"
63
64 #include "IMB_imbuf.h"
65 #include "IMB_imbuf_types.h"
66
67 #include "BKE_bmfont.h"
68 #include "BKE_global.h"
69 #include "BKE_image.h"
70 #include "BKE_main.h"
71 #include "BKE_material.h"
72 #include "BKE_node.h"
73 #include "BKE_object.h"
74 #include "BKE_scene.h"
75 #include "BKE_subsurf.h"
76 #include "BKE_DerivedMesh.h"
77
78 #include "GPU_basic_shader.h"
79 #include "GPU_buffers.h"
80 #include "GPU_draw.h"
81 #include "GPU_extensions.h"
82 #include "GPU_material.h"
83 #include "GPU_shader.h"
84 #include "GPU_texture.h"
85
86 #include "PIL_time.h"
87
88 #include "smoke_API.h"
89
90 #ifdef WITH_OPENSUBDIV
91 #  include "DNA_mesh_types.h"
92 #  include "BKE_editmesh.h"
93
94 #  include "gpu_codegen.h"
95 #endif
96
97 extern Material defmaterial; /* from material.c */
98
99 /* Text Rendering */
100
101 static void gpu_mcol(unsigned int ucol)
102 {
103         /* mcol order is swapped */
104         const char *cp = (char *)&ucol;
105         glColor3ub(cp[3], cp[2], cp[1]);
106 }
107
108 void GPU_render_text(
109         MTexPoly *mtexpoly, int mode,
110         const char *textstr, int textlen, unsigned int *col,
111         const float *v_quad[4], const float *uv_quad[4],
112         int glattrib)
113 {
114         if ((mode & GEMAT_TEXT) && (textlen > 0) && mtexpoly->tpage) {
115                 const float *v1 = v_quad[0];
116                 const float *v2 = v_quad[1];
117                 const float *v3 = v_quad[2];
118                 const float *v4 = v_quad[3];
119                 Image *ima = (Image *)mtexpoly->tpage;
120                 ImBuf *first_ibuf;
121                 const size_t textlen_st = textlen;
122                 size_t index;
123                 float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
124                 float advance_tab;
125                 
126                 /* multiline */
127                 float line_start = 0.0f, line_height;
128                 
129                 if (v4)
130                         line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
131                 else
132                         line_height = max_fff(v1[1], v2[1], v3[1]) - min_fff(v1[1], v2[1], v3[1]);
133                 line_height *= 1.2f; /* could be an option? */
134                 /* end multiline */
135
136                 
137                 /* color has been set */
138                 if (mtexpoly->mode & TF_OBCOL)
139                         col = NULL;
140                 else if (!col)
141                         glColor3f(1.0f, 1.0f, 1.0f);
142
143                 glPushMatrix();
144                 
145                 /* get the tab width */
146                 first_ibuf = BKE_image_get_first_ibuf(ima);
147                 matrixGlyph(first_ibuf, ' ', &centerx, &centery,
148                         &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
149                 
150                 advance_tab = advance * 4; /* tab width could also be an option */
151                 
152                 
153                 for (index = 0; index < textlen_st; ) {
154                         unsigned int character;
155                         float uv[4][2];
156
157                         /* lets calculate offset stuff */
158                         character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index);
159                         
160                         if (character == '\n') {
161                                 glTranslatef(line_start, -line_height, 0.0f);
162                                 line_start = 0.0f;
163                                 continue;
164                         }
165                         else if (character == '\t') {
166                                 glTranslatef(advance_tab, 0.0f, 0.0f);
167                                 line_start -= advance_tab; /* so we can go back to the start of the line */
168                                 continue;
169                                 
170                         }
171                         else if (character > USHRT_MAX) {
172                                 /* not much we can do here bmfonts take ushort */
173                                 character = '?';
174                         }
175                         
176                         /* space starts at offset 1 */
177                         /* character = character - ' ' + 1; */
178                         matrixGlyph(first_ibuf, character, & centerx, &centery,
179                                 &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
180
181                         uv[0][0] = (uv_quad[0][0] - centerx) * sizex + transx;
182                         uv[0][1] = (uv_quad[0][1] - centery) * sizey + transy;
183                         uv[1][0] = (uv_quad[1][0] - centerx) * sizex + transx;
184                         uv[1][1] = (uv_quad[1][1] - centery) * sizey + transy;
185                         uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx;
186                         uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy;
187                         
188                         glBegin(GL_POLYGON);
189                         if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[0]);
190                         else glTexCoord2fv(uv[0]);
191                         if (col) gpu_mcol(col[0]);
192                         glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
193                         
194                         if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[1]);
195                         else glTexCoord2fv(uv[1]);
196                         if (col) gpu_mcol(col[1]);
197                         glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
198
199                         if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[2]);
200                         else glTexCoord2fv(uv[2]);
201                         if (col) gpu_mcol(col[2]);
202                         glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
203
204                         if (v4) {
205                                 uv[3][0] = (uv_quad[3][0] - centerx) * sizex + transx;
206                                 uv[3][1] = (uv_quad[3][1] - centery) * sizey + transy;
207
208                                 if (glattrib >= 0) glVertexAttrib2fv(glattrib, uv[3]);
209                                 else glTexCoord2fv(uv[3]);
210                                 if (col) gpu_mcol(col[3]);
211                                 glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
212                         }
213                         glEnd();
214
215                         glTranslatef(advance, 0.0f, 0.0f);
216                         line_start -= advance; /* so we can go back to the start of the line */
217                 }
218                 glPopMatrix();
219
220                 BKE_image_release_ibuf(ima, first_ibuf, NULL);
221         }
222 }
223
224 /* Checking powers of two for images since opengl 1.x requires it */
225
226 static bool is_power_of_2_resolution(int w, int h)
227 {
228         return is_power_of_2_i(w) && is_power_of_2_i(h);
229 }
230
231 static bool is_over_resolution_limit(int w, int h)
232 {
233         int reslimit = (U.glreslimit != 0)?
234                 min_ii(U.glreslimit, GPU_max_texture_size()) :
235                 GPU_max_texture_size();
236
237         return (w > reslimit || h > reslimit);
238 }
239
240 static int smaller_power_of_2_limit(int num)
241 {
242         int reslimit = (U.glreslimit != 0)?
243                 min_ii(U.glreslimit, GPU_max_texture_size()) :
244                 GPU_max_texture_size();
245         /* take texture clamping into account */
246         if (num > reslimit)
247                 return reslimit;
248
249         return power_of_2_min_i(num);
250 }
251
252 /* Current OpenGL state caching for GPU_set_tpage */
253
254 static struct GPUTextureState {
255         int curtile, tile;
256         int curtilemode, tilemode;
257         int curtileXRep, tileXRep;
258         int curtileYRep, tileYRep;
259         Image *ima, *curima;
260
261         /* also controls min/mag filtering */
262         bool domipmap;
263         /* only use when 'domipmap' is set */
264         bool linearmipmap;
265         /* store this so that new images created while texture painting won't be set to mipmapped */
266         bool texpaint;
267
268         int alphablend;
269         float anisotropic;
270         int gpu_mipmap;
271         MTexPoly *lasttface;
272 } GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.0f, 0, NULL};
273
274 /* Mipmap settings */
275
276 void GPU_set_gpu_mipmapping(int gpu_mipmap)
277 {
278         int old_value = GTS.gpu_mipmap;
279
280         /* only actually enable if it's supported */
281         GTS.gpu_mipmap = gpu_mipmap && GLEW_EXT_framebuffer_object;
282
283         if (old_value != GTS.gpu_mipmap) {
284                 GPU_free_images();
285         }
286 }
287
288 static void gpu_generate_mipmap(GLenum target)
289 {
290         const bool is_ati = GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY);
291         int target_enabled = 0;
292
293         /* work around bug in ATI driver, need to have GL_TEXTURE_2D enabled
294          * http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation */
295         if (is_ati) {
296                 target_enabled = glIsEnabled(target);
297                 if (!target_enabled)
298                         glEnable(target);
299         }
300
301         glGenerateMipmapEXT(target);
302
303         if (is_ati && !target_enabled)
304                 glDisable(target);
305 }
306
307 void GPU_set_mipmap(bool mipmap)
308 {
309         if (GTS.domipmap != mipmap) {
310                 GPU_free_images();
311                 GTS.domipmap = mipmap;
312         }
313 }
314
315 void GPU_set_linear_mipmap(bool linear)
316 {
317         if (GTS.linearmipmap != linear) {
318                 GTS.linearmipmap = linear;
319         }
320 }
321
322 bool GPU_get_mipmap(void)
323 {
324         return GTS.domipmap && !GTS.texpaint;
325 }
326
327 bool GPU_get_linear_mipmap(void)
328 {
329         return GTS.linearmipmap;
330 }
331
332 static GLenum gpu_get_mipmap_filter(bool mag)
333 {
334         /* linearmipmap is off by default *when mipmapping is off,
335          * use unfiltered display */
336         if (mag) {
337                 if (GTS.domipmap)
338                         return GL_LINEAR;
339                 else
340                         return GL_NEAREST;
341         }
342         else {
343                 if (GTS.domipmap) {
344                         if (GTS.linearmipmap) {
345                                 return GL_LINEAR_MIPMAP_LINEAR;
346                         }
347                         else {
348                                 return GL_LINEAR_MIPMAP_NEAREST;
349                         }
350                 }
351                 else {
352                         return GL_NEAREST;
353                 }
354         }
355 }
356
357 /* Anisotropic filtering settings */
358 void GPU_set_anisotropic(float value)
359 {
360         if (GTS.anisotropic != value) {
361                 GPU_free_images();
362
363                 /* Clamp value to the maximum value the graphics card supports */
364                 if (value > GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)
365                         value = GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT;
366
367                 GTS.anisotropic = value;
368         }
369 }
370
371 float GPU_get_anisotropic(void)
372 {
373         return GTS.anisotropic;
374 }
375
376 /* Set OpenGL state for an MTFace */
377
378 static void gpu_make_repbind(Image *ima)
379 {
380         ImBuf *ibuf;
381         
382         ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
383         if (ibuf == NULL)
384                 return;
385
386         if (ima->repbind) {
387                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
388                 MEM_freeN(ima->repbind);
389                 ima->repbind = NULL;
390                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
391         }
392
393         ima->totbind = ima->xrep*ima->yrep;
394
395         if (ima->totbind>1)
396                 ima->repbind = MEM_callocN(sizeof(int) * ima->totbind, "repbind");
397
398         BKE_image_release_ibuf(ima, ibuf, NULL);
399 }
400
401 void GPU_clear_tpage(bool force)
402 {
403         if (GTS.lasttface == NULL && !force)
404                 return;
405         
406         GTS.lasttface = NULL;
407         GTS.curtile = 0;
408         GTS.curima = NULL;
409         if (GTS.curtilemode != 0) {
410                 glMatrixMode(GL_TEXTURE);
411                 glLoadIdentity();
412                 glMatrixMode(GL_MODELVIEW);
413         }
414         GTS.curtilemode = 0;
415         GTS.curtileXRep = 0;
416         GTS.curtileYRep = 0;
417         GTS.alphablend = -1;
418         
419         glDisable(GL_BLEND);
420         glDisable(GL_TEXTURE_2D);
421         glDisable(GL_TEXTURE_GEN_S);
422         glDisable(GL_TEXTURE_GEN_T);
423         glDisable(GL_ALPHA_TEST);
424 }
425
426 static void gpu_set_alpha_blend(GPUBlendMode alphablend)
427 {
428         if (alphablend == GPU_BLEND_SOLID) {
429                 glDisable(GL_BLEND);
430                 glDisable(GL_ALPHA_TEST);
431                 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
432                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
433         }
434         else if (alphablend == GPU_BLEND_ADD) {
435                 glEnable(GL_BLEND);
436                 glBlendFunc(GL_ONE, GL_ONE);
437                 glDisable(GL_ALPHA_TEST);
438                 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
439         }
440         else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) {
441                 glEnable(GL_BLEND);
442                 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
443
444                 /* for OpenGL render we use the alpha channel, this makes alpha blend correct */
445                 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
446                 
447                 /* if U.glalphaclip == 1.0, some cards go bonkers...
448                  * turn off alpha test in this case */
449
450                 /* added after 2.45 to clip alpha */
451                 if (U.glalphaclip == 1.0f) {
452                         glDisable(GL_ALPHA_TEST);
453                 }
454                 else {
455                         glEnable(GL_ALPHA_TEST);
456                         glAlphaFunc(GL_GREATER, U.glalphaclip);
457                 }
458         }
459         else if (alphablend == GPU_BLEND_CLIP) {
460                 glDisable(GL_BLEND);
461                 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
462                 glEnable(GL_ALPHA_TEST);
463                 glAlphaFunc(GL_GREATER, 0.5f);
464         }
465         else if (alphablend == GPU_BLEND_ALPHA_TO_COVERAGE) {
466                 glEnable(GL_ALPHA_TEST);
467                 glAlphaFunc(GL_GREATER, U.glalphaclip);
468                 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
469         }
470 }
471
472 static void gpu_verify_alpha_blend(int alphablend)
473 {
474         /* verify alpha blending modes */
475         if (GTS.alphablend == alphablend)
476                 return;
477
478         gpu_set_alpha_blend(alphablend);
479         GTS.alphablend = alphablend;
480 }
481
482 static void gpu_verify_reflection(Image *ima)
483 {
484         if (ima && (ima->flag & IMA_REFLECT)) {
485                 /* enable reflection mapping */
486                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
487                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
488
489                 glEnable(GL_TEXTURE_GEN_S);
490                 glEnable(GL_TEXTURE_GEN_T);
491         }
492         else {
493                 /* disable reflection mapping */
494                 glDisable(GL_TEXTURE_GEN_S);
495                 glDisable(GL_TEXTURE_GEN_T);
496         }
497 }
498
499 int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data)
500 {
501         ImBuf *ibuf = NULL;
502         unsigned int *bind = NULL;
503         int rectw, recth, tpx = 0, tpy = 0, y;
504         unsigned int *tilerect = NULL, *rect = NULL;
505         float *ftilerect = NULL, *frect = NULL;
506         float *srgb_frect = NULL;
507         short texwindx, texwindy, texwinsx, texwinsy;
508         /* flag to determine whether high resolution format is used */
509         bool use_high_bit_depth = false, do_color_management = false;
510
511         /* initialize tile mode and number of repeats */
512         GTS.ima = ima;
513         GTS.tilemode = (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM)));
514         GTS.tileXRep = 0;
515         GTS.tileYRep = 0;
516
517         /* setting current tile according to frame */
518         if (ima && (ima->tpageflag & IMA_TWINANIM))
519                 GTS.tile = ima->lastframe;
520         else
521                 GTS.tile = tftile;
522
523         GTS.tile = MAX2(0, GTS.tile);
524
525         if (ima) {
526                 GTS.tileXRep = ima->xrep;
527                 GTS.tileYRep = ima->yrep;
528         }
529
530         /* if same image & tile, we're done */
531         if (compare && ima == GTS.curima && GTS.curtile == GTS.tile &&
532             GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep &&
533             GTS.curtileYRep == GTS.tileYRep)
534         {
535                 return (ima != NULL);
536         }
537
538         /* if tiling mode or repeat changed, change texture matrix to fit */
539         if (GTS.tilemode != GTS.curtilemode || GTS.curtileXRep != GTS.tileXRep ||
540             GTS.curtileYRep != GTS.tileYRep)
541         {
542                 glMatrixMode(GL_TEXTURE);
543                 glLoadIdentity();
544
545                 if (ima && (ima->tpageflag & IMA_TILES))
546                         glScalef(ima->xrep, ima->yrep, 1.0f);
547
548                 glMatrixMode(GL_MODELVIEW);
549         }
550
551         /* check if we have a valid image */
552         if (ima == NULL || ima->ok == 0)
553                 return 0;
554
555         /* check if we have a valid image buffer */
556         ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
557
558         if (ibuf == NULL)
559                 return 0;
560
561         if (ibuf->rect_float) {
562                 if (U.use_16bit_textures) {
563                         /* use high precision textures. This is relatively harmless because OpenGL gives us
564                          * a high precision format only if it is available */
565                         use_high_bit_depth = true;
566                 }
567                 /* we may skip this in high precision, but if not, we need to have a valid buffer here */
568                 else if (ibuf->userflags & IB_RECT_INVALID) {
569                         IMB_rect_from_float(ibuf);
570                 }
571
572                 /* TODO unneeded when float images are correctly treated as linear always */
573                 if (!is_data)
574                         do_color_management = true;
575
576                 if (ibuf->rect == NULL)
577                         IMB_rect_from_float(ibuf);
578         }
579
580         /* currently, tpage refresh is used by ima sequences */
581         if (ima->tpageflag & IMA_TPAGE_REFRESH) {
582                 GPU_free_image(ima);
583                 ima->tpageflag &= ~IMA_TPAGE_REFRESH;
584         }
585         
586         if (GTS.tilemode) {
587                 /* tiled mode */
588                 if (ima->repbind == NULL) gpu_make_repbind(ima);
589                 if (GTS.tile >= ima->totbind) GTS.tile = 0;
590                 
591                 /* this happens when you change repeat buttons */
592                 if (ima->repbind) bind = &ima->repbind[GTS.tile];
593                 else bind = &ima->bindcode;
594                 
595                 if (*bind == 0) {
596                         texwindx = ibuf->x / ima->xrep;
597                         texwindy = ibuf->y / ima->yrep;
598                         
599                         if (GTS.tile >= ima->xrep * ima->yrep)
600                                 GTS.tile = ima->xrep * ima->yrep - 1;
601         
602                         texwinsy = GTS.tile / ima->xrep;
603                         texwinsx = GTS.tile - texwinsy * ima->xrep;
604         
605                         texwinsx *= texwindx;
606                         texwinsy *= texwindy;
607         
608                         tpx = texwindx;
609                         tpy = texwindy;
610
611                         if (use_high_bit_depth) {
612                                 if (do_color_management) {
613                                         srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "floar_buf_col_cor");
614                                         IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
615                                                 ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true,
616                                                 ibuf->x, ibuf->y, ibuf->x, ibuf->x);
617                                         IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
618                                         /* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
619                                         IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
620                                         frect = srgb_frect + texwinsy*ibuf->x + texwinsx;
621                                 }
622                                 else
623                                         frect = ibuf->rect_float + texwinsy*ibuf->x + texwinsx;
624                         }
625                         else
626                                 rect = ibuf->rect + texwinsy*ibuf->x + texwinsx;
627                 }
628         }
629         else {
630                 /* regular image mode */
631                 bind= &ima->bindcode;
632
633                 if (*bind == 0) {
634                         tpx = ibuf->x;
635                         tpy = ibuf->y;
636                         rect = ibuf->rect;
637                         if (use_high_bit_depth) {
638                                 if (do_color_management) {
639                                         frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, "floar_buf_col_cor");
640                                         IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
641                                                         ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true,
642                                                         ibuf->x, ibuf->y, ibuf->x, ibuf->x);
643                                         IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
644                                         /* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
645                                         IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
646                                 }
647                                 else
648                                         frect = ibuf->rect_float;
649                         }
650                 }
651         }
652
653         if (*bind != 0) {
654                 /* enable opengl drawing with textures */
655                 glBindTexture(GL_TEXTURE_2D, *bind);
656                 BKE_image_release_ibuf(ima, ibuf, NULL);
657                 return *bind;
658         }
659
660         rectw = tpx;
661         recth = tpy;
662
663         /* for tiles, copy only part of image into buffer */
664         if (GTS.tilemode) {
665                 if (use_high_bit_depth) {
666                         float *frectrow, *ftilerectrow;
667
668                         ftilerect = MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect");
669
670                         for (y = 0; y < recth; y++) {
671                                 frectrow = &frect[y * ibuf->x];
672                                 ftilerectrow = &ftilerect[y * rectw];
673
674                                 memcpy(ftilerectrow, frectrow, tpx * sizeof(*frectrow));
675                         }
676
677                         frect = ftilerect;
678                 }
679                 else {
680                         unsigned int *rectrow, *tilerectrow;
681
682                         tilerect = MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
683
684                         for (y = 0; y < recth; y++) {
685                                 rectrow = &rect[y * ibuf->x];
686                                 tilerectrow = &tilerect[y * rectw];
687
688                                 memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow));
689                         }
690                         
691                         rect = tilerect;
692                 }
693         }
694
695 #ifdef WITH_DDS
696         if (ibuf->ftype == IMB_FTYPE_DDS)
697                 GPU_create_gl_tex_compressed(bind, rect, rectw, recth, mipmap, ima, ibuf);
698         else
699 #endif
700                 GPU_create_gl_tex(bind, rect, frect, rectw, recth, mipmap, use_high_bit_depth, ima);
701         
702         /* mark as non-color data texture */
703         if (*bind) {
704                 if (is_data)
705                         ima->tpageflag |= IMA_GLBIND_IS_DATA;   
706                 else
707                         ima->tpageflag &= ~IMA_GLBIND_IS_DATA;  
708         }
709
710         /* clean up */
711         if (tilerect)
712                 MEM_freeN(tilerect);
713         if (ftilerect)
714                 MEM_freeN(ftilerect);
715         if (srgb_frect)
716                 MEM_freeN(srgb_frect);
717
718         BKE_image_release_ibuf(ima, ibuf, NULL);
719
720         return *bind;
721 }
722
723 /* Image *ima can be NULL */
724 void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
725                        bool mipmap, bool use_high_bit_depth, Image *ima)
726 {
727         ImBuf *ibuf = NULL;
728
729         int tpx = rectw;
730         int tpy = recth;
731
732         /* scale if not a power of two. this is not strictly necessary for newer
733          * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures 
734          * Then don't bother scaling for hardware that supports NPOT textures! */
735         if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) ||
736                 is_over_resolution_limit(rectw, recth)) {
737                 rectw = smaller_power_of_2_limit(rectw);
738                 recth = smaller_power_of_2_limit(recth);
739                 
740                 if (use_high_bit_depth) {
741                         ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
742                         IMB_scaleImBuf(ibuf, rectw, recth);
743
744                         frect = ibuf->rect_float;
745                 }
746                 else {
747                         ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
748                         IMB_scaleImBuf(ibuf, rectw, recth);
749
750                         rect = ibuf->rect;
751                 }
752         }
753
754         /* create image */
755         glGenTextures(1, (GLuint *)bind);
756         glBindTexture(GL_TEXTURE_2D, *bind);
757
758         if (use_high_bit_depth) {
759                 if (GLEW_ARB_texture_float)
760                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
761                 else
762                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
763         }
764         else
765                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
766
767         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
768
769         if (GPU_get_mipmap() && mipmap) {
770                 if (GTS.gpu_mipmap) {
771                         gpu_generate_mipmap(GL_TEXTURE_2D);
772                 }
773                 else {
774                         int i;
775
776                         if (!ibuf) {
777                                 if (use_high_bit_depth) {
778                                         ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
779                                 }
780                                 else {
781                                         ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
782                                 }
783                         }
784
785                         IMB_makemipmap(ibuf, true);
786
787                         for (i = 1; i < ibuf->miptot; i++) {
788                                 ImBuf *mip = ibuf->mipmap[i - 1];
789                                 if (use_high_bit_depth) {
790                                         if (GLEW_ARB_texture_float)
791                                                 glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F_ARB, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
792                                         else
793                                                 glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
794                                 }
795                                 else {
796                                         glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
797                                 }
798                         }
799                 }
800                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
801
802                 if (ima)
803                         ima->tpageflag |= IMA_MIPMAP_COMPLETE;
804         }
805         else {
806                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
807         }
808
809         if (GLEW_EXT_texture_filter_anisotropic)
810                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
811
812         if (ibuf)
813                 IMB_freeImBuf(ibuf);
814 }
815
816 /**
817  * GPU_upload_dxt_texture() assumes that the texture is already bound and ready to go.
818  * This is so the viewport and the BGE can share some code.
819  * Returns false if the provided ImBuf doesn't have a supported DXT compression format
820  */
821 bool GPU_upload_dxt_texture(ImBuf *ibuf)
822 {
823 #ifdef WITH_DDS
824         GLint format = 0;
825         int blocksize, height, width, i, size, offset = 0;
826
827         width = ibuf->x;
828         height = ibuf->y;
829
830         if (GLEW_EXT_texture_compression_s3tc) {
831                 if (ibuf->dds_data.fourcc == FOURCC_DXT1)
832                         format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
833                 else if (ibuf->dds_data.fourcc == FOURCC_DXT3)
834                         format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
835                 else if (ibuf->dds_data.fourcc == FOURCC_DXT5)
836                         format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
837         }
838
839         if (format == 0) {
840                 fprintf(stderr, "Unable to find a suitable DXT compression, falling back to uncompressed\n");
841                 return false;
842         }
843
844         if (!is_power_of_2_resolution(width, height)) {
845                 fprintf(stderr, "Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
846                 return false;
847         }
848
849         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
850         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
851
852         if (GLEW_EXT_texture_filter_anisotropic)
853                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
854
855         blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
856         for (i = 0; i < ibuf->dds_data.nummipmaps && (width||height); ++i) {
857                 if (width == 0)
858                         width = 1;
859                 if (height == 0)
860                         height = 1;
861
862                 size = ((width+3)/4)*((height+3)/4)*blocksize;
863
864                 glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height,
865                         0, size, ibuf->dds_data.data + offset);
866
867                 offset += size;
868                 width >>= 1;
869                 height >>= 1;
870         }
871
872         /* set number of mipmap levels we have, needed in case they don't go down to 1x1 */
873         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1);
874
875         return true;
876 #else
877         (void)ibuf;
878         return false;
879 #endif
880 }
881
882 void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, Image *ima, ImBuf *ibuf)
883 {
884 #ifndef WITH_DDS
885         (void)ibuf;
886         /* Fall back to uncompressed if DDS isn't enabled */
887         GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima);
888 #else
889
890
891         glGenTextures(1, (GLuint *)bind);
892         glBindTexture(GL_TEXTURE_2D, *bind);
893
894         if (GPU_upload_dxt_texture(ibuf) == 0) {
895                 glDeleteTextures(1, (GLuint *)bind);
896                 GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima);
897         }
898 #endif
899 }
900 static void gpu_verify_repeat(Image *ima)
901 {
902         /* set either clamp or repeat in X/Y */
903         if (ima->tpageflag & IMA_CLAMP_U)
904                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
905         else
906                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
907
908         if (ima->tpageflag & IMA_CLAMP_V)
909                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
910         else
911                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
912 }
913
914 int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
915 {
916         Image *ima;
917         
918         /* check if we need to clear the state */
919         if (mtexpoly == NULL) {
920                 GPU_clear_tpage(false);
921                 return 0;
922         }
923
924         ima = mtexpoly->tpage;
925         GTS.lasttface = mtexpoly;
926
927         gpu_verify_alpha_blend(alphablend);
928         gpu_verify_reflection(ima);
929
930         if (GPU_verify_image(ima, NULL, mtexpoly->tile, 1, mipmap, false)) {
931                 GTS.curtile = GTS.tile;
932                 GTS.curima = GTS.ima;
933                 GTS.curtilemode = GTS.tilemode;
934                 GTS.curtileXRep = GTS.tileXRep;
935                 GTS.curtileYRep = GTS.tileYRep;
936
937                 glEnable(GL_TEXTURE_2D);
938         }
939         else {
940                 glDisable(GL_TEXTURE_2D);
941                 
942                 GTS.curtile = 0;
943                 GTS.curima = NULL;
944                 GTS.curtilemode = 0;
945                 GTS.curtileXRep = 0;
946                 GTS.curtileYRep = 0;
947
948                 return 0;
949         }
950         
951         gpu_verify_repeat(ima);
952         
953         /* Did this get lost in the image recode? */
954         /* BKE_image_tag_time(ima);*/
955
956         return 1;
957 }
958
959 /* these two functions are called on entering and exiting texture paint mode,
960  * temporary disabling/enabling mipmapping on all images for quick texture
961  * updates with glTexSubImage2D. images that didn't change don't have to be
962  * re-uploaded to OpenGL */
963 void GPU_paint_set_mipmap(bool mipmap)
964 {
965         Image *ima;
966         
967         if (!GTS.domipmap)
968                 return;
969
970         GTS.texpaint = !mipmap;
971
972         if (mipmap) {
973                 for (ima = G.main->image.first; ima; ima = ima->id.next) {
974                         if (ima->bindcode) {
975                                 if (ima->tpageflag & IMA_MIPMAP_COMPLETE) {
976                                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
977                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
978                                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
979                                 }
980                                 else
981                                         GPU_free_image(ima);
982                         }
983                         else
984                                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
985                 }
986
987         }
988         else {
989                 for (ima = G.main->image.first; ima; ima = ima->id.next) {
990                         if (ima->bindcode) {
991                                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
992                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
993                                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
994                         }
995                         else
996                                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
997                 }
998         }
999 }
1000
1001
1002 /* check if image has been downscaled and do scaled partial update */
1003 static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
1004 {
1005         if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) ||
1006             is_over_resolution_limit(ibuf->x, ibuf->y))
1007         {
1008                 int x_limit = smaller_power_of_2_limit(ibuf->x);
1009                 int y_limit = smaller_power_of_2_limit(ibuf->y);
1010
1011                 float xratio = x_limit / (float)ibuf->x;
1012                 float yratio = y_limit / (float)ibuf->y;
1013
1014                 /* find new width, height and x,y gpu texture coordinates */
1015
1016                 /* take ceiling because we will be losing 1 pixel due to rounding errors in x,y... */
1017                 int rectw = (int)ceil(xratio * w);
1018                 int recth = (int)ceil(yratio * h);
1019
1020                 x *= xratio;
1021                 y *= yratio;
1022
1023                 /* ...but take back if we are over the limit! */
1024                 if (rectw + x > x_limit) rectw--;
1025                 if (recth + y > y_limit) recth--;
1026
1027                 /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */
1028                 if (frect) {
1029                         ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h);
1030                         IMB_scaleImBuf(ibuf_scale, rectw, recth);
1031
1032                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
1033                         glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
1034                                         GL_FLOAT, ibuf_scale->rect_float);
1035
1036                         IMB_freeImBuf(ibuf_scale);
1037                 }
1038                 /* byte images are not continuous in memory so do manual interpolation */
1039                 else {
1040                         unsigned char *scalerect = MEM_mallocN(rectw * recth * sizeof(*scalerect) * 4, "scalerect");
1041                         unsigned int *p = (unsigned int *)scalerect;
1042                         int i, j;
1043                         float inv_xratio = 1.0f / xratio;
1044                         float inv_yratio = 1.0f / yratio;
1045                         for (i = 0; i < rectw; i++) {
1046                                 float u = (x + i) * inv_xratio;
1047                                 for (j = 0; j < recth; j++) {
1048                                         float v = (y + j) * inv_yratio;
1049                                         bilinear_interpolation_color_wrap(ibuf, (unsigned char *)(p + i + j * (rectw)), NULL, u, v);
1050                                 }
1051                         }
1052                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
1053                         glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
1054                                         GL_UNSIGNED_BYTE, scalerect);
1055
1056                         MEM_freeN(scalerect);
1057                 }
1058
1059                 if (GPU_get_mipmap()) {
1060                         gpu_generate_mipmap(GL_TEXTURE_2D);
1061                 }
1062                 else {
1063                         ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
1064                 }
1065
1066                 return true;
1067         }
1068
1069         return false;
1070 }
1071
1072 void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
1073 {
1074         ImBuf *ibuf;
1075         
1076         ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
1077         
1078         if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf ||
1079                 (w == 0) || (h == 0))
1080         {
1081                 /* these cases require full reload still */
1082                 GPU_free_image(ima);
1083         }
1084         else {
1085                 /* for the special case, we can do a partial update
1086                  * which is much quicker for painting */
1087                 GLint row_length, skip_pixels, skip_rows;
1088
1089                 /* if color correction is needed, we must update the part that needs updating. */
1090                 if (ibuf->rect_float) {
1091                         float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
1092                         bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
1093                         IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
1094                         
1095                         if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
1096                                 MEM_freeN(buffer);
1097                                 BKE_image_release_ibuf(ima, ibuf, NULL);
1098                                 return;
1099                         }
1100
1101                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
1102                         glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer);
1103
1104                         MEM_freeN(buffer);
1105
1106                         /* we have already accounted for the case where GTS.gpu_mipmap is false
1107                          * so we will be using GPU mipmap generation here */
1108                         if (GPU_get_mipmap()) {
1109                                 gpu_generate_mipmap(GL_TEXTURE_2D);
1110                         }
1111                         else {
1112                                 ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
1113                         }
1114
1115                         BKE_image_release_ibuf(ima, ibuf, NULL);
1116                         return;
1117                 }
1118
1119                 if (GPU_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
1120                         BKE_image_release_ibuf(ima, ibuf, NULL);
1121                         return;
1122                 }
1123
1124                 glBindTexture(GL_TEXTURE_2D, ima->bindcode);
1125
1126                 glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
1127                 glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
1128                 glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
1129
1130                 glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
1131                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
1132                 glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
1133
1134                 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
1135                         GL_UNSIGNED_BYTE, ibuf->rect);
1136
1137                 glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
1138                 glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
1139                 glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
1140
1141                 /* see comment above as to why we are using gpu mipmap generation here */
1142                 if (GPU_get_mipmap()) {
1143                         gpu_generate_mipmap(GL_TEXTURE_2D);
1144                 }
1145                 else {
1146                         ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
1147                 }
1148         }
1149
1150         BKE_image_release_ibuf(ima, ibuf, NULL);
1151 }
1152
1153 void GPU_update_images_framechange(void)
1154 {
1155         Image *ima;
1156         
1157         for (ima = G.main->image.first; ima; ima = ima->id.next) {
1158                 if (ima->tpageflag & IMA_TWINANIM) {
1159                         if (ima->twend >= ima->xrep * ima->yrep)
1160                                 ima->twend = ima->xrep * ima->yrep - 1;
1161                 
1162                         /* check: is bindcode not in the array? free. (to do) */
1163                         
1164                         ima->lastframe++;
1165                         if (ima->lastframe > ima->twend)
1166                                 ima->lastframe = ima->twsta;
1167                 }
1168         }
1169 }
1170
1171 int GPU_update_image_time(Image *ima, double time)
1172 {
1173         int     inc = 0;
1174         float diff;
1175         int     newframe;
1176
1177         if (!ima)
1178                 return 0;
1179
1180         if (ima->lastupdate < 0)
1181                 ima->lastupdate = 0;
1182
1183         if (ima->lastupdate > (float)time)
1184                 ima->lastupdate = (float)time;
1185
1186         if (ima->tpageflag & IMA_TWINANIM) {
1187                 if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1;
1188                 
1189                 /* check: is the bindcode not in the array? Then free. (still to do) */
1190                 
1191                 diff = (float)((float)time - ima->lastupdate);
1192                 inc = (int)(diff * (float)ima->animspeed);
1193
1194                 ima->lastupdate += ((float)inc / (float)ima->animspeed);
1195
1196                 newframe = ima->lastframe + inc;
1197
1198                 if (newframe > (int)ima->twend) {
1199                         if (ima->twend - ima->twsta != 0)
1200                                 newframe = (int)ima->twsta - 1 + (newframe - ima->twend) % (ima->twend - ima->twsta);
1201                         else
1202                                 newframe = ima->twsta;
1203                 }
1204
1205                 ima->lastframe = newframe;
1206         }
1207
1208         return inc;
1209 }
1210
1211
1212 void GPU_free_smoke(SmokeModifierData *smd)
1213 {
1214         if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
1215                 if (smd->domain->tex)
1216                         GPU_texture_free(smd->domain->tex);
1217                 smd->domain->tex = NULL;
1218
1219                 if (smd->domain->tex_shadow)
1220                         GPU_texture_free(smd->domain->tex_shadow);
1221                 smd->domain->tex_shadow = NULL;
1222
1223                 if (smd->domain->tex_flame)
1224                         GPU_texture_free(smd->domain->tex_flame);
1225                 smd->domain->tex_flame = NULL;
1226         }
1227 }
1228
1229 void GPU_create_smoke(SmokeModifierData *smd, int highres)
1230 {
1231 #ifdef WITH_SMOKE
1232         if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1233                 SmokeDomainSettings *sds = smd->domain;
1234                 if (!sds->tex && !highres) {
1235                         /* rgba texture for color + density */
1236                         if (smoke_has_colors(sds->fluid)) {
1237                                 float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture");
1238                                 smoke_get_rgba(sds->fluid, data, 0);
1239                                 sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data);
1240                                 MEM_freeN(data);
1241                         }
1242                         /* density only */
1243                         else {
1244                                 sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_density(sds->fluid));
1245                         }
1246                         sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_flame(sds->fluid)) : NULL;
1247                 }
1248                 else if (!sds->tex && highres) {
1249                         /* rgba texture for color + density */
1250                         if (smoke_turbulence_has_colors(sds->wt)) {
1251                                 float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture");
1252                                 smoke_turbulence_get_rgba(sds->wt, data, 0);
1253                                 sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data);
1254                                 MEM_freeN(data);
1255                         }
1256                         /* density only */
1257                         else {
1258                                 sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_density(sds->wt));
1259                         }
1260                         sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_flame(sds->wt)) : NULL;
1261                 }
1262
1263                 sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, sds->shadow);
1264         }
1265 #else // WITH_SMOKE
1266         (void)highres;
1267         smd->domain->tex = NULL;
1268         smd->domain->tex_flame = NULL;
1269         smd->domain->tex_shadow = NULL;
1270 #endif // WITH_SMOKE
1271 }
1272
1273 static LinkNode *image_free_queue = NULL;
1274
1275 static void gpu_queue_image_for_free(Image *ima)
1276 {
1277         BLI_lock_thread(LOCK_OPENGL);
1278         BLI_linklist_prepend(&image_free_queue, ima);
1279         BLI_unlock_thread(LOCK_OPENGL);
1280 }
1281
1282 void GPU_free_unused_buffers(void)
1283 {
1284         LinkNode *node;
1285         Image *ima;
1286
1287         if (!BLI_thread_is_main())
1288                 return;
1289
1290         BLI_lock_thread(LOCK_OPENGL);
1291
1292         /* images */
1293         for (node = image_free_queue; node; node = node->next) {
1294                 ima = node->link;
1295
1296                 /* check in case it was freed in the meantime */
1297                 if (G.main && BLI_findindex(&G.main->image, ima) != -1)
1298                         GPU_free_image(ima);
1299         }
1300
1301         BLI_linklist_free(image_free_queue, NULL);
1302         image_free_queue = NULL;
1303
1304         /* vbo buffers */
1305         GPU_global_buffer_pool_free_unused();
1306
1307         BLI_unlock_thread(LOCK_OPENGL);
1308 }
1309
1310 void GPU_free_image(Image *ima)
1311 {
1312         if (!BLI_thread_is_main()) {
1313                 gpu_queue_image_for_free(ima);
1314                 return;
1315         }
1316
1317         /* free regular image binding */
1318         if (ima->bindcode) {
1319                 glDeleteTextures(1, (GLuint *)&ima->bindcode);
1320                 ima->bindcode = 0;
1321         }
1322
1323         /* free glsl image binding */
1324         if (ima->gputexture) {
1325                 GPU_texture_free(ima->gputexture);
1326                 ima->gputexture = NULL;
1327         }
1328
1329         /* free repeated image binding */
1330         if (ima->repbind) {
1331                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
1332         
1333                 MEM_freeN(ima->repbind);
1334                 ima->repbind = NULL;
1335         }
1336
1337         ima->tpageflag &= ~(IMA_MIPMAP_COMPLETE|IMA_GLBIND_IS_DATA);
1338 }
1339
1340 void GPU_free_images(void)
1341 {
1342         Image *ima;
1343
1344         if (G.main)
1345                 for (ima = G.main->image.first; ima; ima = ima->id.next)
1346                         GPU_free_image(ima);
1347 }
1348
1349 /* same as above but only free animated images */
1350 void GPU_free_images_anim(void)
1351 {
1352         Image *ima;
1353
1354         if (G.main)
1355                 for (ima = G.main->image.first; ima; ima = ima->id.next)
1356                         if (BKE_image_is_animated(ima))
1357                                 GPU_free_image(ima);
1358 }
1359
1360
1361 void GPU_free_images_old(void)
1362 {
1363         Image *ima;
1364         static int lasttime = 0;
1365         int ctime = (int)PIL_check_seconds_timer();
1366
1367         /*
1368          * Run garbage collector once for every collecting period of time
1369          * if textimeout is 0, that's the option to NOT run the collector
1370          */
1371         if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime)
1372                 return;
1373
1374         /* of course not! */
1375         if (G.is_rendering)
1376                 return;
1377
1378         lasttime = ctime;
1379
1380         ima = G.main->image.first;
1381         while (ima) {
1382                 if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) {
1383                         /* If it's in GL memory, deallocate and set time tag to current time
1384                          * This gives textures a "second chance" to be used before dying. */
1385                         if (ima->bindcode || ima->repbind) {
1386                                 GPU_free_image(ima);
1387                                 ima->lastused = ctime;
1388                         }
1389                         /* Otherwise, just kill the buffers */
1390                         else {
1391                                 BKE_image_free_buffers(ima);
1392                         }
1393                 }
1394                 ima = ima->id.next;
1395         }
1396 }
1397
1398
1399 /* OpenGL Materials */
1400
1401 #define FIXEDMAT 8
1402
1403 /* OpenGL state caching for materials */
1404
1405 typedef struct GPUMaterialFixed {
1406         float diff[3];
1407         float spec[3];
1408         int hard;
1409         float alpha;
1410 } GPUMaterialFixed; 
1411
1412 static struct GPUMaterialState {
1413         GPUMaterialFixed (*matbuf);
1414         GPUMaterialFixed matbuf_fixed[FIXEDMAT];
1415         int totmat;
1416
1417         /* set when called inside GPU_begin_object_materials / GPU_end_object_materials
1418          * otherwise calling GPU_object_material_bind returns zero */
1419         bool is_enabled;
1420
1421         Material **gmatbuf;
1422         Material *gmatbuf_fixed[FIXEDMAT];
1423         Material *gboundmat;
1424         Object *gob;
1425         DupliObject *dob;
1426         Scene *gscene;
1427         int glay;
1428         bool gscenelock;
1429         float (*gviewmat)[4];
1430         float (*gviewinv)[4];
1431         float (*gviewcamtexcofac);
1432
1433         bool backface_culling;
1434         bool two_sided_lighting;
1435
1436         GPUBlendMode *alphablend;
1437         GPUBlendMode alphablend_fixed[FIXEDMAT];
1438         bool use_alpha_pass, is_alpha_pass;
1439         bool use_matcaps;
1440
1441         int lastmatnr, lastretval;
1442         GPUBlendMode lastalphablend;
1443         bool is_opensubdiv;
1444 } GMS = {NULL};
1445
1446 /* fixed function material, alpha handed by caller */
1447 static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob, const int new_shading_nodes, 
1448                                   const bool dimdown)
1449 {
1450         if (bmat->mode & MA_SHLESS) {
1451                 copy_v3_v3(smat->diff, &bmat->r);
1452
1453                 if (gamma)
1454                         linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
1455
1456                 zero_v3(smat->spec);
1457                 smat->alpha = 1.0f;
1458                 smat->hard = 0;
1459         }
1460         else if (new_shading_nodes) {
1461                 copy_v3_v3(smat->diff, &bmat->r);
1462                 copy_v3_v3(smat->spec, &bmat->specr);
1463                 smat->alpha = 1.0f;
1464                 smat->hard = CLAMPIS(bmat->har, 0, 128);
1465                 
1466                 if (dimdown) {
1467                         mul_v3_fl(smat->diff, 0.8f);
1468                         mul_v3_fl(smat->spec, 0.5f);
1469                 }
1470                 
1471                 if (gamma) {
1472                         linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
1473                         linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
1474                 }
1475         }
1476         else {
1477                 mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit);
1478
1479                 if (bmat->shade_flag & MA_OBCOLOR)
1480                         mul_v3_v3(smat->diff, ob->col);
1481                 
1482                 mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec);
1483                 smat->hard = CLAMPIS(bmat->har, 1, 128);
1484                 smat->alpha = 1.0f;
1485
1486                 if (gamma) {
1487                         linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
1488                         linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
1489                 }
1490         }
1491 }
1492
1493 static Material *gpu_active_node_material(Material *ma)
1494 {
1495         if (ma && ma->use_nodes && ma->nodetree) {
1496                 bNode *node = nodeGetActiveID(ma->nodetree, ID_MA);
1497
1498                 if (node)
1499                         return (Material *)node->id;
1500                 else
1501                         return NULL;
1502         }
1503
1504         return ma;
1505 }
1506
1507 void GPU_begin_dupli_object(DupliObject *dob)
1508 {
1509         GMS.dob = dob;
1510 }
1511
1512 void GPU_end_dupli_object(void)
1513 {
1514         GMS.dob = NULL;
1515 }
1516
1517 void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, bool glsl, bool *do_alpha_after)
1518 {
1519         Material *ma;
1520         GPUMaterial *gpumat;
1521         GPUBlendMode alphablend;
1522         DupliObject *dob;
1523         int a;
1524         const bool gamma = BKE_scene_check_color_management_enabled(scene);
1525         const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
1526         const bool use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) != 0;  /* assumes v3d->defmaterial->preview is set */
1527         bool use_opensubdiv = false;
1528
1529 #ifdef WITH_OPENSUBDIV
1530         {
1531                 DerivedMesh *derivedFinal = NULL;
1532                 if (ob->type == OB_MESH) {
1533                         Mesh *me = ob->data;
1534                         BMEditMesh *em = me->edit_btmesh;
1535                         if (em != NULL) {
1536                                 derivedFinal = em->derivedFinal;
1537                         }
1538                         else {
1539                                 derivedFinal = ob->derivedFinal;
1540                         }
1541                 }
1542                 else {
1543                         derivedFinal = ob->derivedFinal;
1544                 }
1545
1546                 if (derivedFinal != NULL && derivedFinal->type == DM_TYPE_CCGDM) {
1547                         CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) derivedFinal;
1548                         use_opensubdiv = ccgdm->useGpuBackend;
1549                 }
1550         }
1551 #endif
1552
1553 #ifdef WITH_GAMEENGINE
1554         if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
1555                 ob = BKE_object_lod_matob_get(ob, scene);
1556         }
1557 #endif
1558
1559         /* initialize state */
1560         /* DupliObject must be restored */
1561         dob = GMS.dob;
1562         memset(&GMS, 0, sizeof(GMS));
1563         GMS.is_enabled = true;
1564         GMS.dob = dob;
1565         GMS.lastmatnr = -1;
1566         GMS.lastretval = -1;
1567         GMS.lastalphablend = GPU_BLEND_SOLID;
1568         GMS.use_matcaps = use_matcap;
1569
1570         GMS.backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
1571
1572         GMS.two_sided_lighting = false;
1573         if (ob && ob->type == OB_MESH)
1574                 GMS.two_sided_lighting = (((Mesh*)ob->data)->flag & ME_TWOSIDED) != 0;
1575
1576         GMS.gob = ob;
1577         GMS.gscene = scene;
1578         GMS.is_opensubdiv = use_opensubdiv;
1579         GMS.totmat = use_matcap ? 1 : ob->totcol + 1;  /* materials start from 1, default material is 0 */
1580         GMS.glay = (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */
1581         GMS.gscenelock = (v3d->scenelock != 0);
1582         GMS.gviewmat = rv3d->viewmat;
1583         GMS.gviewinv = rv3d->viewinv;
1584         GMS.gviewcamtexcofac = rv3d->viewcamtexcofac;
1585
1586         /* alpha pass setup. there's various cases to handle here:
1587          * - object transparency on: only solid materials draw in the first pass,
1588          * and only transparent in the second 'alpha' pass.
1589          * - object transparency off: for glsl we draw both in a single pass, and
1590          * for solid we don't use transparency at all. */
1591         GMS.use_alpha_pass = (do_alpha_after != NULL);
1592         GMS.is_alpha_pass = (v3d->transp != false);
1593         if (GMS.use_alpha_pass)
1594                 *do_alpha_after = false;
1595         
1596         if (GMS.totmat > FIXEDMAT) {
1597                 GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf");
1598                 GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * GMS.totmat, "GMS.matbuf");
1599                 GMS.alphablend = MEM_callocN(sizeof(*GMS.alphablend) * GMS.totmat, "GMS.matbuf");
1600         }
1601         else {
1602                 GMS.matbuf = GMS.matbuf_fixed;
1603                 GMS.gmatbuf = GMS.gmatbuf_fixed;
1604                 GMS.alphablend = GMS.alphablend_fixed;
1605         }
1606
1607         /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */
1608         if (use_matcap) {
1609                 GMS.gmatbuf[0] = v3d->defmaterial;
1610                 GPU_material_matcap(scene, v3d->defmaterial, use_opensubdiv);
1611
1612                 /* do material 1 too, for displists! */
1613                 memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
1614         
1615                 GMS.alphablend[0] = GPU_BLEND_SOLID;
1616         }
1617         else {
1618         
1619                 /* no materials assigned? */
1620                 if (ob->totcol == 0) {
1621                         gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true);
1622
1623                         /* do material 1 too, for displists! */
1624                         memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
1625
1626                         if (glsl) {
1627                                 GMS.gmatbuf[0] = &defmaterial;
1628                                 GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv);
1629                         }
1630
1631                         GMS.alphablend[0] = GPU_BLEND_SOLID;
1632                 }
1633                 
1634                 /* setup materials */
1635                 for (a = 1; a <= ob->totcol; a++) {
1636                         /* find a suitable material */
1637                         ma = give_current_material(ob, a);
1638                         if (!glsl && !new_shading_nodes) ma = gpu_active_node_material(ma);
1639                         if (ma == NULL) ma = &defmaterial;
1640
1641                         /* create glsl material if requested */
1642                         gpumat = glsl? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv): NULL;
1643
1644                         if (gpumat) {
1645                                 /* do glsl only if creating it succeed, else fallback */
1646                                 GMS.gmatbuf[a] = ma;
1647                                 alphablend = GPU_material_alpha_blend(gpumat, ob->col);
1648                         }
1649                         else {
1650                                 /* fixed function opengl materials */
1651                                 gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false);
1652
1653                                 if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) {
1654                                         GMS.matbuf[a].alpha = ma->alpha;
1655                                         alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
1656                                 }
1657                                 else {
1658                                         GMS.matbuf[a].alpha = 1.0f;
1659                                         alphablend = GPU_BLEND_SOLID;
1660                                 }
1661                         }
1662
1663                         /* setting 'do_alpha_after = true' indicates this object needs to be
1664                          * drawn in a second alpha pass for improved blending */
1665                         if (do_alpha_after && !GMS.is_alpha_pass)
1666                                 if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
1667                                         *do_alpha_after = true;
1668
1669                         GMS.alphablend[a] = alphablend;
1670                 }
1671         }
1672
1673         /* let's start with a clean state */
1674         GPU_object_material_unbind();
1675 }
1676
1677 static int GPU_get_particle_info(GPUParticleInfo *pi)
1678 {
1679         ParticleData *p;
1680         DupliObject *dob = GMS.dob;
1681         int ind;
1682         if (dob->particle_system) {
1683                 if (dob->persistent_id[0] < dob->particle_system->totpart)
1684                         ind = dob->persistent_id[0];
1685                 else {
1686                         ind = dob->particle_system->child[dob->persistent_id[0] - dob->particle_system->totpart].parent;
1687                 }
1688                 if (ind >= 0) {
1689                         p = &dob->particle_system->particles[ind];
1690
1691                         pi->scalprops[0] = ind;
1692                         pi->scalprops[1] = GMS.gscene->r.cfra - p->time;
1693                         pi->scalprops[2] = p->lifetime;
1694                         pi->scalprops[3] = p->size;
1695
1696                         copy_v3_v3(pi->location, p->state.co);
1697                         copy_v3_v3(pi->velocity, p->state.vel);
1698                         copy_v3_v3(pi->angular_velocity, p->state.ave);
1699                         return 1;
1700                 }
1701                 else return 0;
1702         }
1703         else
1704                 return 0;
1705 }
1706
1707 int GPU_object_material_bind(int nr, void *attribs)
1708 {
1709         GPUVertexAttribs *gattribs = attribs;
1710         GPUMaterial *gpumat;
1711         GPUBlendMode alphablend;
1712
1713         /* no GPU_begin_object_materials, use default material */
1714         if (!GMS.matbuf) {
1715                 memset(&GMS, 0, sizeof(GMS));
1716
1717                 float diffuse[3], specular[3];
1718                 mul_v3_v3fl(diffuse, &defmaterial.r, defmaterial.ref + defmaterial.emit);
1719                 mul_v3_v3fl(specular, &defmaterial.specr, defmaterial.spec);
1720                 GPU_basic_shader_colors(diffuse, specular, 35, 1.0f);
1721
1722                 if (GMS.two_sided_lighting)
1723                         GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED);
1724                 else
1725                         GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
1726
1727                 return 0;
1728         }
1729
1730         /* prevent index to use un-initialized array items */
1731         if (nr >= GMS.totmat)
1732                 nr = 0;
1733
1734         if (gattribs)
1735                 memset(gattribs, 0, sizeof(*gattribs));
1736
1737         /* keep current material */
1738         if (nr == GMS.lastmatnr)
1739                 return GMS.lastretval;
1740
1741         /* unbind glsl material */
1742         if (GMS.gboundmat) {
1743                 if (GMS.is_alpha_pass) glDepthMask(0);
1744                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv));
1745                 GMS.gboundmat = NULL;
1746         }
1747
1748         /* draw materials with alpha in alpha pass */
1749         GMS.lastmatnr = nr;
1750         GMS.lastretval = 1;
1751
1752         if (GMS.use_alpha_pass) {
1753                 GMS.lastretval = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
1754                 if (GMS.is_alpha_pass)
1755                         GMS.lastretval = !GMS.lastretval;
1756         }
1757         else
1758                 GMS.lastretval = !GMS.is_alpha_pass;
1759
1760         if (GMS.lastretval) {
1761                 /* for alpha pass, use alpha blend */
1762                 alphablend = GMS.alphablend[nr];
1763
1764                 if (gattribs && GMS.gmatbuf[nr]) {
1765                         /* bind glsl material and get attributes */
1766                         Material *mat = GMS.gmatbuf[nr];
1767                         GPUParticleInfo partile_info;
1768
1769                         float auto_bump_scale;
1770
1771                         gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
1772                         GPU_material_vertex_attributes(gpumat, gattribs);
1773
1774                         if (GMS.dob)
1775                                 GPU_get_particle_info(&partile_info);
1776
1777                         GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
1778
1779                         auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
1780                         GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale, &partile_info);
1781                         GMS.gboundmat = mat;
1782
1783                         /* for glsl use alpha blend mode, unless it's set to solid and
1784                          * we are already drawing in an alpha pass */
1785                         if (mat->game.alpha_blend != GPU_BLEND_SOLID)
1786                                 alphablend= mat->game.alpha_blend;
1787
1788                         if (GMS.is_alpha_pass) glDepthMask(1);
1789
1790                         if (GMS.backface_culling) {
1791                                 if (mat->game.flag)
1792                                         glEnable(GL_CULL_FACE);
1793                                 else
1794                                         glDisable(GL_CULL_FACE);
1795                         }
1796
1797                         if (GMS.use_matcaps)
1798                                 glColor3f(1.0f, 1.0f, 1.0f);
1799                 }
1800                 else {
1801                         /* or do fixed function opengl material */
1802                         GPU_basic_shader_colors(GMS.matbuf[nr].diff,
1803                                 GMS.matbuf[nr].spec, GMS.matbuf[nr].hard, GMS.matbuf[nr].alpha);
1804
1805                         if (GMS.two_sided_lighting)
1806                                 GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED);
1807                         else
1808                                 GPU_basic_shader_bind(GPU_SHADER_LIGHTING);
1809                 }
1810
1811                 /* set (alpha) blending mode */
1812                 GPU_set_material_alpha_blend(alphablend);
1813         }
1814
1815         return GMS.lastretval;
1816 }
1817
1818 int GPU_object_material_visible(int nr, void *attribs)
1819 {
1820         GPUVertexAttribs *gattribs = attribs;
1821         int visible;
1822
1823         if (!GMS.matbuf)
1824                 return 0;
1825
1826         if (gattribs)
1827                 memset(gattribs, 0, sizeof(*gattribs));
1828
1829         if (nr>=GMS.totmat)
1830                 nr = 0;
1831
1832         if (GMS.use_alpha_pass) {
1833                 visible = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
1834                 if (GMS.is_alpha_pass)
1835                         visible = !visible;
1836         }
1837         else
1838                 visible = !GMS.is_alpha_pass;
1839
1840         return visible;
1841 }
1842
1843 void GPU_set_material_alpha_blend(int alphablend)
1844 {
1845         if (GMS.lastalphablend == alphablend)
1846                 return;
1847         
1848         gpu_set_alpha_blend(alphablend);
1849         GMS.lastalphablend = alphablend;
1850 }
1851
1852 int GPU_get_material_alpha_blend(void)
1853 {
1854         return GMS.lastalphablend;
1855 }
1856
1857 void GPU_object_material_unbind(void)
1858 {
1859         GMS.lastmatnr = -1;
1860         GMS.lastretval = 1;
1861
1862         if (GMS.gboundmat) {
1863                 if (GMS.backface_culling)
1864                         glDisable(GL_CULL_FACE);
1865
1866                 if (GMS.is_alpha_pass) glDepthMask(0);
1867                 GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv));
1868                 GMS.gboundmat = NULL;
1869         }
1870         else
1871                 GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
1872
1873         GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
1874 }
1875
1876 void GPU_material_diffuse_get(int nr, float diff[4])
1877 {
1878         /* prevent index to use un-initialized array items */
1879         if (nr >= GMS.totmat)
1880                 nr = 0;
1881
1882         /* no GPU_begin_object_materials, use default material */
1883         if (!GMS.matbuf) {
1884                 mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit);
1885         }
1886         else {
1887                 copy_v3_v3(diff, GMS.matbuf[nr].diff);
1888                 diff[3] = GMS.matbuf[nr].alpha;
1889         }
1890 }
1891
1892 bool GPU_material_use_matcaps_get(void)
1893 {
1894         return GMS.use_matcaps;
1895 }
1896
1897 bool GPU_object_materials_check(void)
1898 {
1899         return GMS.is_enabled;
1900 }
1901
1902 void GPU_end_object_materials(void)
1903 {
1904         GPU_object_material_unbind();
1905
1906         GMS.is_enabled = false;
1907
1908         if (GMS.matbuf && GMS.matbuf != GMS.matbuf_fixed) {
1909                 MEM_freeN(GMS.matbuf);
1910                 MEM_freeN(GMS.gmatbuf);
1911                 MEM_freeN(GMS.alphablend);
1912         }
1913
1914         GMS.matbuf = NULL;
1915         GMS.gmatbuf = NULL;
1916         GMS.alphablend = NULL;
1917         GMS.two_sided_lighting = false;
1918
1919         /* resetting the texture matrix after the scaling needed for tiled textures */
1920         if (GTS.tilemode) {
1921                 glMatrixMode(GL_TEXTURE);
1922                 glLoadIdentity();
1923                 glMatrixMode(GL_MODELVIEW);
1924         }
1925 }
1926
1927 /* Lights */
1928
1929 int GPU_default_lights(void)
1930 {
1931         int a, count = 0;
1932         
1933         /* initialize */
1934         if (U.light[0].flag == 0 && U.light[1].flag == 0 && U.light[2].flag == 0) {
1935                 U.light[0].flag = 1;
1936                 U.light[0].vec[0] = -0.3; U.light[0].vec[1] = 0.3; U.light[0].vec[2] = 0.9;
1937                 U.light[0].col[0] = 0.8; U.light[0].col[1] = 0.8; U.light[0].col[2] = 0.8;
1938                 U.light[0].spec[0] = 0.5; U.light[0].spec[1] = 0.5; U.light[0].spec[2] = 0.5;
1939                 U.light[0].spec[3] = 1.0;
1940                 
1941                 U.light[1].flag = 0;
1942                 U.light[1].vec[0] = 0.5; U.light[1].vec[1] = 0.5; U.light[1].vec[2] = 0.1;
1943                 U.light[1].col[0] = 0.4; U.light[1].col[1] = 0.4; U.light[1].col[2] = 0.8;
1944                 U.light[1].spec[0] = 0.3; U.light[1].spec[1] = 0.3; U.light[1].spec[2] = 0.5;
1945                 U.light[1].spec[3] = 1.0;
1946         
1947                 U.light[2].flag = 0;
1948                 U.light[2].vec[0] = 0.3; U.light[2].vec[1] = -0.3; U.light[2].vec[2] = -0.2;
1949                 U.light[2].col[0] = 0.8; U.light[2].col[1] = 0.5; U.light[2].col[2] = 0.4;
1950                 U.light[2].spec[0] = 0.5; U.light[2].spec[1] = 0.4; U.light[2].spec[2] = 0.3;
1951                 U.light[2].spec[3] = 1.0;
1952         }
1953
1954         GPU_basic_shader_light_set_viewer(false);
1955
1956         for (a = 0; a < 8; a++) {
1957                 if (a < 3 && U.light[a].flag) {
1958                         GPULightData light = {0};
1959
1960                         light.type = GPU_LIGHT_SUN;
1961
1962                         normalize_v3_v3(light.direction, U.light[a].vec);
1963                         copy_v3_v3(light.diffuse, U.light[a].col);
1964                         copy_v3_v3(light.specular, U.light[a].spec);
1965
1966                         GPU_basic_shader_light_set(a, &light);
1967
1968                         count++;
1969                 }
1970                 else
1971                         GPU_basic_shader_light_set(a, NULL);
1972         }
1973
1974         return count;
1975 }
1976
1977 int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][4], int ortho)
1978 {
1979         Base *base;
1980         Lamp *la;
1981         int count;
1982         
1983         /* disable all lights */
1984         for (count = 0; count < 8; count++)
1985                 GPU_basic_shader_light_set(count, NULL);
1986         
1987         /* view direction for specular is not computed correct by default in
1988          * opengl, so we set the settings ourselfs */
1989         GPU_basic_shader_light_set_viewer(!ortho);
1990
1991         count = 0;
1992
1993         for (base = scene->base.first; base; base = base->next) {
1994                 if (base->object->type != OB_LAMP)
1995                         continue;
1996
1997                 if (!(base->lay & lay) || !(base->lay & ob->lay))
1998                         continue;
1999
2000                 la = base->object->data;
2001                 
2002                 /* setup lamp transform */
2003                 glPushMatrix();
2004                 glLoadMatrixf((float *)viewmat);
2005                 
2006                 /* setup light */
2007                 GPULightData light = {0};
2008
2009                 mul_v3_v3fl(light.diffuse, &la->r, la->energy);
2010                 mul_v3_v3fl(light.specular, &la->r, la->energy);
2011
2012                 if (la->type == LA_SUN) {
2013                         /* directional sun light */
2014                         light.type = GPU_LIGHT_SUN;
2015                         normalize_v3_v3(light.direction, base->object->obmat[2]);
2016                 }
2017                 else {
2018                         /* other lamps with position attenuation */
2019                         copy_v3_v3(light.position, base->object->obmat[3]);
2020
2021                         light.constant_attenuation = 1.0f;
2022                         light.linear_attenuation = la->att1 / la->dist;
2023                         light.quadratic_attenuation = la->att2 / (la->dist * la->dist);
2024                         
2025                         if (la->type == LA_SPOT) {
2026                                 light.type = GPU_LIGHT_SPOT;
2027                                 negate_v3_v3(light.direction, base->object->obmat[2]);
2028                                 normalize_v3(light.direction);
2029                                 light.spot_cutoff = RAD2DEGF(la->spotsize * 0.5f);
2030                                 light.spot_exponent = 128.0f * la->spotblend;
2031                         }
2032                         else
2033                                 light.type = GPU_LIGHT_POINT;
2034                 }
2035                 
2036                 GPU_basic_shader_light_set(count, &light);
2037                 
2038                 glPopMatrix();
2039                 
2040                 count++;
2041                 if (count == 8)
2042                         break;
2043         }
2044
2045         return count;
2046 }
2047
2048 static void gpu_multisample(bool enable)
2049 {
2050 #ifdef __linux__
2051         /* changing multisample from the default (enabled) causes problems on some
2052          * systems (NVIDIA/Linux) when the pixel format doesn't have a multisample buffer */
2053         bool toggle_ok = true;
2054
2055         if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
2056                 int samples = 0;
2057                 glGetIntegerv(GL_SAMPLES, &samples);
2058
2059                 if (samples == 0)
2060                         toggle_ok = false;
2061         }
2062
2063         if (toggle_ok) {
2064                 if (enable)
2065                         glEnable(GL_MULTISAMPLE);
2066                 else
2067                         glDisable(GL_MULTISAMPLE);
2068         }
2069 #else
2070         if (enable)
2071                 glEnable(GL_MULTISAMPLE);
2072         else
2073                 glDisable(GL_MULTISAMPLE);
2074 #endif
2075 }
2076
2077 /* Default OpenGL State
2078  *
2079  * This is called on startup, for opengl offscreen render and to restore state
2080  * for the game engine. Generally we should always return to this state when
2081  * temporarily modifying the state for drawing, though that are (undocumented)
2082  * exceptions that we should try to get rid of. */
2083
2084 void GPU_state_init(void)
2085 {
2086         float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
2087         float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
2088         int a, x, y;
2089         GLubyte pat[32 * 32];
2090         const GLubyte *patc = pat;
2091         
2092         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
2093         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
2094         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
2095         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35);
2096         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2097
2098         GPU_default_lights();
2099         
2100         glDepthFunc(GL_LEQUAL);
2101         /* scaling matrices */
2102         glEnable(GL_NORMALIZE);
2103
2104         glShadeModel(GL_FLAT);
2105
2106         glDisable(GL_ALPHA_TEST);
2107         glDisable(GL_BLEND);
2108         glDisable(GL_DEPTH_TEST);
2109         glDisable(GL_FOG);
2110         glDisable(GL_LIGHTING);
2111         glDisable(GL_COLOR_MATERIAL);
2112         glDisable(GL_LOGIC_OP);
2113         glDisable(GL_STENCIL_TEST);
2114         glDisable(GL_TEXTURE_1D);
2115         glDisable(GL_TEXTURE_2D);
2116         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2117
2118         /* default disabled, enable should be local per function */
2119         glDisableClientState(GL_VERTEX_ARRAY);
2120         glDisableClientState(GL_NORMAL_ARRAY);
2121         glDisableClientState(GL_COLOR_ARRAY);
2122         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2123         
2124         glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
2125         glPixelTransferi(GL_RED_SCALE, 1);
2126         glPixelTransferi(GL_RED_BIAS, 0);
2127         glPixelTransferi(GL_GREEN_SCALE, 1);
2128         glPixelTransferi(GL_GREEN_BIAS, 0);
2129         glPixelTransferi(GL_BLUE_SCALE, 1);
2130         glPixelTransferi(GL_BLUE_BIAS, 0);
2131         glPixelTransferi(GL_ALPHA_SCALE, 1);
2132         glPixelTransferi(GL_ALPHA_BIAS, 0);
2133         
2134         glPixelTransferi(GL_DEPTH_BIAS, 0);
2135         glPixelTransferi(GL_DEPTH_SCALE, 1);
2136         glDepthRange(0.0, 1.0);
2137         
2138         a = 0;
2139         for (x = 0; x < 32; x++) {
2140                 for (y = 0; y < 4; y++) {
2141                         if (x & 1) pat[a++] = 0x88;
2142                         else pat[a++] = 0x22;
2143                 }
2144         }
2145
2146         glPolygonStipple(patc);
2147
2148         glMatrixMode(GL_TEXTURE);
2149         glLoadIdentity();
2150         glMatrixMode(GL_MODELVIEW);
2151
2152         glFrontFace(GL_CCW);
2153         glCullFace(GL_BACK);
2154         glDisable(GL_CULL_FACE);
2155
2156         gpu_multisample(false);
2157
2158         GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
2159 }
2160
2161 #ifdef WITH_OPENSUBDIV
2162 /* Update face-varying variables offset which might be
2163  * different from mesh to mesh sharing the same material.
2164  */
2165 void GPU_draw_update_fvar_offset(DerivedMesh *dm)
2166 {
2167         int i;
2168
2169         /* Sanity check to be sure we only do this for OpenSubdiv draw. */
2170         BLI_assert(dm->type == DM_TYPE_CCGDM);
2171         BLI_assert(GMS.is_opensubdiv);
2172
2173         for (i = 0; i < GMS.totmat; ++i) {
2174                 Material *material = GMS.gmatbuf[i];
2175                 GPUMaterial *gpu_material;
2176
2177                 if (material == NULL) {
2178                         continue;
2179                 }
2180
2181                 gpu_material = GPU_material_from_blender(GMS.gscene,
2182                                                          material,
2183                                                          GMS.is_opensubdiv);
2184
2185                 GPU_material_update_fvar_offset(gpu_material, dm);
2186         }
2187 }
2188 #endif