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