Fix T64678: wrong DDS normal map rendering after recent changes
[blender.git] / source / blender / gpu / intern / gpu_draw.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup gpu
22  *
23  * Utility functions for dealing with OpenGL texture & material context,
24  * mipmap generation and light objects.
25  *
26  * These are some obscure rendering functions shared between the game engine (not anymore)
27  * and the blender, in this module to avoid duplication
28  * and abstract them away from the rest a bit.
29  */
30
31 #include <string.h>
32
33 #include "BLI_blenlib.h"
34 #include "BLI_linklist.h"
35 #include "BLI_math.h"
36 #include "BLI_threads.h"
37 #include "BLI_utildefines.h"
38
39 #include "DNA_light_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_modifier_types.h"
44 #include "DNA_node_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_smoke_types.h"
48 #include "DNA_view3d_types.h"
49 #include "DNA_particle_types.h"
50
51 #include "MEM_guardedalloc.h"
52
53 #include "IMB_colormanagement.h"
54 #include "IMB_imbuf.h"
55 #include "IMB_imbuf_types.h"
56
57 #include "BKE_colorband.h"
58 #include "BKE_global.h"
59 #include "BKE_image.h"
60 #include "BKE_main.h"
61 #include "BKE_material.h"
62 #include "BKE_node.h"
63 #include "BKE_scene.h"
64
65 #include "GPU_draw.h"
66 #include "GPU_extensions.h"
67 #include "GPU_glew.h"
68 #include "GPU_material.h"
69 #include "GPU_matrix.h"
70 #include "GPU_shader.h"
71 #include "GPU_texture.h"
72
73 #include "PIL_time.h"
74
75 #ifdef WITH_SMOKE
76 #  include "smoke_API.h"
77 #endif
78
79 static void gpu_free_image_immediate(Image *ima);
80
81 //* Checking powers of two for images since OpenGL ES requires it */
82 #ifdef WITH_DDS
83 static bool is_power_of_2_resolution(int w, int h)
84 {
85   return is_power_of_2_i(w) && is_power_of_2_i(h);
86 }
87 #endif
88
89 static bool is_over_resolution_limit(GLenum textarget, int w, int h)
90 {
91   int size = (textarget == GL_TEXTURE_2D) ? GPU_max_texture_size() : GPU_max_cube_map_size();
92   int reslimit = (U.glreslimit != 0) ? min_ii(U.glreslimit, size) : size;
93
94   return (w > reslimit || h > reslimit);
95 }
96
97 static int smaller_power_of_2_limit(int num)
98 {
99   int reslimit = (U.glreslimit != 0) ? min_ii(U.glreslimit, GPU_max_texture_size()) :
100                                        GPU_max_texture_size();
101   /* take texture clamping into account */
102   if (num > reslimit) {
103     return reslimit;
104   }
105
106   return power_of_2_min_i(num);
107 }
108
109 /* Current OpenGL state caching for GPU_set_tpage */
110
111 static struct GPUTextureState {
112   /* also controls min/mag filtering */
113   bool domipmap;
114   /* only use when 'domipmap' is set */
115   bool linearmipmap;
116   /* store this so that new images created while texture painting won't be set to mipmapped */
117   bool texpaint;
118
119   float anisotropic;
120 } GTS = {1, 0, 0, 1.0f};
121
122 /* Mipmap settings */
123
124 void GPU_set_mipmap(Main *bmain, bool mipmap)
125 {
126   if (GTS.domipmap != mipmap) {
127     GPU_free_images(bmain);
128     GTS.domipmap = mipmap;
129   }
130 }
131
132 void GPU_set_linear_mipmap(bool linear)
133 {
134   if (GTS.linearmipmap != linear) {
135     GTS.linearmipmap = linear;
136   }
137 }
138
139 bool GPU_get_mipmap(void)
140 {
141   return GTS.domipmap && !GTS.texpaint;
142 }
143
144 bool GPU_get_linear_mipmap(void)
145 {
146   return GTS.linearmipmap;
147 }
148
149 static GLenum gpu_get_mipmap_filter(bool mag)
150 {
151   /* linearmipmap is off by default *when mipmapping is off,
152    * use unfiltered display */
153   if (mag) {
154     if (GTS.domipmap) {
155       return GL_LINEAR;
156     }
157     else {
158       return GL_NEAREST;
159     }
160   }
161   else {
162     if (GTS.domipmap) {
163       if (GTS.linearmipmap) {
164         return GL_LINEAR_MIPMAP_LINEAR;
165       }
166       else {
167         return GL_LINEAR_MIPMAP_NEAREST;
168       }
169     }
170     else {
171       return GL_NEAREST;
172     }
173   }
174 }
175
176 /* Anisotropic filtering settings */
177 void GPU_set_anisotropic(Main *bmain, float value)
178 {
179   if (GTS.anisotropic != value) {
180     GPU_free_images(bmain);
181
182     /* Clamp value to the maximum value the graphics card supports */
183     const float max = GPU_max_texture_anisotropy();
184     if (value > max) {
185       value = max;
186     }
187
188     GTS.anisotropic = value;
189   }
190 }
191
192 float GPU_get_anisotropic(void)
193 {
194   return GTS.anisotropic;
195 }
196
197 /* Set OpenGL state for an MTFace */
198
199 static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget)
200 {
201   if (textarget == GL_TEXTURE_2D) {
202     return &ima->gputexture[TEXTARGET_TEXTURE_2D];
203   }
204   else if (textarget == GL_TEXTURE_CUBE_MAP) {
205     return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP];
206   }
207
208   return NULL;
209 }
210
211 static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
212 {
213   uint bindcode = 0;
214   const bool mipmap = GPU_get_mipmap();
215
216 #ifdef WITH_DDS
217   if (ibuf->ftype == IMB_FTYPE_DDS) {
218     /* DDS is loaded directly in compressed form. */
219     GPU_create_gl_tex_compressed(&bindcode, textarget, ima, ibuf);
220     return bindcode;
221   }
222 #endif
223
224   /* Regular uncompressed texture. */
225   float *rect_float = ibuf->rect_float;
226   uchar *rect = (uchar *)ibuf->rect;
227   bool compress_as_srgb = false;
228
229   if (rect_float == NULL) {
230     /* Byte image is in original colorspace from the file. If the file is sRGB
231      * scene linear, or non-color data no conversion is needed. Otherwise we
232      * compress as scene linear + sRGB transfer function to avoid precision loss
233      * in common cases.
234      *
235      * We must also convert to premultiplied for correct texture interpolation
236      * and consistency with float images. */
237     if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
238       compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace);
239
240       rect = MEM_mallocN(sizeof(uchar) * 4 * ibuf->x * ibuf->y, __func__);
241       if (rect == NULL) {
242         return bindcode;
243       }
244
245       IMB_colormanagement_imbuf_to_srgb_texture(
246           rect, 0, 0, ibuf->x, ibuf->y, ibuf, compress_as_srgb);
247     }
248   }
249   else if (ibuf->channels != 4) {
250     /* Float image is already in scene linear colorspace or non-color data by
251      * convention, no colorspace conversion needed. But we do require 4 channels
252      * currently. */
253     rect_float = MEM_mallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, __func__);
254     if (rect_float == NULL) {
255       return bindcode;
256     }
257
258     IMB_buffer_float_from_float(rect_float,
259                                 ibuf->rect_float,
260                                 ibuf->channels,
261                                 IB_PROFILE_LINEAR_RGB,
262                                 IB_PROFILE_LINEAR_RGB,
263                                 false,
264                                 ibuf->x,
265                                 ibuf->y,
266                                 ibuf->x,
267                                 ibuf->x);
268   }
269
270   /* Create OpenGL texture. */
271   GPU_create_gl_tex(&bindcode,
272                     (uint *)rect,
273                     rect_float,
274                     ibuf->x,
275                     ibuf->y,
276                     textarget,
277                     mipmap,
278                     compress_as_srgb,
279                     ima);
280
281   /* Free buffers if needed. */
282   if (rect && rect != (uchar *)ibuf->rect) {
283     MEM_freeN(rect);
284   }
285   if (rect_float && rect_float != ibuf->rect_float) {
286     MEM_freeN(rect_float);
287   }
288
289   return bindcode;
290 }
291
292 static void gpu_texture_update_scaled(
293     uchar *rect, float *rect_float, int full_w, int full_h, int x, int y, int w, int h)
294 {
295   /* Partial update with scaling. */
296   int limit_w = smaller_power_of_2_limit(full_w);
297   int limit_h = smaller_power_of_2_limit(full_h);
298   float xratio = limit_w / (float)full_w;
299   float yratio = limit_h / (float)full_h;
300
301   /* Find sub coordinates in scaled image. Take ceiling because we will be
302    * losing 1 pixel due to rounding errors in x,y. */
303   int sub_x = x * xratio;
304   int sub_y = y * yratio;
305   int sub_w = (int)ceil(xratio * w);
306   int sub_h = (int)ceil(yratio * h);
307
308   /* ...but take back if we are over the limit! */
309   if (sub_w + sub_x > limit_w) {
310     sub_w--;
311   }
312   if (sub_h + sub_y > limit_h) {
313     sub_h--;
314   }
315
316   /* Scale pixels. */
317   ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h);
318   IMB_scaleImBuf(ibuf, sub_w, sub_h);
319
320   if (ibuf->rect_float) {
321     glTexSubImage2D(
322         GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_FLOAT, ibuf->rect_float);
323   }
324   else {
325     glTexSubImage2D(
326         GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
327   }
328
329   IMB_freeImBuf(ibuf);
330 }
331
332 static void gpu_texture_update_unscaled(
333     uchar *rect, float *rect_float, int x, int y, int w, int h, GLint tex_stride, GLint tex_offset)
334 {
335   /* Partial update without scaling. Stride and offset are used to copy only a
336    * subset of a possible larger buffer than what we are updating. */
337   GLint row_length;
338   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
339   glPixelStorei(GL_UNPACK_ROW_LENGTH, tex_stride);
340
341   if (rect_float == NULL) {
342     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect + tex_offset);
343   }
344   else {
345     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, rect_float + tex_offset);
346   }
347
348   glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
349 }
350
351 static void gpu_texture_update_from_ibuf(ImBuf *ibuf, int x, int y, int w, int h)
352 {
353   /* Partial update of texture for texture painting. This is often much
354    * quicker than fully updating the texture for high resolution images.
355    * Assumes the OpenGL texture is bound to 0. */
356   const bool scaled = is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y);
357
358   if (scaled) {
359     /* Extra padding to account for bleed from neighboring pixels. */
360     const int padding = 4;
361     const int xmax = min_ii(x + w + padding, ibuf->x);
362     const int ymax = min_ii(y + h + padding, ibuf->y);
363     x = max_ii(x - padding, 0);
364     y = max_ii(y - padding, 0);
365     w = xmax - x;
366     h = ymax - y;
367   }
368
369   /* Get texture data pointers. */
370   float *rect_float = ibuf->rect_float;
371   uchar *rect = (uchar *)ibuf->rect;
372   GLint tex_stride = ibuf->x;
373   GLint tex_offset = ibuf->channels * (y * ibuf->x + x);
374
375   if (rect_float == NULL) {
376     /* Byte pixels. */
377     if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
378       const bool compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(
379           ibuf->rect_colorspace);
380
381       rect = MEM_mallocN(sizeof(uchar) * 4 * w * h, __func__);
382       if (rect == NULL) {
383         return;
384       }
385
386       tex_stride = w;
387       tex_offset = 0;
388
389       /* Convert to scene linear with sRGB compression, and premultiplied for
390        * correct texture interpolation. */
391       IMB_colormanagement_imbuf_to_srgb_texture(rect, x, y, w, h, ibuf, compress_as_srgb);
392     }
393   }
394   else if (ibuf->channels != 4 || scaled) {
395     /* Float pixels. */
396     rect_float = MEM_mallocN(sizeof(float) * 4 * x * y, __func__);
397     if (rect_float == NULL) {
398       return;
399     }
400
401     tex_stride = w;
402     tex_offset = 0;
403
404     size_t ibuf_offset = (y * ibuf->x + x) * ibuf->channels;
405     IMB_buffer_float_from_float(rect_float,
406                                 ibuf->rect_float + ibuf_offset,
407                                 ibuf->channels,
408                                 IB_PROFILE_LINEAR_RGB,
409                                 IB_PROFILE_LINEAR_RGB,
410                                 false,
411                                 w,
412                                 h,
413                                 x,
414                                 ibuf->x);
415   }
416
417   if (scaled) {
418     /* Slower update where we first have to scale the input pixels. */
419     gpu_texture_update_scaled(rect, rect_float, ibuf->x, ibuf->y, x, y, w, h);
420   }
421   else {
422     /* Fast update at same resolution. */
423     gpu_texture_update_unscaled(rect, rect_float, x, y, w, h, tex_stride, tex_offset);
424   }
425
426   /* Free buffers if needed. */
427   if (rect && rect != (uchar *)ibuf->rect) {
428     MEM_freeN(rect);
429   }
430   if (rect_float && rect_float != ibuf->rect_float) {
431     MEM_freeN(rect_float);
432   }
433 }
434
435 GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget)
436 {
437   if (ima == NULL) {
438     return NULL;
439   }
440
441   /* currently, gpu refresh tagging is used by ima sequences */
442   if (ima->gpuflag & IMA_GPU_REFRESH) {
443     gpu_free_image_immediate(ima);
444     ima->gpuflag &= ~IMA_GPU_REFRESH;
445   }
446
447   /* Test if we already have a texture. */
448   GPUTexture **tex = gpu_get_image_gputexture(ima, textarget);
449   if (*tex) {
450     return *tex;
451   }
452
453   /* Check if we have a valid image. If not, we return a dummy
454    * texture with zero bindcode so we don't keep trying. */
455   uint bindcode = 0;
456   if (ima->ok == 0) {
457     *tex = GPU_texture_from_bindcode(textarget, bindcode);
458     return *tex;
459   }
460
461   /* check if we have a valid image buffer */
462   ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
463   if (ibuf == NULL) {
464     *tex = GPU_texture_from_bindcode(textarget, bindcode);
465     return *tex;
466   }
467
468   bindcode = gpu_texture_create_from_ibuf(ima, ibuf, textarget);
469
470   BKE_image_release_ibuf(ima, ibuf, NULL);
471
472   *tex = GPU_texture_from_bindcode(textarget, bindcode);
473   return *tex;
474 }
475
476 static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth)
477 {
478   size_t block_size = frect ? sizeof(float[4]) : sizeof(uchar[4]);
479   void **sides = NULL;
480   int h = recth / 2;
481   int w = rectw / 3;
482
483   if (w != h) {
484     return sides;
485   }
486
487   /* PosX, NegX, PosY, NegY, PosZ, NegZ */
488   sides = MEM_mallocN(sizeof(void *) * 6, "");
489   for (int i = 0; i < 6; i++) {
490     sides[i] = MEM_mallocN(block_size * w * h, "");
491   }
492
493   /* divide image into six parts */
494   /* ______________________
495    * |      |      |      |
496    * | NegX | NegY | PosX |
497    * |______|______|______|
498    * |      |      |      |
499    * | NegZ | PosZ | PosY |
500    * |______|______|______|
501    */
502   if (frect) {
503     float(*frectb)[4] = (float(*)[4])frect;
504     float(**fsides)[4] = (float(**)[4])sides;
505
506     for (int y = 0; y < h; y++) {
507       for (int x = 0; x < w; x++) {
508         memcpy(&fsides[0][x * h + y], &frectb[(recth - y - 1) * rectw + 2 * w + x], block_size);
509         memcpy(&fsides[1][x * h + y], &frectb[(y + h) * rectw + w - 1 - x], block_size);
510         memcpy(
511             &fsides[3][y * w + x], &frectb[(recth - y - 1) * rectw + 2 * w - 1 - x], block_size);
512         memcpy(&fsides[5][y * w + x], &frectb[(h - y - 1) * rectw + w - 1 - x], block_size);
513       }
514       memcpy(&fsides[2][y * w], frectb[y * rectw + 2 * w], block_size * w);
515       memcpy(&fsides[4][y * w], frectb[y * rectw + w], block_size * w);
516     }
517   }
518   else {
519     uint **isides = (uint **)sides;
520
521     for (int y = 0; y < h; y++) {
522       for (int x = 0; x < w; x++) {
523         isides[0][x * h + y] = rect[(recth - y - 1) * rectw + 2 * w + x];
524         isides[1][x * h + y] = rect[(y + h) * rectw + w - 1 - x];
525         isides[3][y * w + x] = rect[(recth - y - 1) * rectw + 2 * w - 1 - x];
526         isides[5][y * w + x] = rect[(h - y - 1) * rectw + w - 1 - x];
527       }
528       memcpy(&isides[2][y * w], &rect[y * rectw + 2 * w], block_size * w);
529       memcpy(&isides[4][y * w], &rect[y * rectw + w], block_size * w);
530     }
531   }
532
533   return sides;
534 }
535
536 static void gpu_del_cube_map(void **cube_map)
537 {
538   int i;
539   if (cube_map == NULL) {
540     return;
541   }
542   for (i = 0; i < 6; i++) {
543     MEM_freeN(cube_map[i]);
544   }
545   MEM_freeN(cube_map);
546 }
547
548 /* Image *ima can be NULL */
549 void GPU_create_gl_tex(uint *bind,
550                        uint *rect,
551                        float *frect,
552                        int rectw,
553                        int recth,
554                        int textarget,
555                        bool mipmap,
556                        bool use_srgb,
557                        Image *ima)
558 {
559   ImBuf *ibuf = NULL;
560
561   if (textarget == GL_TEXTURE_2D && is_over_resolution_limit(textarget, rectw, recth)) {
562     int tpx = rectw;
563     int tpy = recth;
564     rectw = smaller_power_of_2_limit(rectw);
565     recth = smaller_power_of_2_limit(recth);
566
567     if (frect) {
568       ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
569       IMB_scaleImBuf(ibuf, rectw, recth);
570
571       frect = ibuf->rect_float;
572     }
573     else {
574       ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
575       IMB_scaleImBuf(ibuf, rectw, recth);
576
577       rect = ibuf->rect;
578     }
579   }
580
581   /* create image */
582   glGenTextures(1, (GLuint *)bind);
583   glBindTexture(textarget, *bind);
584
585   GLenum internal_format = (frect) ? GL_RGBA16F : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
586
587   if (textarget == GL_TEXTURE_2D) {
588     if (frect) {
589       glTexImage2D(GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
590     }
591     else {
592       glTexImage2D(
593           GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
594     }
595
596     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
597
598     if (GPU_get_mipmap() && mipmap) {
599       glGenerateMipmap(GL_TEXTURE_2D);
600       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
601       if (ima) {
602         ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
603       }
604     }
605     else {
606       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
607     }
608   }
609   else if (textarget == GL_TEXTURE_CUBE_MAP) {
610     int w = rectw / 3, h = recth / 2;
611
612     if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) {
613       void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth);
614       GLenum type = frect ? GL_FLOAT : GL_UNSIGNED_BYTE;
615
616       if (cube_map) {
617         for (int i = 0; i < 6; i++) {
618           glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
619                        0,
620                        internal_format,
621                        w,
622                        h,
623                        0,
624                        GL_RGBA,
625                        type,
626                        cube_map[i]);
627         }
628       }
629
630       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
631
632       if (GPU_get_mipmap() && mipmap) {
633         glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
634         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
635
636         if (ima) {
637           ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
638         }
639       }
640       else {
641         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
642       }
643       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
644       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
645       glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
646
647       gpu_del_cube_map(cube_map);
648     }
649     else {
650       printf("Incorrect envmap size\n");
651     }
652   }
653
654   if (GLEW_EXT_texture_filter_anisotropic) {
655     glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
656   }
657
658   glBindTexture(textarget, 0);
659
660   if (ibuf) {
661     IMB_freeImBuf(ibuf);
662   }
663 }
664
665 /**
666  * GPU_upload_dxt_texture() assumes that the texture is already bound and ready to go.
667  * This is so the viewport and the BGE can share some code.
668  * Returns false if the provided ImBuf doesn't have a supported DXT compression format
669  */
670 bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
671 {
672 #ifdef WITH_DDS
673   GLint format = 0;
674   int blocksize, height, width, i, size, offset = 0;
675
676   width = ibuf->x;
677   height = ibuf->y;
678
679   if (GLEW_EXT_texture_compression_s3tc) {
680     if (ibuf->dds_data.fourcc == FOURCC_DXT1) {
681       format = (use_srgb) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT :
682                             GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
683     }
684     else if (ibuf->dds_data.fourcc == FOURCC_DXT3) {
685       format = (use_srgb) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT :
686                             GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
687     }
688     else if (ibuf->dds_data.fourcc == FOURCC_DXT5) {
689       format = (use_srgb) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT :
690                             GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
691     }
692   }
693
694   if (format == 0) {
695     fprintf(stderr, "Unable to find a suitable DXT compression, falling back to uncompressed\n");
696     return false;
697   }
698
699   if (!is_power_of_2_resolution(width, height)) {
700     fprintf(
701         stderr,
702         "Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
703     return false;
704   }
705
706   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
707   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
708
709   if (GLEW_EXT_texture_filter_anisotropic) {
710     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
711   }
712
713   blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
714   for (i = 0; i < ibuf->dds_data.nummipmaps && (width || height); ++i) {
715     if (width == 0) {
716       width = 1;
717     }
718     if (height == 0) {
719       height = 1;
720     }
721
722     size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize;
723
724     glCompressedTexImage2D(
725         GL_TEXTURE_2D, i, format, width, height, 0, size, ibuf->dds_data.data + offset);
726
727     offset += size;
728     width >>= 1;
729     height >>= 1;
730   }
731
732   /* set number of mipmap levels we have, needed in case they don't go down to 1x1 */
733   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1);
734
735   return true;
736 #else
737   (void)ibuf;
738   return false;
739 #endif
740 }
741
742 void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima, ImBuf *ibuf)
743 {
744   /* For DDS we only support data, scene linear and sRGB. Converting to
745    * different colorspace would break the compression. */
746   const bool use_srgb = !(IMB_colormanagement_space_is_data(ibuf->rect_colorspace) ||
747                           IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace));
748   const bool mipmap = GPU_get_mipmap();
749
750 #ifndef WITH_DDS
751   (void)ibuf;
752   /* Fall back to uncompressed if DDS isn't enabled */
753   GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, use_srgb, ima);
754 #else
755   glGenTextures(1, (GLuint *)bind);
756   glBindTexture(textarget, *bind);
757
758   if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf, use_srgb) == 0) {
759     glDeleteTextures(1, (GLuint *)bind);
760     GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->x, textarget, mipmap, use_srgb, ima);
761   }
762
763   glBindTexture(textarget, 0);
764 #endif
765 }
766
767 /* these two functions are called on entering and exiting texture paint mode,
768  * temporary disabling/enabling mipmapping on all images for quick texture
769  * updates with glTexSubImage2D. images that didn't change don't have to be
770  * re-uploaded to OpenGL */
771 void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
772 {
773   if (!GTS.domipmap) {
774     return;
775   }
776
777   GTS.texpaint = !mipmap;
778
779   if (mipmap) {
780     for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
781       if (BKE_image_has_opengl_texture(ima)) {
782         if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) {
783           if (ima->gputexture[TEXTARGET_TEXTURE_2D]) {
784             GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
785             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
786             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
787             GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
788           }
789         }
790         else {
791           GPU_free_image(ima);
792         }
793       }
794       else {
795         ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
796       }
797     }
798   }
799   else {
800     for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
801       if (BKE_image_has_opengl_texture(ima)) {
802         if (ima->gputexture[TEXTARGET_TEXTURE_2D]) {
803           GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
804           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
805           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
806           GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
807         }
808       }
809       else {
810         ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
811       }
812     }
813   }
814 }
815
816 void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
817 {
818   ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
819
820   if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) {
821     /* Full reload of texture. */
822     GPU_free_image(ima);
823   }
824   else {
825     /* Partial update of texture. */
826     GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
827
828     gpu_texture_update_from_ibuf(ibuf, x, y, w, h);
829
830     if (GPU_get_mipmap()) {
831       glGenerateMipmap(GL_TEXTURE_2D);
832     }
833     else {
834       ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
835     }
836
837     GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
838   }
839
840   BKE_image_release_ibuf(ima, ibuf, NULL);
841 }
842
843 /* *************************** Transfer functions *************************** */
844
845 enum {
846   TFUNC_FLAME_SPECTRUM = 0,
847   TFUNC_COLOR_RAMP = 1,
848 };
849
850 #define TFUNC_WIDTH 256
851
852 #ifdef WITH_SMOKE
853 static void create_flame_spectrum_texture(float *data)
854 {
855 #  define FIRE_THRESH 7
856 #  define MAX_FIRE_ALPHA 0.06f
857 #  define FULL_ON_FIRE 100
858
859   float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
860
861   blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000);
862
863   for (int i = 0; i < 16; i++) {
864     for (int j = 0; j < 16; j++) {
865       for (int k = 0; k < TFUNC_WIDTH; k++) {
866         int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4;
867         if (k >= FIRE_THRESH) {
868           spec_pixels[index] = (data[k * 4]);
869           spec_pixels[index + 1] = (data[k * 4 + 1]);
870           spec_pixels[index + 2] = (data[k * 4 + 2]);
871           spec_pixels[index + 3] = MAX_FIRE_ALPHA *
872                                    ((k > FULL_ON_FIRE) ?
873                                         1.0f :
874                                         (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
875         }
876         else {
877           zero_v4(&spec_pixels[index]);
878         }
879       }
880     }
881   }
882
883   memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
884
885   MEM_freeN(spec_pixels);
886
887 #  undef FIRE_THRESH
888 #  undef MAX_FIRE_ALPHA
889 #  undef FULL_ON_FIRE
890 }
891
892 static void create_color_ramp(const ColorBand *coba, float *data)
893 {
894   for (int i = 0; i < TFUNC_WIDTH; i++) {
895     BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
896   }
897 }
898
899 static GPUTexture *create_transfer_function(int type, const ColorBand *coba)
900 {
901   float *data = MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__);
902
903   switch (type) {
904     case TFUNC_FLAME_SPECTRUM:
905       create_flame_spectrum_texture(data);
906       break;
907     case TFUNC_COLOR_RAMP:
908       create_color_ramp(coba, data);
909       break;
910   }
911
912   GPUTexture *tex = GPU_texture_create_1d(TFUNC_WIDTH, GPU_RGBA8, data, NULL);
913
914   MEM_freeN(data);
915
916   return tex;
917 }
918
919 static void swizzle_texture_channel_rrrr(GPUTexture *tex)
920 {
921   GPU_texture_bind(tex, 0);
922   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED);
923   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED);
924   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED);
925   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED);
926   GPU_texture_unbind(tex);
927 }
928
929 static GPUTexture *create_field_texture(SmokeDomainSettings *sds)
930 {
931   float *field = NULL;
932
933   switch (sds->coba_field) {
934     case FLUID_FIELD_DENSITY:
935       field = smoke_get_density(sds->fluid);
936       break;
937     case FLUID_FIELD_HEAT:
938       field = smoke_get_heat(sds->fluid);
939       break;
940     case FLUID_FIELD_FUEL:
941       field = smoke_get_fuel(sds->fluid);
942       break;
943     case FLUID_FIELD_REACT:
944       field = smoke_get_react(sds->fluid);
945       break;
946     case FLUID_FIELD_FLAME:
947       field = smoke_get_flame(sds->fluid);
948       break;
949     case FLUID_FIELD_VELOCITY_X:
950       field = smoke_get_velocity_x(sds->fluid);
951       break;
952     case FLUID_FIELD_VELOCITY_Y:
953       field = smoke_get_velocity_y(sds->fluid);
954       break;
955     case FLUID_FIELD_VELOCITY_Z:
956       field = smoke_get_velocity_z(sds->fluid);
957       break;
958     case FLUID_FIELD_COLOR_R:
959       field = smoke_get_color_r(sds->fluid);
960       break;
961     case FLUID_FIELD_COLOR_G:
962       field = smoke_get_color_g(sds->fluid);
963       break;
964     case FLUID_FIELD_COLOR_B:
965       field = smoke_get_color_b(sds->fluid);
966       break;
967     case FLUID_FIELD_FORCE_X:
968       field = smoke_get_force_x(sds->fluid);
969       break;
970     case FLUID_FIELD_FORCE_Y:
971       field = smoke_get_force_y(sds->fluid);
972       break;
973     case FLUID_FIELD_FORCE_Z:
974       field = smoke_get_force_z(sds->fluid);
975       break;
976     default:
977       return NULL;
978   }
979
980   GPUTexture *tex = GPU_texture_create_nD(
981       sds->res[0], sds->res[1], sds->res[2], 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
982
983   swizzle_texture_channel_rrrr(tex);
984   return tex;
985 }
986
987 static GPUTexture *create_density_texture(SmokeDomainSettings *sds, int highres)
988 {
989   float *data = NULL, *source;
990   int cell_count = (highres) ? smoke_turbulence_get_cells(sds->wt) : sds->total_cells;
991   const bool has_color = (highres) ? smoke_turbulence_has_colors(sds->wt) :
992                                      smoke_has_colors(sds->fluid);
993   int *dim = (highres) ? sds->res_wt : sds->res;
994   eGPUTextureFormat format = (has_color) ? GPU_RGBA8 : GPU_R8;
995
996   if (has_color) {
997     data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture");
998   }
999
1000   if (highres) {
1001     if (has_color) {
1002       smoke_turbulence_get_rgba(sds->wt, data, 0);
1003     }
1004     else {
1005       source = smoke_turbulence_get_density(sds->wt);
1006     }
1007   }
1008   else {
1009     if (has_color) {
1010       smoke_get_rgba(sds->fluid, data, 0);
1011     }
1012     else {
1013       source = smoke_get_density(sds->fluid);
1014     }
1015   }
1016
1017   GPUTexture *tex = GPU_texture_create_nD(dim[0],
1018                                           dim[1],
1019                                           dim[2],
1020                                           3,
1021                                           (has_color) ? data : source,
1022                                           format,
1023                                           GPU_DATA_FLOAT,
1024                                           0,
1025                                           true,
1026                                           NULL);
1027   if (data) {
1028     MEM_freeN(data);
1029   }
1030
1031   if (format == GPU_R8) {
1032     /* Swizzle the RGBA components to read the Red channel so
1033      * that the shader stay the same for colored and non color
1034      * density textures. */
1035     swizzle_texture_channel_rrrr(tex);
1036   }
1037   return tex;
1038 }
1039
1040 static GPUTexture *create_flame_texture(SmokeDomainSettings *sds, int highres)
1041 {
1042   float *source = NULL;
1043   const bool has_fuel = (highres) ? smoke_turbulence_has_fuel(sds->wt) :
1044                                     smoke_has_fuel(sds->fluid);
1045   int *dim = (highres) ? sds->res_wt : sds->res;
1046
1047   if (!has_fuel)
1048     return NULL;
1049
1050   if (highres) {
1051     source = smoke_turbulence_get_flame(sds->wt);
1052   }
1053   else {
1054     source = smoke_get_flame(sds->fluid);
1055   }
1056
1057   GPUTexture *tex = GPU_texture_create_nD(
1058       dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL);
1059
1060   swizzle_texture_channel_rrrr(tex);
1061
1062   return tex;
1063 }
1064 #endif /* WITH_SMOKE */
1065
1066 void GPU_free_smoke(SmokeModifierData *smd)
1067 {
1068   if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
1069     if (smd->domain->tex) {
1070       GPU_texture_free(smd->domain->tex);
1071     }
1072     smd->domain->tex = NULL;
1073
1074     if (smd->domain->tex_shadow) {
1075       GPU_texture_free(smd->domain->tex_shadow);
1076     }
1077     smd->domain->tex_shadow = NULL;
1078
1079     if (smd->domain->tex_flame) {
1080       GPU_texture_free(smd->domain->tex_flame);
1081     }
1082     smd->domain->tex_flame = NULL;
1083
1084     if (smd->domain->tex_flame_coba) {
1085       GPU_texture_free(smd->domain->tex_flame_coba);
1086     }
1087     smd->domain->tex_flame_coba = NULL;
1088
1089     if (smd->domain->tex_coba) {
1090       GPU_texture_free(smd->domain->tex_coba);
1091     }
1092     smd->domain->tex_coba = NULL;
1093
1094     if (smd->domain->tex_field) {
1095       GPU_texture_free(smd->domain->tex_field);
1096     }
1097     smd->domain->tex_field = NULL;
1098   }
1099 }
1100
1101 void GPU_create_smoke_coba_field(SmokeModifierData *smd)
1102 {
1103 #ifdef WITH_SMOKE
1104   if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1105     SmokeDomainSettings *sds = smd->domain;
1106
1107     if (!sds->tex_field) {
1108       sds->tex_field = create_field_texture(sds);
1109     }
1110     if (!sds->tex_coba) {
1111       sds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, sds->coba);
1112     }
1113   }
1114 #else   // WITH_SMOKE
1115   smd->domain->tex_field = NULL;
1116 #endif  // WITH_SMOKE
1117 }
1118
1119 void GPU_create_smoke(SmokeModifierData *smd, int highres)
1120 {
1121 #ifdef WITH_SMOKE
1122   if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1123     SmokeDomainSettings *sds = smd->domain;
1124
1125     if (!sds->tex) {
1126       sds->tex = create_density_texture(sds, highres);
1127     }
1128     if (!sds->tex_flame) {
1129       sds->tex_flame = create_flame_texture(sds, highres);
1130     }
1131     if (!sds->tex_flame_coba && sds->tex_flame) {
1132       sds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL);
1133     }
1134     if (!sds->tex_shadow) {
1135       sds->tex_shadow = GPU_texture_create_nD(sds->res[0],
1136                                               sds->res[1],
1137                                               sds->res[2],
1138                                               3,
1139                                               sds->shadow,
1140                                               GPU_R8,
1141                                               GPU_DATA_FLOAT,
1142                                               0,
1143                                               true,
1144                                               NULL);
1145     }
1146   }
1147 #else   // WITH_SMOKE
1148   (void)highres;
1149   smd->domain->tex = NULL;
1150   smd->domain->tex_flame = NULL;
1151   smd->domain->tex_flame_coba = NULL;
1152   smd->domain->tex_shadow = NULL;
1153 #endif  // WITH_SMOKE
1154 }
1155
1156 void GPU_create_smoke_velocity(SmokeModifierData *smd)
1157 {
1158 #ifdef WITH_SMOKE
1159   if (smd->type & MOD_SMOKE_TYPE_DOMAIN) {
1160     SmokeDomainSettings *sds = smd->domain;
1161
1162     const float *vel_x = smoke_get_velocity_x(sds->fluid);
1163     const float *vel_y = smoke_get_velocity_y(sds->fluid);
1164     const float *vel_z = smoke_get_velocity_z(sds->fluid);
1165
1166     if (ELEM(NULL, vel_x, vel_y, vel_z)) {
1167       return;
1168     }
1169
1170     if (!sds->tex_velocity_x) {
1171       sds->tex_velocity_x = GPU_texture_create_3d(
1172           sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_x, NULL);
1173       sds->tex_velocity_y = GPU_texture_create_3d(
1174           sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_y, NULL);
1175       sds->tex_velocity_z = GPU_texture_create_3d(
1176           sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_z, NULL);
1177     }
1178   }
1179 #else   // WITH_SMOKE
1180   smd->domain->tex_velocity_x = NULL;
1181   smd->domain->tex_velocity_y = NULL;
1182   smd->domain->tex_velocity_z = NULL;
1183 #endif  // WITH_SMOKE
1184 }
1185
1186 /* TODO Unify with the other GPU_free_smoke. */
1187 void GPU_free_smoke_velocity(SmokeModifierData *smd)
1188 {
1189   if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
1190     if (smd->domain->tex_velocity_x) {
1191       GPU_texture_free(smd->domain->tex_velocity_x);
1192     }
1193
1194     if (smd->domain->tex_velocity_y) {
1195       GPU_texture_free(smd->domain->tex_velocity_y);
1196     }
1197
1198     if (smd->domain->tex_velocity_z) {
1199       GPU_texture_free(smd->domain->tex_velocity_z);
1200     }
1201
1202     smd->domain->tex_velocity_x = NULL;
1203     smd->domain->tex_velocity_y = NULL;
1204     smd->domain->tex_velocity_z = NULL;
1205   }
1206 }
1207
1208 static LinkNode *image_free_queue = NULL;
1209 static ThreadMutex img_queue_mutex = BLI_MUTEX_INITIALIZER;
1210
1211 static void gpu_queue_image_for_free(Image *ima)
1212 {
1213   BLI_mutex_lock(&img_queue_mutex);
1214   BLI_linklist_prepend(&image_free_queue, ima);
1215   BLI_mutex_unlock(&img_queue_mutex);
1216 }
1217
1218 void GPU_free_unused_buffers(Main *bmain)
1219 {
1220   if (!BLI_thread_is_main()) {
1221     return;
1222   }
1223
1224   BLI_mutex_lock(&img_queue_mutex);
1225
1226   /* images */
1227   for (LinkNode *node = image_free_queue; node; node = node->next) {
1228     Image *ima = node->link;
1229
1230     /* check in case it was freed in the meantime */
1231     if (bmain && BLI_findindex(&bmain->images, ima) != -1) {
1232       GPU_free_image(ima);
1233     }
1234   }
1235
1236   BLI_linklist_free(image_free_queue, NULL);
1237   image_free_queue = NULL;
1238
1239   BLI_mutex_unlock(&img_queue_mutex);
1240 }
1241
1242 static void gpu_free_image_immediate(Image *ima)
1243 {
1244   for (int i = 0; i < TEXTARGET_COUNT; i++) {
1245     /* free glsl image binding */
1246     if (ima->gputexture[i]) {
1247       GPU_texture_free(ima->gputexture[i]);
1248       ima->gputexture[i] = NULL;
1249     }
1250   }
1251
1252   ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE);
1253 }
1254
1255 void GPU_free_image(Image *ima)
1256 {
1257   if (!BLI_thread_is_main()) {
1258     gpu_queue_image_for_free(ima);
1259     return;
1260   }
1261
1262   gpu_free_image_immediate(ima);
1263 }
1264
1265 void GPU_free_images(Main *bmain)
1266 {
1267   if (bmain) {
1268     for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
1269       GPU_free_image(ima);
1270     }
1271   }
1272 }
1273
1274 /* same as above but only free animated images */
1275 void GPU_free_images_anim(Main *bmain)
1276 {
1277   if (bmain) {
1278     for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
1279       if (BKE_image_is_animated(ima)) {
1280         GPU_free_image(ima);
1281       }
1282     }
1283   }
1284 }
1285
1286 void GPU_free_images_old(Main *bmain)
1287 {
1288   static int lasttime = 0;
1289   int ctime = (int)PIL_check_seconds_timer();
1290
1291   /*
1292    * Run garbage collector once for every collecting period of time
1293    * if textimeout is 0, that's the option to NOT run the collector
1294    */
1295   if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) {
1296     return;
1297   }
1298
1299   /* of course not! */
1300   if (G.is_rendering) {
1301     return;
1302   }
1303
1304   lasttime = ctime;
1305
1306   Image *ima = bmain->images.first;
1307   while (ima) {
1308     if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) {
1309       /* If it's in GL memory, deallocate and set time tag to current time
1310        * This gives textures a "second chance" to be used before dying. */
1311       if (BKE_image_has_opengl_texture(ima)) {
1312         GPU_free_image(ima);
1313         ima->lastused = ctime;
1314       }
1315       /* Otherwise, just kill the buffers */
1316       else {
1317         BKE_image_free_buffers(ima);
1318       }
1319     }
1320     ima = ima->id.next;
1321   }
1322 }
1323
1324 static void gpu_disable_multisample(void)
1325 {
1326 #ifdef __linux__
1327   /* changing multisample from the default (enabled) causes problems on some
1328    * systems (NVIDIA/Linux) when the pixel format doesn't have a multisample buffer */
1329   bool toggle_ok = true;
1330
1331   if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
1332     int samples = 0;
1333     glGetIntegerv(GL_SAMPLES, &samples);
1334
1335     if (samples == 0) {
1336       toggle_ok = false;
1337     }
1338   }
1339
1340   if (toggle_ok) {
1341     glDisable(GL_MULTISAMPLE);
1342   }
1343 #else
1344   glDisable(GL_MULTISAMPLE);
1345 #endif
1346 }
1347
1348 /* Default OpenGL State
1349  *
1350  * This is called on startup, for opengl offscreen render.
1351  * Generally we should always return to this state when
1352  * temporarily modifying the state for drawing, though that are (undocumented)
1353  * exceptions that we should try to get rid of. */
1354
1355 void GPU_state_init(void)
1356 {
1357   GPU_disable_program_point_size();
1358
1359   glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
1360
1361   glDepthFunc(GL_LEQUAL);
1362
1363   glDisable(GL_BLEND);
1364   glDisable(GL_DEPTH_TEST);
1365   glDisable(GL_COLOR_LOGIC_OP);
1366   glDisable(GL_STENCIL_TEST);
1367
1368   glDepthRange(0.0, 1.0);
1369
1370   glFrontFace(GL_CCW);
1371   glCullFace(GL_BACK);
1372   glDisable(GL_CULL_FACE);
1373
1374   gpu_disable_multisample();
1375 }
1376
1377 void GPU_enable_program_point_size(void)
1378 {
1379   glEnable(GL_PROGRAM_POINT_SIZE);
1380 }
1381
1382 void GPU_disable_program_point_size(void)
1383 {
1384   glDisable(GL_PROGRAM_POINT_SIZE);
1385 }
1386
1387 /** \name Framebuffer color depth, for selection codes
1388  * \{ */
1389
1390 #define STATE_STACK_DEPTH 16
1391
1392 typedef struct {
1393   eGPUAttrMask mask;
1394
1395   /* GL_ENABLE_BIT */
1396   uint is_blend : 1;
1397   uint is_cull_face : 1;
1398   uint is_depth_test : 1;
1399   uint is_dither : 1;
1400   uint is_lighting : 1;
1401   uint is_line_smooth : 1;
1402   uint is_color_logic_op : 1;
1403   uint is_multisample : 1;
1404   uint is_polygon_offset_line : 1;
1405   uint is_polygon_offset_fill : 1;
1406   uint is_polygon_smooth : 1;
1407   uint is_sample_alpha_to_coverage : 1;
1408   uint is_scissor_test : 1;
1409   uint is_stencil_test : 1;
1410
1411   bool is_clip_plane[6];
1412
1413   /* GL_DEPTH_BUFFER_BIT */
1414   /* uint is_depth_test : 1; */
1415   int depth_func;
1416   double depth_clear_value;
1417   bool depth_write_mask;
1418
1419   /* GL_SCISSOR_BIT */
1420   int scissor_box[4];
1421   /* uint is_scissor_test : 1; */
1422
1423   /* GL_VIEWPORT_BIT */
1424   int viewport[4];
1425   double near_far[2];
1426 } GPUAttrValues;
1427
1428 typedef struct {
1429   GPUAttrValues attr_stack[STATE_STACK_DEPTH];
1430   uint top;
1431 } GPUAttrStack;
1432
1433 static GPUAttrStack state = {
1434     .top = 0,
1435 };
1436
1437 #define AttrStack state
1438 #define Attr state.attr_stack[state.top]
1439
1440 /**
1441  * Replacement for glPush/PopAttributes
1442  *
1443  * We don't need to cover all the options of legacy OpenGL
1444  * but simply the ones used by Blender.
1445  */
1446 void gpuPushAttr(eGPUAttrMask mask)
1447 {
1448   Attr.mask = mask;
1449
1450   if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
1451     Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
1452     glGetIntegerv(GL_DEPTH_FUNC, &Attr.depth_func);
1453     glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attr.depth_clear_value);
1454     glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attr.depth_write_mask);
1455   }
1456
1457   if ((mask & GPU_ENABLE_BIT) != 0) {
1458     Attr.is_blend = glIsEnabled(GL_BLEND);
1459
1460     for (int i = 0; i < 6; i++) {
1461       Attr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
1462     }
1463
1464     Attr.is_cull_face = glIsEnabled(GL_CULL_FACE);
1465     Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST);
1466     Attr.is_dither = glIsEnabled(GL_DITHER);
1467     Attr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH);
1468     Attr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
1469     Attr.is_multisample = glIsEnabled(GL_MULTISAMPLE);
1470     Attr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE);
1471     Attr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL);
1472     Attr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH);
1473     Attr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
1474     Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
1475     Attr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST);
1476   }
1477
1478   if ((mask & GPU_SCISSOR_BIT) != 0) {
1479     Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
1480     glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attr.scissor_box);
1481   }
1482
1483   if ((mask & GPU_VIEWPORT_BIT) != 0) {
1484     glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attr.near_far);
1485     glGetIntegerv(GL_VIEWPORT, (GLint *)&Attr.viewport);
1486   }
1487
1488   if ((mask & GPU_BLEND_BIT) != 0) {
1489     Attr.is_blend = glIsEnabled(GL_BLEND);
1490   }
1491
1492   BLI_assert(AttrStack.top < STATE_STACK_DEPTH);
1493   AttrStack.top++;
1494 }
1495
1496 static void restore_mask(GLenum cap, const bool value)
1497 {
1498   if (value) {
1499     glEnable(cap);
1500   }
1501   else {
1502     glDisable(cap);
1503   }
1504 }
1505
1506 void gpuPopAttr(void)
1507 {
1508   BLI_assert(AttrStack.top > 0);
1509   AttrStack.top--;
1510
1511   GLint mask = Attr.mask;
1512
1513   if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) {
1514     restore_mask(GL_DEPTH_TEST, Attr.is_depth_test);
1515     glDepthFunc(Attr.depth_func);
1516     glClearDepth(Attr.depth_clear_value);
1517     glDepthMask(Attr.depth_write_mask);
1518   }
1519
1520   if ((mask & GPU_ENABLE_BIT) != 0) {
1521     restore_mask(GL_BLEND, Attr.is_blend);
1522
1523     for (int i = 0; i < 6; i++) {
1524       restore_mask(GL_CLIP_PLANE0 + i, Attr.is_clip_plane[i]);
1525     }
1526
1527     restore_mask(GL_CULL_FACE, Attr.is_cull_face);
1528     restore_mask(GL_DEPTH_TEST, Attr.is_depth_test);
1529     restore_mask(GL_DITHER, Attr.is_dither);
1530     restore_mask(GL_LINE_SMOOTH, Attr.is_line_smooth);
1531     restore_mask(GL_COLOR_LOGIC_OP, Attr.is_color_logic_op);
1532     restore_mask(GL_MULTISAMPLE, Attr.is_multisample);
1533     restore_mask(GL_POLYGON_OFFSET_LINE, Attr.is_polygon_offset_line);
1534     restore_mask(GL_POLYGON_OFFSET_FILL, Attr.is_polygon_offset_fill);
1535     restore_mask(GL_POLYGON_SMOOTH, Attr.is_polygon_smooth);
1536     restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attr.is_sample_alpha_to_coverage);
1537     restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test);
1538     restore_mask(GL_STENCIL_TEST, Attr.is_stencil_test);
1539   }
1540
1541   if ((mask & GPU_VIEWPORT_BIT) != 0) {
1542     glViewport(Attr.viewport[0], Attr.viewport[1], Attr.viewport[2], Attr.viewport[3]);
1543     glDepthRange(Attr.near_far[0], Attr.near_far[1]);
1544   }
1545
1546   if ((mask & GPU_SCISSOR_BIT) != 0) {
1547     restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test);
1548     glScissor(Attr.scissor_box[0], Attr.scissor_box[1], Attr.scissor_box[2], Attr.scissor_box[3]);
1549   }
1550
1551   if ((mask & GPU_BLEND_BIT) != 0) {
1552     restore_mask(GL_BLEND, Attr.is_blend);
1553   }
1554 }
1555
1556 #undef Attr
1557 #undef AttrStack
1558
1559 /** \} */