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