aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llrender/llrender.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llrender/llrender.cpp')
-rw-r--r--linden/indra/llrender/llrender.cpp364
1 files changed, 312 insertions, 52 deletions
diff --git a/linden/indra/llrender/llrender.cpp b/linden/indra/llrender/llrender.cpp
index 7be06af..80fed06 100644
--- a/linden/indra/llrender/llrender.cpp
+++ b/linden/indra/llrender/llrender.cpp
@@ -32,7 +32,11 @@
32#include "linden_common.h" 32#include "linden_common.h"
33 33
34#include "llrender.h" 34#include "llrender.h"
35
35#include "llvertexbuffer.h" 36#include "llvertexbuffer.h"
37#include "llcubemap.h"
38#include "llimagegl.h"
39#include "llrendertarget.h"
36 40
37LLRender gGL; 41LLRender gGL;
38 42
@@ -44,6 +48,20 @@ S32 gGLViewport[4];
44 48
45static const U32 LL_NUM_TEXTURE_LAYERS = 8; 49static const U32 LL_NUM_TEXTURE_LAYERS = 8;
46 50
51static GLenum sGLTextureType[] =
52{
53 GL_TEXTURE_2D,
54 GL_TEXTURE_RECTANGLE_ARB,
55 GL_TEXTURE_CUBE_MAP_ARB
56};
57
58static GLint sGLAddressMode[] =
59{
60 GL_REPEAT,
61 GL_MIRRORED_REPEAT,
62 GL_CLAMP_TO_EDGE
63};
64
47static GLenum sGLCompareFunc[] = 65static GLenum sGLCompareFunc[] =
48{ 66{
49 GL_NEVER, 67 GL_NEVER,
@@ -72,82 +90,217 @@ static GLenum sGLBlendFactor[] =
72 GL_ONE_MINUS_SRC_ALPHA 90 GL_ONE_MINUS_SRC_ALPHA
73}; 91};
74 92
75LLTexUnit::LLTexUnit(U32 index) 93LLTexUnit::LLTexUnit(S32 index)
76: mIsEnabled(false), mCurrBlendType(TB_MULT), 94: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT),
77mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), 95mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
78mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), 96mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
79mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), 97mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
80mCurrColorScale(1), mCurrAlphaScale(1) 98mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0)
81{ 99{
82 llassert_always(index < LL_NUM_TEXTURE_LAYERS); 100 llassert_always(index < LL_NUM_TEXTURE_LAYERS);
83 mIndex = index; 101 mIndex = index;
84} 102}
85 103
86U32 LLTexUnit::getIndex(void) 104//static
105U32 LLTexUnit::getInternalType(eTextureType type)
87{ 106{
88 return mIndex; 107 return sGLTextureType[type];
89} 108}
90 109
91void LLTexUnit::enable(void) 110void LLTexUnit::refreshState(void)
92{ 111{
93 if (!mIsEnabled) 112 // We set dirty to true so that the tex unit knows to ignore caching
113 // and we reset the cached tex unit state
114
115 glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
116 if (mCurrTexType != TT_NONE)
94 { 117 {
95 activate(); 118 glEnable(sGLTextureType[mCurrTexType]);
96 glEnable(GL_TEXTURE_2D); 119 glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
97 mIsEnabled = true;
98 } 120 }
99} 121 else
100
101void LLTexUnit::disable(void)
102{
103 if (mIsEnabled)
104 { 122 {
105 activate();
106 glDisable(GL_TEXTURE_2D); 123 glDisable(GL_TEXTURE_2D);
107 mIsEnabled = false; 124 glBindTexture(GL_TEXTURE_2D, 0);
125 }
126
127 if (mCurrBlendType != TB_COMBINE)
128 {
129 setTextureBlendType(mCurrBlendType);
130 }
131 else
132 {
133 setTextureCombiner(mCurrColorOp, mCurrColorSrc1, mCurrColorSrc2, false);
134 setTextureCombiner(mCurrAlphaOp, mCurrAlphaSrc1, mCurrAlphaSrc2, true);
108 } 135 }
109} 136}
110 137
111void LLTexUnit::activate(void) 138void LLTexUnit::activate(void)
112{ 139{
113 //if (gGL.mCurrTextureUnitIndex != mIndex) 140 if (mIndex < 0) return;
141
142 if (gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
114 { 143 {
115 glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); 144 glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
116 gGL.mCurrTextureUnitIndex = mIndex; 145 gGL.mCurrTextureUnitIndex = mIndex;
117 } 146 }
118} 147}
119 148
120// Useful for debugging that you've manually assigned a texture operation to the correct 149void LLTexUnit::enable(eTextureType type)
121// texture unit based on the currently set active texture in opengl.
122void LLTexUnit::debugTextureUnit(void)
123{ 150{
124 GLint activeTexture; 151 if (mIndex < 0) return;
125 glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture); 152
126 if ((GL_TEXTURE0_ARB + mIndex) != activeTexture) 153 if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )
154 {
155 activate();
156 if (mCurrTexType != TT_NONE && !gGL.mDirty)
157 {
158 disable(); // Force a disable of a previous texture type if it's enabled.
159 }
160 mCurrTexType = type;
161 glEnable(sGLTextureType[type]);
162 }
163}
164
165void LLTexUnit::disable(void)
166{
167 if (mIndex < 0) return;
168
169 if (mCurrTexType != TT_NONE)
127 { 170 {
128 llerrs << "Incorrect Texture Unit! Expected: " << (activeTexture - GL_TEXTURE0_ARB) << " Actual: " << mIndex << llendl; 171 activate();
172 unbind(mCurrTexType);
173 glDisable(sGLTextureType[mCurrTexType]);
174 mCurrTexType = TT_NONE;
129 } 175 }
130} 176}
131 177
132void LLTexUnit::bindTexture(const LLImageGL* texture) 178bool LLTexUnit::bind(const LLImageGL* texture)
133{ 179{
180 if (mIndex < 0) return false;
181
182 gGL.flush();
183
184 if (texture == NULL)
185 {
186 return texture->bindError(mIndex);
187 }
188
189 if (!texture->isInitialized())
190 {
191 return texture->bindDefaultImage(mIndex);
192 }
193
194 // Disabled caching of binding state.
134 if (texture != NULL) 195 if (texture != NULL)
135 { 196 {
136 activate(); 197 activate();
137 texture->bind(mIndex); 198 enable(texture->getTarget());
199 mCurrTexture = texture->getTexName();
200 glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
201 texture->updateBindStats();
202 return true;
138 } 203 }
204 return false;
139} 205}
140 206
141void LLTexUnit::unbindTexture(void) 207bool LLTexUnit::bind(LLCubeMap* cubeMap)
142{ 208{
209 if (mIndex < 0) return false;
210
211 gGL.flush();
212
213 // Disabled caching of binding state.
214 if (cubeMap != NULL)
215 {
216 if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
217 {
218 activate();
219 enable(LLTexUnit::TT_CUBE_MAP);
220 mCurrTexture = cubeMap->mImages[0]->getTexName();
221 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
222 cubeMap->mImages[0]->updateBindStats();
223 cubeMap->mImages[0]->setMipFilterNearest (FALSE, FALSE);
224 return true;
225 }
226 else
227 {
228 llwarns << "Using cube map without extension!" << llendl
229 }
230 }
231 return false;
232}
233
234bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
235{
236 if (mIndex < 0) return false;
237
238 gGL.flush();
239
240 if (bindDepth)
241 {
242 bindManual(renderTarget->getUsage(), renderTarget->getDepth());
243 }
244 else
245 {
246 bindManual(renderTarget->getUsage(), renderTarget->getTexture());
247 }
248
249 return true;
250}
251
252bool LLTexUnit::bindManual(eTextureType type, U32 texture)
253{
254 if (mIndex < 0) return false;
255
256 // Disabled caching of binding state.
257 gGL.flush();
258
143 activate(); 259 activate();
144 glBindTexture(GL_TEXTURE_2D, 0); 260 enable(type);
261 mCurrTexture = texture;
262 glBindTexture(sGLTextureType[type], texture);
263 return true;
264}
265
266void LLTexUnit::unbind(eTextureType type)
267{
268 if (mIndex < 0) return;
269
270 // Disabled caching of binding state.
271 if (mCurrTexType == type)
272 {
273 gGL.flush();
274
275 activate();
276 mCurrTexture = 0;
277 glBindTexture(sGLTextureType[type], 0);
278 }
279}
280
281void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
282{
283 if (mIndex < 0) return;
284
285 if (true)
286 {
287 activate();
288
289 glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
290 glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]);
291 if (mCurrTexType == TT_CUBE_MAP)
292 {
293 glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
294 }
295 }
145} 296}
146 297
147void LLTexUnit::setTextureBlendType(eTextureBlendType type) 298void LLTexUnit::setTextureBlendType(eTextureBlendType type)
148{ 299{
300 if (mIndex < 0) return;
301
149 // Do nothing if it's already correctly set. 302 // Do nothing if it's already correctly set.
150 if (mCurrBlendType == type) 303 if (mCurrBlendType == type && !gGL.mDirty)
151 { 304 {
152 return; 305 return;
153 } 306 }
@@ -262,16 +415,18 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
262 415
263void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha) 416void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha)
264{ 417{
418 if (mIndex < 0) return;
419
265 activate(); 420 activate();
266 if (mCurrBlendType != TB_COMBINE) 421 if (mCurrBlendType != TB_COMBINE || gGL.mDirty)
267 { 422 {
268 mCurrBlendType = TB_COMBINE; 423 mCurrBlendType = TB_COMBINE;
269 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); 424 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
270 } 425 }
271 426
272 // We want an early out, because this function does a LOT of stuff. 427 // We want an early out, because this function does a LOT of stuff.
273 if ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2) ) 428 if ( ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2))
274 || (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2) )) 429 || (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2)) ) && !gGL.mDirty)
275 { 430 {
276 return; 431 return;
277 } 432 }
@@ -304,7 +459,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
304 } 459 }
305 else 460 else
306 { 461 {
307 // Set enums to ALPHA ones 462 // Set enums to RGB ones
308 comb_enum = GL_COMBINE_RGB_ARB; 463 comb_enum = GL_COMBINE_RGB_ARB;
309 src0_enum = GL_SOURCE0_RGB_ARB; 464 src0_enum = GL_SOURCE0_RGB_ARB;
310 src1_enum = GL_SOURCE1_RGB_ARB; 465 src1_enum = GL_SOURCE1_RGB_ARB;
@@ -405,7 +560,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
405 560
406void LLTexUnit::setColorScale(S32 scale) 561void LLTexUnit::setColorScale(S32 scale)
407{ 562{
408 if (mCurrColorScale != scale) 563 if (mCurrColorScale != scale || gGL.mDirty)
409 { 564 {
410 mCurrColorScale = scale; 565 mCurrColorScale = scale;
411 glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale ); 566 glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
@@ -414,27 +569,52 @@ void LLTexUnit::setColorScale(S32 scale)
414 569
415void LLTexUnit::setAlphaScale(S32 scale) 570void LLTexUnit::setAlphaScale(S32 scale)
416{ 571{
417 if (mCurrAlphaScale != scale) 572 if (mCurrAlphaScale != scale || gGL.mDirty)
418 { 573 {
419 mCurrAlphaScale = scale; 574 mCurrAlphaScale = scale;
420 glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale ); 575 glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
421 } 576 }
422} 577}
423 578
579// Useful for debugging that you've manually assigned a texture operation to the correct
580// texture unit based on the currently set active texture in opengl.
581void LLTexUnit::debugTextureUnit(void)
582{
583 if (mIndex < 0) return;
584
585 GLint activeTexture;
586 glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
587 if ((GL_TEXTURE0_ARB + mIndex) != activeTexture)
588 {
589 U32 set_unit = (activeTexture - GL_TEXTURE0_ARB);
590 llwarns << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << llendl;
591 }
592}
593
594
424LLRender::LLRender() 595LLRender::LLRender()
596: mDirty(false), mCount(0), mMode(LLRender::TRIANGLES)
425{ 597{
426 mCount = 0;
427 mMode = LLVertexBuffer::TRIANGLES;
428 mBuffer = new LLVertexBuffer(immediate_mask, 0); 598 mBuffer = new LLVertexBuffer(immediate_mask, 0);
429 mBuffer->allocateBuffer(4096, 0, TRUE); 599 mBuffer->allocateBuffer(4096, 0, TRUE);
430 mBuffer->getVertexStrider(mVerticesp); 600 mBuffer->getVertexStrider(mVerticesp);
431 mBuffer->getTexCoordStrider(mTexcoordsp); 601 mBuffer->getTexCoordStrider(mTexcoordsp);
432 mBuffer->getColorStrider(mColorsp); 602 mBuffer->getColorStrider(mColorsp);
433 603
434 for (unsigned int i = 0; i < LL_NUM_TEXTURE_LAYERS; i++) 604 mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS);
605 for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
435 { 606 {
436 mTexUnits.push_back(new LLTexUnit(i)); 607 mTexUnits.push_back(new LLTexUnit(i));
437 } 608 }
609 mDummyTexUnit = new LLTexUnit(-1);
610
611 for (U32 i = 0; i < 4; i++)
612 {
613 mCurrColorMask[i] = true;
614 }
615
616 mCurrAlphaFunc = CF_DEFAULT;
617 mCurrAlphaFuncVal = 0.01f;
438} 618}
439 619
440LLRender::~LLRender() 620LLRender::~LLRender()
@@ -449,6 +629,28 @@ void LLRender::shutdown()
449 delete mTexUnits[i]; 629 delete mTexUnits[i];
450 } 630 }
451 mTexUnits.clear(); 631 mTexUnits.clear();
632 delete mDummyTexUnit;
633 mDummyTexUnit = NULL;
634}
635
636void LLRender::refreshState(void)
637{
638 mDirty = true;
639
640 U32 active_unit = mCurrTextureUnitIndex;
641
642 for (U32 i = 0; i < mTexUnits.size(); i++)
643 {
644 mTexUnits[i]->refreshState();
645 }
646
647 mTexUnits[active_unit]->activate();
648
649 setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
650
651 setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal);
652
653 mDirty = false;
452} 654}
453 655
454void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) 656void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
@@ -483,6 +685,12 @@ void LLRender::setColorMask(bool writeColor, bool writeAlpha)
483void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha) 685void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha)
484{ 686{
485 flush(); 687 flush();
688
689 mCurrColorMask[0] = writeColorR;
690 mCurrColorMask[1] = writeColorG;
691 mCurrColorMask[2] = writeColorB;
692 mCurrColorMask[3] = writeAlpha;
693
486 glColorMask(writeColorR, writeColorG, writeColorB, writeAlpha); 694 glColorMask(writeColorR, writeColorG, writeColorB, writeAlpha);
487} 695}
488 696
@@ -518,6 +726,9 @@ void LLRender::setSceneBlendType(eBlendType type)
518void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) 726void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value)
519{ 727{
520 flush(); 728 flush();
729
730 mCurrAlphaFunc = func;
731 mCurrAlphaFuncVal = value;
521 if (func == CF_DEFAULT) 732 if (func == CF_DEFAULT)
522 { 733 {
523 glAlphaFunc(GL_GREATER, 0.01f); 734 glAlphaFunc(GL_GREATER, 0.01f);
@@ -536,22 +747,38 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
536 747
537LLTexUnit* LLRender::getTexUnit(U32 index) 748LLTexUnit* LLRender::getTexUnit(U32 index)
538{ 749{
539 if (index < mTexUnits.size()) 750 if ((index >= 0) && (index < mTexUnits.size()))
540 { 751 {
541 return mTexUnits[index]; 752 return mTexUnits[index];
542 } 753 }
543 llerrs << "Non-existing texture unit layer requested: " << index << llendl; 754 else
544 return NULL; 755 {
756 lldebugs << "Non-existing texture unit layer requested: " << index << llendl;
757 return mDummyTexUnit;
758 }
759}
760
761bool LLRender::verifyTexUnitActive(U32 unitToVerify)
762{
763 if (mCurrTextureUnitIndex == unitToVerify)
764 {
765 return true;
766 }
767 else
768 {
769 llwarns << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << llendl;
770 return false;
771 }
545} 772}
546 773
547void LLRender::begin(const GLuint& mode) 774void LLRender::begin(const GLuint& mode)
548{ 775{
549 if (mode != mMode) 776 if (mode != mMode)
550 { 777 {
551 if (mMode == LLVertexBuffer::QUADS || 778 if (mMode == LLRender::QUADS ||
552 mMode == LLVertexBuffer::LINES || 779 mMode == LLRender::LINES ||
553 mMode == LLVertexBuffer::TRIANGLES || 780 mMode == LLRender::TRIANGLES ||
554 mMode == LLVertexBuffer::POINTS) 781 mMode == LLRender::POINTS)
555 { 782 {
556 flush(); 783 flush();
557 } 784 }
@@ -572,10 +799,10 @@ void LLRender::end()
572 //IMM_ERRS << "GL begin and end called with no vertices specified." << llendl; 799 //IMM_ERRS << "GL begin and end called with no vertices specified." << llendl;
573 } 800 }
574 801
575 if ((mMode != LLVertexBuffer::QUADS && 802 if ((mMode != LLRender::QUADS &&
576 mMode != LLVertexBuffer::LINES && 803 mMode != LLRender::LINES &&
577 mMode != LLVertexBuffer::TRIANGLES && 804 mMode != LLRender::TRIANGLES &&
578 mMode != LLVertexBuffer::POINTS) || 805 mMode != LLRender::POINTS) ||
579 mCount > 2048) 806 mCount > 2048)
580 { 807 {
581 flush(); 808 flush();
@@ -638,7 +865,8 @@ void LLRender::flush()
638} 865}
639void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) 866void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
640{ 867{
641 if (mCount >= 4096) 868 //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095]
869 if (mCount > 4094)
642 { 870 {
643 // llwarns << "GL immediate mode overflow. Some geometry not drawn." << llendl; 871 // llwarns << "GL immediate mode overflow. Some geometry not drawn." << llendl;
644 return; 872 return;
@@ -720,3 +948,35 @@ void LLRender::color3fv(const GLfloat* c)
720 color4f(c[0],c[1],c[2],1); 948 color4f(c[0],c[1],c[2],1);
721} 949}
722 950
951void LLRender::debugTexUnits(void)
952{
953 LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL;
954 std::string active_enabled = "false";
955 for (U32 i = 0; i < mTexUnits.size(); i++)
956 {
957 if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE)
958 {
959 if (i == mCurrTextureUnitIndex) active_enabled = "true";
960 LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL;
961 LL_INFOS("TextureUnit") << "Enabled As: " ;
962 switch (getTexUnit(i)->mCurrTexType)
963 {
964 case LLTexUnit::TT_TEXTURE:
965 LL_CONT << "Texture 2D";
966 break;
967 case LLTexUnit::TT_RECT_TEXTURE:
968 LL_CONT << "Texture Rectangle";
969 break;
970 case LLTexUnit::TT_CUBE_MAP:
971 LL_CONT << "Cube Map";
972 break;
973 default:
974 LL_CONT << "ARGH!!! NONE!";
975 break;
976 }
977 LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL;
978 }
979 }
980 LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL;
981}
982