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