aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llrender/llimagegl.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llrender/llimagegl.cpp394
1 files changed, 243 insertions, 151 deletions
diff --git a/linden/indra/llrender/llimagegl.cpp b/linden/indra/llrender/llimagegl.cpp
index a871758..6a142a7 100644
--- a/linden/indra/llrender/llimagegl.cpp
+++ b/linden/indra/llrender/llimagegl.cpp
@@ -4,7 +4,7 @@
4 * 4 *
5 * $LicenseInfo:firstyear=2001&license=viewergpl$ 5 * $LicenseInfo:firstyear=2001&license=viewergpl$
6 * 6 *
7 * Copyright (c) 2001-2008, Linden Research, Inc. 7 * Copyright (c) 2001-2009, Linden Research, Inc.
8 * 8 *
9 * Second Life Viewer Source Code 9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab 10 * The source code in this file ("Source Code") is provided by Linden Lab
@@ -63,6 +63,52 @@ F32 LLImageGL::sLastFrameTime = 0.f;
63 63
64std::set<LLImageGL*> LLImageGL::sImageList; 64std::set<LLImageGL*> LLImageGL::sImageList;
65 65
66//**************************************************************************************
67//below are functions for debug use
68//do not delete them even though they are not currently being used.
69void check_all_images()
70{
71 for (std::set<LLImageGL*>::iterator iter = LLImageGL::sImageList.begin();
72 iter != LLImageGL::sImageList.end(); iter++)
73 {
74 LLImageGL* glimage = *iter;
75 if (glimage->getTexName() && glimage->isGLTextureCreated())
76 {
77 gGL.getTexUnit(0)->bind(glimage) ;
78 glimage->checkTexSize() ;
79 gGL.getTexUnit(0)->unbind(glimage->getTarget()) ;
80 }
81 }
82}
83
84void LLImageGL::checkTexSize() const
85{
86 if (gDebugGL && mTarget == GL_TEXTURE_2D)
87 {
88 GLint texname;
89 glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
90 if (texname != mTexName)
91 {
92 llerrs << "Invalid texture bound!" << llendl;
93 }
94 stop_glerror() ;
95 LLGLint x = 0, y = 0 ;
96 glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_WIDTH, (GLint*)&x);
97 glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_HEIGHT, (GLint*)&y) ;
98 stop_glerror() ;
99 if(!x || !y)
100 {
101 return ;
102 }
103 if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel))
104 {
105 llerrs << "wrong texture size and discard level!" << llendl ;
106 }
107 }
108}
109//end of debug functions
110//**************************************************************************************
111
66//---------------------------------------------------------------------------- 112//----------------------------------------------------------------------------
67 113
68//static 114//static
@@ -125,49 +171,6 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
125//---------------------------------------------------------------------------- 171//----------------------------------------------------------------------------
126 172
127// static 173// static
128void LLImageGL::bindExternalTexture(LLGLuint gl_name, S32 stage, LLGLenum bind_target )
129{
130 gGL.flush();
131 if (stage > 0)
132 {
133 gGL.getTexUnit(stage)->activate();
134 }
135 glBindTexture(bind_target, gl_name);
136 sCurrentBoundTextures[stage] = gl_name;
137 if (stage > 0)
138 {
139 gGL.getTexUnit(0)->activate();
140 }
141}
142
143// static
144void LLImageGL::unbindTexture(S32 stage, LLGLenum bind_target)
145{
146 // LLGLSLShader can return -1
147 if (stage >= 0)
148 {
149 gGL.flush();
150 if (stage > 0)
151 {
152 gGL.getTexUnit(stage)->activate();
153 glBindTexture(GL_TEXTURE_2D, 0);
154 gGL.getTexUnit(0)->activate();
155 }
156 else
157 {
158 glBindTexture(GL_TEXTURE_2D, 0);
159 }
160 sCurrentBoundTextures[stage] = 0;
161 }
162}
163
164// static (duplicated for speed and to avoid GL_TEXTURE_2D default argument which requires GL header dependency)
165void LLImageGL::unbindTexture(S32 stage)
166{
167 unbindTexture(stage, GL_TEXTURE_2D);
168}
169
170// static
171void LLImageGL::updateStats(F32 current_time) 174void LLImageGL::updateStats(F32 current_time)
172{ 175{
173 sLastFrameTime = current_time; 176 sLastFrameTime = current_time;
@@ -189,19 +192,24 @@ void LLImageGL::destroyGL(BOOL save_state)
189{ 192{
190 for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++) 193 for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++)
191 { 194 {
192 LLImageGL::unbindTexture(stage, GL_TEXTURE_2D); 195 gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
193 } 196 }
197
194 for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); 198 for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
195 iter != sImageList.end(); iter++) 199 iter != sImageList.end(); iter++)
196 { 200 {
197 LLImageGL* glimage = *iter; 201 LLImageGL* glimage = *iter;
198 if (glimage->mTexName && glimage->mComponents) 202 if (glimage->mTexName)
199 { 203 {
200 if (save_state) 204 if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
201 { 205 {
202 glimage->mSaveData = new LLImageRaw; 206 glimage->mSaveData = new LLImageRaw;
203 glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false); 207 if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false))
208 {
209 glimage->mSaveData = NULL ;
210 }
204 } 211 }
212
205 glimage->destroyGLTexture(); 213 glimage->destroyGLTexture();
206 stop_glerror(); 214 stop_glerror();
207 } 215 }
@@ -215,9 +223,13 @@ void LLImageGL::restoreGL()
215 iter != sImageList.end(); iter++) 223 iter != sImageList.end(); iter++)
216 { 224 {
217 LLImageGL* glimage = *iter; 225 LLImageGL* glimage = *iter;
218 if (glimage->mSaveData.notNull() && glimage->mSaveData->getComponents()) 226 if(glimage->getTexName())
227 {
228 llerrs << "tex name is not 0." << llendl ;
229 }
230 if (glimage->mSaveData.notNull())
219 { 231 {
220 if (glimage->getComponents()) 232 if (glimage->getComponents() && glimage->mSaveData->getComponents())
221 { 233 {
222 glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); 234 glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData);
223 stop_glerror(); 235 stop_glerror();
@@ -284,6 +296,8 @@ LLImageGL::~LLImageGL()
284{ 296{
285 LLImageGL::cleanup(); 297 LLImageGL::cleanup();
286 sImageList.erase(this); 298 sImageList.erase(this);
299 delete [] mPickMask;
300 mPickMask = NULL;
287 sCount--; 301 sCount--;
288} 302}
289 303
@@ -293,11 +307,12 @@ void LLImageGL::init(BOOL usemipmaps)
293 mMissed = FALSE; 307 mMissed = FALSE;
294#endif 308#endif
295 309
310 mPickMask = NULL;
296 mTextureMemory = 0; 311 mTextureMemory = 0;
297 mLastBindTime = 0.f; 312 mLastBindTime = 0.f;
298 313
299 mTarget = GL_TEXTURE_2D; 314 mTarget = GL_TEXTURE_2D;
300 mBindTarget = GL_TEXTURE_2D; 315 mBindTarget = LLTexUnit::TT_TEXTURE;
301 mUseMipMaps = usemipmaps; 316 mUseMipMaps = usemipmaps;
302 mHasMipMaps = FALSE; 317 mHasMipMaps = FALSE;
303 mAutoGenMips = FALSE; 318 mAutoGenMips = FALSE;
@@ -321,6 +336,8 @@ void LLImageGL::init(BOOL usemipmaps)
321 mFormatType = GL_UNSIGNED_BYTE; 336 mFormatType = GL_UNSIGNED_BYTE;
322 mFormatSwapBytes = FALSE; 337 mFormatSwapBytes = FALSE;
323 mHasExplicitFormat = FALSE; 338 mHasExplicitFormat = FALSE;
339
340 mGLTextureCreated = FALSE ;
324} 341}
325 342
326void LLImageGL::cleanup() 343void LLImageGL::cleanup()
@@ -421,41 +438,14 @@ void LLImageGL::dump()
421 438
422//---------------------------------------------------------------------------- 439//----------------------------------------------------------------------------
423 440
424BOOL LLImageGL::bindTextureInternal(const S32 stage) const 441void LLImageGL::updateBindStats(void) const
425{ 442{
426 if (gGLManager.mIsDisabled)
427 {
428 llwarns << "Trying to bind a texture while GL is disabled!" << llendl;
429 }
430
431
432 if (sCurrentBoundTextures[stage] && sCurrentBoundTextures[stage] == mTexName)
433 {
434 // already set!
435 return TRUE;
436 }
437
438 if (mTexName != 0) 443 if (mTexName != 0)
439 { 444 {
440#ifdef DEBUG_MISS 445#ifdef DEBUG_MISS
441 mMissed = ! getIsResident(TRUE); 446 mMissed = ! getIsResident(TRUE);
442#endif 447#endif
443
444 gGL.flush();
445 if (stage > 0)
446 {
447 gGL.getTexUnit(stage)->activate();
448 }
449
450 glBindTexture(mBindTarget, mTexName);
451 sCurrentBoundTextures[stage] = mTexName;
452 sBindCount++; 448 sBindCount++;
453
454 if (stage > 0)
455 {
456 gGL.getTexUnit(0)->activate();
457 }
458
459 if (mLastBindTime != sLastFrameTime) 449 if (mLastBindTime != sLastFrameTime)
460 { 450 {
461 // we haven't accounted for this texture yet this frame 451 // we haven't accounted for this texture yet this frame
@@ -463,38 +453,22 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
463 updateBoundTexMem(mTextureMemory); 453 updateBoundTexMem(mTextureMemory);
464 mLastBindTime = sLastFrameTime; 454 mLastBindTime = sLastFrameTime;
465 } 455 }
466
467 return TRUE;
468 }
469 else
470 {
471 gGL.flush();
472 if (stage > 0)
473 {
474 gGL.getTexUnit(stage)->activate();
475 }
476 glBindTexture(mBindTarget, 0);
477 if (stage > 0)
478 {
479 gGL.getTexUnit(0)->activate();
480 }
481 sCurrentBoundTextures[stage] = 0;
482 return FALSE;
483 } 456 }
484} 457}
485 458
486//virtual 459//virtual
487BOOL LLImageGL::bind(const S32 stage) const 460bool LLImageGL::bindError(const S32 stage) const
488{ 461{
489 if (stage == -1) 462 return false;
490 { 463}
491 return FALSE; 464
492 } 465//virtual
493 BOOL res = bindTextureInternal(stage); 466bool LLImageGL::bindDefaultImage(const S32 stage) const
494 //llassert(res); 467{
495 return res; 468 return false;
496} 469}
497 470
471
498void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes ) 472void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes )
499{ 473{
500 // Note: must be called before createTexture() 474 // Note: must be called before createTexture()
@@ -532,7 +506,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
532 506
533 { 507 {
534// LLFastTimer t2(LLFastTimer::FTM_TEMP2); 508// LLFastTimer t2(LLFastTimer::FTM_TEMP2);
535 llverify(bindTextureInternal(0)); 509 llverify(gGL.getTexUnit(0)->bind(this));
536 } 510 }
537 511
538 if (mUseMipMaps) 512 if (mUseMipMaps)
@@ -569,7 +543,8 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
569 } 543 }
570 544
571 glTexImage2D(mTarget, gl_level, mFormatInternal, w, h, 0, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in); 545 glTexImage2D(mTarget, gl_level, mFormatInternal, w, h, 0, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in);
572 546 updatePickMask(w, h, data_in);
547
573 if(mFormatSwapBytes) 548 if(mFormatSwapBytes)
574 { 549 {
575 glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); 550 glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
@@ -585,7 +560,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
585 { 560 {
586 if (mAutoGenMips) 561 if (mAutoGenMips)
587 { 562 {
588 glTexParameteri(mBindTarget, GL_GENERATE_MIPMAP_SGIS, TRUE); 563 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
589 stop_glerror(); 564 stop_glerror();
590 { 565 {
591// LLFastTimer t2(LLFastTimer::FTM_TEMP4); 566// LLFastTimer t2(LLFastTimer::FTM_TEMP4);
@@ -596,12 +571,17 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
596 stop_glerror(); 571 stop_glerror();
597 } 572 }
598 573
574 S32 w = getWidth(mCurrentDiscardLevel);
575 S32 h = getHeight(mCurrentDiscardLevel);
576
599 glTexImage2D(mTarget, 0, mFormatInternal, 577 glTexImage2D(mTarget, 0, mFormatInternal,
600 getWidth(mCurrentDiscardLevel), getHeight(mCurrentDiscardLevel), 0, 578 w, h, 0,
601 mFormatPrimary, mFormatType, 579 mFormatPrimary, mFormatType,
602 data_in); 580 data_in);
603 stop_glerror(); 581 stop_glerror();
604 582
583 updatePickMask(w, h, data_in);
584
605 if(mFormatSwapBytes) 585 if(mFormatSwapBytes)
606 { 586 {
607 glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); 587 glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
@@ -651,6 +631,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
651 631
652 glTexImage2D(mTarget, m, mFormatInternal, w, h, 0, mFormatPrimary, mFormatType, cur_mip_data); 632 glTexImage2D(mTarget, m, mFormatInternal, w, h, 0, mFormatPrimary, mFormatType, cur_mip_data);
653 stop_glerror(); 633 stop_glerror();
634 if (m == 0)
635 {
636 updatePickMask(w, h, cur_mip_data);
637 }
654 638
655 if(mFormatSwapBytes) 639 if(mFormatSwapBytes)
656 { 640 {
@@ -701,6 +685,8 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
701 685
702 glTexImage2D(mTarget, 0, mFormatInternal, w, h, 0, 686 glTexImage2D(mTarget, 0, mFormatInternal, w, h, 0,
703 mFormatPrimary, mFormatType, (GLvoid *)data_in); 687 mFormatPrimary, mFormatType, (GLvoid *)data_in);
688 updatePickMask(w, h, data_in);
689
704 stop_glerror(); 690 stop_glerror();
705 691
706 if(mFormatSwapBytes) 692 if(mFormatSwapBytes)
@@ -713,6 +699,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
713 mHasMipMaps = FALSE; 699 mHasMipMaps = FALSE;
714 } 700 }
715 stop_glerror(); 701 stop_glerror();
702 mGLTextureCreated = true;
716} 703}
717 704
718BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) 705BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
@@ -786,12 +773,10 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
786 773
787 datap += (y_pos * data_width + x_pos) * getComponents(); 774 datap += (y_pos * data_width + x_pos) * getComponents();
788 // Update the GL texture 775 // Update the GL texture
789 BOOL res = bindTextureInternal(0); 776 BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName);
790 if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl; 777 if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl;
791 stop_glerror(); 778 stop_glerror();
792 779
793 LLGLEnable tex( GL_TEXTURE_2D );
794
795 glTexSubImage2D(mTarget, 0, x_pos, y_pos, 780 glTexSubImage2D(mTarget, 0, x_pos, y_pos,
796 width, height, mFormatPrimary, mFormatType, datap); 781 width, height, mFormatPrimary, mFormatType, datap);
797 stop_glerror(); 782 stop_glerror();
@@ -804,8 +789,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
804 789
805 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 790 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
806 stop_glerror(); 791 stop_glerror();
792 mGLTextureCreated = true;
807 } 793 }
808
809 return TRUE; 794 return TRUE;
810} 795}
811 796
@@ -817,9 +802,10 @@ BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S3
817// Copy sub image from frame buffer 802// Copy sub image from frame buffer
818BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height) 803BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
819{ 804{
820 if (bindTextureInternal(0)) 805 if (gGL.getTexUnit(0)->bind(this, true))
821 { 806 {
822 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); 807 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
808 mGLTextureCreated = true;
823 stop_glerror(); 809 stop_glerror();
824 return TRUE; 810 return TRUE;
825 } 811 }
@@ -829,6 +815,36 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
829 } 815 }
830} 816}
831 817
818//create an empty GL texture: just create a texture name
819//the texture is assiciate with some image by calling glTexImage outside LLImageGL
820BOOL LLImageGL::createGLTexture()
821{
822 if (gGLManager.mIsDisabled)
823 {
824 llwarns << "Trying to create a texture while GL is disabled!" << llendl;
825 return FALSE;
826 }
827
828 mGLTextureCreated = false ; //do not save this texture when gl is destroyed.
829
830 llassert(gGLManager.mInited);
831 stop_glerror();
832
833 if(mTexName)
834 {
835 glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ;
836 }
837
838 glGenTextures(1, (GLuint*)&mTexName);
839 stop_glerror();
840 if (!mTexName)
841 {
842 llerrs << "LLImageGL::createGLTexture failed to make an empty texture" << llendl;
843 }
844
845 return TRUE ;
846}
847
832BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) 848BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/)
833{ 849{
834 if (gGLManager.mIsDisabled) 850 if (gGLManager.mIsDisabled)
@@ -836,6 +852,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
836 llwarns << "Trying to create a texture while GL is disabled!" << llendl; 852 llwarns << "Trying to create a texture while GL is disabled!" << llendl;
837 return FALSE; 853 return FALSE;
838 } 854 }
855 mGLTextureCreated = false ;
839 llassert(gGLManager.mInited); 856 llassert(gGLManager.mInited);
840 stop_glerror(); 857 stop_glerror();
841 858
@@ -919,9 +936,9 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
919 stop_glerror(); 936 stop_glerror();
920 { 937 {
921// LLFastTimer t1(LLFastTimer::FTM_TEMP6); 938// LLFastTimer t1(LLFastTimer::FTM_TEMP6);
922 llverify(bindTextureInternal(0)); 939 llverify(gGL.getTexUnit(0)->bind(this));
923 glTexParameteri(mBindTarget, GL_TEXTURE_BASE_LEVEL, 0); 940 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0);
924 glTexParameteri(mBindTarget, GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level); 941 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level);
925 } 942 }
926 } 943 }
927 if (!mTexName) 944 if (!mTexName)
@@ -941,7 +958,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
941#endif 958#endif
942 } 959 }
943 960
944 mCurrentDiscardLevel = discard_level; 961 mCurrentDiscardLevel = discard_level;
945 962
946 setImage(data_in, data_hasmips); 963 setImage(data_in, data_hasmips);
947 964
@@ -949,7 +966,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
949 setMipFilterNearest(mMagFilterNearest); 966 setMipFilterNearest(mMagFilterNearest);
950 967
951 // things will break if we don't unbind after creation 968 // things will break if we don't unbind after creation
952 unbindTexture(0, mBindTarget); 969 gGL.getTexUnit(0)->unbind(mBindTarget);
953 stop_glerror(); 970 stop_glerror();
954 971
955 if (old_name != 0) 972 if (old_name != 0)
@@ -1042,7 +1059,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
1042 discard_level = mCurrentDiscardLevel; 1059 discard_level = mCurrentDiscardLevel;
1043 } 1060 }
1044 1061
1045 if (mTexName == 0 || discard_level < mCurrentDiscardLevel) 1062 if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel )
1046 { 1063 {
1047 return FALSE; 1064 return FALSE;
1048 } 1065 }
@@ -1050,21 +1067,11 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
1050 S32 gl_discard = discard_level - mCurrentDiscardLevel; 1067 S32 gl_discard = discard_level - mCurrentDiscardLevel;
1051 1068
1052 //explicitly unbind texture 1069 //explicitly unbind texture
1053 LLImageGL::unbindTexture(0, mTarget); 1070 gGL.getTexUnit(0)->unbind(mBindTarget);
1054 llverify(bindTextureInternal(0)); 1071 llverify(gGL.getTexUnit(0)->bind(this));
1055 1072
1056 if (gDebugGL) 1073 //debug code, leave it there commented.
1057 { 1074 //checkTexSize() ;
1058 if (mTarget == GL_TEXTURE_2D)
1059 {
1060 GLint texname;
1061 glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
1062 if (texname != mTexName)
1063 {
1064 llerrs << "Invalid texture bound!" << llendl;
1065 }
1066 }
1067 }
1068 1075
1069 LLGLint glwidth = 0; 1076 LLGLint glwidth = 0;
1070 glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); 1077 glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth);
@@ -1073,7 +1080,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
1073 // No mip data smaller than current discard level 1080 // No mip data smaller than current discard level
1074 return FALSE; 1081 return FALSE;
1075 } 1082 }
1076 1083
1077 S32 width = getWidth(discard_level); 1084 S32 width = getWidth(discard_level);
1078 S32 height = getHeight(discard_level); 1085 S32 height = getHeight(discard_level);
1079 S32 ncomponents = getComponents(); 1086 S32 ncomponents = getComponents();
@@ -1081,6 +1088,13 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
1081 { 1088 {
1082 return FALSE; 1089 return FALSE;
1083 } 1090 }
1091 if(width < glwidth)
1092 {
1093 llwarns << "texture size is smaller than it should be." << llendl ;
1094 llwarns << "width: " << width << " glwidth: " << glwidth << " mWidth: " << mWidth <<
1095 " mCurrentDiscardLevel: " << (S32)mCurrentDiscardLevel << " discard_level: " << (S32)discard_level << llendl ;
1096 return FALSE ;
1097 }
1084 1098
1085 if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4) 1099 if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4)
1086 { 1100 {
@@ -1148,15 +1162,15 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
1148 1162
1149void LLImageGL::destroyGLTexture() 1163void LLImageGL::destroyGLTexture()
1150{ 1164{
1151 stop_glerror();
1152
1153 if (mTexName != 0) 1165 if (mTexName != 0)
1154 { 1166 {
1167 stop_glerror();
1168
1155 for (int i = 0; i < gGLManager.mNumTextureUnits; i++) 1169 for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
1156 { 1170 {
1157 if (sCurrentBoundTextures[i] == mTexName) 1171 if (sCurrentBoundTextures[i] == mTexName)
1158 { 1172 {
1159 unbindTexture(i, GL_TEXTURE_2D); 1173 gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
1160 stop_glerror(); 1174 stop_glerror();
1161 } 1175 }
1162 } 1176 }
@@ -1166,7 +1180,7 @@ void LLImageGL::destroyGLTexture()
1166 1180
1167 glDeleteTextures(1, (GLuint*)&mTexName); 1181 glDeleteTextures(1, (GLuint*)&mTexName);
1168 mTexName = 0; 1182 mTexName = 0;
1169 1183 mGLTextureCreated = FALSE ;
1170 stop_glerror(); 1184 stop_glerror();
1171 } 1185 }
1172} 1186}
@@ -1184,8 +1198,8 @@ void LLImageGL::glClamp (BOOL clamps, BOOL clampt)
1184{ 1198{
1185 if (mTexName != 0) 1199 if (mTexName != 0)
1186 { 1200 {
1187 glTexParameteri (mBindTarget, GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); 1201 glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT);
1188 glTexParameteri (mBindTarget, GL_TEXTURE_WRAP_T, clampt ? GL_CLAMP_TO_EDGE : GL_REPEAT); 1202 glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_T, clampt ? GL_CLAMP_TO_EDGE : GL_REPEAT);
1189 } 1203 }
1190} 1204}
1191 1205
@@ -1223,23 +1237,23 @@ void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest)
1223 { 1237 {
1224 if (mMinFilterNearest) 1238 if (mMinFilterNearest)
1225 { 1239 {
1226 glTexParameteri(mBindTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1240 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1227 } 1241 }
1228 else if (mHasMipMaps) 1242 else if (mHasMipMaps)
1229 { 1243 {
1230 glTexParameteri(mBindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 1244 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1231 } 1245 }
1232 else 1246 else
1233 { 1247 {
1234 glTexParameteri(mBindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1248 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1235 } 1249 }
1236 if (mMagFilterNearest) 1250 if (mMagFilterNearest)
1237 { 1251 {
1238 glTexParameteri(mBindTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1252 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1239 } 1253 }
1240 else 1254 else
1241 { 1255 {
1242 glTexParameteri(mBindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1256 glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1243 } 1257 }
1244 if (gGLManager.mHasAnisotropic) 1258 if (gGLManager.mHasAnisotropic)
1245 { 1259 {
@@ -1247,16 +1261,15 @@ void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest)
1247 { 1261 {
1248 F32 largest_anisotropy; 1262 F32 largest_anisotropy;
1249 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_anisotropy); 1263 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_anisotropy);
1250 glTexParameterf(mBindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_anisotropy); 1264 glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_anisotropy);
1251 } 1265 }
1252 else 1266 else
1253 { 1267 {
1254 glTexParameterf(mBindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); 1268 glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
1255 } 1269 }
1256 } 1270 }
1257 } 1271 stop_glerror();
1258 1272 }
1259 stop_glerror();
1260} 1273}
1261 1274
1262BOOL LLImageGL::getIsResident(BOOL test_now) 1275BOOL LLImageGL::getIsResident(BOOL test_now)
@@ -1337,14 +1350,93 @@ BOOL LLImageGL::getBoundRecently() const
1337 return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME); 1350 return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
1338} 1351}
1339 1352
1340void LLImageGL::setTarget(const LLGLenum target, const LLGLenum bind_target) 1353void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
1341{ 1354{
1342 mTarget = target; 1355 mTarget = target;
1343 mBindTarget = bind_target; 1356 mBindTarget = bind_target;
1344} 1357}
1345 1358
1359void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
1360{
1361 if (mFormatType != GL_UNSIGNED_BYTE ||
1362 mFormatPrimary != GL_RGBA)
1363 {
1364 //cannot generate a pick mask for this texture
1365 delete [] mPickMask;
1366 mPickMask = NULL;
1367 return;
1368 }
1369
1370 U32 pick_width = width/2;
1371 U32 pick_height = height/2;
1372
1373 U32 size = llmax(pick_width, (U32) 1) * llmax(pick_height, (U32) 1);
1374
1375 size = size/8 + 1;
1376
1377 delete[] mPickMask;
1378 mPickMask = new U8[size];
1379
1380 memset(mPickMask, 0, sizeof(U8) * size);
1381
1382 U32 pick_bit = 0;
1383
1384 for (S32 y = 0; y < height; y += 2)
1385 {
1386 for (S32 x = 0; x < width; x += 2)
1387 {
1388 U8 alpha = data_in[(y*width+x)*4+3];
1389
1390 if (alpha > 32)
1391 {
1392 U32 pick_idx = pick_bit/8;
1393 U32 pick_offset = pick_bit%8;
1394 if (pick_idx >= size)
1395 {
1396 llerrs << "WTF?" << llendl;
1397 }
1398
1399 mPickMask[pick_idx] |= 1 << pick_offset;
1400 }
1401
1402 ++pick_bit;
1403 }
1404 }
1405}
1406
1407BOOL LLImageGL::getMask(const LLVector2 &tc)
1408{
1409 BOOL res = TRUE;
1410
1411 if (mPickMask)
1412 {
1413 S32 width = getWidth()/2;
1414 S32 height = getHeight()/2;
1415
1416 F32 u = tc.mV[0] - floorf(tc.mV[0]);
1417 F32 v = tc.mV[1] - floorf(tc.mV[1]);
1418
1419 if (u < 0.f || u > 1.f ||
1420 v < 0.f || v > 1.f)
1421 {
1422 llerrs << "WTF?" << llendl;
1423 }
1424
1425 S32 x = (S32)(u * width);
1426 S32 y = (S32)(v * height);
1427
1428 S32 idx = y*width+x;
1429 S32 offset = idx%8;
1430
1431 res = mPickMask[idx/8] & (1 << offset) ? TRUE : FALSE;
1432 }
1433
1434 return res;
1435}
1436
1346//---------------------------------------------------------------------------- 1437//----------------------------------------------------------------------------
1347 1438
1439
1348// Manual Mip Generation 1440// Manual Mip Generation
1349/* 1441/*
1350 S32 width = getWidth(discard_level); 1442 S32 width = getWidth(discard_level);