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