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