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