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