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