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