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