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