diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llrender/llimagegl.cpp | 394 |
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 | ||
64 | std::set<LLImageGL*> LLImageGL::sImageList; | 64 | std::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. | ||
69 | void 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 | |||
84 | void 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 |
128 | void 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 | ||
144 | void 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) | ||
165 | void LLImageGL::unbindTexture(S32 stage) | ||
166 | { | ||
167 | unbindTexture(stage, GL_TEXTURE_2D); | ||
168 | } | ||
169 | |||
170 | // static | ||
171 | void LLImageGL::updateStats(F32 current_time) | 174 | void 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 | ||
326 | void LLImageGL::cleanup() | 343 | void LLImageGL::cleanup() |
@@ -421,41 +438,14 @@ void LLImageGL::dump() | |||
421 | 438 | ||
422 | //---------------------------------------------------------------------------- | 439 | //---------------------------------------------------------------------------- |
423 | 440 | ||
424 | BOOL LLImageGL::bindTextureInternal(const S32 stage) const | 441 | void 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 |
487 | BOOL LLImageGL::bind(const S32 stage) const | 460 | bool 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); | 466 | bool LLImageGL::bindDefaultImage(const S32 stage) const |
494 | //llassert(res); | 467 | { |
495 | return res; | 468 | return false; |
496 | } | 469 | } |
497 | 470 | ||
471 | |||
498 | void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes ) | 472 | void 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 | ||
718 | BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) | 705 | BOOL 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 |
818 | BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height) | 803 | BOOL 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 | ||
820 | BOOL 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 | |||
832 | BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) | 848 | BOOL 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 | ||
1149 | void LLImageGL::destroyGLTexture() | 1163 | void 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 | ||
1262 | BOOL LLImageGL::getIsResident(BOOL test_now) | 1275 | BOOL 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 | ||
1340 | void LLImageGL::setTarget(const LLGLenum target, const LLGLenum bind_target) | 1353 | void 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 | ||
1359 | void 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 | |||
1407 | BOOL 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); |