Ghost Context Refactor
[blender-staging.git] / source / gameengine / Ketsji / BL_Texture.cpp
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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file gameengine/Ketsji/BL_Texture.cpp
22  *  \ingroup ketsji
23  */
24
25 #include "glew-mx.h"
26
27 #include <iostream>
28 #include <map>
29 #include <stdlib.h>
30
31 #include "BL_Material.h"
32 #include "BL_Texture.h"
33 #include "MT_assert.h"
34
35 #include "DNA_texture_types.h"
36 #include "DNA_image_types.h"
37 #include "IMB_imbuf_types.h"
38 #include "BKE_image.h"
39 #include "BLI_blenlib.h"
40
41 #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
42 #include "RAS_ICanvas.h"
43 #include "RAS_Rect.h"
44
45 #include "KX_GameObject.h"
46
47 #define spit(x) std::cout << x << std::endl;
48
49 #include "MEM_guardedalloc.h"
50 #include "GPU_draw.h"
51 #include "GPU_extensions.h"
52
53 extern "C" {
54         // envmaps
55         #include "IMB_imbuf.h"
56         void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf);
57         void my_free_envmapdata(EnvMap *env);
58 }
59
60 // (n&(n-1)) zeros the least significant bit of n 
61 static int is_power_of_2_i(int num)
62 {
63         return ((num)&(num-1))==0;
64 }
65 static int power_of_2_min_i(int num)
66 {
67         while (!is_power_of_2_i(num))
68                 num= num&(num-1);
69         return num;
70 }
71
72 // Place holder for a full texture manager
73 class BL_TextureObject
74 {
75 public:
76         unsigned int    gl_texture;
77         void*                   ref_buffer;
78 };
79
80 typedef std::map<char*, BL_TextureObject> BL_TextureMap;
81 static BL_TextureMap g_textureManager;
82 static GLint g_max_units = -1;
83
84
85 BL_Texture::BL_Texture()
86 :       mTexture(0),
87         mOk(0),
88         mNeedsDeleted(0),
89         mType(0),
90         mUnit(0),
91         mEnvState(0)
92 {
93         // --
94 }
95
96 BL_Texture::~BL_Texture()
97 {
98         // --
99 }
100
101 void BL_Texture::DeleteTex()
102 {
103         if ( mNeedsDeleted ) {
104                 glDeleteTextures(1, (GLuint*)&mTexture);
105                 mNeedsDeleted = 0;
106                 mOk = 0;
107         }
108
109         if (mEnvState) {
110                 glDeleteLists((GLuint)mEnvState, 1);
111                 mEnvState =0;
112         }
113
114         if (mDisableState) {
115                 glDeleteLists((GLuint)mDisableState, 1);
116                 mDisableState =0;
117         }
118         g_textureManager.clear();
119 }
120
121
122 bool BL_Texture::InitFromImage(int unit,  Image *img, bool mipmap)
123 {
124
125         ImBuf *ibuf;
126         if (!img || img->ok==0) 
127         {
128                 mOk = false;
129                 return mOk;
130         }
131
132         ibuf= BKE_image_acquire_ibuf(img, NULL, NULL);
133         if (ibuf==NULL)
134         {
135                 img->ok = 0;
136                 mOk = false;
137                 return mOk;
138         }
139
140         mipmap = mipmap && GPU_get_mipmap();
141
142         mTexture = img->bindcode;
143         mType = GL_TEXTURE_2D;
144         mUnit = unit;
145
146         ActivateUnit(mUnit);
147
148         if (mTexture != 0) {
149                 glBindTexture(GL_TEXTURE_2D, mTexture );
150                 Validate();
151                 BKE_image_release_ibuf(img, ibuf, NULL);
152                 return mOk;
153         }
154
155         // look for an existing gl image
156         BL_TextureMap::iterator mapLook = g_textureManager.find(img->id.name);
157         if (mapLook != g_textureManager.end())
158         {
159                 if (mapLook->second.gl_texture != 0)
160                 {
161                         mTexture = mapLook->second.gl_texture;
162                         glBindTexture(GL_TEXTURE_2D, mTexture);
163                         mOk = IsValid();
164                         BKE_image_release_ibuf(img, ibuf, NULL);
165                         return mOk;
166                 }
167         }
168
169         mNeedsDeleted = 1;
170         glGenTextures(1, (GLuint*)&mTexture);
171
172 #ifdef WITH_DDS
173         if (ibuf->ftype & DDS)
174                 InitGLCompressedTex(ibuf, mipmap);
175         else
176                 InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
177 #else
178         InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
179 #endif
180
181         // track created units
182         BL_TextureObject obj;
183         obj.gl_texture = mTexture;
184         obj.ref_buffer = img;
185         g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)img->id.name, obj));
186
187
188         glDisable(GL_TEXTURE_2D);
189         ActivateUnit(0);
190         Validate();
191
192         BKE_image_release_ibuf(img, ibuf, NULL);
193
194         return mOk;
195 }
196
197 void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
198 {
199         if (!GPU_non_power_of_two_support() && (!is_power_of_2_i(x) || !is_power_of_2_i(y)) ) {
200                 InitNonPow2Tex(pix, x,y,mipmap);
201                 return;
202         }
203
204         glBindTexture(GL_TEXTURE_2D, mTexture );
205         if ( mipmap ) {
206                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
207                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
208                 gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix );
209         } 
210         else {
211                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
212                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
213                 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix );
214         }
215
216         if (GLEW_EXT_texture_filter_anisotropic)
217                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
218         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
219 }
220
221 void BL_Texture::InitGLCompressedTex(ImBuf *ibuf, bool mipmap)
222 {
223 #ifndef WITH_DDS
224         // Fall back to uncompressed if DDS isn't enabled
225         InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
226         return;
227 #else
228         glBindTexture(GL_TEXTURE_2D, mTexture);
229         
230         if (GPU_upload_dxt_texture(ibuf) == 0) {
231                 InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
232                 return;
233         }
234 #endif
235 }
236
237 void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
238 {
239         int nx= power_of_2_min_i(x);
240         int ny= power_of_2_min_i(y);
241
242         unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int));
243         
244         gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels);
245         glBindTexture(GL_TEXTURE_2D, mTexture );
246
247         if ( mipmap ) {
248                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
249                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
250                 gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
251         }
252         else {
253                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
254                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
255                 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
256         }
257
258         if (GLEW_EXT_texture_filter_anisotropic)
259                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
260         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
261         free(newPixels);
262 }
263
264
265 bool BL_Texture::InitCubeMap(int unit,  EnvMap *cubemap)
266 {
267         if (!GLEW_ARB_texture_cube_map)
268         {
269                 spit("cubemaps not supported");
270                 mOk = false;
271                 return mOk;
272         }
273         else if (!cubemap || cubemap->ima->ok==0) 
274         {
275                 mOk = false;
276                 return mOk;
277         }
278
279         ImBuf *ibuf= BKE_image_acquire_ibuf(cubemap->ima, NULL, NULL);
280         if (ibuf==0)
281         {
282                 cubemap->ima->ok = 0;
283                 mOk = false;
284                 return mOk;
285         }
286
287         mNeedsDeleted = 1;
288         mType = GL_TEXTURE_CUBE_MAP_ARB;
289         mTexture = 0;
290         mUnit = unit;
291
292         ActivateUnit(mUnit);
293
294         BL_TextureMap::iterator mapLook = g_textureManager.find(cubemap->ima->id.name);
295         if (mapLook != g_textureManager.end())
296         {
297                 if (mapLook->second.gl_texture != 0 && mapLook->second.ref_buffer == cubemap->ima)
298                 {
299                         mTexture = mapLook->second.gl_texture;
300                         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture);
301                         mOk = IsValid();
302                         BKE_image_release_ibuf(cubemap->ima, ibuf, NULL);
303                         return mOk;
304                 }
305         }
306
307
308         glGenTextures(1, (GLuint*)&mTexture);
309         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture);
310
311
312         // track created units
313         BL_TextureObject obj;
314         obj.gl_texture = mTexture;
315         obj.ref_buffer = cubemap->ima;
316         g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)cubemap->ima->id.name, obj));
317
318
319         bool needs_split = false;
320         if (!cubemap->cube[0]) 
321         {
322                 needs_split = true;
323                 spit ("Re-Generating texture buffer");
324         }
325
326         if (needs_split)
327                 my_envmap_split_ima(cubemap, ibuf);
328
329
330         if (!is_power_of_2_i(cubemap->cube[0]->x) || !is_power_of_2_i(cubemap->cube[0]->y))
331         {
332                 spit("invalid envmap size please render with CubeRes @ power of two");
333
334                 my_free_envmapdata(cubemap);
335                 mOk = false;
336                 BKE_image_release_ibuf(cubemap->ima, ibuf, NULL);
337                 return mOk;
338         }
339
340
341 #define SetCubeMapFace(face, num)   \
342         glTexImage2D(face, 0,GL_RGBA,   \
343         cubemap->cube[num]->x,          \
344         cubemap->cube[num]->y,          \
345         0, GL_RGBA, GL_UNSIGNED_BYTE,   \
346         cubemap->cube[num]->rect)
347
348         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5);
349         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3);
350         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0);
351         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1);
352         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2);
353         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4);
354
355         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
356         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
357         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE );
358         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE );
359         if (GLEW_VERSION_1_2)
360                 glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R,     GL_CLAMP_TO_EDGE );
361
362         if (needs_split)
363                 my_free_envmapdata(cubemap);
364
365
366
367         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
368         ActivateUnit(0);
369
370         mOk = IsValid();
371
372         BKE_image_release_ibuf(cubemap->ima, ibuf, NULL);
373
374         return mOk;
375 }
376
377 bool BL_Texture::IsValid()
378 {
379         return (mTexture!= 0)?glIsTexture(mTexture)!=0:false;
380 }
381
382
383 void BL_Texture::Validate()
384 {
385         mOk = IsValid();
386 }
387
388
389 bool BL_Texture::Ok()
390 {
391         return  (mTexture!= 0); 
392 }
393
394
395 unsigned int BL_Texture::GetTextureType() const
396 {
397         return mType;
398 }
399
400 int BL_Texture::GetMaxUnits()
401 {
402         if (g_max_units < 0) {
403                 GLint unit;
404                 if (GLEW_ARB_multitexture) {
405                         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
406                         g_max_units = (MAXTEX>=unit)?unit:MAXTEX;
407                 } else {
408                         g_max_units = 0;
409                 }
410         }
411
412         return g_max_units;
413 }
414
415 void BL_Texture::ActivateFirst()
416 {
417         if (GLEW_ARB_multitexture)
418                 glActiveTextureARB(GL_TEXTURE0_ARB);
419 }
420
421 void BL_Texture::ActivateUnit(int unit)
422 {
423         if (GLEW_ARB_multitexture)
424                 if (unit <= MAXTEX)
425                         glActiveTextureARB(GL_TEXTURE0_ARB+unit);
426 }
427
428
429 void BL_Texture::DisableUnit()
430 {
431         if (GLEW_ARB_multitexture)
432                 glActiveTextureARB(GL_TEXTURE0_ARB+mUnit);
433
434         glMatrixMode(GL_TEXTURE);
435         glLoadIdentity();
436         glMatrixMode(GL_MODELVIEW);
437
438         if (GLEW_ARB_texture_cube_map && glIsEnabled(GL_TEXTURE_CUBE_MAP_ARB))
439                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
440         else
441         {
442                 if (glIsEnabled(GL_TEXTURE_2D))
443                         glDisable(GL_TEXTURE_2D);
444         }
445
446         glDisable(GL_TEXTURE_GEN_S);
447         glDisable(GL_TEXTURE_GEN_T);
448         glDisable(GL_TEXTURE_GEN_R);
449         glDisable(GL_TEXTURE_GEN_Q);
450         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
451 }
452
453
454 void BL_Texture::DisableAllTextures()
455 {
456         for (int i=0; i<MAXTEX; i++) {
457                 if (GLEW_ARB_multitexture)
458                         glActiveTextureARB(GL_TEXTURE0_ARB+i);
459
460                 glMatrixMode(GL_TEXTURE);
461                 glLoadIdentity();
462                 glMatrixMode(GL_MODELVIEW);
463                 glDisable(GL_TEXTURE_2D);
464                 glDisable(GL_TEXTURE_GEN_S);
465                 glDisable(GL_TEXTURE_GEN_T);
466                 glDisable(GL_TEXTURE_GEN_R);
467                 glDisable(GL_TEXTURE_GEN_Q);
468                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
469         }
470
471         if (GLEW_ARB_multitexture)
472                 glActiveTextureARB(GL_TEXTURE0_ARB);
473 }
474
475
476 void BL_Texture::ActivateTexture()
477 {
478         if (GLEW_ARB_multitexture)
479                 glActiveTextureARB(GL_TEXTURE0_ARB+mUnit);
480
481         if (mType == GL_TEXTURE_CUBE_MAP_ARB && GLEW_ARB_texture_cube_map)
482         {
483                 glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture );
484                 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
485         }
486         else {
487                 if (GLEW_ARB_texture_cube_map )
488                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
489
490                 glBindTexture( GL_TEXTURE_2D, mTexture );
491                 glEnable(GL_TEXTURE_2D);
492         }
493 }
494
495 void BL_Texture::SetMapping(int mode)
496 {
497
498         if (!(mode &USEREFL)) {
499                 glDisable(GL_TEXTURE_GEN_S);
500                 glDisable(GL_TEXTURE_GEN_T);
501                 glDisable(GL_TEXTURE_GEN_R);
502                 glDisable(GL_TEXTURE_GEN_Q);
503                 return;
504         }
505
506         if ( mType == GL_TEXTURE_CUBE_MAP_ARB && 
507                 GLEW_ARB_texture_cube_map &&
508                 mode &USEREFL) 
509         {
510                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
511                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
512                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
513                 
514                 glEnable(GL_TEXTURE_GEN_S);
515                 glEnable(GL_TEXTURE_GEN_T);
516                 glEnable(GL_TEXTURE_GEN_R);
517                 glDisable(GL_TEXTURE_GEN_Q);
518                 return;
519         }
520         else
521         {
522                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
523                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
524
525                 glEnable(GL_TEXTURE_GEN_S);
526                 glEnable(GL_TEXTURE_GEN_T);
527                 glDisable(GL_TEXTURE_GEN_R);
528                 glDisable(GL_TEXTURE_GEN_Q);
529         }
530 }
531
532
533 void BL_Texture::setTexEnv(BL_Material *mat, bool modulate)
534 {
535         if (modulate || !GLEW_ARB_texture_env_combine) {
536                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
537                 return;
538         }
539
540         if (glIsList(mEnvState))
541         {
542                 glCallList(mEnvState);
543                 return;
544         }
545         if (!mEnvState)
546                 mEnvState = glGenLists(1);
547
548         glNewList(mEnvState, GL_COMPILE_AND_EXECUTE);
549
550         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
551
552         GLfloat blend_operand           = GL_SRC_COLOR;
553         GLfloat blend_operand_prev  = GL_SRC_COLOR;
554         GLfloat alphaOp                         = GL_SRC_ALPHA;
555
556         GLenum combiner = GL_COMBINE_RGB_ARB;
557         GLenum source0  = GL_SOURCE0_RGB_ARB;
558         GLenum source1  = GL_SOURCE1_RGB_ARB;
559         GLenum source2  = GL_SOURCE2_RGB_ARB;
560         GLenum op0              = GL_OPERAND0_RGB_ARB;
561         GLenum op1              = GL_OPERAND1_RGB_ARB;
562         GLenum op2              = GL_OPERAND2_RGB_ARB;
563
564         // switch to alpha combiners
565         if ( mat->flag[mUnit]  &TEXALPHA ) {
566                 combiner = GL_COMBINE_ALPHA_ARB;
567                 source0 = GL_SOURCE0_ALPHA_ARB;
568                 source1 = GL_SOURCE1_ALPHA_ARB;
569                 source2 = GL_SOURCE2_ALPHA_ARB;
570                 op0 = GL_OPERAND0_ALPHA_ARB;
571                 op1 = GL_OPERAND1_ALPHA_ARB;
572                 op2 = GL_OPERAND2_ALPHA_ARB;
573                 blend_operand = GL_SRC_ALPHA;
574                 blend_operand_prev = GL_SRC_ALPHA;
575                 // invert
576                 if (mat->flag[mUnit] &TEXNEG) {
577                         blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA;
578                         blend_operand = GL_ONE_MINUS_SRC_ALPHA;
579                 }
580         }
581         else {
582                 if (mat->flag[mUnit] &TEXNEG) {
583                         blend_operand_prev=GL_ONE_MINUS_SRC_COLOR;
584                         blend_operand = GL_ONE_MINUS_SRC_COLOR;
585                 }
586         }
587         bool using_alpha = false;
588
589         if (mat->flag[mUnit]  &USEALPHA) {
590                 alphaOp = GL_ONE_MINUS_SRC_ALPHA;
591                 using_alpha=true;
592         }
593         else if (mat->flag[mUnit]  &USENEGALPHA) {
594                 alphaOp = GL_SRC_ALPHA;
595                 using_alpha = true;
596         }
597
598         switch (mat->blend_mode[mUnit]) {
599                 case BLEND_MIX:
600                         {
601                                 // ------------------------------
602                                 if (!using_alpha) {
603                                         GLfloat base_col[4];
604                                         base_col[0]      = base_col[1]  = base_col[2]  = 0.f;
605                                         base_col[3]      = 1.f-mat->color_blend[mUnit];
606                                         glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col );
607                                 }
608                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_INTERPOLATE_ARB);
609                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
610                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
611                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
612                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
613                                 if (!using_alpha)
614                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_CONSTANT_ARB );
615                                 else
616                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_TEXTURE );
617
618                                 glTexEnvf(      GL_TEXTURE_ENV, op2,            alphaOp);
619                         }break;
620                 case BLEND_MUL: 
621                         {
622                                 // ------------------------------
623                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_MODULATE);
624                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
625                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev);
626                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
627                                 if (using_alpha)
628                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
629                                 else
630                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
631                         }break;
632                 case BLEND_ADD: 
633                         {
634                                 // ------------------------------
635                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD_SIGNED_ARB);
636                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
637                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
638                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
639                                 if (using_alpha)
640                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
641                                 else
642                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
643                         }break;
644                 case BLEND_SUB: 
645                         {
646                                 // ------------------------------
647                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_SUBTRACT_ARB);
648                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
649                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
650                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
651                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
652                         }break;
653                 case BLEND_SCR: 
654                         {
655                                 // ------------------------------
656                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD);
657                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
658                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
659                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
660                                 if (using_alpha)
661                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
662                                 else
663                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
664                         } break;
665         }
666         glTexEnvf(      GL_TEXTURE_ENV, GL_RGB_SCALE_ARB,       1.0);
667
668         glEndList();
669 }
670
671 int BL_Texture::GetPow2(int n)
672 {
673         if (!is_power_of_2_i(n))
674                 n = power_of_2_min_i(n);
675
676         return n;
677 }
678
679 void BL_Texture::SplitEnvMap(EnvMap *map)
680 {
681         if (!map || !map->ima || (map->ima && !map->ima->ok)) return;
682         ImBuf *ibuf= BKE_image_acquire_ibuf(map->ima, NULL, NULL);
683         if (ibuf) {
684                 my_envmap_split_ima(map, ibuf);
685                 BKE_image_release_ibuf(map->ima, ibuf, NULL);
686         }
687 }
688
689 unsigned int BL_Texture::mDisableState = 0;
690
691 extern "C" {
692
693 void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf)
694 {
695         int dx, part;
696         
697         my_free_envmapdata(env);
698         
699         dx= ibuf->y;
700         dx/= 2;
701         if (3*dx != ibuf->x) {
702                 printf("Incorrect envmap size\n");
703                 env->ok= 0;
704                 env->ima->ok= 0;
705         }
706         else {
707                 for (part=0; part<6; part++) {
708                         env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect);
709                 }
710                 IMB_rectcpy(env->cube[0], ibuf, 
711                         0, 0, 0, 0, dx, dx);
712                 IMB_rectcpy(env->cube[1], ibuf, 
713                         0, 0, dx, 0, dx, dx);
714                 IMB_rectcpy(env->cube[2], ibuf, 
715                         0, 0, 2*dx, 0, dx, dx);
716                 IMB_rectcpy(env->cube[3], ibuf, 
717                         0, 0, 0, dx, dx, dx);
718                 IMB_rectcpy(env->cube[4], ibuf, 
719                         0, 0, dx, dx, dx, dx);
720                 IMB_rectcpy(env->cube[5], ibuf, 
721                         0, 0, 2*dx, dx, dx, dx);
722
723                 env->ok= 2;// ENV_OSA
724         }
725 }
726
727
728 void my_free_envmapdata(EnvMap *env)
729 {
730         unsigned int part;
731         
732         for (part=0; part<6; part++) {
733                 ImBuf *ibuf= env->cube[part];
734                 if (ibuf) {
735                         IMB_freeImBuf(ibuf);
736                         env->cube[part] = NULL;
737                 }
738         }
739         env->ok= 0;
740 }
741
742
743 } // extern C
744