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