Moving more duplicate code from GPU_create_gl_tex_compressed() and BL_Texture::InitGL...
[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         
205         if (GPU_upload_dxt_texture(ibuf) == 0) {
206                 InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
207                 return;
208         }
209 #endif
210 }
211
212 void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
213 {
214         int nx= power_of_2_min_i(x);
215         int ny= power_of_2_min_i(y);
216
217         unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int));
218         
219         gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels);
220         glBindTexture(GL_TEXTURE_2D, mTexture );
221
222         if ( mipmap ) {
223                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
224                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
225                 gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
226         }
227         else {
228                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
229                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
230                 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
231         }
232
233         if (GLEW_EXT_texture_filter_anisotropic)
234                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
235         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
236         free(newPixels);
237 }
238
239
240 bool BL_Texture::InitCubeMap(int unit,  EnvMap *cubemap)
241 {
242         if (!GLEW_ARB_texture_cube_map)
243         {
244                 spit("cubemaps not supported");
245                 mOk = false;
246                 return mOk;
247         }
248         else if (!cubemap || cubemap->ima->ok==0) 
249         {
250                 mOk = false;
251                 return mOk;
252         }
253
254         ImBuf *ibuf= BKE_image_get_ibuf(cubemap->ima, NULL);
255         if (ibuf==0)
256         {
257                 cubemap->ima->ok = 0;
258                 mOk = false;
259                 return mOk;
260         }
261
262         mNeedsDeleted = 1;
263         mType = GL_TEXTURE_CUBE_MAP_ARB;
264         mTexture = 0;
265         mUnit = unit;
266
267         ActivateUnit(mUnit);
268
269         BL_TextureMap::iterator mapLook = g_textureManager.find(cubemap->ima->id.name);
270         if (mapLook != g_textureManager.end())
271         {
272                 if (mapLook->second.gl_texture != 0 && mapLook->second.ref_buffer == cubemap->ima)
273                 {
274                         mTexture = mapLook->second.gl_texture;
275                         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture);
276                         mOk = IsValid();
277                         return mOk;
278                 }
279         }
280
281
282         glGenTextures(1, (GLuint*)&mTexture);
283         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture);
284
285
286         // track created units
287         BL_TextureObject obj;
288         obj.gl_texture = mTexture;
289         obj.ref_buffer = cubemap->ima;
290         g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)cubemap->ima->id.name, obj));
291
292
293         bool needs_split = false;
294         if (!cubemap->cube[0]) 
295         {
296                 needs_split = true;
297                 spit ("Re-Generating texture buffer");
298         }
299
300         if (needs_split)
301                 my_envmap_split_ima(cubemap, ibuf);
302
303
304         if (!is_power_of_2_i(cubemap->cube[0]->x) || !is_power_of_2_i(cubemap->cube[0]->y))
305         {
306                 spit("invalid envmap size please render with CubeRes @ power of two");
307
308                 my_free_envmapdata(cubemap);
309                 mOk = false;
310                 return mOk;
311         }
312
313
314 #define SetCubeMapFace(face, num)   \
315         glTexImage2D(face, 0,GL_RGBA,   \
316         cubemap->cube[num]->x,          \
317         cubemap->cube[num]->y,          \
318         0, GL_RGBA, GL_UNSIGNED_BYTE,   \
319         cubemap->cube[num]->rect)
320
321         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5);
322         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3);
323         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0);
324         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1);
325         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2);
326         SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4);
327
328         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
329         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
330         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S,     GL_CLAMP_TO_EDGE );
331         glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T,     GL_CLAMP_TO_EDGE );
332         if (GLEW_VERSION_1_2)
333                 glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R,     GL_CLAMP_TO_EDGE );
334
335         if (needs_split)
336                 my_free_envmapdata(cubemap);
337
338
339
340         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
341         ActivateUnit(0);
342
343         mOk = IsValid();
344         return mOk;
345 }
346
347 bool BL_Texture::IsValid()
348 {
349         return (mTexture!= 0)?glIsTexture(mTexture)!=0:false;
350 }
351
352
353 void BL_Texture::Validate()
354 {
355         mOk = IsValid();
356 }
357
358
359 bool BL_Texture::Ok()
360 {
361         return  (mTexture!= 0); 
362 }
363
364
365 unsigned int BL_Texture::GetTextureType() const
366 {
367         return mType;
368 }
369
370 int BL_Texture::GetMaxUnits()
371 {
372         GLint unit=0;
373
374         if (GLEW_ARB_multitexture) {
375                 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
376                 return (MAXTEX>=unit?unit:MAXTEX);
377         }
378
379         return 0;
380 }
381
382 void BL_Texture::ActivateFirst()
383 {
384         if (GLEW_ARB_multitexture)
385                 glActiveTextureARB(GL_TEXTURE0_ARB);
386 }
387
388 void BL_Texture::ActivateUnit(int unit)
389 {
390         if (GLEW_ARB_multitexture)
391                 if (unit <= MAXTEX)
392                         glActiveTextureARB(GL_TEXTURE0_ARB+unit);
393 }
394
395
396 void BL_Texture::DisableUnit()
397 {
398         if (GLEW_ARB_multitexture)
399                 glActiveTextureARB(GL_TEXTURE0_ARB+mUnit);
400
401         glMatrixMode(GL_TEXTURE);
402         glLoadIdentity();
403         glMatrixMode(GL_MODELVIEW);
404
405         if (GLEW_ARB_texture_cube_map && glIsEnabled(GL_TEXTURE_CUBE_MAP_ARB))
406                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
407         else
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         for (int i=0; i<MAXTEX; i++) {
424                 if (GLEW_ARB_multitexture)
425                         glActiveTextureARB(GL_TEXTURE0_ARB+i);
426
427                 glMatrixMode(GL_TEXTURE);
428                 glLoadIdentity();
429                 glMatrixMode(GL_MODELVIEW);
430                 glDisable(GL_TEXTURE_2D);       
431                 glDisable(GL_TEXTURE_GEN_S);
432                 glDisable(GL_TEXTURE_GEN_T);
433                 glDisable(GL_TEXTURE_GEN_R);
434                 glDisable(GL_TEXTURE_GEN_Q);
435                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
436         }
437
438         if (GLEW_ARB_multitexture)
439                 glActiveTextureARB(GL_TEXTURE0_ARB);
440 }
441
442
443 void BL_Texture::ActivateTexture()
444 {
445         if (GLEW_ARB_multitexture)
446                 glActiveTextureARB(GL_TEXTURE0_ARB+mUnit);
447
448         if (mType == GL_TEXTURE_CUBE_MAP_ARB && GLEW_ARB_texture_cube_map)
449         {
450                 glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture );     
451                 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
452         }
453         else {
454                 if (GLEW_ARB_texture_cube_map )
455                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
456
457                 glBindTexture( GL_TEXTURE_2D, mTexture );       
458                 glEnable(GL_TEXTURE_2D);
459         }
460 }
461
462 void BL_Texture::SetMapping(int mode)
463 {
464
465         if (!(mode &USEREFL)) {
466                 glDisable(GL_TEXTURE_GEN_S);
467                 glDisable(GL_TEXTURE_GEN_T);
468                 glDisable(GL_TEXTURE_GEN_R);
469                 glDisable(GL_TEXTURE_GEN_Q);
470                 return;
471         }
472
473         if ( mType == GL_TEXTURE_CUBE_MAP_ARB && 
474                 GLEW_ARB_texture_cube_map &&
475                 mode &USEREFL) 
476         {
477                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
478                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
479                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
480                 
481                 glEnable(GL_TEXTURE_GEN_S);
482                 glEnable(GL_TEXTURE_GEN_T);
483                 glEnable(GL_TEXTURE_GEN_R);
484                 glDisable(GL_TEXTURE_GEN_Q);
485                 return;
486         }
487         else
488         {
489                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
490                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
491
492                 glEnable(GL_TEXTURE_GEN_S);
493                 glEnable(GL_TEXTURE_GEN_T);
494                 glDisable(GL_TEXTURE_GEN_R);
495                 glDisable(GL_TEXTURE_GEN_Q);
496         }
497 }
498
499
500 void BL_Texture::setTexEnv(BL_Material *mat, bool modulate)
501 {
502         if (modulate || !GLEW_ARB_texture_env_combine) {
503                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
504                 return;
505         }
506
507         if (glIsList(mEnvState))
508         {
509                 glCallList(mEnvState);
510                 return;
511         }
512         if (!mEnvState)
513                 mEnvState = glGenLists(1);
514
515         glNewList(mEnvState, GL_COMPILE_AND_EXECUTE);
516
517         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
518
519         GLfloat blend_operand           = GL_SRC_COLOR;
520         GLfloat blend_operand_prev  = GL_SRC_COLOR;
521         GLfloat alphaOp                         = GL_SRC_ALPHA;
522
523         GLenum combiner = GL_COMBINE_RGB_ARB;
524         GLenum source0  = GL_SOURCE0_RGB_ARB;
525         GLenum source1  = GL_SOURCE1_RGB_ARB;
526         GLenum source2  = GL_SOURCE2_RGB_ARB;
527         GLenum op0              = GL_OPERAND0_RGB_ARB;
528         GLenum op1              = GL_OPERAND1_RGB_ARB;
529         GLenum op2              = GL_OPERAND2_RGB_ARB;
530
531         // switch to alpha combiners
532         if ( mat->flag[mUnit]  &TEXALPHA ) {
533                 combiner = GL_COMBINE_ALPHA_ARB;
534                 source0 = GL_SOURCE0_ALPHA_ARB;
535                 source1 = GL_SOURCE1_ALPHA_ARB;
536                 source2 = GL_SOURCE2_ALPHA_ARB;
537                 op0 = GL_OPERAND0_ALPHA_ARB;
538                 op1 = GL_OPERAND1_ALPHA_ARB;
539                 op2 = GL_OPERAND2_ALPHA_ARB;
540                 blend_operand = GL_SRC_ALPHA;
541                 blend_operand_prev = GL_SRC_ALPHA;
542                 // invert
543                 if (mat->flag[mUnit] &TEXNEG) {
544                         blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA;
545                         blend_operand = GL_ONE_MINUS_SRC_ALPHA;
546                 }
547         }
548         else {
549                 if (mat->flag[mUnit] &TEXNEG) {
550                         blend_operand_prev=GL_ONE_MINUS_SRC_COLOR;
551                         blend_operand = GL_ONE_MINUS_SRC_COLOR;
552                 }
553         }
554         bool using_alpha = false;
555
556         if (mat->flag[mUnit]  &USEALPHA) {
557                 alphaOp = GL_ONE_MINUS_SRC_ALPHA;
558                 using_alpha=true;
559         }
560         else if (mat->flag[mUnit]  &USENEGALPHA) {
561                 alphaOp = GL_SRC_ALPHA;
562                 using_alpha = true;
563         }
564
565         switch( mat->blend_mode[mUnit] ) {
566                 case BLEND_MIX:
567                         {
568                                 // ------------------------------
569                                 if (!using_alpha) {
570                                         GLfloat base_col[4];
571                                         base_col[0]      = base_col[1]  = base_col[2]  = 0.f;
572                                         base_col[3]      = 1.f-mat->color_blend[mUnit];
573                                         glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col );
574                                 }
575                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_INTERPOLATE_ARB);
576                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
577                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
578                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
579                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
580                                 if (!using_alpha)
581                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_CONSTANT_ARB );
582                                 else
583                                         glTexEnvf(      GL_TEXTURE_ENV, source2,        GL_TEXTURE );
584
585                                 glTexEnvf(      GL_TEXTURE_ENV, op2,            alphaOp);
586                         }break;
587                 case BLEND_MUL: 
588                         {
589                                 // ------------------------------
590                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_MODULATE);
591                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB);
592                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev);
593                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
594                                 if (using_alpha)
595                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
596                                 else
597                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
598                         }break;
599                 case BLEND_ADD: 
600                         {
601                                 // ------------------------------
602                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD_SIGNED_ARB);
603                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
604                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
605                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
606                                 if (using_alpha)
607                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
608                                 else
609                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
610                         }break;
611                 case BLEND_SUB: 
612                         {
613                                 // ------------------------------
614                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_SUBTRACT_ARB);
615                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
616                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
617                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
618                                 glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
619                         }break;
620                 case BLEND_SCR: 
621                         {
622                                 // ------------------------------
623                                 glTexEnvf(      GL_TEXTURE_ENV, combiner,       GL_ADD);
624                                 glTexEnvf(      GL_TEXTURE_ENV, source0,        GL_PREVIOUS_ARB );
625                                 glTexEnvf(      GL_TEXTURE_ENV, op0,            blend_operand_prev );
626                                 glTexEnvf(      GL_TEXTURE_ENV, source1,        GL_TEXTURE );
627                                 if (using_alpha)
628                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            alphaOp);
629                                 else
630                                         glTexEnvf(      GL_TEXTURE_ENV, op1,            blend_operand);
631                         } break;
632         }
633         glTexEnvf(      GL_TEXTURE_ENV, GL_RGB_SCALE_ARB,       1.0);
634
635         glEndList();
636 }
637
638 int BL_Texture::GetPow2(int n)
639 {
640         if (!is_power_of_2_i(n))
641                 n = power_of_2_min_i(n);
642
643         return n;
644 }
645
646 void BL_Texture::SplitEnvMap(EnvMap *map)
647 {
648         if (!map || !map->ima || (map->ima && !map->ima->ok)) return;
649         ImBuf *ibuf= BKE_image_get_ibuf(map->ima, NULL);
650         if (ibuf)
651                 my_envmap_split_ima(map, ibuf);
652 }
653
654 unsigned int BL_Texture::mDisableState = 0;
655
656 extern "C" {
657
658 void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf)
659 {
660         int dx, part;
661         
662         my_free_envmapdata(env);        
663         
664         dx= ibuf->y;
665         dx/= 2;
666         if (3*dx != ibuf->x) {
667                 printf("Incorrect envmap size\n");
668                 env->ok= 0;
669                 env->ima->ok= 0;
670         }
671         else {
672                 for (part=0; part<6; part++) {
673                         env->cube[part]= IMB_allocImBuf(dx, dx, 24, IB_rect);
674                 }
675                 IMB_rectcpy(env->cube[0], ibuf, 
676                         0, 0, 0, 0, dx, dx);
677                 IMB_rectcpy(env->cube[1], ibuf, 
678                         0, 0, dx, 0, dx, dx);
679                 IMB_rectcpy(env->cube[2], ibuf, 
680                         0, 0, 2*dx, 0, dx, dx);
681                 IMB_rectcpy(env->cube[3], ibuf, 
682                         0, 0, 0, dx, dx, dx);
683                 IMB_rectcpy(env->cube[4], ibuf, 
684                         0, 0, dx, dx, dx, dx);
685                 IMB_rectcpy(env->cube[5], ibuf, 
686                         0, 0, 2*dx, dx, dx, dx);
687
688                 env->ok= 2;// ENV_OSA
689         }
690 }
691
692
693 void my_free_envmapdata(EnvMap *env)
694 {
695         unsigned int part;
696         
697         for (part=0; part<6; part++) {
698                 ImBuf *ibuf= env->cube[part];
699                 if (ibuf) {
700                         IMB_freeImBuf(ibuf);
701                         env->cube[part]= NULL;
702                 }
703         }
704         env->ok= 0;
705 }
706
707
708 } // extern C
709