diff options
Diffstat (limited to 'linden/indra/llrender/llimagegl.cpp')
-rw-r--r-- | linden/indra/llrender/llimagegl.cpp | 148 |
1 files changed, 121 insertions, 27 deletions
diff --git a/linden/indra/llrender/llimagegl.cpp b/linden/indra/llrender/llimagegl.cpp index 9a392d7..8195eee 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 |
@@ -61,8 +61,56 @@ S32 LLImageGL::sCount = 0; | |||
61 | BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; | 61 | BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; |
62 | F32 LLImageGL::sLastFrameTime = 0.f; | 62 | F32 LLImageGL::sLastFrameTime = 0.f; |
63 | 63 | ||
64 | S32 LLImageGL::sMaxTextureSize = 0 ; | ||
65 | |||
64 | std::set<LLImageGL*> LLImageGL::sImageList; | 66 | std::set<LLImageGL*> LLImageGL::sImageList; |
65 | 67 | ||
68 | //************************************************************************************** | ||
69 | //below are functions for debug use | ||
70 | //do not delete them even though they are not currently being used. | ||
71 | void check_all_images() | ||
72 | { | ||
73 | for (std::set<LLImageGL*>::iterator iter = LLImageGL::sImageList.begin(); | ||
74 | iter != LLImageGL::sImageList.end(); iter++) | ||
75 | { | ||
76 | LLImageGL* glimage = *iter; | ||
77 | if (glimage->getTexName() && glimage->isGLTextureCreated()) | ||
78 | { | ||
79 | gGL.getTexUnit(0)->bind(glimage) ; | ||
80 | glimage->checkTexSize() ; | ||
81 | gGL.getTexUnit(0)->unbind(glimage->getTarget()) ; | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | void LLImageGL::checkTexSize() const | ||
87 | { | ||
88 | if (gDebugGL && mTarget == GL_TEXTURE_2D) | ||
89 | { | ||
90 | GLint texname; | ||
91 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); | ||
92 | if (texname != mTexName) | ||
93 | { | ||
94 | llerrs << "Invalid texture bound!" << llendl; | ||
95 | } | ||
96 | stop_glerror() ; | ||
97 | LLGLint x = 0, y = 0 ; | ||
98 | glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_WIDTH, (GLint*)&x); | ||
99 | glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_HEIGHT, (GLint*)&y) ; | ||
100 | stop_glerror() ; | ||
101 | if(!x || !y) | ||
102 | { | ||
103 | return ; | ||
104 | } | ||
105 | if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel)) | ||
106 | { | ||
107 | llerrs << "wrong texture size and discard level!" << llendl ; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | //end of debug functions | ||
112 | //************************************************************************************** | ||
113 | |||
66 | //---------------------------------------------------------------------------- | 114 | //---------------------------------------------------------------------------- |
67 | 115 | ||
68 | //static | 116 | //static |
@@ -148,17 +196,22 @@ void LLImageGL::destroyGL(BOOL save_state) | |||
148 | { | 196 | { |
149 | gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); | 197 | gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); |
150 | } | 198 | } |
199 | |||
151 | for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); | 200 | for (std::set<LLImageGL*>::iterator iter = sImageList.begin(); |
152 | iter != sImageList.end(); iter++) | 201 | iter != sImageList.end(); iter++) |
153 | { | 202 | { |
154 | LLImageGL* glimage = *iter; | 203 | LLImageGL* glimage = *iter; |
155 | if (glimage->mTexName && glimage->mComponents) | 204 | if (glimage->mTexName) |
156 | { | 205 | { |
157 | if (save_state && glimage->isInitialized()) | 206 | if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) |
158 | { | 207 | { |
159 | glimage->mSaveData = new LLImageRaw; | 208 | glimage->mSaveData = new LLImageRaw; |
160 | glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false); | 209 | if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) |
210 | { | ||
211 | glimage->mSaveData = NULL ; | ||
212 | } | ||
161 | } | 213 | } |
214 | |||
162 | glimage->destroyGLTexture(); | 215 | glimage->destroyGLTexture(); |
163 | stop_glerror(); | 216 | stop_glerror(); |
164 | } | 217 | } |
@@ -172,9 +225,13 @@ void LLImageGL::restoreGL() | |||
172 | iter != sImageList.end(); iter++) | 225 | iter != sImageList.end(); iter++) |
173 | { | 226 | { |
174 | LLImageGL* glimage = *iter; | 227 | LLImageGL* glimage = *iter; |
175 | if (glimage->mSaveData.notNull() && glimage->mSaveData->getComponents()) | 228 | if(glimage->getTexName()) |
229 | { | ||
230 | llerrs << "tex name is not 0." << llendl ; | ||
231 | } | ||
232 | if (glimage->mSaveData.notNull()) | ||
176 | { | 233 | { |
177 | if (glimage->getComponents()) | 234 | if (glimage->getComponents() && glimage->mSaveData->getComponents()) |
178 | { | 235 | { |
179 | glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); | 236 | glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); |
180 | stop_glerror(); | 237 | stop_glerror(); |
@@ -282,7 +339,7 @@ void LLImageGL::init(BOOL usemipmaps) | |||
282 | mFormatSwapBytes = FALSE; | 339 | mFormatSwapBytes = FALSE; |
283 | mHasExplicitFormat = FALSE; | 340 | mHasExplicitFormat = FALSE; |
284 | 341 | ||
285 | mInitialized = true; | 342 | mGLTextureCreated = FALSE ; |
286 | } | 343 | } |
287 | 344 | ||
288 | void LLImageGL::cleanup() | 345 | void LLImageGL::cleanup() |
@@ -321,6 +378,16 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) | |||
321 | { | 378 | { |
322 | if (width != mWidth || height != mHeight || ncomponents != mComponents) | 379 | if (width != mWidth || height != mHeight || ncomponents != mComponents) |
323 | { | 380 | { |
381 | if(width > 1024 || height > 1024) | ||
382 | { | ||
383 | llwarns << "texture size is big: width: " << width << " height: " << height << llendl ; | ||
384 | if(!sMaxTextureSize) | ||
385 | { | ||
386 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&sMaxTextureSize) ; | ||
387 | } | ||
388 | llwarns << "max texture size is: " << sMaxTextureSize << llendl ; | ||
389 | } | ||
390 | |||
324 | // Check if dimensions are a power of two! | 391 | // Check if dimensions are a power of two! |
325 | if (!checkSize(width,height)) | 392 | if (!checkSize(width,height)) |
326 | { | 393 | { |
@@ -644,7 +711,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
644 | mHasMipMaps = FALSE; | 711 | mHasMipMaps = FALSE; |
645 | } | 712 | } |
646 | stop_glerror(); | 713 | stop_glerror(); |
647 | mInitialized = true; | 714 | mGLTextureCreated = true; |
648 | } | 715 | } |
649 | 716 | ||
650 | BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) | 717 | BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) |
@@ -734,9 +801,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 | |||
734 | 801 | ||
735 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | 802 | glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |
736 | stop_glerror(); | 803 | stop_glerror(); |
737 | mInitialized = true; | 804 | mGLTextureCreated = true; |
738 | } | 805 | } |
739 | |||
740 | return TRUE; | 806 | return TRUE; |
741 | } | 807 | } |
742 | 808 | ||
@@ -751,7 +817,7 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ | |||
751 | if (gGL.getTexUnit(0)->bind(this, true)) | 817 | if (gGL.getTexUnit(0)->bind(this, true)) |
752 | { | 818 | { |
753 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); | 819 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); |
754 | mInitialized = true; | 820 | mGLTextureCreated = true; |
755 | stop_glerror(); | 821 | stop_glerror(); |
756 | return TRUE; | 822 | return TRUE; |
757 | } | 823 | } |
@@ -761,6 +827,36 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ | |||
761 | } | 827 | } |
762 | } | 828 | } |
763 | 829 | ||
830 | //create an empty GL texture: just create a texture name | ||
831 | //the texture is assiciate with some image by calling glTexImage outside LLImageGL | ||
832 | BOOL LLImageGL::createGLTexture() | ||
833 | { | ||
834 | if (gGLManager.mIsDisabled) | ||
835 | { | ||
836 | llwarns << "Trying to create a texture while GL is disabled!" << llendl; | ||
837 | return FALSE; | ||
838 | } | ||
839 | |||
840 | mGLTextureCreated = false ; //do not save this texture when gl is destroyed. | ||
841 | |||
842 | llassert(gGLManager.mInited); | ||
843 | stop_glerror(); | ||
844 | |||
845 | if(mTexName) | ||
846 | { | ||
847 | glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ; | ||
848 | } | ||
849 | |||
850 | glGenTextures(1, (GLuint*)&mTexName); | ||
851 | stop_glerror(); | ||
852 | if (!mTexName) | ||
853 | { | ||
854 | llerrs << "LLImageGL::createGLTexture failed to make an empty texture" << llendl; | ||
855 | } | ||
856 | |||
857 | return TRUE ; | ||
858 | } | ||
859 | |||
764 | BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) | 860 | BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) |
765 | { | 861 | { |
766 | if (gGLManager.mIsDisabled) | 862 | if (gGLManager.mIsDisabled) |
@@ -768,6 +864,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S | |||
768 | llwarns << "Trying to create a texture while GL is disabled!" << llendl; | 864 | llwarns << "Trying to create a texture while GL is disabled!" << llendl; |
769 | return FALSE; | 865 | return FALSE; |
770 | } | 866 | } |
867 | mGLTextureCreated = false ; | ||
771 | llassert(gGLManager.mInited); | 868 | llassert(gGLManager.mInited); |
772 | stop_glerror(); | 869 | stop_glerror(); |
773 | 870 | ||
@@ -873,7 +970,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ | |||
873 | #endif | 970 | #endif |
874 | } | 971 | } |
875 | 972 | ||
876 | mCurrentDiscardLevel = discard_level; | 973 | mCurrentDiscardLevel = discard_level; |
877 | 974 | ||
878 | setImage(data_in, data_hasmips); | 975 | setImage(data_in, data_hasmips); |
879 | 976 | ||
@@ -974,7 +1071,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre | |||
974 | discard_level = mCurrentDiscardLevel; | 1071 | discard_level = mCurrentDiscardLevel; |
975 | } | 1072 | } |
976 | 1073 | ||
977 | if (mTexName == 0 || discard_level < mCurrentDiscardLevel) | 1074 | if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel ) |
978 | { | 1075 | { |
979 | return FALSE; | 1076 | return FALSE; |
980 | } | 1077 | } |
@@ -985,18 +1082,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre | |||
985 | gGL.getTexUnit(0)->unbind(mBindTarget); | 1082 | gGL.getTexUnit(0)->unbind(mBindTarget); |
986 | llverify(gGL.getTexUnit(0)->bind(this)); | 1083 | llverify(gGL.getTexUnit(0)->bind(this)); |
987 | 1084 | ||
988 | if (gDebugGL) | 1085 | //debug code, leave it there commented. |
989 | { | 1086 | //checkTexSize() ; |
990 | if (mTarget == GL_TEXTURE_2D) | ||
991 | { | ||
992 | GLint texname; | ||
993 | glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); | ||
994 | if (texname != mTexName) | ||
995 | { | ||
996 | llerrs << "Invalid texture bound!" << llendl; | ||
997 | } | ||
998 | } | ||
999 | } | ||
1000 | 1087 | ||
1001 | LLGLint glwidth = 0; | 1088 | LLGLint glwidth = 0; |
1002 | glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); | 1089 | glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); |
@@ -1005,7 +1092,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre | |||
1005 | // No mip data smaller than current discard level | 1092 | // No mip data smaller than current discard level |
1006 | return FALSE; | 1093 | return FALSE; |
1007 | } | 1094 | } |
1008 | 1095 | ||
1009 | S32 width = getWidth(discard_level); | 1096 | S32 width = getWidth(discard_level); |
1010 | S32 height = getHeight(discard_level); | 1097 | S32 height = getHeight(discard_level); |
1011 | S32 ncomponents = getComponents(); | 1098 | S32 ncomponents = getComponents(); |
@@ -1013,6 +1100,13 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre | |||
1013 | { | 1100 | { |
1014 | return FALSE; | 1101 | return FALSE; |
1015 | } | 1102 | } |
1103 | if(width < glwidth) | ||
1104 | { | ||
1105 | llwarns << "texture size is smaller than it should be." << llendl ; | ||
1106 | llwarns << "width: " << width << " glwidth: " << glwidth << " mWidth: " << mWidth << | ||
1107 | " mCurrentDiscardLevel: " << (S32)mCurrentDiscardLevel << " discard_level: " << (S32)discard_level << llendl ; | ||
1108 | return FALSE ; | ||
1109 | } | ||
1016 | 1110 | ||
1017 | if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4) | 1111 | if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4) |
1018 | { | 1112 | { |
@@ -1098,7 +1192,7 @@ void LLImageGL::destroyGLTexture() | |||
1098 | 1192 | ||
1099 | glDeleteTextures(1, (GLuint*)&mTexName); | 1193 | glDeleteTextures(1, (GLuint*)&mTexName); |
1100 | mTexName = 0; | 1194 | mTexName = 0; |
1101 | 1195 | mGLTextureCreated = FALSE ; | |
1102 | stop_glerror(); | 1196 | stop_glerror(); |
1103 | } | 1197 | } |
1104 | } | 1198 | } |