diff options
Diffstat (limited to '')
36 files changed, 2883 insertions, 1378 deletions
diff --git a/linden/indra/llrender/CMakeLists.txt b/linden/indra/llrender/CMakeLists.txt index 76858d9..0bdb55f 100644 --- a/linden/indra/llrender/CMakeLists.txt +++ b/linden/indra/llrender/CMakeLists.txt | |||
@@ -9,6 +9,8 @@ include(LLImage) | |||
9 | include(LLMath) | 9 | include(LLMath) |
10 | include(LLRender) | 10 | include(LLRender) |
11 | include(LLWindow) | 11 | include(LLWindow) |
12 | include(LLXML) | ||
13 | include(LLVFS) | ||
12 | 14 | ||
13 | include_directories( | 15 | include_directories( |
14 | ${FREETYPE_INCLUDE_DIRS} | 16 | ${FREETYPE_INCLUDE_DIRS} |
@@ -17,19 +19,21 @@ include_directories( | |||
17 | ${LLMATH_INCLUDE_DIRS} | 19 | ${LLMATH_INCLUDE_DIRS} |
18 | ${LLRENDER_INCLUDE_DIRS} | 20 | ${LLRENDER_INCLUDE_DIRS} |
19 | ${LLWINDOW_INCLUDE_DIRS} | 21 | ${LLWINDOW_INCLUDE_DIRS} |
22 | ${LLXML_INCLUDE_DIRS} | ||
23 | ${LLVFS_INCLUDE_DIRS} | ||
20 | ) | 24 | ) |
21 | 25 | ||
22 | set(llrender_SOURCE_FILES | 26 | set(llrender_SOURCE_FILES |
23 | llcubemap.cpp | 27 | llcubemap.cpp |
24 | llfont.cpp | 28 | llfont.cpp |
25 | llfontgl.cpp | 29 | llfontgl.cpp |
30 | llfontbitmapcache.cpp | ||
31 | llfontregistry.cpp | ||
26 | llgldbg.cpp | 32 | llgldbg.cpp |
27 | llglslshader.cpp | 33 | llglslshader.cpp |
28 | llimagegl.cpp | 34 | llimagegl.cpp |
29 | llpostprocess.cpp | 35 | llpostprocess.cpp |
30 | llrender.cpp | ||
31 | llrendersphere.cpp | 36 | llrendersphere.cpp |
32 | llrendertarget.cpp | ||
33 | llshadermgr.cpp | 37 | llshadermgr.cpp |
34 | llvertexbuffer.cpp | 38 | llvertexbuffer.cpp |
35 | ) | 39 | ) |
@@ -40,6 +44,8 @@ set(llrender_HEADER_FILES | |||
40 | llcubemap.h | 44 | llcubemap.h |
41 | llfontgl.h | 45 | llfontgl.h |
42 | llfont.h | 46 | llfont.h |
47 | llfontbitmapcache.h | ||
48 | llfontregistry.h | ||
43 | llgl.h | 49 | llgl.h |
44 | llgldbg.h | 50 | llgldbg.h |
45 | llglheaders.h | 51 | llglheaders.h |
@@ -50,7 +56,6 @@ set(llrender_HEADER_FILES | |||
50 | llpostprocess.h | 56 | llpostprocess.h |
51 | llrender.h | 57 | llrender.h |
52 | llrendersphere.h | 58 | llrendersphere.h |
53 | llrendertarget.h | ||
54 | llshadermgr.h | 59 | llshadermgr.h |
55 | llvertexbuffer.h | 60 | llvertexbuffer.h |
56 | ) | 61 | ) |
@@ -63,6 +68,7 @@ list(APPEND llrender_SOURCE_FILES ${llrender_HEADER_FILES}) | |||
63 | if (SERVER AND NOT WINDOWS AND NOT DARWIN) | 68 | if (SERVER AND NOT WINDOWS AND NOT DARWIN) |
64 | copy_server_sources( | 69 | copy_server_sources( |
65 | llgl | 70 | llgl |
71 | llrender | ||
66 | ) | 72 | ) |
67 | 73 | ||
68 | 74 | ||
@@ -78,6 +84,8 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN) | |||
78 | else (SERVER AND NOT WINDOWS AND NOT DARWIN) | 84 | else (SERVER AND NOT WINDOWS AND NOT DARWIN) |
79 | list(APPEND llrender_SOURCE_FILES | 85 | list(APPEND llrender_SOURCE_FILES |
80 | llgl.cpp | 86 | llgl.cpp |
87 | llrender.cpp | ||
88 | llrendertarget.cpp | ||
81 | ) | 89 | ) |
82 | endif (SERVER AND NOT WINDOWS AND NOT DARWIN) | 90 | endif (SERVER AND NOT WINDOWS AND NOT DARWIN) |
83 | add_library (llrender ${llrender_SOURCE_FILES}) | 91 | add_library (llrender ${llrender_SOURCE_FILES}) |
diff --git a/linden/indra/llrender/llcubemap.cpp b/linden/indra/llrender/llcubemap.cpp index 60215f0..754d90c 100644 --- a/linden/indra/llrender/llcubemap.cpp +++ b/linden/indra/llrender/llcubemap.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -39,7 +40,6 @@ | |||
39 | #include "v3dmath.h" | 40 | #include "v3dmath.h" |
40 | #include "m3math.h" | 41 | #include "m3math.h" |
41 | #include "m4math.h" | 42 | #include "m4math.h" |
42 | #include "llcamera.h" | ||
43 | 43 | ||
44 | #include "llrender.h" | 44 | #include "llrender.h" |
45 | 45 | ||
@@ -85,9 +85,9 @@ void LLCubeMap::initGL() | |||
85 | // Not initialized, do stuff. | 85 | // Not initialized, do stuff. |
86 | if (mImages[0].isNull()) | 86 | if (mImages[0].isNull()) |
87 | { | 87 | { |
88 | GLuint texname = 0; | 88 | U32 texname = 0; |
89 | 89 | ||
90 | glGenTextures(1, &texname); | 90 | LLImageGL::generateTextures(1, &texname); |
91 | 91 | ||
92 | for (int i = 0; i < 6; i++) | 92 | for (int i = 0; i < 6; i++) |
93 | { | 93 | { |
@@ -97,9 +97,10 @@ void LLCubeMap::initGL() | |||
97 | mImages[i]->createGLTexture(0, mRawImages[i], texname); | 97 | mImages[i]->createGLTexture(0, mRawImages[i], texname); |
98 | 98 | ||
99 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); | 99 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); |
100 | mImages[i]->setClampCubemap (TRUE, TRUE, TRUE); | 100 | mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); |
101 | stop_glerror(); | 101 | stop_glerror(); |
102 | } | 102 | } |
103 | gGL.getTexUnit(0)->disable(); | ||
103 | } | 104 | } |
104 | disable(); | 105 | disable(); |
105 | } | 106 | } |
@@ -311,8 +312,8 @@ void LLCubeMap::restoreMatrix() | |||
311 | void LLCubeMap::setReflection (void) | 312 | void LLCubeMap::setReflection (void) |
312 | { | 313 | { |
313 | gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName()); | 314 | gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName()); |
314 | mImages[0]->setMipFilterNearest (FALSE, FALSE); | 315 | mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); |
315 | mImages[0]->setClampCubemap (TRUE, TRUE); | 316 | mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP); |
316 | } | 317 | } |
317 | 318 | ||
318 | LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const | 319 | LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const |
diff --git a/linden/indra/llrender/llcubemap.h b/linden/indra/llrender/llcubemap.h index 8c83e6e..c854485 100644 --- a/linden/indra/llrender/llcubemap.h +++ b/linden/indra/llrender/llcubemap.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llrender/llfont.cpp b/linden/indra/llrender/llfont.cpp index d7310bd..9245803 100644 --- a/linden/indra/llrender/llfont.cpp +++ b/linden/indra/llrender/llfont.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -52,6 +53,8 @@ | |||
52 | #include "llmath.h" // Linden math | 53 | #include "llmath.h" // Linden math |
53 | #include "llstring.h" | 54 | #include "llstring.h" |
54 | //#include "imdebug.h" | 55 | //#include "imdebug.h" |
56 | #include "llfontbitmapcache.h" | ||
57 | #include "llgl.h" | ||
55 | 58 | ||
56 | FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; | 59 | FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; |
57 | 60 | ||
@@ -124,30 +127,28 @@ void LLFontList::addAtEnd(LLFont *font) | |||
124 | this->push_back(font); | 127 | this->push_back(font); |
125 | } | 128 | } |
126 | 129 | ||
127 | LLFont::LLFont(LLImageRaw *imagep) | 130 | LLFont::LLFont() |
128 | : mRawImagep(imagep) | ||
129 | { | 131 | { |
132 | mFontBitmapCachep = new LLFontBitmapCache; | ||
133 | |||
130 | mValid = FALSE; | 134 | mValid = FALSE; |
131 | mAscender = 0.f; | 135 | mAscender = 0.f; |
132 | mDescender = 0.f; | 136 | mDescender = 0.f; |
133 | mLineHeight = 0.f; | 137 | mLineHeight = 0.f; |
134 | mBitmapWidth = 0; | 138 | |
135 | mBitmapHeight = 0; | ||
136 | mCurrentOffsetX = 1; | ||
137 | mCurrentOffsetY = 1; | ||
138 | mMaxCharWidth = 0; | ||
139 | mMaxCharHeight = 0; | ||
140 | mNumComponents = 0; | ||
141 | mFallbackFontp = NULL; | 139 | mFallbackFontp = NULL; |
142 | mIsFallback = FALSE; | 140 | mIsFallback = FALSE; |
143 | mFTFace = NULL; | 141 | mFTFace = NULL; |
142 | |||
143 | mRenderGlyphCount = 0; | ||
144 | mAddGlyphCount = 0; | ||
145 | |||
146 | mPointSize = 0; | ||
144 | } | 147 | } |
145 | 148 | ||
146 | 149 | ||
147 | LLFont::~LLFont() | 150 | LLFont::~LLFont() |
148 | { | 151 | { |
149 | mRawImagep = NULL; // dereferences or deletes image | ||
150 | |||
151 | // Clean up freetype libs. | 152 | // Clean up freetype libs. |
152 | if (mFTFace) | 153 | if (mFTFace) |
153 | FT_Done_Face(mFTFace); | 154 | FT_Done_Face(mFTFace); |
@@ -155,11 +156,8 @@ LLFont::~LLFont() | |||
155 | 156 | ||
156 | // Delete glyph info | 157 | // Delete glyph info |
157 | std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); | 158 | std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); |
158 | } | ||
159 | 159 | ||
160 | void LLFont::setRawImage(LLImageRaw *imagep) | 160 | // mFontBitmapCachep will be cleaned up by LLPointer destructor. |
161 | { | ||
162 | mRawImagep = imagep; // will delete old raw image if we have one and created it | ||
163 | } | 161 | } |
164 | 162 | ||
165 | // virtual | 163 | // virtual |
@@ -203,7 +201,6 @@ BOOL LLFont::loadFace(const std::string& filename, const F32 point_size, const F | |||
203 | } | 201 | } |
204 | 202 | ||
205 | mIsFallback = is_fallback; | 203 | mIsFallback = is_fallback; |
206 | mNumComponents = components; | ||
207 | F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi | 204 | F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi |
208 | 205 | ||
209 | error = FT_Set_Char_Size(mFTFace, /* handle to face object */ | 206 | error = FT_Set_Char_Size(mFTFace, /* handle to face object */ |
@@ -233,8 +230,10 @@ BOOL LLFont::loadFace(const std::string& filename, const F32 point_size, const F | |||
233 | mDescender = -mFTFace->descender * pixels_per_unit; | 230 | mDescender = -mFTFace->descender * pixels_per_unit; |
234 | mLineHeight = mFTFace->height * pixels_per_unit; | 231 | mLineHeight = mFTFace->height * pixels_per_unit; |
235 | 232 | ||
236 | mMaxCharWidth = llround(0.5f + (x_max - x_min)); | 233 | S32 max_char_width = llround(0.5f + (x_max - x_min)); |
237 | mMaxCharHeight = llround(0.5f + (y_max - y_min)); | 234 | S32 max_char_height = llround(0.5f + (y_max - y_min)); |
235 | |||
236 | mFontBitmapCachep->init(components, max_char_width, max_char_height); | ||
238 | 237 | ||
239 | if (!mFTFace->charmap) | 238 | if (!mFTFace->charmap) |
240 | { | 239 | { |
@@ -242,62 +241,20 @@ BOOL LLFont::loadFace(const std::string& filename, const F32 point_size, const F | |||
242 | FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]); | 241 | FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]); |
243 | } | 242 | } |
244 | 243 | ||
245 | if (mRawImagep.isNull() && !mIsFallback) | ||
246 | { | ||
247 | mRawImagep = new LLImageRaw(); | ||
248 | } | ||
249 | |||
250 | if (!mIsFallback) | 244 | if (!mIsFallback) |
251 | { | 245 | { |
252 | // Place text into bitmap, and generate all necessary positions/ | ||
253 | // offsets for the individual characters. | ||
254 | |||
255 | // calc width and height for mRawImagep (holds all characters) | ||
256 | // Guess for approximately 20*20 characters | ||
257 | S32 image_width = mMaxCharWidth * 20; | ||
258 | S32 pow_iw = 2; | ||
259 | while (pow_iw < image_width) | ||
260 | { | ||
261 | pow_iw *= 2; | ||
262 | } | ||
263 | image_width = pow_iw; | ||
264 | image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever. | ||
265 | S32 image_height = image_width; | ||
266 | |||
267 | //llinfos << "Guessing texture size of " << image_width << " pixels square" << llendl; | ||
268 | |||
269 | mRawImagep->resize(image_width, image_height, components); | ||
270 | |||
271 | mBitmapWidth = image_width; | ||
272 | mBitmapHeight = image_height; | ||
273 | |||
274 | switch (components) | ||
275 | { | ||
276 | case 1: | ||
277 | mRawImagep->clear(); | ||
278 | break; | ||
279 | case 2: | ||
280 | mRawImagep->clear(255, 0); | ||
281 | break; | ||
282 | } | ||
283 | |||
284 | mCurrentOffsetX = 1; | ||
285 | mCurrentOffsetY = 1; | ||
286 | |||
287 | // Add the default glyph | 246 | // Add the default glyph |
288 | addGlyph(0, 0); | 247 | addGlyph(0, 0); |
289 | } | 248 | } |
290 | 249 | ||
291 | mName = filename; | 250 | mName = filename; |
251 | mPointSize = point_size; | ||
292 | 252 | ||
293 | return TRUE; | 253 | return TRUE; |
294 | } | 254 | } |
295 | 255 | ||
296 | 256 | void LLFont::resetBitmapCache() | |
297 | void LLFont::resetBitmap() | ||
298 | { | 257 | { |
299 | llinfos << "Rebuilding bitmap for glyph" << llendl; | ||
300 | |||
301 | // Iterate through glyphs and clear the mIsRendered flag | 258 | // Iterate through glyphs and clear the mIsRendered flag |
302 | for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin(); | 259 | for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin(); |
303 | iter != mCharGlyphInfoMap.end(); ++iter) | 260 | iter != mCharGlyphInfoMap.end(); ++iter) |
@@ -307,9 +264,7 @@ void LLFont::resetBitmap() | |||
307 | //not just flushing the bitmap | 264 | //not just flushing the bitmap |
308 | iter->second->mMetricsValid = FALSE; | 265 | iter->second->mMetricsValid = FALSE; |
309 | } | 266 | } |
310 | mRawImagep->clear(255, 0); | 267 | mFontBitmapCachep->reset(); |
311 | mCurrentOffsetX = 1; | ||
312 | mCurrentOffsetY = 1; | ||
313 | 268 | ||
314 | // Add the empty glyph`5 | 269 | // Add the empty glyph`5 |
315 | addGlyph(0, 0); | 270 | addGlyph(0, 0); |
@@ -340,7 +295,7 @@ BOOL LLFont::hasGlyph(const llwchar wch) const | |||
340 | } | 295 | } |
341 | } | 296 | } |
342 | 297 | ||
343 | BOOL LLFont::addChar(const llwchar wch) | 298 | BOOL LLFont::addChar(const llwchar wch) const |
344 | { | 299 | { |
345 | if (mFTFace == NULL) | 300 | if (mFTFace == NULL) |
346 | return FALSE; | 301 | return FALSE; |
@@ -375,7 +330,6 @@ BOOL LLFont::addChar(const llwchar wch) | |||
375 | if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered)) | 330 | if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered)) |
376 | { | 331 | { |
377 | BOOL result = addGlyph(wch, glyph_index); | 332 | BOOL result = addGlyph(wch, glyph_index); |
378 | //imdebug("luma b=8 w=%d h=%d t=%s %p", mRawImagep->getWidth(), mRawImagep->getHeight(), mName.c_str(), mRawImagep->getData()); | ||
379 | return result; | 333 | return result; |
380 | } | 334 | } |
381 | return FALSE; | 335 | return FALSE; |
@@ -395,7 +349,7 @@ void LLFont::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const | |||
395 | } | 349 | } |
396 | } | 350 | } |
397 | 351 | ||
398 | BOOL LLFont::addGlyphFromFont(LLFont *fontp, const llwchar wch, const U32 glyph_index) | 352 | BOOL LLFont::addGlyphFromFont(const LLFont *fontp, const llwchar wch, const U32 glyph_index) const |
399 | { | 353 | { |
400 | if (mFTFace == NULL) | 354 | if (mFTFace == NULL) |
401 | return FALSE; | 355 | return FALSE; |
@@ -405,35 +359,15 @@ BOOL LLFont::addGlyphFromFont(LLFont *fontp, const llwchar wch, const U32 glyph_ | |||
405 | S32 width = fontp->mFTFace->glyph->bitmap.width; | 359 | S32 width = fontp->mFTFace->glyph->bitmap.width; |
406 | S32 height = fontp->mFTFace->glyph->bitmap.rows; | 360 | S32 height = fontp->mFTFace->glyph->bitmap.rows; |
407 | 361 | ||
408 | if ((mCurrentOffsetX + width + 1) > mRawImagep->getWidth()) | 362 | S32 pos_x, pos_y; |
409 | { | 363 | S32 bitmap_num; |
410 | if ((mCurrentOffsetY + 2*mMaxCharHeight + 2) > mBitmapHeight) | 364 | mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num); |
411 | { | 365 | mAddGlyphCount++; |
412 | // We're out of space in this texture - clear it an all of the glyphs | ||
413 | // and start over again. Easier than LRU and should work just as well | ||
414 | // (just slightly slower on the rebuild). As long as the texture has | ||
415 | // enough room to hold all glyphs needed for a particular frame this | ||
416 | // shouldn't be too slow. | ||
417 | |||
418 | resetBitmap(); | ||
419 | |||
420 | // Need to rerender the glyph, as it's been overwritten by the default glyph. | ||
421 | fontp->renderGlyph(glyph_index); | ||
422 | width = fontp->mFTFace->glyph->bitmap.width; | ||
423 | height = fontp->mFTFace->glyph->bitmap.rows; | ||
424 | |||
425 | // We should have a reasonable offset for x and y, no need to check that it's in range | ||
426 | } | ||
427 | else | ||
428 | { | ||
429 | mCurrentOffsetX = 1; | ||
430 | mCurrentOffsetY += mMaxCharHeight + 1; | ||
431 | } | ||
432 | } | ||
433 | 366 | ||
434 | LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); | 367 | LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); |
435 | gi->mXBitmapOffset = mCurrentOffsetX; | 368 | gi->mXBitmapOffset = pos_x; |
436 | gi->mYBitmapOffset = mCurrentOffsetY; | 369 | gi->mYBitmapOffset = pos_y; |
370 | gi->mBitmapNum = bitmap_num; | ||
437 | gi->mWidth = width; | 371 | gi->mWidth = width; |
438 | gi->mHeight = height; | 372 | gi->mHeight = height; |
439 | gi->mXBearing = fontp->mFTFace->glyph->bitmap_left; | 373 | gi->mXBearing = fontp->mFTFace->glyph->bitmap_left; |
@@ -482,24 +416,25 @@ BOOL LLFont::addGlyphFromFont(LLFont *fontp, const llwchar wch, const U32 glyph_ | |||
482 | buffer_row_stride = width; | 416 | buffer_row_stride = width; |
483 | } | 417 | } |
484 | 418 | ||
485 | switch (mNumComponents) | 419 | switch (mFontBitmapCachep->getNumComponents()) |
486 | { | 420 | { |
487 | case 1: | 421 | case 1: |
488 | mRawImagep->setSubImage(mCurrentOffsetX, | 422 | mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x, |
489 | mCurrentOffsetY, | 423 | pos_y, |
490 | width, | 424 | width, |
491 | height, | 425 | height, |
492 | buffer_data, | 426 | buffer_data, |
493 | buffer_row_stride, | 427 | buffer_row_stride, |
494 | TRUE); | 428 | TRUE); |
495 | break; | 429 | break; |
496 | case 2: | 430 | case 2: |
497 | setSubImageLuminanceAlpha(mCurrentOffsetX, | 431 | setSubImageLuminanceAlpha(pos_x, |
498 | mCurrentOffsetY, | 432 | pos_y, |
499 | width, | 433 | bitmap_num, |
500 | height, | 434 | width, |
501 | buffer_data, | 435 | height, |
502 | buffer_row_stride); | 436 | buffer_data, |
437 | buffer_row_stride); | ||
503 | break; | 438 | break; |
504 | default: | 439 | default: |
505 | break; | 440 | break; |
@@ -512,11 +447,10 @@ BOOL LLFont::addGlyphFromFont(LLFont *fontp, const llwchar wch, const U32 glyph_ | |||
512 | // omit it from the font-image. | 447 | // omit it from the font-image. |
513 | } | 448 | } |
514 | 449 | ||
515 | mCurrentOffsetX += width + 1; | ||
516 | return TRUE; | 450 | return TRUE; |
517 | } | 451 | } |
518 | 452 | ||
519 | BOOL LLFont::addGlyph(const llwchar wch, const U32 glyph_index) | 453 | BOOL LLFont::addGlyph(const llwchar wch, const U32 glyph_index) const |
520 | { | 454 | { |
521 | return addGlyphFromFont(this, wch, glyph_index); | 455 | return addGlyphFromFont(this, wch, glyph_index); |
522 | } | 456 | } |
@@ -557,7 +491,7 @@ F32 LLFont::getXAdvance(const llwchar wch) const | |||
557 | if (glyph_index) | 491 | if (glyph_index) |
558 | { | 492 | { |
559 | // This font has this glyph | 493 | // This font has this glyph |
560 | (const_cast<LLFont *>(fontp))->renderGlyph(glyph_index); | 494 | fontp->renderGlyph(glyph_index); |
561 | 495 | ||
562 | // Create the entry if it's not there | 496 | // Create the entry if it's not there |
563 | char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch); | 497 | char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch); |
@@ -590,11 +524,11 @@ F32 LLFont::getXAdvance(const llwchar wch) const | |||
590 | } | 524 | } |
591 | 525 | ||
592 | // Last ditch fallback - no glyphs defined at all. | 526 | // Last ditch fallback - no glyphs defined at all. |
593 | return (F32)mMaxCharWidth; | 527 | return (F32)mFontBitmapCachep->getMaxCharWidth(); |
594 | } | 528 | } |
595 | 529 | ||
596 | 530 | ||
597 | void LLFont::renderGlyph(const U32 glyph_index) | 531 | void LLFont::renderGlyph(const U32 glyph_index) const |
598 | { | 532 | { |
599 | if (mFTFace == NULL) | 533 | if (mFTFace == NULL) |
600 | return; | 534 | return; |
@@ -603,6 +537,9 @@ void LLFont::renderGlyph(const U32 glyph_index) | |||
603 | llassert(!error); | 537 | llassert(!error); |
604 | 538 | ||
605 | error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode); | 539 | error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode); |
540 | |||
541 | mRenderGlyphCount++; | ||
542 | |||
606 | llassert(!error); | 543 | llassert(!error); |
607 | } | 544 | } |
608 | 545 | ||
@@ -627,16 +564,20 @@ F32 LLFont::getXKerning(const llwchar char_left, const llwchar char_right) const | |||
627 | } | 564 | } |
628 | 565 | ||
629 | void LLFont::setSubImageLuminanceAlpha(const U32 x, | 566 | void LLFont::setSubImageLuminanceAlpha(const U32 x, |
630 | const U32 y, | 567 | const U32 y, |
631 | const U32 width, | 568 | const U32 bitmap_num, |
632 | const U32 height, | 569 | const U32 width, |
633 | const U8 *data, | 570 | const U32 height, |
634 | S32 stride) | 571 | const U8 *data, |
572 | S32 stride) const | ||
635 | { | 573 | { |
574 | LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); | ||
575 | |||
636 | llassert(!mIsFallback); | 576 | llassert(!mIsFallback); |
637 | llassert(mRawImagep->getComponents() == 2); | 577 | llassert(image_raw && (image_raw->getComponents() == 2)); |
638 | 578 | ||
639 | U8 *target = mRawImagep->getData(); | 579 | |
580 | U8 *target = image_raw->getData(); | ||
640 | 581 | ||
641 | if (!data) | 582 | if (!data) |
642 | { | 583 | { |
@@ -649,7 +590,7 @@ void LLFont::setSubImageLuminanceAlpha(const U32 x, | |||
649 | U32 i, j; | 590 | U32 i, j; |
650 | U32 to_offset; | 591 | U32 to_offset; |
651 | U32 from_offset; | 592 | U32 from_offset; |
652 | U32 target_width = mRawImagep->getWidth(); | 593 | U32 target_width = image_raw->getWidth(); |
653 | for (i = 0; i < height; i++) | 594 | for (i = 0; i < height; i++) |
654 | { | 595 | { |
655 | to_offset = (y + i)*target_width + x; | 596 | to_offset = (y + i)*target_width + x; |
diff --git a/linden/indra/llrender/llfont.h b/linden/indra/llrender/llfont.h index bce8d76..b423f7d 100644 --- a/linden/indra/llrender/llfont.h +++ b/linden/indra/llrender/llfont.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -37,6 +38,9 @@ | |||
37 | #include "llmemory.h" | 38 | #include "llmemory.h" |
38 | #include "llstl.h" | 39 | #include "llstl.h" |
39 | 40 | ||
41 | #include "llimagegl.h" | ||
42 | #include "llfontbitmapcache.h" | ||
43 | |||
40 | class LLImageRaw; | 44 | class LLImageRaw; |
41 | class LLFontManager; | 45 | class LLFontManager; |
42 | class LLFont; | 46 | class LLFont; |
@@ -80,6 +84,7 @@ public: | |||
80 | S32 mYBitmapOffset; // Offset to the origin in the bitmap | 84 | S32 mYBitmapOffset; // Offset to the origin in the bitmap |
81 | S32 mXBearing; // Distance from baseline to left in pixels | 85 | S32 mXBearing; // Distance from baseline to left in pixels |
82 | S32 mYBearing; // Distance from baseline to top in pixels | 86 | S32 mYBearing; // Distance from baseline to top in pixels |
87 | S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph | ||
83 | }; | 88 | }; |
84 | 89 | ||
85 | // Used for lists of fallback fonts | 90 | // Used for lists of fallback fonts |
@@ -91,14 +96,14 @@ public: | |||
91 | void addAtEnd(LLFont *font); | 96 | void addAtEnd(LLFont *font); |
92 | }; | 97 | }; |
93 | 98 | ||
94 | |||
95 | class LLFont | 99 | class LLFont |
96 | { | 100 | { |
97 | public: | 101 | public: |
98 | LLFont(LLImageRaw *imagep = NULL); | 102 | LLFont(); |
99 | virtual ~LLFont(); | 103 | virtual ~LLFont(); |
100 | 104 | ||
101 | // is_fallback should be true for fallback fonts that aren't used to render directly (Unicode backup, primarily) | 105 | // is_fallback should be true for fallback fonts that aren't used |
106 | // to render directly (Unicode backup, primarily) | ||
102 | virtual BOOL loadFace(const std::string& filename, | 107 | virtual BOOL loadFace(const std::string& filename, |
103 | const F32 point_size, | 108 | const F32 point_size, |
104 | const F32 vert_dpi, | 109 | const F32 vert_dpi, |
@@ -108,7 +113,6 @@ public: | |||
108 | void setFallbackFont(LLFontList *fontp) { mFallbackFontp = fontp; } | 113 | void setFallbackFont(LLFontList *fontp) { mFallbackFontp = fontp; } |
109 | 114 | ||
110 | void setCharToGlyphMap(llwchar wch, U32 glyph_index) const; | 115 | void setCharToGlyphMap(llwchar wch, U32 glyph_index) const; |
111 | void setRawImage( LLImageRaw *imagep ); | ||
112 | 116 | ||
113 | // Global font metrics - in units of pixels | 117 | // Global font metrics - in units of pixels |
114 | virtual F32 getLineHeight() const; | 118 | virtual F32 getLineHeight() const; |
@@ -145,31 +149,29 @@ public: | |||
145 | const LLFontGlyphInfo &getMetrics(const llwchar wc) const; | 149 | const LLFontGlyphInfo &getMetrics(const llwchar wc) const; |
146 | F32 getXAdvance(const llwchar wc) const; | 150 | F32 getXAdvance(const llwchar wc) const; |
147 | F32 getXKerning(const llwchar char_left, const llwchar char_right) const; // Get the kerning between the two characters | 151 | F32 getXKerning(const llwchar char_left, const llwchar char_right) const; // Get the kerning between the two characters |
152 | virtual void reset() = 0; | ||
153 | |||
148 | protected: | 154 | protected: |
149 | virtual BOOL hasGlyph(const llwchar wch) const; // Has a glyph for this character | 155 | virtual BOOL hasGlyph(const llwchar wch) const; // Has a glyph for this character |
150 | virtual BOOL addChar(const llwchar wch); // Add a new character to the font if necessary | 156 | virtual BOOL addChar(const llwchar wch) const; // Add a new character to the font if necessary |
151 | virtual BOOL addGlyph(const llwchar wch, const U32 glyph_index); // Add a new glyph to the existing font | 157 | virtual BOOL addGlyph(const llwchar wch, const U32 glyph_index) const; // Add a new glyph to the existing font |
152 | virtual BOOL addGlyphFromFont(LLFont *fontp, const llwchar wch, const U32 glyph_index); // Add a glyph from this font to the other (returns the glyph_index, 0 if not found) | 158 | virtual BOOL addGlyphFromFont(const LLFont *fontp, const llwchar wch, const U32 glyph_index) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found) |
153 | 159 | ||
154 | virtual LLFontGlyphInfo* getGlyphInfo(const llwchar wch) const; | 160 | virtual LLFontGlyphInfo* getGlyphInfo(const llwchar wch) const; |
155 | 161 | ||
156 | void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; | 162 | void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; |
157 | void renderGlyph(const U32 glyph_index); | 163 | void renderGlyph(const U32 glyph_index) const; |
164 | |||
165 | void resetBitmapCache(); | ||
158 | 166 | ||
159 | void resetBitmap(); // Reset bitmap to contain only the null glyph | ||
160 | protected: | 167 | protected: |
161 | std::string mName; | 168 | std::string mName; |
169 | F32 mPointSize; | ||
162 | F32 mAscender; | 170 | F32 mAscender; |
163 | F32 mDescender; | 171 | F32 mDescender; |
164 | F32 mLineHeight; | 172 | F32 mLineHeight; |
165 | 173 | ||
166 | S32 mNumComponents; | 174 | mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep; |
167 | S32 mBitmapWidth; | ||
168 | S32 mBitmapHeight; | ||
169 | S32 mMaxCharWidth; | ||
170 | S32 mMaxCharHeight; | ||
171 | S32 mCurrentOffsetX; | ||
172 | S32 mCurrentOffsetY; | ||
173 | 175 | ||
174 | LLFT_Face mFTFace; | 176 | LLFT_Face mFTFace; |
175 | 177 | ||
@@ -181,14 +183,14 @@ protected: | |||
181 | 183 | ||
182 | BOOL mValid; | 184 | BOOL mValid; |
183 | void setSubImageLuminanceAlpha(const U32 x, | 185 | void setSubImageLuminanceAlpha(const U32 x, |
184 | const U32 y, | 186 | const U32 y, |
185 | const U32 width, | 187 | const U32 bitmap_num, |
186 | const U32 height, | 188 | const U32 width, |
187 | const U8 *data, | 189 | const U32 height, |
188 | S32 stride = 0); | 190 | const U8 *data, |
189 | 191 | S32 stride = 0) const; | |
190 | private: | 192 | mutable S32 mRenderGlyphCount; |
191 | LLPointer<LLImageRaw> mRawImagep; // Bitmaps of glyphs are stored here. | 193 | mutable S32 mAddGlyphCount; |
192 | }; | 194 | }; |
193 | 195 | ||
194 | #endif // LL_FONT_ | 196 | #endif // LL_FONT_ |
diff --git a/linden/indra/llrender/llfontbitmapcache.cpp b/linden/indra/llrender/llfontbitmapcache.cpp new file mode 100644 index 0000000..052510e --- /dev/null +++ b/linden/indra/llrender/llfontbitmapcache.cpp | |||
@@ -0,0 +1,169 @@ | |||
1 | /** | ||
2 | * @file llfontbitmapcache.cpp | ||
3 | * @brief Storage for previously rendered glyphs. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | |||
35 | #include "llgl.h" | ||
36 | #include "llfontbitmapcache.h" | ||
37 | |||
38 | LLFontBitmapCache::LLFontBitmapCache(): | ||
39 | mNumComponents(0), | ||
40 | mMaxCharWidth(0), | ||
41 | mMaxCharHeight(0), | ||
42 | mBitmapWidth(0), | ||
43 | mBitmapHeight(0), | ||
44 | mCurrentOffsetX(1), | ||
45 | mCurrentOffsetY(1), | ||
46 | mCurrentBitmapNum(-1) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | LLFontBitmapCache::~LLFontBitmapCache() | ||
51 | { | ||
52 | } | ||
53 | |||
54 | void LLFontBitmapCache::init(S32 num_components, | ||
55 | S32 max_char_width, | ||
56 | S32 max_char_height) | ||
57 | { | ||
58 | reset(); | ||
59 | |||
60 | mNumComponents = num_components; | ||
61 | mMaxCharWidth = max_char_width; | ||
62 | mMaxCharHeight = max_char_height; | ||
63 | } | ||
64 | |||
65 | LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const | ||
66 | { | ||
67 | if ((bitmap_num < 0) || (bitmap_num >= mImageRawVec.size())) | ||
68 | return NULL; | ||
69 | |||
70 | return mImageRawVec[bitmap_num]; | ||
71 | } | ||
72 | |||
73 | LLImageGL *LLFontBitmapCache::getImageGL(U32 bitmap_num) const | ||
74 | { | ||
75 | if ((bitmap_num < 0) || (bitmap_num >= mImageGLVec.size())) | ||
76 | return NULL; | ||
77 | |||
78 | return mImageGLVec[bitmap_num]; | ||
79 | } | ||
80 | |||
81 | |||
82 | BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32 &pos_x, S32 &pos_y, S32& bitmap_num) | ||
83 | { | ||
84 | if ((mBitmapNum<0) || (mCurrentOffsetX + width + 1) > mBitmapWidth) | ||
85 | { | ||
86 | if ((mBitmapNum<0) || (mCurrentOffsetY + 2*mMaxCharHeight + 2) > mBitmapHeight) | ||
87 | { | ||
88 | // We're out of space in the current image, or no image | ||
89 | // has been allocated yet. Make a new one. | ||
90 | mImageRawVec.push_back(new LLImageRaw); | ||
91 | mBitmapNum = mImageRawVec.size()-1; | ||
92 | LLImageRaw *image_raw = getImageRaw(mBitmapNum); | ||
93 | |||
94 | // Make corresponding GL image. | ||
95 | mImageGLVec.push_back(new LLImageGL(FALSE)); | ||
96 | LLImageGL *image_gl = getImageGL(mBitmapNum); | ||
97 | |||
98 | S32 image_width = mMaxCharWidth * 20; | ||
99 | S32 pow_iw = 2; | ||
100 | while (pow_iw < image_width) | ||
101 | { | ||
102 | pow_iw *= 2; | ||
103 | } | ||
104 | image_width = pow_iw; | ||
105 | image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever. | ||
106 | S32 image_height = image_width; | ||
107 | |||
108 | image_raw->resize(image_width, image_height, mNumComponents); | ||
109 | |||
110 | mBitmapWidth = image_width; | ||
111 | mBitmapHeight = image_height; | ||
112 | |||
113 | switch (mNumComponents) | ||
114 | { | ||
115 | case 1: | ||
116 | image_raw->clear(); | ||
117 | break; | ||
118 | case 2: | ||
119 | image_raw->clear(255, 0); | ||
120 | break; | ||
121 | } | ||
122 | |||
123 | // Start at beginning of the new image. | ||
124 | mCurrentOffsetX = 1; | ||
125 | mCurrentOffsetY = 1; | ||
126 | |||
127 | // Attach corresponding GL texture. | ||
128 | image_gl->createGLTexture(0, image_raw); | ||
129 | gGL.getTexUnit(0)->bind(image_gl); | ||
130 | image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE); | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | // Move to next row in current image. | ||
135 | mCurrentOffsetX = 1; | ||
136 | mCurrentOffsetY += mMaxCharHeight + 1; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | pos_x = mCurrentOffsetX; | ||
141 | pos_y = mCurrentOffsetY; | ||
142 | bitmap_num = mBitmapNum; | ||
143 | |||
144 | mCurrentOffsetX += width + 1; | ||
145 | |||
146 | return TRUE; | ||
147 | } | ||
148 | |||
149 | void LLFontBitmapCache::destroyGL() | ||
150 | { | ||
151 | for (std::vector<LLPointer<LLImageGL> >::iterator it = mImageGLVec.begin(); | ||
152 | it != mImageGLVec.end(); ++it) | ||
153 | { | ||
154 | (*it)->destroyGLTexture(); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | void LLFontBitmapCache::reset() | ||
159 | { | ||
160 | mImageRawVec.clear(); | ||
161 | mImageGLVec.clear(); | ||
162 | |||
163 | mBitmapWidth = 0, | ||
164 | mBitmapHeight = 0, | ||
165 | mCurrentOffsetX = 0, | ||
166 | mCurrentOffsetY = 0, | ||
167 | mCurrentBitmapNum = -1; | ||
168 | } | ||
169 | |||
diff --git a/linden/indra/llrender/llfontbitmapcache.h b/linden/indra/llrender/llfontbitmapcache.h new file mode 100644 index 0000000..4beea0d --- /dev/null +++ b/linden/indra/llrender/llfontbitmapcache.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /** | ||
2 | * @file llfontbitmapcache.h | ||
3 | * @brief Storage for previously rendered glyphs. | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #ifndef LL_LLFONTBITMAPCACHE_H | ||
34 | #define LL_LLFONTBITMAPCACHE_H | ||
35 | |||
36 | #include <vector> | ||
37 | |||
38 | // Maintain a collection of bitmaps containing rendered glyphs. | ||
39 | // Generalizes the single-bitmap logic from LLFont and LLFontGL. | ||
40 | class LLFontBitmapCache: public LLRefCount | ||
41 | { | ||
42 | public: | ||
43 | LLFontBitmapCache(); | ||
44 | ~LLFontBitmapCache(); | ||
45 | |||
46 | // Need to call this once, before caching any glyphs. | ||
47 | void init(S32 num_components, | ||
48 | S32 max_char_width, | ||
49 | S32 max_char_height); | ||
50 | |||
51 | void reset(); | ||
52 | |||
53 | BOOL nextOpenPos(S32 width, S32 &posX, S32 &posY, S32 &bitmapNum); | ||
54 | |||
55 | void destroyGL(); | ||
56 | |||
57 | LLImageRaw *getImageRaw(U32 bitmapNum = 0) const; | ||
58 | LLImageGL *getImageGL(U32 bitmapNum = 0) const; | ||
59 | |||
60 | S32 getMaxCharWidth() const { return mMaxCharWidth; } | ||
61 | S32 getNumComponents() const { return mNumComponents; } | ||
62 | S32 getBitmapWidth() const { return mBitmapWidth; } | ||
63 | S32 getBitmapHeight() const { return mBitmapHeight; } | ||
64 | |||
65 | private: | ||
66 | S32 mNumComponents; | ||
67 | S32 mBitmapWidth; | ||
68 | S32 mBitmapHeight; | ||
69 | S32 mBitmapNum; | ||
70 | S32 mMaxCharWidth; | ||
71 | S32 mMaxCharHeight; | ||
72 | S32 mCurrentOffsetX; | ||
73 | S32 mCurrentOffsetY; | ||
74 | S32 mCurrentBitmapNum; | ||
75 | std::vector<LLPointer<LLImageRaw> > mImageRawVec; | ||
76 | std::vector<LLPointer<LLImageGL> > mImageGLVec; | ||
77 | }; | ||
78 | |||
79 | #endif //LL_LLFONTBITMAPCACHE_H | ||
diff --git a/linden/indra/llrender/llfontgl.cpp b/linden/indra/llrender/llfontgl.cpp index 526f1a9..beecb6b 100644 --- a/linden/indra/llrender/llfontgl.cpp +++ b/linden/indra/llrender/llfontgl.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -35,6 +36,8 @@ | |||
35 | 36 | ||
36 | #include "llfont.h" | 37 | #include "llfont.h" |
37 | #include "llfontgl.h" | 38 | #include "llfontgl.h" |
39 | #include "llfontbitmapcache.h" | ||
40 | #include "llfontregistry.h" | ||
38 | #include "llgl.h" | 41 | #include "llgl.h" |
39 | #include "llrender.h" | 42 | #include "llrender.h" |
40 | #include "v4color.h" | 43 | #include "v4color.h" |
@@ -50,32 +53,19 @@ F32 LLFontGL::sScaleY = 1.f; | |||
50 | BOOL LLFontGL::sDisplayFont = TRUE ; | 53 | BOOL LLFontGL::sDisplayFont = TRUE ; |
51 | std::string LLFontGL::sAppDir; | 54 | std::string LLFontGL::sAppDir; |
52 | 55 | ||
53 | LLFontGL* LLFontGL::sMonospace = NULL; | ||
54 | LLFontGL* LLFontGL::sSansSerifSmall = NULL; | ||
55 | LLFontGL* LLFontGL::sSansSerif = NULL; | ||
56 | LLFontGL* LLFontGL::sSansSerifBig = NULL; | ||
57 | LLFontGL* LLFontGL::sSansSerifHuge = NULL; | ||
58 | LLFontGL* LLFontGL::sSansSerifBold = NULL; | ||
59 | LLFontList* LLFontGL::sMonospaceFallback = NULL; | ||
60 | LLFontList* LLFontGL::sSSFallback = NULL; | ||
61 | LLFontList* LLFontGL::sSSSmallFallback = NULL; | ||
62 | LLFontList* LLFontGL::sSSBigFallback = NULL; | ||
63 | LLFontList* LLFontGL::sSSHugeFallback = NULL; | ||
64 | LLFontList* LLFontGL::sSSBoldFallback = NULL; | ||
65 | LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f); | 56 | LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f); |
57 | LLFontRegistry* LLFontGL::sFontRegistry = NULL; | ||
66 | 58 | ||
67 | LLCoordFont LLFontGL::sCurOrigin; | 59 | LLCoordFont LLFontGL::sCurOrigin; |
68 | std::vector<LLCoordFont> LLFontGL::sOriginStack; | 60 | std::vector<LLCoordFont> LLFontGL::sOriginStack; |
69 | 61 | ||
70 | LLFontGL*& gExtCharFont = LLFontGL::sSansSerif; | ||
71 | |||
72 | const F32 EXT_X_BEARING = 1.f; | 62 | const F32 EXT_X_BEARING = 1.f; |
73 | const F32 EXT_Y_BEARING = 0.f; | 63 | const F32 EXT_Y_BEARING = 0.f; |
74 | const F32 EXT_KERNING = 1.f; | 64 | const F32 EXT_KERNING = 1.f; |
75 | const F32 PIXEL_BORDER_THRESHOLD = 0.0001f; | 65 | const F32 PIXEL_BORDER_THRESHOLD = 0.0001f; |
76 | const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; | 66 | const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; |
77 | 67 | ||
78 | const F32 PAD_AMT = 0.5f; | 68 | const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture |
79 | const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; | 69 | const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; |
80 | 70 | ||
81 | F32 llfont_round_x(F32 x) | 71 | F32 llfont_round_x(F32 x) |
@@ -126,7 +116,6 @@ U8 LLFontGL::getStyleFromString(const std::string &style) | |||
126 | LLFontGL::LLFontGL() | 116 | LLFontGL::LLFontGL() |
127 | : LLFont() | 117 | : LLFont() |
128 | { | 118 | { |
129 | init(); | ||
130 | clearEmbeddedChars(); | 119 | clearEmbeddedChars(); |
131 | } | 120 | } |
132 | 121 | ||
@@ -137,32 +126,30 @@ LLFontGL::LLFontGL(const LLFontGL &source) | |||
137 | 126 | ||
138 | LLFontGL::~LLFontGL() | 127 | LLFontGL::~LLFontGL() |
139 | { | 128 | { |
140 | mImageGLp = NULL; | ||
141 | mRawImageGLp = NULL; | ||
142 | clearEmbeddedChars(); | 129 | clearEmbeddedChars(); |
143 | } | 130 | } |
144 | 131 | ||
145 | void LLFontGL::init() | 132 | void LLFontGL::reset() |
146 | { | 133 | { |
147 | if (mImageGLp.isNull()) | 134 | if (!mIsFallback) |
148 | { | ||
149 | mImageGLp = new LLImageGL(FALSE); | ||
150 | //RN: use nearest mipmap filtering to obviate the need to do pixel-accurate positioning | ||
151 | gGL.getTexUnit(0)->bind(mImageGLp); | ||
152 | // we allow bilinear filtering to get sub-pixel positioning for drop shadows | ||
153 | //mImageGLp->setMipFilterNearest(TRUE, TRUE); | ||
154 | } | ||
155 | if (mRawImageGLp.isNull()) | ||
156 | { | 135 | { |
157 | mRawImageGLp = new LLImageRaw; // Note LLFontGL owns the image, not LLFont. | 136 | // This is the head of the list - need to rebuild ourself and all fallbacks. |
137 | loadFace(mName,mPointSize,sVertDPI,sHorizDPI,mFontBitmapCachep->getNumComponents(),mIsFallback); | ||
138 | if (mFallbackFontp==NULL) | ||
139 | { | ||
140 | llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | for (LLFontList::iterator it = mFallbackFontp->begin(); | ||
145 | it != mFallbackFontp->end(); | ||
146 | ++it) | ||
147 | { | ||
148 | (*it)->reset(); | ||
149 | } | ||
150 | } | ||
158 | } | 151 | } |
159 | setRawImage( mRawImageGLp ); | 152 | resetBitmapCache(); |
160 | } | ||
161 | |||
162 | void LLFontGL::reset() | ||
163 | { | ||
164 | init(); | ||
165 | resetBitmap(); | ||
166 | } | 153 | } |
167 | 154 | ||
168 | // static | 155 | // static |
@@ -219,243 +206,48 @@ std::string LLFontGL::getFontPathLocal() | |||
219 | return local_path; | 206 | return local_path; |
220 | } | 207 | } |
221 | 208 | ||
222 | //static | 209 | bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc) |
223 | bool LLFontGL::loadFaceFallback(LLFontList *fontlistp, const std::string& fontname, const F32 point_size) | ||
224 | { | 210 | { |
225 | std::string local_path = getFontPathLocal(); | 211 | // Don't delete existing fonts, if any, here, because they've |
226 | std::string sys_path = getFontPathSystem(); | 212 | // already been deleted by LLFontRegistry::clear() |
227 | 213 | fontp = LLFontGL::getFont(desc); | |
228 | // The fontname string may contain multiple font file names separated by semicolons. | 214 | return (fontp != NULL); |
229 | // Break it apart and try loading each one, in order. | ||
230 | typedef boost::tokenizer<boost::char_separator<char> > tokenizer; | ||
231 | boost::char_separator<char> sep(";"); | ||
232 | tokenizer tokens(fontname, sep); | ||
233 | tokenizer::iterator token_iter; | ||
234 | |||
235 | for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) | ||
236 | { | ||
237 | LLFont *fontp = new LLFont(); | ||
238 | std::string font_path = local_path + *token_iter; | ||
239 | if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, TRUE)) | ||
240 | { | ||
241 | font_path = sys_path + *token_iter; | ||
242 | if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, TRUE)) | ||
243 | { | ||
244 | LL_INFOS_ONCE("ViewerImages") << "Couldn't load font " << *token_iter << LL_ENDL; | ||
245 | delete fontp; | ||
246 | fontp = NULL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | if(fontp) | ||
251 | { | ||
252 | fontlistp->addAtEnd(fontp); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | // We want to return true if at least one fallback font loaded correctly. | ||
257 | return (fontlistp->size() > 0); | ||
258 | } | 215 | } |
259 | 216 | ||
260 | //static | ||
261 | bool LLFontGL::loadFace(LLFontGL *fontp, const std::string& fontname, const F32 point_size, LLFontList *fallback_fontp) | ||
262 | { | ||
263 | std::string local_path = getFontPathLocal(); | ||
264 | std::string font_path = local_path + fontname; | ||
265 | if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, FALSE)) | ||
266 | { | ||
267 | std::string sys_path = getFontPathSystem(); | ||
268 | font_path = sys_path + fontname; | ||
269 | if (!fontp->loadFace(font_path, point_size, sVertDPI, sHorizDPI, 2, FALSE)) | ||
270 | { | ||
271 | LL_WARNS("ViewerImages") << "Couldn't load font " << fontname << LL_ENDL; | ||
272 | return false; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | fontp->setFallbackFont(fallback_fontp); | ||
277 | return true; | ||
278 | } | ||
279 | |||
280 | |||
281 | // static | 217 | // static |
282 | BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, | 218 | BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, |
283 | const std::string& monospace_file, F32 monospace_size, | 219 | const std::string& app_dir, |
284 | const std::string& sansserif_file, | 220 | const std::vector<std::string>& xui_paths) |
285 | const std::string& sanserif_fallback_file, F32 ss_fallback_scale, | ||
286 | F32 small_size, F32 medium_size, F32 big_size, F32 huge_size, | ||
287 | const std::string& sansserif_bold_file, F32 bold_size, | ||
288 | const std::string& app_dir) | ||
289 | { | 221 | { |
290 | BOOL failed = FALSE; | 222 | bool succ = true; |
291 | sVertDPI = (F32)llfloor(screen_dpi * y_scale); | 223 | sVertDPI = (F32)llfloor(screen_dpi * y_scale); |
292 | sHorizDPI = (F32)llfloor(screen_dpi * x_scale); | 224 | sHorizDPI = (F32)llfloor(screen_dpi * x_scale); |
293 | sScaleX = x_scale; | 225 | sScaleX = x_scale; |
294 | sScaleY = y_scale; | 226 | sScaleY = y_scale; |
295 | sAppDir = app_dir; | 227 | sAppDir = app_dir; |
296 | 228 | ||
297 | // | 229 | // Font registry init |
298 | // Monospace font | 230 | if (!sFontRegistry) |
299 | // | ||
300 | |||
301 | if (!sMonospace) | ||
302 | { | 231 | { |
303 | sMonospace = new LLFontGL(); | 232 | sFontRegistry = new LLFontRegistry(xui_paths); |
233 | sFontRegistry->parseFontInfo("fonts.xml"); | ||
304 | } | 234 | } |
305 | else | 235 | else |
306 | { | 236 | { |
307 | sMonospace->reset(); | 237 | sFontRegistry->reset(); |
308 | } | ||
309 | |||
310 | if (sMonospaceFallback) | ||
311 | { | ||
312 | delete sMonospaceFallback; | ||
313 | } | ||
314 | sMonospaceFallback = new LLFontList(); | ||
315 | if (!loadFaceFallback( | ||
316 | sMonospaceFallback, | ||
317 | sanserif_fallback_file, | ||
318 | monospace_size * ss_fallback_scale)) | ||
319 | { | ||
320 | delete sMonospaceFallback; | ||
321 | sMonospaceFallback = NULL; | ||
322 | } | 238 | } |
323 | 239 | ||
324 | failed |= !loadFace(sMonospace, monospace_file, monospace_size, sMonospaceFallback); | 240 | // Force standard fonts to get generated up front. |
325 | 241 | // This is primarily for error detection purposes. | |
326 | // | 242 | succ &= (NULL != getFontSansSerifSmall()); |
327 | // Sans-serif fonts | 243 | succ &= (NULL != getFontSansSerif()); |
328 | // | 244 | succ &= (NULL != getFontSansSerifBig()); |
329 | if(!sSansSerifHuge) | 245 | succ &= (NULL != getFontSansSerifHuge()); |
330 | { | 246 | succ &= (NULL != getFontSansSerifBold()); |
331 | sSansSerifHuge = new LLFontGL(); | 247 | succ &= (NULL != getFontMonospace()); |
332 | } | 248 | succ &= (NULL != getFontExtChar()); |
333 | else | 249 | |
334 | { | 250 | return succ; |
335 | sSansSerifHuge->reset(); | ||
336 | } | ||
337 | |||
338 | if (sSSHugeFallback) | ||
339 | { | ||
340 | delete sSSHugeFallback; | ||
341 | } | ||
342 | sSSHugeFallback = new LLFontList(); | ||
343 | if (!loadFaceFallback( | ||
344 | sSSHugeFallback, | ||
345 | sanserif_fallback_file, | ||
346 | huge_size*ss_fallback_scale)) | ||
347 | { | ||
348 | delete sSSHugeFallback; | ||
349 | sSSHugeFallback = NULL; | ||
350 | } | ||
351 | |||
352 | failed |= !loadFace(sSansSerifHuge, sansserif_file, huge_size, sSSHugeFallback); | ||
353 | |||
354 | |||
355 | if(!sSansSerifBig) | ||
356 | { | ||
357 | sSansSerifBig = new LLFontGL(); | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | sSansSerifBig->reset(); | ||
362 | } | ||
363 | |||
364 | if (sSSBigFallback) | ||
365 | { | ||
366 | delete sSSBigFallback; | ||
367 | } | ||
368 | sSSBigFallback = new LLFontList(); | ||
369 | if (!loadFaceFallback( | ||
370 | sSSBigFallback, | ||
371 | sanserif_fallback_file, | ||
372 | big_size*ss_fallback_scale)) | ||
373 | { | ||
374 | delete sSSBigFallback; | ||
375 | sSSBigFallback = NULL; | ||
376 | } | ||
377 | |||
378 | failed |= !loadFace(sSansSerifBig, sansserif_file, big_size, sSSBigFallback); | ||
379 | |||
380 | |||
381 | if(!sSansSerif) | ||
382 | { | ||
383 | sSansSerif = new LLFontGL(); | ||
384 | } | ||
385 | else | ||
386 | { | ||
387 | sSansSerif->reset(); | ||
388 | } | ||
389 | |||
390 | if (sSSFallback) | ||
391 | { | ||
392 | delete sSSFallback; | ||
393 | } | ||
394 | sSSFallback = new LLFontList(); | ||
395 | if (!loadFaceFallback( | ||
396 | sSSFallback, | ||
397 | sanserif_fallback_file, | ||
398 | medium_size*ss_fallback_scale)) | ||
399 | { | ||
400 | delete sSSFallback; | ||
401 | sSSFallback = NULL; | ||
402 | } | ||
403 | failed |= !loadFace(sSansSerif, sansserif_file, medium_size, sSSFallback); | ||
404 | |||
405 | |||
406 | if(!sSansSerifSmall) | ||
407 | { | ||
408 | sSansSerifSmall = new LLFontGL(); | ||
409 | } | ||
410 | else | ||
411 | { | ||
412 | sSansSerifSmall->reset(); | ||
413 | } | ||
414 | |||
415 | if(sSSSmallFallback) | ||
416 | { | ||
417 | delete sSSSmallFallback; | ||
418 | } | ||
419 | sSSSmallFallback = new LLFontList(); | ||
420 | if (!loadFaceFallback( | ||
421 | sSSSmallFallback, | ||
422 | sanserif_fallback_file, | ||
423 | small_size*ss_fallback_scale)) | ||
424 | { | ||
425 | delete sSSSmallFallback; | ||
426 | sSSSmallFallback = NULL; | ||
427 | } | ||
428 | failed |= !loadFace(sSansSerifSmall, sansserif_file, small_size, sSSSmallFallback); | ||
429 | |||
430 | |||
431 | // | ||
432 | // Sans-serif bold | ||
433 | // | ||
434 | if(!sSansSerifBold) | ||
435 | { | ||
436 | sSansSerifBold = new LLFontGL(); | ||
437 | } | ||
438 | else | ||
439 | { | ||
440 | sSansSerifBold->reset(); | ||
441 | } | ||
442 | |||
443 | if (sSSBoldFallback) | ||
444 | { | ||
445 | delete sSSBoldFallback; | ||
446 | } | ||
447 | sSSBoldFallback = new LLFontList(); | ||
448 | if (!loadFaceFallback( | ||
449 | sSSBoldFallback, | ||
450 | sanserif_fallback_file, | ||
451 | medium_size*ss_fallback_scale)) | ||
452 | { | ||
453 | delete sSSBoldFallback; | ||
454 | sSSBoldFallback = NULL; | ||
455 | } | ||
456 | failed |= !loadFace(sSansSerifBold, sansserif_bold_file, medium_size, sSSBoldFallback); | ||
457 | |||
458 | return !failed; | ||
459 | } | 251 | } |
460 | 252 | ||
461 | 253 | ||
@@ -463,57 +255,23 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, | |||
463 | // static | 255 | // static |
464 | void LLFontGL::destroyDefaultFonts() | 256 | void LLFontGL::destroyDefaultFonts() |
465 | { | 257 | { |
466 | delete sMonospace; | 258 | // Remove the actual fonts. |
467 | sMonospace = NULL; | 259 | delete sFontRegistry; |
468 | 260 | sFontRegistry = NULL; | |
469 | delete sSansSerifHuge; | ||
470 | sSansSerifHuge = NULL; | ||
471 | |||
472 | delete sSansSerifBig; | ||
473 | sSansSerifBig = NULL; | ||
474 | |||
475 | delete sSansSerif; | ||
476 | sSansSerif = NULL; | ||
477 | |||
478 | delete sSansSerifSmall; | ||
479 | sSansSerifSmall = NULL; | ||
480 | |||
481 | delete sSansSerifBold; | ||
482 | sSansSerifBold = NULL; | ||
483 | |||
484 | delete sMonospaceFallback; | ||
485 | sMonospaceFallback = NULL; | ||
486 | |||
487 | delete sSSHugeFallback; | ||
488 | sSSHugeFallback = NULL; | ||
489 | |||
490 | delete sSSBigFallback; | ||
491 | sSSBigFallback = NULL; | ||
492 | |||
493 | delete sSSFallback; | ||
494 | sSSFallback = NULL; | ||
495 | |||
496 | delete sSSSmallFallback; | ||
497 | sSSSmallFallback = NULL; | ||
498 | |||
499 | delete sSSBoldFallback; | ||
500 | sSSBoldFallback = NULL; | ||
501 | } | 261 | } |
502 | 262 | ||
503 | //static | 263 | //static |
504 | void LLFontGL::destroyGL() | 264 | void LLFontGL::destroyAllGL() |
505 | { | 265 | { |
506 | if (!sMonospace) | 266 | if (sFontRegistry) |
507 | { | 267 | { |
508 | // Already all destroyed. | 268 | sFontRegistry->destroyGL(); |
509 | return; | ||
510 | } | 269 | } |
511 | sMonospace->mImageGLp->destroyGLTexture(); | 270 | } |
512 | sSansSerifHuge->mImageGLp->destroyGLTexture(); | 271 | |
513 | sSansSerifSmall->mImageGLp->destroyGLTexture(); | 272 | void LLFontGL::destroyGL() |
514 | sSansSerif->mImageGLp->destroyGLTexture(); | 273 | { |
515 | sSansSerifBig->mImageGLp->destroyGLTexture(); | 274 | mFontBitmapCachep->destroyGL(); |
516 | sSansSerifBold->mImageGLp->destroyGLTexture(); | ||
517 | } | 275 | } |
518 | 276 | ||
519 | 277 | ||
@@ -532,13 +290,58 @@ BOOL LLFontGL::loadFace(const std::string& filename, | |||
532 | { | 290 | { |
533 | return FALSE; | 291 | return FALSE; |
534 | } | 292 | } |
535 | mImageGLp->createGLTexture(0, mRawImageGLp); | ||
536 | gGL.getTexUnit(0)->bind(mImageGLp); | ||
537 | mImageGLp->setMipFilterNearest(TRUE, TRUE); | ||
538 | return TRUE; | 293 | return TRUE; |
539 | } | 294 | } |
540 | 295 | ||
541 | BOOL LLFontGL::addChar(const llwchar wch) | 296 | //static |
297 | LLFontGL* LLFontGL::getFontMonospace() | ||
298 | { | ||
299 | return getFont(LLFontDescriptor("Monospace","Monospace",0)); | ||
300 | } | ||
301 | |||
302 | //static | ||
303 | LLFontGL* LLFontGL::getFontSansSerifSmall() | ||
304 | { | ||
305 | return getFont(LLFontDescriptor("SansSerif","Small",0)); | ||
306 | } | ||
307 | |||
308 | //static | ||
309 | LLFontGL* LLFontGL::getFontSansSerif() | ||
310 | { | ||
311 | return getFont(LLFontDescriptor("SansSerif","Medium",0)); | ||
312 | } | ||
313 | |||
314 | //static | ||
315 | LLFontGL* LLFontGL::getFontSansSerifBig() | ||
316 | { | ||
317 | return getFont(LLFontDescriptor("SansSerif","Large",0)); | ||
318 | } | ||
319 | |||
320 | //static | ||
321 | LLFontGL* LLFontGL::getFontSansSerifHuge() | ||
322 | { | ||
323 | return getFont(LLFontDescriptor("SansSerif","Huge",0)); | ||
324 | } | ||
325 | |||
326 | //static | ||
327 | LLFontGL* LLFontGL::getFontSansSerifBold() | ||
328 | { | ||
329 | return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); | ||
330 | } | ||
331 | |||
332 | //static | ||
333 | LLFontGL* LLFontGL::getFontExtChar() | ||
334 | { | ||
335 | return getFontSansSerif(); | ||
336 | } | ||
337 | |||
338 | //static | ||
339 | LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) | ||
340 | { | ||
341 | return sFontRegistry->getFont(desc); | ||
342 | } | ||
343 | |||
344 | BOOL LLFontGL::addChar(const llwchar wch) const | ||
542 | { | 345 | { |
543 | if (!LLFont::addChar(wch)) | 346 | if (!LLFont::addChar(wch)) |
544 | { | 347 | { |
@@ -546,10 +349,12 @@ BOOL LLFontGL::addChar(const llwchar wch) | |||
546 | } | 349 | } |
547 | 350 | ||
548 | stop_glerror(); | 351 | stop_glerror(); |
549 | mImageGLp->setSubImage(mRawImageGLp, 0, 0, mImageGLp->getWidth(), mImageGLp->getHeight()); | 352 | |
550 | gGL.getTexUnit(0)->bind(mImageGLp); | 353 | LLFontGlyphInfo *glyph_info = getGlyphInfo(wch); |
551 | mImageGLp->setMipFilterNearest(TRUE, TRUE); | 354 | U32 bitmap_num = glyph_info->mBitmapNum; |
552 | stop_glerror(); | 355 | LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num); |
356 | LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); | ||
357 | image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); | ||
553 | return TRUE; | 358 | return TRUE; |
554 | } | 359 | } |
555 | 360 | ||
@@ -564,7 +369,7 @@ S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset, | |||
564 | BOOL use_ellipses) const | 369 | BOOL use_ellipses) const |
565 | { | 370 | { |
566 | LLWString wstr = utf8str_to_wstring(text); | 371 | LLWString wstr = utf8str_to_wstring(text); |
567 | return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, use_ellipses); | 372 | return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, FALSE, use_ellipses); |
568 | } | 373 | } |
569 | 374 | ||
570 | S32 LLFontGL::render(const LLWString &wstr, | 375 | S32 LLFontGL::render(const LLWString &wstr, |
@@ -583,30 +388,17 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
583 | return wstr.length() ; | 388 | return wstr.length() ; |
584 | } | 389 | } |
585 | 390 | ||
586 | gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); | ||
587 | |||
588 | if (wstr.empty()) | 391 | if (wstr.empty()) |
589 | { | 392 | { |
590 | return 0; | 393 | return 0; |
591 | } | 394 | } |
592 | 395 | ||
396 | gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); | ||
397 | |||
593 | S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); | 398 | S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); |
594 | 399 | ||
595 | // HACK for better bolding | 400 | // Strip off any style bits that are already accounted for by the font. |
596 | if (style & BOLD) | 401 | style = style & (~getFontDesc().getStyle()); |
597 | { | ||
598 | if (this == LLFontGL::sSansSerif) | ||
599 | { | ||
600 | return LLFontGL::sSansSerifBold->render( | ||
601 | wstr, begin_offset, | ||
602 | x, y, | ||
603 | color, | ||
604 | halign, valign, | ||
605 | (style & ~BOLD), | ||
606 | max_chars, max_pixels, | ||
607 | right_x, use_embedded); | ||
608 | } | ||
609 | } | ||
610 | 402 | ||
611 | F32 drop_shadow_strength = 0.f; | 403 | F32 drop_shadow_strength = 0.f; |
612 | if (style & (DROP_SHADOW | DROP_SHADOW_SOFT)) | 404 | if (style & (DROP_SHADOW | DROP_SHADOW_SOFT)) |
@@ -623,25 +415,12 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
623 | gGL.pushMatrix(); | 415 | gGL.pushMatrix(); |
624 | glLoadIdentity(); | 416 | glLoadIdentity(); |
625 | gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); | 417 | gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); |
626 | //glScalef(sScaleX, sScaleY, 1.0f); | 418 | |
627 | 419 | // this code snaps the text origin to a pixel grid to start with | |
628 | // avoid half pixels | 420 | F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); |
629 | // RN: if we're going to this trouble, might as well snap to nearest pixel all the time | 421 | F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); |
630 | // but the plan is to get rid of this so that fonts "just work" | 422 | gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f); |
631 | //F32 half_pixel_distance = llabs(fmodf(sCurOrigin.mX * sScaleX, 1.f) - 0.5f); | 423 | |
632 | //if (half_pixel_distance < PIXEL_BORDER_THRESHOLD) | ||
633 | //{ | ||
634 | gGL.translatef(PIXEL_CORRECTION_DISTANCE*sScaleX, 0.f, 0.f); | ||
635 | //} | ||
636 | |||
637 | // this code would just snap to pixel grid, although it seems to introduce more jitter | ||
638 | //F32 pixel_offset_x = llround(sCurOrigin.mX * sScaleX) - (sCurOrigin.mX * sScaleX); | ||
639 | //F32 pixel_offset_y = llround(sCurOrigin.mY * sScaleY) - (sCurOrigin.mY * sScaleY); | ||
640 | //gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f); | ||
641 | |||
642 | // scale back to native pixel size | ||
643 | //glScalef(1.f / sScaleX, 1.f / sScaleY, 1.f); | ||
644 | //glScaled(1.0 / (F64) sScaleX, 1.0 / (F64) sScaleY, 1.0f); | ||
645 | LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS); | 424 | LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS); |
646 | 425 | ||
647 | gGL.color4fv( color.mV ); | 426 | gGL.color4fv( color.mV ); |
@@ -661,10 +440,6 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
661 | 440 | ||
662 | F32 cur_x, cur_y, cur_render_x, cur_render_y; | 441 | F32 cur_x, cur_y, cur_render_x, cur_render_y; |
663 | 442 | ||
664 | // Bind the font texture | ||
665 | |||
666 | gGL.getTexUnit(0)->bind(mImageGLp); | ||
667 | |||
668 | // Not guaranteed to be set correctly | 443 | // Not guaranteed to be set correctly |
669 | gGL.setSceneBlendType(LLRender::BT_ALPHA); | 444 | gGL.setSceneBlendType(LLRender::BT_ALPHA); |
670 | 445 | ||
@@ -704,17 +479,13 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
704 | break; | 479 | break; |
705 | } | 480 | } |
706 | 481 | ||
707 | // Round properly. | ||
708 | //cur_render_y = (F32)llfloor(cur_y/sScaleY + 0.5f)*sScaleY; | ||
709 | //cur_render_x = (F32)llfloor(cur_x/sScaleX + 0.5f)*sScaleX; | ||
710 | |||
711 | cur_render_y = cur_y; | 482 | cur_render_y = cur_y; |
712 | cur_render_x = cur_x; | 483 | cur_render_x = cur_x; |
713 | 484 | ||
714 | F32 start_x = cur_x; | 485 | F32 start_x = cur_x; |
715 | 486 | ||
716 | F32 inv_width = 1.f / mImageGLp->getWidth(); | 487 | F32 inv_width = 1.f / mFontBitmapCachep->getBitmapWidth(); |
717 | F32 inv_height = 1.f / mImageGLp->getHeight(); | 488 | F32 inv_height = 1.f / mFontBitmapCachep->getBitmapHeight(); |
718 | 489 | ||
719 | const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; | 490 | const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; |
720 | 491 | ||
@@ -733,6 +504,9 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
733 | } | 504 | } |
734 | 505 | ||
735 | 506 | ||
507 | // Remember last-used texture to avoid unnecesssary bind calls. | ||
508 | LLImageGL *last_bound_texture = NULL; | ||
509 | |||
736 | for (i = begin_offset; i < begin_offset + length; i++) | 510 | for (i = begin_offset; i < begin_offset + length; i++) |
737 | { | 511 | { |
738 | llwchar wch = wstr[i]; | 512 | llwchar wch = wstr[i]; |
@@ -752,7 +526,7 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
752 | 526 | ||
753 | if (!label.empty()) | 527 | if (!label.empty()) |
754 | { | 528 | { |
755 | ext_advance += (EXT_X_BEARING + gExtCharFont->getWidthF32( label.c_str() )) * sScaleX; | 529 | ext_advance += (EXT_X_BEARING + getFontExtChar()->getWidthF32( label.c_str() )) * sScaleX; |
756 | } | 530 | } |
757 | 531 | ||
758 | if (start_x + scaled_max_pixels < cur_x + ext_advance) | 532 | if (start_x + scaled_max_pixels < cur_x + ext_advance) |
@@ -761,9 +535,15 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
761 | break; | 535 | break; |
762 | } | 536 | } |
763 | 537 | ||
764 | gGL.getTexUnit(0)->bind(ext_image); | 538 | if (last_bound_texture != ext_image) |
765 | const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX); | 539 | { |
766 | const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight); | 540 | gGL.getTexUnit(0)->bind(ext_image); |
541 | last_bound_texture = ext_image; | ||
542 | } | ||
543 | |||
544 | // snap origin to whole screen pixel | ||
545 | const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX)); | ||
546 | const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight)); | ||
767 | 547 | ||
768 | LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); | 548 | LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); |
769 | LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); | 549 | LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); |
@@ -775,7 +555,7 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
775 | //glLoadIdentity(); | 555 | //glLoadIdentity(); |
776 | //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); | 556 | //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); |
777 | //glScalef(sScaleX, sScaleY, 1.f); | 557 | //glScalef(sScaleX, sScaleY, 1.f); |
778 | gExtCharFont->render(label, 0, | 558 | getFontExtChar()->render(label, 0, |
779 | /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), | 559 | /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), |
780 | /*llfloor*/(cur_y / sScaleY), | 560 | /*llfloor*/(cur_y / sScaleY), |
781 | color, | 561 | color, |
@@ -793,15 +573,12 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
793 | cur_x += EXT_KERNING * sScaleX; | 573 | cur_x += EXT_KERNING * sScaleX; |
794 | } | 574 | } |
795 | cur_render_x = cur_x; | 575 | cur_render_x = cur_x; |
796 | |||
797 | // Bind the font texture | ||
798 | gGL.getTexUnit(0)->bind(mImageGLp); | ||
799 | } | 576 | } |
800 | else | 577 | else |
801 | { | 578 | { |
802 | if (!hasGlyph(wch)) | 579 | if (!hasGlyph(wch)) |
803 | { | 580 | { |
804 | (const_cast<LLFontGL*>(this))->addChar(wch); | 581 | addChar(wch); |
805 | } | 582 | } |
806 | 583 | ||
807 | const LLFontGlyphInfo* fgi= getGlyphInfo(wch); | 584 | const LLFontGlyphInfo* fgi= getGlyphInfo(wch); |
@@ -810,6 +587,14 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
810 | llerrs << "Missing Glyph Info" << llendl; | 587 | llerrs << "Missing Glyph Info" << llendl; |
811 | break; | 588 | break; |
812 | } | 589 | } |
590 | // Per-glyph bitmap texture. | ||
591 | LLImageGL *image_gl = mFontBitmapCachep->getImageGL(fgi->mBitmapNum); | ||
592 | if (last_bound_texture != image_gl) | ||
593 | { | ||
594 | gGL.getTexUnit(0)->bind(image_gl); | ||
595 | last_bound_texture = image_gl; | ||
596 | } | ||
597 | |||
813 | if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) | 598 | if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) |
814 | { | 599 | { |
815 | // Not enough room for this character. | 600 | // Not enough room for this character. |
@@ -818,15 +603,16 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
818 | 603 | ||
819 | // Draw the text at the appropriate location | 604 | // Draw the text at the appropriate location |
820 | //Specify vertices and texture coordinates | 605 | //Specify vertices and texture coordinates |
821 | LLRectf uv_rect((fgi->mXBitmapOffset - PAD_AMT) * inv_width, | 606 | LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width, |
822 | (fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height, | 607 | (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height, |
823 | (fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width, | 608 | (fgi->mXBitmapOffset + fgi->mWidth) * inv_width, |
824 | (fgi->mYBitmapOffset - PAD_AMT) * inv_height); | 609 | (fgi->mYBitmapOffset - PAD_UVY) * inv_height); |
825 | LLRectf screen_rect(cur_render_x + (F32)fgi->mXBearing - PAD_AMT, | 610 | // snap glyph origin to whole screen pixel |
826 | cur_render_y + (F32)fgi->mYBearing + PAD_AMT, | 611 | LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing), |
827 | cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + PAD_AMT, | 612 | llround(cur_render_y + (F32)fgi->mYBearing), |
828 | cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT); | 613 | llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, |
829 | 614 | llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); | |
615 | |||
830 | drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); | 616 | drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); |
831 | 617 | ||
832 | chars_drawn++; | 618 | chars_drawn++; |
@@ -839,7 +625,7 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
839 | // Kern this puppy. | 625 | // Kern this puppy. |
840 | if (!hasGlyph(next_char)) | 626 | if (!hasGlyph(next_char)) |
841 | { | 627 | { |
842 | (const_cast<LLFontGL*>(this))->addChar(next_char); | 628 | addChar(next_char); |
843 | } | 629 | } |
844 | cur_x += getXKerning(wch, next_char); | 630 | cur_x += getXKerning(wch, next_char); |
845 | } | 631 | } |
@@ -896,11 +682,6 @@ S32 LLFontGL::render(const LLWString &wstr, | |||
896 | return chars_drawn; | 682 | return chars_drawn; |
897 | } | 683 | } |
898 | 684 | ||
899 | |||
900 | LLImageGL *LLFontGL::getImageGL() const | ||
901 | { | ||
902 | return mImageGLp; | ||
903 | } | ||
904 | 685 | ||
905 | S32 LLFontGL::getWidth(const std::string& utf8text) const | 686 | S32 LLFontGL::getWidth(const std::string& utf8text) const |
906 | { | 687 | { |
@@ -1118,59 +899,32 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_ | |||
1118 | llwchar wch = wchars[i]; | 899 | llwchar wch = wchars[i]; |
1119 | 900 | ||
1120 | const embedded_data_t* ext_data = getEmbeddedCharData(wch); | 901 | const embedded_data_t* ext_data = getEmbeddedCharData(wch); |
1121 | if (ext_data) | 902 | F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch); |
1122 | { | ||
1123 | F32 char_width = getEmbeddedCharAdvance(ext_data); | ||
1124 | |||
1125 | if( scaled_max_pixels < (total_width + char_width) ) | ||
1126 | { | ||
1127 | break; | ||
1128 | } | ||
1129 | 903 | ||
1130 | total_width += char_width; | 904 | if( scaled_max_pixels < (total_width + char_width) ) |
1131 | |||
1132 | drawable_chars++; | ||
1133 | if( max_chars >= 0 && drawable_chars >= max_chars ) | ||
1134 | { | ||
1135 | break; | ||
1136 | } | ||
1137 | |||
1138 | if ( i > 0 ) | ||
1139 | { | ||
1140 | total_width += EXT_KERNING * sScaleX; | ||
1141 | } | ||
1142 | |||
1143 | // Round after kerning. | ||
1144 | total_width = (F32)llfloor(total_width + 0.5f); | ||
1145 | } | ||
1146 | else | ||
1147 | { | 905 | { |
1148 | F32 char_width = getXAdvance(wch); | 906 | break; |
1149 | if( scaled_max_pixels < (total_width + char_width) ) | 907 | } |
1150 | { | ||
1151 | break; | ||
1152 | } | ||
1153 | |||
1154 | total_width += char_width; | ||
1155 | 908 | ||
1156 | drawable_chars++; | 909 | total_width += char_width; |
1157 | if( max_chars >= 0 && drawable_chars >= max_chars ) | 910 | drawable_chars++; |
1158 | { | ||
1159 | break; | ||
1160 | } | ||
1161 | 911 | ||
1162 | if ( i > 0 ) | 912 | if( max_chars >= 0 && drawable_chars >= max_chars ) |
1163 | { | 913 | { |
1164 | // Kerning | 914 | break; |
1165 | total_width += getXKerning(wchars[i-1], wch); | 915 | } |
1166 | } | ||
1167 | 916 | ||
1168 | // Round after kerning. | 917 | if ( i > 0 ) |
1169 | total_width = (F32)llfloor(total_width + 0.5f); | 918 | { |
919 | // kerning | ||
920 | total_width += ext_data ? (EXT_KERNING * sScaleX) : getXKerning(wchars[i-1], wch); | ||
1170 | } | 921 | } |
922 | |||
923 | // Round after kerning. | ||
924 | total_width = llround(total_width); | ||
1171 | } | 925 | } |
1172 | 926 | ||
1173 | return text_len - drawable_chars; | 927 | return start_pos - drawable_chars; |
1174 | } | 928 | } |
1175 | 929 | ||
1176 | 930 | ||
@@ -1299,7 +1053,7 @@ F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const | |||
1299 | F32 ext_width = (F32)ext_image->getWidth(); | 1053 | F32 ext_width = (F32)ext_image->getWidth(); |
1300 | if( !label.empty() ) | 1054 | if( !label.empty() ) |
1301 | { | 1055 | { |
1302 | ext_width += (EXT_X_BEARING + gExtCharFont->getWidthF32(label.c_str())) * sScaleX; | 1056 | ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX; |
1303 | } | 1057 | } |
1304 | 1058 | ||
1305 | return (EXT_X_BEARING * sScaleX) + ext_width; | 1059 | return (EXT_X_BEARING * sScaleX) + ext_width; |
@@ -1312,19 +1066,19 @@ void LLFontGL::clearEmbeddedChars() | |||
1312 | mEmbeddedChars.clear(); | 1066 | mEmbeddedChars.clear(); |
1313 | } | 1067 | } |
1314 | 1068 | ||
1315 | void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label ) | 1069 | void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label ) const |
1316 | { | 1070 | { |
1317 | LLWString wlabel = utf8str_to_wstring(label); | 1071 | LLWString wlabel = utf8str_to_wstring(label); |
1318 | addEmbeddedChar(wc, image, wlabel); | 1072 | addEmbeddedChar(wc, image, wlabel); |
1319 | } | 1073 | } |
1320 | 1074 | ||
1321 | void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& wlabel ) | 1075 | void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& wlabel ) const |
1322 | { | 1076 | { |
1323 | embedded_data_t* ext_data = new embedded_data_t(image, wlabel); | 1077 | embedded_data_t* ext_data = new embedded_data_t(image, wlabel); |
1324 | mEmbeddedChars[wc] = ext_data; | 1078 | mEmbeddedChars[wc] = ext_data; |
1325 | } | 1079 | } |
1326 | 1080 | ||
1327 | void LLFontGL::removeEmbeddedChar( llwchar wc ) | 1081 | void LLFontGL::removeEmbeddedChar( llwchar wc ) const |
1328 | { | 1082 | { |
1329 | embedded_map_t::iterator iter = mEmbeddedChars.find(wc); | 1083 | embedded_map_t::iterator iter = mEmbeddedChars.find(wc); |
1330 | if (iter != mEmbeddedChars.end()) | 1084 | if (iter != mEmbeddedChars.end()) |
@@ -1428,68 +1182,9 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con | |||
1428 | gGL.end(); | 1182 | gGL.end(); |
1429 | } | 1183 | } |
1430 | 1184 | ||
1431 | // static | ||
1432 | std::string LLFontGL::nameFromFont(const LLFontGL* fontp) | 1185 | std::string LLFontGL::nameFromFont(const LLFontGL* fontp) |
1433 | { | 1186 | { |
1434 | if (fontp == sSansSerifHuge) | 1187 | return fontp->getFontDesc().getName(); |
1435 | { | ||
1436 | return std::string("SansSerifHuge"); | ||
1437 | } | ||
1438 | else if (fontp == sSansSerifSmall) | ||
1439 | { | ||
1440 | return std::string("SansSerifSmall"); | ||
1441 | } | ||
1442 | else if (fontp == sSansSerif) | ||
1443 | { | ||
1444 | return std::string("SansSerif"); | ||
1445 | } | ||
1446 | else if (fontp == sSansSerifBig) | ||
1447 | { | ||
1448 | return std::string("SansSerifBig"); | ||
1449 | } | ||
1450 | else if (fontp == sSansSerifBold) | ||
1451 | { | ||
1452 | return std::string("SansSerifBold"); | ||
1453 | } | ||
1454 | else if (fontp == sMonospace) | ||
1455 | { | ||
1456 | return std::string("Monospace"); | ||
1457 | } | ||
1458 | else | ||
1459 | { | ||
1460 | return std::string(); | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1464 | // static | ||
1465 | LLFontGL* LLFontGL::fontFromName(const std::string& font_name) | ||
1466 | { | ||
1467 | LLFontGL* gl_font = NULL; | ||
1468 | if (font_name == "SansSerifHuge") | ||
1469 | { | ||
1470 | gl_font = LLFontGL::sSansSerifHuge; | ||
1471 | } | ||
1472 | else if (font_name == "SansSerifSmall") | ||
1473 | { | ||
1474 | gl_font = LLFontGL::sSansSerifSmall; | ||
1475 | } | ||
1476 | else if (font_name == "SansSerif") | ||
1477 | { | ||
1478 | gl_font = LLFontGL::sSansSerif; | ||
1479 | } | ||
1480 | else if (font_name == "SansSerifBig") | ||
1481 | { | ||
1482 | gl_font = LLFontGL::sSansSerifBig; | ||
1483 | } | ||
1484 | else if (font_name == "SansSerifBold") | ||
1485 | { | ||
1486 | gl_font = LLFontGL::sSansSerifBold; | ||
1487 | } | ||
1488 | else if (font_name == "Monospace") | ||
1489 | { | ||
1490 | gl_font = LLFontGL::sMonospace; | ||
1491 | } | ||
1492 | return gl_font; | ||
1493 | } | 1188 | } |
1494 | 1189 | ||
1495 | // static | 1190 | // static |
diff --git a/linden/indra/llrender/llfontgl.h b/linden/indra/llrender/llfontgl.h index 97bdd1a..6cb1727 100644 --- a/linden/indra/llrender/llfontgl.h +++ b/linden/indra/llrender/llfontgl.h | |||
@@ -18,7 +18,8 @@ | |||
18 | * There are special exceptions to the terms and conditions of the GPL as | 18 | * There are special exceptions to the terms and conditions of the GPL as |
19 | * it is applied to this Source Code. View the full text of the exception | 19 | * it is applied to this Source Code. View the full text of the exception |
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 20 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
21 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 21 | * online at |
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | 23 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 24 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 25 | * that you have read and understood your obligations described above, |
@@ -39,8 +40,16 @@ | |||
39 | #include "llcoord.h" | 40 | #include "llcoord.h" |
40 | #include "llrect.h" | 41 | #include "llrect.h" |
41 | 42 | ||
43 | #include "llfontregistry.h" | ||
44 | |||
42 | class LLColor4; | 45 | class LLColor4; |
43 | 46 | ||
47 | // Key used to request a font. | ||
48 | class LLFontDescriptor; | ||
49 | |||
50 | // Structure used to store previously requested fonts. | ||
51 | class LLFontRegistry; | ||
52 | |||
44 | class LLFontGL : public LLFont | 53 | class LLFontGL : public LLFont |
45 | { | 54 | { |
46 | public: | 55 | public: |
@@ -85,18 +94,13 @@ public: | |||
85 | LLFontGL &operator=(const LLFontGL &source); | 94 | LLFontGL &operator=(const LLFontGL &source); |
86 | 95 | ||
87 | static BOOL initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, | 96 | static BOOL initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, |
88 | const std::string& monospace_file, F32 monospace_size, | 97 | const std::string& app_dir, |
89 | const std::string& sansserif_file, | 98 | const std::vector<std::string>& xui_paths); |
90 | const std::string& sansserif_fallback_file, F32 ss_fallback_scale, | ||
91 | F32 small_size, F32 medium_size, F32 large_size, F32 huge_size, | ||
92 | const std::string& sansserif_bold_file, F32 bold_size, | ||
93 | const std::string& app_dir = LLStringUtil::null); | ||
94 | 99 | ||
95 | static void destroyDefaultFonts(); | 100 | static void destroyDefaultFonts(); |
96 | static void destroyGL(); | 101 | static void destroyAllGL(); |
102 | void destroyGL(); | ||
97 | 103 | ||
98 | static bool loadFaceFallback(LLFontList *fontp, const std::string& fontname, const F32 point_size); | ||
99 | static bool loadFace(LLFontGL *fontp, const std::string& fontname, const F32 point_size, LLFontList *fallback_fontp); | ||
100 | /* virtual*/ BOOL loadFace(const std::string& filename, | 104 | /* virtual*/ BOOL loadFace(const std::string& filename, |
101 | const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, | 105 | const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, |
102 | const S32 components, BOOL is_fallback); | 106 | const S32 components, BOOL is_fallback); |
@@ -180,7 +184,7 @@ public: | |||
180 | F32* drawn_pixels = NULL) const; | 184 | F32* drawn_pixels = NULL) const; |
181 | 185 | ||
182 | // Returns the index of the first complete characters from text that can be drawn in max_pixels | 186 | // Returns the index of the first complete characters from text that can be drawn in max_pixels |
183 | // starting on the right side (at character start_pos). | 187 | // given that the character at start_pos should be the last character (or as close to last as possible). |
184 | virtual S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; | 188 | virtual S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; |
185 | 189 | ||
186 | // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) | 190 | // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) |
@@ -191,12 +195,11 @@ public: | |||
191 | 195 | ||
192 | LLImageGL *getImageGL() const; | 196 | LLImageGL *getImageGL() const; |
193 | 197 | ||
194 | void addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label); | 198 | void addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label) const; |
195 | void addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& label); | 199 | void addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& label) const; |
196 | void removeEmbeddedChar( llwchar wc ); | 200 | void removeEmbeddedChar( llwchar wc ) const; |
197 | 201 | ||
198 | static std::string nameFromFont(const LLFontGL* fontp); | 202 | static std::string nameFromFont(const LLFontGL* fontp); |
199 | static LLFontGL* fontFromName(const std::string& name); | ||
200 | 203 | ||
201 | static std::string nameFromHAlign(LLFontGL::HAlign align); | 204 | static std::string nameFromHAlign(LLFontGL::HAlign align); |
202 | static LLFontGL::HAlign hAlignFromName(const std::string& name); | 205 | static LLFontGL::HAlign hAlignFromName(const std::string& name); |
@@ -227,20 +230,14 @@ public: | |||
227 | static BOOL sDisplayFont ; | 230 | static BOOL sDisplayFont ; |
228 | static std::string sAppDir; // For loading fonts | 231 | static std::string sAppDir; // For loading fonts |
229 | 232 | ||
230 | static LLFontGL* sMonospace; // medium | 233 | static LLFontGL* getFontMonospace(); |
231 | static LLFontList* sMonospaceFallback; | 234 | static LLFontGL* getFontSansSerifSmall(); |
232 | 235 | static LLFontGL* getFontSansSerif(); | |
233 | static LLFontGL* sSansSerifSmall; // small | 236 | static LLFontGL* getFontSansSerifBig(); |
234 | static LLFontList* sSSSmallFallback; | 237 | static LLFontGL* getFontSansSerifHuge(); |
235 | static LLFontGL* sSansSerif; // medium | 238 | static LLFontGL* getFontSansSerifBold(); |
236 | static LLFontList* sSSFallback; | 239 | static LLFontGL* getFontExtChar(); |
237 | static LLFontGL* sSansSerifBig; // large | 240 | static LLFontGL* getFont(const LLFontDescriptor& desc); |
238 | static LLFontList* sSSBigFallback; | ||
239 | static LLFontGL* sSansSerifHuge; // very large | ||
240 | static LLFontList* sSSHugeFallback; | ||
241 | |||
242 | static LLFontGL* sSansSerifBold; // medium, bolded | ||
243 | static LLFontList* sSSBoldFallback; | ||
244 | 241 | ||
245 | static LLColor4 sShadowColor; | 242 | static LLColor4 sShadowColor; |
246 | 243 | ||
@@ -248,19 +245,26 @@ public: | |||
248 | friend class LLHUDText; | 245 | friend class LLHUDText; |
249 | 246 | ||
250 | protected: | 247 | protected: |
251 | /*virtual*/ BOOL addChar(const llwchar wch); | 248 | /*virtual*/ BOOL addChar(const llwchar wch) const; |
252 | static std::string getFontPathLocal(); | ||
253 | static std::string getFontPathSystem(); | ||
254 | 249 | ||
255 | protected: | 250 | protected: |
256 | LLPointer<LLImageRaw> mRawImageGLp; | ||
257 | LLPointer<LLImageGL> mImageGLp; | ||
258 | typedef std::map<llwchar,embedded_data_t*> embedded_map_t; | 251 | typedef std::map<llwchar,embedded_data_t*> embedded_map_t; |
259 | embedded_map_t mEmbeddedChars; | 252 | mutable embedded_map_t mEmbeddedChars; |
260 | 253 | ||
254 | LLFontDescriptor mFontDesc; | ||
255 | |||
256 | // Registry holds all instantiated fonts. | ||
257 | static LLFontRegistry* sFontRegistry; | ||
258 | |||
261 | public: | 259 | public: |
260 | static std::string getFontPathLocal(); | ||
261 | static std::string getFontPathSystem(); | ||
262 | |||
262 | static LLCoordFont sCurOrigin; | 263 | static LLCoordFont sCurOrigin; |
263 | static std::vector<LLCoordFont> sOriginStack; | 264 | static std::vector<LLCoordFont> sOriginStack; |
265 | |||
266 | const LLFontDescriptor &getFontDesc() const { return mFontDesc; } | ||
267 | void setFontDesc(const LLFontDescriptor& font_desc) { mFontDesc = font_desc; } | ||
264 | }; | 268 | }; |
265 | 269 | ||
266 | #endif | 270 | #endif |
diff --git a/linden/indra/llrender/llfontregistry.cpp b/linden/indra/llrender/llfontregistry.cpp new file mode 100644 index 0000000..619228e --- /dev/null +++ b/linden/indra/llrender/llfontregistry.cpp | |||
@@ -0,0 +1,651 @@ | |||
1 | /** | ||
2 | * @file llfontregistry.cpp | ||
3 | * @author Brad Payne | ||
4 | * @brief Storage for fonts. | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #include "linden_common.h" | ||
35 | #include "llgl.h" | ||
36 | #include "llfontregistry.h" | ||
37 | #include "llfontgl.h" | ||
38 | #include <boost/tokenizer.hpp> | ||
39 | #include "llcontrol.h" | ||
40 | #include "lldir.h" | ||
41 | #include "llwindow.h" | ||
42 | |||
43 | extern LLControlGroup gSavedSettings; | ||
44 | |||
45 | using std::string; | ||
46 | using std::map; | ||
47 | |||
48 | bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc); | ||
49 | |||
50 | LLFontDescriptor::LLFontDescriptor(): | ||
51 | mStyle(0) | ||
52 | { | ||
53 | } | ||
54 | |||
55 | LLFontDescriptor::LLFontDescriptor(const std::string& name, | ||
56 | const std::string& size, | ||
57 | const U8 style, | ||
58 | const string_vec_t& file_names): | ||
59 | mName(name), | ||
60 | mSize(size), | ||
61 | mStyle(style), | ||
62 | mFileNames(file_names) | ||
63 | { | ||
64 | } | ||
65 | |||
66 | LLFontDescriptor::LLFontDescriptor(const std::string& name, | ||
67 | const std::string& size, | ||
68 | const U8 style): | ||
69 | mName(name), | ||
70 | mSize(size), | ||
71 | mStyle(style) | ||
72 | { | ||
73 | } | ||
74 | |||
75 | |||
76 | bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const | ||
77 | { | ||
78 | if (mName < b.mName) | ||
79 | return true; | ||
80 | else if (mName > b.mName) | ||
81 | return false; | ||
82 | |||
83 | if (mStyle < b.mStyle) | ||
84 | return true; | ||
85 | else if (mStyle > b.mStyle) | ||
86 | return false; | ||
87 | |||
88 | if (mSize < b.mSize) | ||
89 | return true; | ||
90 | else | ||
91 | return false; | ||
92 | } | ||
93 | |||
94 | static const std::string s_template_string("TEMPLATE"); | ||
95 | |||
96 | bool LLFontDescriptor::isTemplate() const | ||
97 | { | ||
98 | return getSize() == s_template_string; | ||
99 | } | ||
100 | |||
101 | // Look for substring match and remove substring if matched. | ||
102 | bool removeSubString(std::string& str, const std::string& substr) | ||
103 | { | ||
104 | size_t pos = str.find(substr); | ||
105 | if (pos != string::npos) | ||
106 | { | ||
107 | str.replace(pos,substr.length(),(const char *)NULL, 0); | ||
108 | return true; | ||
109 | } | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | // Check for substring match without modifying the source string. | ||
114 | bool findSubString(std::string& str, const std::string& substr) | ||
115 | { | ||
116 | size_t pos = str.find(substr); | ||
117 | if (pos != string::npos) | ||
118 | { | ||
119 | return true; | ||
120 | } | ||
121 | return false; | ||
122 | } | ||
123 | |||
124 | |||
125 | // Normal form is | ||
126 | // - raw name | ||
127 | // - bold, italic style info reflected in both style and font name. | ||
128 | // - other style info removed. | ||
129 | // - size info moved to mSize, defaults to Medium | ||
130 | // For example, | ||
131 | // - "SansSerifHuge" would normalize to { "SansSerif", "Huge", 0 } | ||
132 | // - "SansSerifBold" would normalize to { "SansSerifBold", "Medium", BOLD } | ||
133 | LLFontDescriptor LLFontDescriptor::normalize() const | ||
134 | { | ||
135 | std::string new_name(mName); | ||
136 | std::string new_size(mSize); | ||
137 | U8 new_style(mStyle); | ||
138 | |||
139 | // Only care about style to extent it can be picked up by font. | ||
140 | new_style &= (LLFontGL::BOLD | LLFontGL::ITALIC); | ||
141 | |||
142 | // All these transformations are to support old-style font specifications. | ||
143 | if (removeSubString(new_name,"Small")) | ||
144 | new_size = "Small"; | ||
145 | if (removeSubString(new_name,"Big")) | ||
146 | new_size = "Large"; | ||
147 | if (removeSubString(new_name,"Medium")) | ||
148 | new_size = "Medium"; | ||
149 | if (removeSubString(new_name,"Large")) | ||
150 | new_size = "Large"; | ||
151 | if (removeSubString(new_name,"Huge")) | ||
152 | new_size = "Huge"; | ||
153 | |||
154 | // HACK - Monospace is the only one we don't remove, so | ||
155 | // name "Monospace" doesn't get taken down to "" | ||
156 | // For other fonts, there's no ambiguity between font name and size specifier. | ||
157 | if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Monospace")) | ||
158 | new_size = "Monospace"; | ||
159 | if (new_size.empty()) | ||
160 | new_size = "Medium"; | ||
161 | |||
162 | if (removeSubString(new_name,"Bold")) | ||
163 | new_style |= LLFontGL::BOLD; | ||
164 | |||
165 | if (removeSubString(new_name,"Italic")) | ||
166 | new_style |= LLFontGL::ITALIC; | ||
167 | |||
168 | return LLFontDescriptor(new_name,new_size,new_style,getFileNames()); | ||
169 | } | ||
170 | |||
171 | LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths) | ||
172 | { | ||
173 | // Propagate this down from LLUICtrlFactory so LLRender doesn't | ||
174 | // need an upstream dependency on LLUI. | ||
175 | mXUIPaths = xui_paths; | ||
176 | |||
177 | // This is potentially a slow directory traversal, so we want to | ||
178 | // cache the result. | ||
179 | mUltimateFallbackList = LLWindow::getDynamicFallbackFontList(); | ||
180 | } | ||
181 | |||
182 | LLFontRegistry::~LLFontRegistry() | ||
183 | { | ||
184 | clear(); | ||
185 | } | ||
186 | |||
187 | bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) | ||
188 | { | ||
189 | bool success = false; // Succeed if we find at least one XUI file | ||
190 | const string_vec_t& xml_paths = mXUIPaths; | ||
191 | for (string_vec_t::const_iterator path_it = xml_paths.begin(); | ||
192 | path_it != xml_paths.end(); | ||
193 | ++path_it) | ||
194 | { | ||
195 | |||
196 | LLXMLNodePtr root; | ||
197 | std::string full_filename = gDirUtilp->findSkinnedFilename(*path_it, xml_filename); | ||
198 | bool parsed_file = LLXMLNode::parseFile(full_filename, root, NULL); | ||
199 | |||
200 | if (!parsed_file) | ||
201 | continue; | ||
202 | |||
203 | if ( root.isNull() || ! root->hasName( "fonts" ) ) | ||
204 | { | ||
205 | llwarns << "Bad font info file: " | ||
206 | << full_filename << llendl; | ||
207 | continue; | ||
208 | } | ||
209 | |||
210 | std::string root_name; | ||
211 | root->getAttributeString("name",root_name); | ||
212 | if (root->hasName("fonts")) | ||
213 | { | ||
214 | // Expect a collection of children consisting of "font" or "font_size" entries | ||
215 | bool init_succ = initFromXML(root); | ||
216 | success = success || init_succ; | ||
217 | } | ||
218 | } | ||
219 | if (success) | ||
220 | dump(); | ||
221 | |||
222 | return success; | ||
223 | } | ||
224 | |||
225 | std::string currentOsName() | ||
226 | { | ||
227 | #if LL_WINDOWS | ||
228 | return "Windows"; | ||
229 | #elif LL_DARWIN | ||
230 | return "Mac"; | ||
231 | #elif LL_SDL | ||
232 | return "Linux"; | ||
233 | #else | ||
234 | return ""; | ||
235 | #endif | ||
236 | } | ||
237 | |||
238 | bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc) | ||
239 | { | ||
240 | if (node->hasName("font")) | ||
241 | { | ||
242 | std::string attr_name; | ||
243 | if (node->getAttributeString("name",attr_name)) | ||
244 | { | ||
245 | desc.setName(attr_name); | ||
246 | } | ||
247 | |||
248 | std::string attr_style; | ||
249 | if (node->getAttributeString("font_style",attr_style)) | ||
250 | { | ||
251 | desc.setStyle(LLFontGL::getStyleFromString(attr_style)); | ||
252 | } | ||
253 | |||
254 | desc.setSize(s_template_string); | ||
255 | } | ||
256 | |||
257 | LLXMLNodePtr child; | ||
258 | for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) | ||
259 | { | ||
260 | std::string child_name; | ||
261 | child->getAttributeString("name",child_name); | ||
262 | if (child->hasName("file")) | ||
263 | { | ||
264 | std::string font_file_name = child->getTextContents(); | ||
265 | desc.getFileNames().push_back(font_file_name); | ||
266 | } | ||
267 | else if (child->hasName("os")) | ||
268 | { | ||
269 | if (child_name == currentOsName()) | ||
270 | { | ||
271 | fontDescInitFromXML(child, desc); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | return true; | ||
276 | } | ||
277 | |||
278 | bool LLFontRegistry::initFromXML(LLXMLNodePtr node) | ||
279 | { | ||
280 | LLXMLNodePtr child; | ||
281 | |||
282 | for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) | ||
283 | { | ||
284 | std::string child_name; | ||
285 | child->getAttributeString("name",child_name); | ||
286 | if (child->hasName("font")) | ||
287 | { | ||
288 | LLFontDescriptor desc; | ||
289 | bool font_succ = fontDescInitFromXML(child, desc); | ||
290 | LLFontDescriptor norm_desc = desc.normalize(); | ||
291 | if (font_succ) | ||
292 | { | ||
293 | // if this is the first time we've seen this font name, | ||
294 | // create a new template map entry for it. | ||
295 | const LLFontDescriptor *match_desc = getMatchingFontDesc(desc); | ||
296 | if (match_desc == NULL) | ||
297 | { | ||
298 | // Create a new entry (with no corresponding font). | ||
299 | mFontMap[norm_desc] = NULL; | ||
300 | } | ||
301 | // otherwise, find the existing entry and combine data. | ||
302 | else | ||
303 | { | ||
304 | // Prepend files from desc. | ||
305 | // A little roundabout because the map key is const, | ||
306 | // so we have to fetch it, make a new map key, and | ||
307 | // replace the old entry. | ||
308 | string_vec_t match_file_names = match_desc->getFileNames(); | ||
309 | match_file_names.insert(match_file_names.begin(), | ||
310 | desc.getFileNames().begin(), | ||
311 | desc.getFileNames().end()); | ||
312 | LLFontDescriptor new_desc = *match_desc; | ||
313 | new_desc.getFileNames() = match_file_names; | ||
314 | mFontMap.erase(*match_desc); | ||
315 | mFontMap[new_desc] = NULL; | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | else if (child->hasName("font_size")) | ||
320 | { | ||
321 | std::string size_name; | ||
322 | F32 size_value; | ||
323 | if (child->getAttributeString("name",size_name) && | ||
324 | child->getAttributeF32("size",size_value)) | ||
325 | { | ||
326 | mFontSizes[size_name] = size_value; | ||
327 | } | ||
328 | |||
329 | } | ||
330 | } | ||
331 | return true; | ||
332 | } | ||
333 | |||
334 | bool LLFontRegistry::nameToSize(const std::string& size_name, F32& size) | ||
335 | { | ||
336 | font_size_map_t::iterator it = mFontSizes.find(size_name); | ||
337 | if (it != mFontSizes.end()) | ||
338 | { | ||
339 | size = it->second; | ||
340 | return true; | ||
341 | } | ||
342 | return false; | ||
343 | } | ||
344 | |||
345 | |||
346 | LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) | ||
347 | { | ||
348 | // Name should hold a font name recognized as a setting; the value | ||
349 | // of the setting should be a list of font files. | ||
350 | // Size should be a recognized string value | ||
351 | // Style should be a set of flags including any implied by the font name. | ||
352 | |||
353 | // First decipher the requested size. | ||
354 | LLFontDescriptor norm_desc = desc.normalize(); | ||
355 | F32 point_size; | ||
356 | bool found_size = nameToSize(norm_desc.getSize(),point_size); | ||
357 | if (!found_size) | ||
358 | { | ||
359 | llwarns << "createFont unrecognized size " << norm_desc.getSize() << llendl; | ||
360 | return NULL; | ||
361 | } | ||
362 | llinfos << "createFont " << norm_desc.getName() << " size " << norm_desc.getSize() << " style " << ((S32) norm_desc.getStyle()) << llendl; | ||
363 | F32 fallback_scale = 1.0; | ||
364 | |||
365 | // Find corresponding font template (based on same descriptor with no size specified) | ||
366 | LLFontDescriptor template_desc(norm_desc); | ||
367 | template_desc.setSize(s_template_string); | ||
368 | const LLFontDescriptor *match_desc = getClosestFontTemplate(template_desc); | ||
369 | if (!match_desc) | ||
370 | { | ||
371 | llwarns << "createFont failed, no template found for " | ||
372 | << norm_desc.getName() << " style [" << ((S32)norm_desc.getStyle()) << "]" << llendl; | ||
373 | return NULL; | ||
374 | } | ||
375 | |||
376 | // See whether this best-match font has already been instantiated in the requested size. | ||
377 | LLFontDescriptor nearest_exact_desc = *match_desc; | ||
378 | nearest_exact_desc.setSize(norm_desc.getSize()); | ||
379 | font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc); | ||
380 | if (it != mFontMap.end()) | ||
381 | { | ||
382 | llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl; | ||
383 | return it->second; | ||
384 | } | ||
385 | |||
386 | // Build list of font names to look for. | ||
387 | // Files specified for this font come first, followed by those from the default descriptor. | ||
388 | string_vec_t file_names = match_desc->getFileNames(); | ||
389 | string_vec_t default_file_names; | ||
390 | LLFontDescriptor default_desc("default",s_template_string,0); | ||
391 | const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc); | ||
392 | if (match_default_desc) | ||
393 | { | ||
394 | file_names.insert(file_names.end(), | ||
395 | match_default_desc->getFileNames().begin(), | ||
396 | match_default_desc->getFileNames().end()); | ||
397 | } | ||
398 | |||
399 | // Add ultimate fallback list - generated dynamically on linux, | ||
400 | // null elsewhere. | ||
401 | file_names.insert(file_names.end(), | ||
402 | getUltimateFallbackList().begin(), | ||
403 | getUltimateFallbackList().end()); | ||
404 | |||
405 | // Load fonts based on names. | ||
406 | if (file_names.empty()) | ||
407 | { | ||
408 | llwarns << "createFont failed, no file names specified" << llendl; | ||
409 | return NULL; | ||
410 | } | ||
411 | LLFontList *fontlistp = new LLFontList; | ||
412 | LLFontGL *result = NULL; | ||
413 | |||
414 | // Snarf all fonts we can into fontlistp. First will get pulled | ||
415 | // off the list and become the "head" font, set to non-fallback. | ||
416 | // Rest will consitute the fallback list. | ||
417 | BOOL is_first_found = TRUE; | ||
418 | |||
419 | std::string local_path = LLFontGL::getFontPathLocal(); | ||
420 | std::string sys_path = LLFontGL::getFontPathSystem(); | ||
421 | |||
422 | // The fontname string may contain multiple font file names separated by semicolons. | ||
423 | // Break it apart and try loading each one, in order. | ||
424 | for(string_vec_t::iterator file_name_it = file_names.begin(); | ||
425 | file_name_it != file_names.end(); | ||
426 | ++file_name_it) | ||
427 | { | ||
428 | LLFontGL *fontp = new LLFontGL; | ||
429 | std::string font_path = local_path + *file_name_it; | ||
430 | BOOL is_fallback = !is_first_found; | ||
431 | F32 extra_scale = (is_fallback)?fallback_scale:1.0; | ||
432 | if (!fontp->loadFace(font_path, extra_scale * point_size, | ||
433 | LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback)) | ||
434 | { | ||
435 | font_path = sys_path + *file_name_it; | ||
436 | |||
437 | if (!fontp->loadFace(font_path, extra_scale * point_size, | ||
438 | LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback)) | ||
439 | { | ||
440 | LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << *file_name_it << LL_ENDL; | ||
441 | delete fontp; | ||
442 | fontp = NULL; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | if(fontp) | ||
447 | { | ||
448 | if (is_first_found) | ||
449 | { | ||
450 | result = fontp; | ||
451 | is_first_found = false; | ||
452 | } | ||
453 | else | ||
454 | fontlistp->addAtEnd(fontp); | ||
455 | } | ||
456 | } | ||
457 | if (result && !fontlistp->empty()) | ||
458 | { | ||
459 | result->setFallbackFont(fontlistp); | ||
460 | } | ||
461 | |||
462 | norm_desc.setStyle(match_desc->getStyle()); | ||
463 | if (result) | ||
464 | result->setFontDesc(norm_desc); | ||
465 | |||
466 | if (!result) | ||
467 | { | ||
468 | llwarns << "createFont failed in some way" << llendl; | ||
469 | } | ||
470 | mFontMap[norm_desc] = result; | ||
471 | return result; | ||
472 | } | ||
473 | |||
474 | void LLFontRegistry::reset() | ||
475 | { | ||
476 | for (font_reg_map_t::iterator it = mFontMap.begin(); | ||
477 | it != mFontMap.end(); | ||
478 | ++it) | ||
479 | { | ||
480 | // Reset the corresponding font but preserve the entry. | ||
481 | if (it->second) | ||
482 | it->second->reset(); | ||
483 | } | ||
484 | } | ||
485 | |||
486 | void LLFontRegistry::clear() | ||
487 | { | ||
488 | for (font_reg_map_t::iterator it = mFontMap.begin(); | ||
489 | it != mFontMap.end(); | ||
490 | ++it) | ||
491 | { | ||
492 | LLFontGL *fontp = it->second; | ||
493 | delete fontp; | ||
494 | } | ||
495 | mFontMap.clear(); | ||
496 | } | ||
497 | |||
498 | void LLFontRegistry::destroyGL() | ||
499 | { | ||
500 | for (font_reg_map_t::iterator it = mFontMap.begin(); | ||
501 | it != mFontMap.end(); | ||
502 | ++it) | ||
503 | { | ||
504 | // Reset the corresponding font but preserve the entry. | ||
505 | if (it->second) | ||
506 | it->second->destroyGL(); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& orig_desc) | ||
511 | { | ||
512 | LLFontDescriptor norm_desc = orig_desc.normalize(); | ||
513 | |||
514 | font_reg_map_t::iterator it = mFontMap.find(norm_desc); | ||
515 | if (it != mFontMap.end()) | ||
516 | return it->second; | ||
517 | else | ||
518 | { | ||
519 | LLFontGL *fontp = createFont(orig_desc); | ||
520 | if (!fontp) | ||
521 | { | ||
522 | llwarns << "getFont failed, name " << orig_desc.getName() | ||
523 | <<" style=[" << ((S32) orig_desc.getStyle()) << "]" | ||
524 | << " size=[" << orig_desc.getSize() << "]" << llendl; | ||
525 | } | ||
526 | return fontp; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | const LLFontDescriptor *LLFontRegistry::getMatchingFontDesc(const LLFontDescriptor& desc) | ||
531 | { | ||
532 | LLFontDescriptor norm_desc = desc.normalize(); | ||
533 | |||
534 | font_reg_map_t::iterator it = mFontMap.find(norm_desc); | ||
535 | if (it != mFontMap.end()) | ||
536 | return &(it->first); | ||
537 | else | ||
538 | return NULL; | ||
539 | } | ||
540 | |||
541 | static U32 bitCount(U8 c) | ||
542 | { | ||
543 | U32 count = 0; | ||
544 | if (c & 1) | ||
545 | count++; | ||
546 | if (c & 2) | ||
547 | count++; | ||
548 | if (c & 4) | ||
549 | count++; | ||
550 | if (c & 8) | ||
551 | count++; | ||
552 | if (c & 16) | ||
553 | count++; | ||
554 | if (c & 32) | ||
555 | count++; | ||
556 | if (c & 64) | ||
557 | count++; | ||
558 | if (c & 128) | ||
559 | count++; | ||
560 | return count; | ||
561 | } | ||
562 | |||
563 | // Find nearest match for the requested descriptor. | ||
564 | const LLFontDescriptor *LLFontRegistry::getClosestFontTemplate(const LLFontDescriptor& desc) | ||
565 | { | ||
566 | const LLFontDescriptor *exact_match_desc = getMatchingFontDesc(desc); | ||
567 | if (exact_match_desc) | ||
568 | { | ||
569 | return exact_match_desc; | ||
570 | } | ||
571 | |||
572 | LLFontDescriptor norm_desc = desc.normalize(); | ||
573 | |||
574 | const LLFontDescriptor *best_match_desc = NULL; | ||
575 | for (font_reg_map_t::iterator it = mFontMap.begin(); | ||
576 | it != mFontMap.end(); | ||
577 | ++it) | ||
578 | { | ||
579 | const LLFontDescriptor* curr_desc = &(it->first); | ||
580 | |||
581 | // Ignore if not a template. | ||
582 | if (!curr_desc->isTemplate()) | ||
583 | continue; | ||
584 | |||
585 | // Ignore if font name is wrong. | ||
586 | if (curr_desc->getName() != norm_desc.getName()) | ||
587 | continue; | ||
588 | |||
589 | // Reject font if it matches any bits we don't want | ||
590 | if (curr_desc->getStyle() & ~norm_desc.getStyle()) | ||
591 | { | ||
592 | continue; | ||
593 | } | ||
594 | |||
595 | // Take if it's the first plausible candidate we've found. | ||
596 | if (!best_match_desc) | ||
597 | { | ||
598 | best_match_desc = curr_desc; | ||
599 | continue; | ||
600 | } | ||
601 | |||
602 | // Take if it matches more bits than anything before. | ||
603 | U8 best_style_match_bits = | ||
604 | norm_desc.getStyle() & best_match_desc->getStyle(); | ||
605 | U8 curr_style_match_bits = | ||
606 | norm_desc.getStyle() & curr_desc->getStyle(); | ||
607 | if (bitCount(curr_style_match_bits) > bitCount(best_style_match_bits)) | ||
608 | { | ||
609 | best_match_desc = curr_desc; | ||
610 | continue; | ||
611 | } | ||
612 | |||
613 | // Tie-breaker: take if it matches bold. | ||
614 | if (curr_style_match_bits & LLFontGL::BOLD) // Bold is requested and this descriptor matches it. | ||
615 | { | ||
616 | best_match_desc = curr_desc; | ||
617 | continue; | ||
618 | } | ||
619 | } | ||
620 | |||
621 | // Nothing matched. | ||
622 | return best_match_desc; | ||
623 | } | ||
624 | |||
625 | void LLFontRegistry::dump() | ||
626 | { | ||
627 | llinfos << "LLFontRegistry dump: " << llendl; | ||
628 | for (font_size_map_t::iterator size_it = mFontSizes.begin(); | ||
629 | size_it != mFontSizes.end(); | ||
630 | ++size_it) | ||
631 | { | ||
632 | llinfos << "Size: " << size_it->first << " => " << size_it->second << llendl; | ||
633 | } | ||
634 | for (font_reg_map_t::iterator font_it = mFontMap.begin(); | ||
635 | font_it != mFontMap.end(); | ||
636 | ++font_it) | ||
637 | { | ||
638 | const LLFontDescriptor& desc = font_it->first; | ||
639 | llinfos << "Font: name=" << desc.getName() | ||
640 | << " style=[" << ((S32)desc.getStyle()) << "]" | ||
641 | << " size=[" << desc.getSize() << "]" | ||
642 | << " fileNames=" | ||
643 | << llendl; | ||
644 | for (string_vec_t::const_iterator file_it=desc.getFileNames().begin(); | ||
645 | file_it != desc.getFileNames().end(); | ||
646 | ++file_it) | ||
647 | { | ||
648 | llinfos << " file: " << *file_it <<llendl; | ||
649 | } | ||
650 | } | ||
651 | } | ||
diff --git a/linden/indra/llrender/llfontregistry.h b/linden/indra/llrender/llfontregistry.h new file mode 100644 index 0000000..523e184 --- /dev/null +++ b/linden/indra/llrender/llfontregistry.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /** | ||
2 | * @file llfontregistry.h | ||
3 | * @author Brad Payne | ||
4 | * @brief Storage for fonts. | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2008-2009, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | #ifndef LL_LLFONTREGISTRY_H | ||
35 | #define LL_LLFONTREGISTRY_H | ||
36 | |||
37 | #include "llxmlnode.h" | ||
38 | |||
39 | class LLFontGL; | ||
40 | |||
41 | typedef std::vector<std::string> string_vec_t; | ||
42 | |||
43 | class LLFontDescriptor | ||
44 | { | ||
45 | public: | ||
46 | LLFontDescriptor(); | ||
47 | LLFontDescriptor(const std::string& name, const std::string& size, const U8 style); | ||
48 | LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const string_vec_t& file_names); | ||
49 | LLFontDescriptor normalize() const; | ||
50 | |||
51 | bool operator<(const LLFontDescriptor& b) const; | ||
52 | |||
53 | bool isTemplate() const; | ||
54 | |||
55 | const std::string& getName() const { return mName; } | ||
56 | void setName(const std::string& name) { mName = name; } | ||
57 | const std::string& getSize() const { return mSize; } | ||
58 | void setSize(const std::string& size) { mSize = size; } | ||
59 | const std::vector<std::string>& getFileNames() const { return mFileNames; } | ||
60 | std::vector<std::string>& getFileNames() { return mFileNames; } | ||
61 | const U8 getStyle() const { return mStyle; } | ||
62 | void setStyle(U8 style) { mStyle = style; } | ||
63 | |||
64 | private: | ||
65 | std::string mName; | ||
66 | std::string mSize; | ||
67 | string_vec_t mFileNames; | ||
68 | U8 mStyle; | ||
69 | }; | ||
70 | |||
71 | class LLFontRegistry | ||
72 | { | ||
73 | public: | ||
74 | LLFontRegistry(const string_vec_t& xui_paths); | ||
75 | ~LLFontRegistry(); | ||
76 | |||
77 | // Load standard font info from XML file(s). | ||
78 | bool parseFontInfo(const std::string& xml_filename); | ||
79 | bool initFromXML(LLXMLNodePtr node); | ||
80 | |||
81 | // Clear cached glyphs for all fonts. | ||
82 | void reset(); | ||
83 | |||
84 | // Destroy all fonts. | ||
85 | void clear(); | ||
86 | |||
87 | // GL cleanup | ||
88 | void destroyGL(); | ||
89 | |||
90 | LLFontGL *getFont(const LLFontDescriptor& desc); | ||
91 | const LLFontDescriptor *getMatchingFontDesc(const LLFontDescriptor& desc); | ||
92 | const LLFontDescriptor *getClosestFontTemplate(const LLFontDescriptor& desc); | ||
93 | |||
94 | bool nameToSize(const std::string& size_name, F32& size); | ||
95 | |||
96 | void dump(); | ||
97 | |||
98 | const string_vec_t& getUltimateFallbackList() const { return mUltimateFallbackList; } | ||
99 | |||
100 | private: | ||
101 | LLFontGL *createFont(const LLFontDescriptor& desc); | ||
102 | typedef std::map<LLFontDescriptor,LLFontGL*> font_reg_map_t; | ||
103 | typedef std::map<std::string,F32> font_size_map_t; | ||
104 | |||
105 | // Given a descriptor, look up specific font instantiation. | ||
106 | font_reg_map_t mFontMap; | ||
107 | // Given a size name, look up the point size. | ||
108 | font_size_map_t mFontSizes; | ||
109 | |||
110 | string_vec_t mUltimateFallbackList; | ||
111 | string_vec_t mXUIPaths; | ||
112 | }; | ||
113 | |||
114 | #endif // LL_LLFONTREGISTRY_H | ||
diff --git a/linden/indra/llrender/llgl.cpp b/linden/indra/llrender/llgl.cpp index a9cf073..61194c4 100644 --- a/linden/indra/llrender/llgl.cpp +++ b/linden/indra/llrender/llgl.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -64,7 +65,7 @@ LLMatrix4 gGLObliqueProjectionInverse; | |||
64 | 65 | ||
65 | LLGLNamePool::pool_list_t LLGLNamePool::sInstances; | 66 | LLGLNamePool::pool_list_t LLGLNamePool::sInstances; |
66 | 67 | ||
67 | #if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS | 68 | #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS |
68 | // ATI prototypes | 69 | // ATI prototypes |
69 | // vertex blending prototypes | 70 | // vertex blending prototypes |
70 | PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL; | 71 | PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL; |
@@ -132,6 +133,15 @@ PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; | |||
132 | PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; | 133 | PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; |
133 | PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; | 134 | PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; |
134 | 135 | ||
136 | // GL_EXT_framebuffer_multisample | ||
137 | PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL; | ||
138 | |||
139 | // GL_EXT_framebuffer_blit | ||
140 | PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL; | ||
141 | |||
142 | // GL_ARB_draw_buffers | ||
143 | PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL; | ||
144 | |||
135 | //shader object prototypes | 145 | //shader object prototypes |
136 | PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL; | 146 | PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL; |
137 | PFNGLGETHANDLEARBPROC glGetHandleARB = NULL; | 147 | PFNGLGETHANDLEARBPROC glGetHandleARB = NULL; |
@@ -174,7 +184,7 @@ PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL; | |||
174 | PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL; | 184 | PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL; |
175 | 185 | ||
176 | // vertex shader prototypes | 186 | // vertex shader prototypes |
177 | #if LL_LINUX | 187 | #if LL_LINUX || LL_SOLARIS |
178 | PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL; | 188 | PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL; |
179 | PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL; | 189 | PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL; |
180 | PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL; | 190 | PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL; |
@@ -193,7 +203,7 @@ PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB = NULL; | |||
193 | PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL; | 203 | PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL; |
194 | PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL; | 204 | PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL; |
195 | PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL; | 205 | PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL; |
196 | #endif // LL_LINUX | 206 | #endif // LL_LINUX || LL_SOLARIS |
197 | PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL; | 207 | PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL; |
198 | PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL; | 208 | PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL; |
199 | PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL; | 209 | PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL; |
@@ -201,7 +211,7 @@ PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB = NULL; | |||
201 | PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL; | 211 | PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL; |
202 | PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL; | 212 | PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL; |
203 | PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL; | 213 | PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL; |
204 | #if LL_LINUX | 214 | #if LL_LINUX || LL_SOLARIS |
205 | PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL; | 215 | PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL; |
206 | PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL; | 216 | PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL; |
207 | PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL; | 217 | PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL; |
@@ -239,7 +249,7 @@ PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB = NULL; | |||
239 | PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL; | 249 | PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL; |
240 | PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL; | 250 | PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL; |
241 | PFNGLISPROGRAMARBPROC glIsProgramARB = NULL; | 251 | PFNGLISPROGRAMARBPROC glIsProgramARB = NULL; |
242 | #endif // LL_LINUX | 252 | #endif // LL_LINUX || LL_SOLARIS |
243 | PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL; | 253 | PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL; |
244 | PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL; | 254 | PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL; |
245 | PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL; | 255 | PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL; |
@@ -248,10 +258,12 @@ PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL; | |||
248 | PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; | 258 | PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; |
249 | #endif | 259 | #endif |
250 | 260 | ||
251 | #if LL_LINUX | 261 | #if LL_LINUX_NV_GL_HEADERS |
252 | PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL; | 262 | // linux nvidia headers. these define these differently to mesa's. ugh. |
253 | #endif // LL_LINUX | 263 | PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL; |
254 | 264 | PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL; | |
265 | PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL; | ||
266 | #endif // LL_LINUX_NV_GL_HEADERS | ||
255 | #endif | 267 | #endif |
256 | 268 | ||
257 | LLGLManager gGLManager; | 269 | LLGLManager gGLManager; |
@@ -265,6 +277,7 @@ LLGLManager::LLGLManager() : | |||
265 | mHasMipMapGeneration(FALSE), | 277 | mHasMipMapGeneration(FALSE), |
266 | mHasCompressedTextures(FALSE), | 278 | mHasCompressedTextures(FALSE), |
267 | mHasFramebufferObject(FALSE), | 279 | mHasFramebufferObject(FALSE), |
280 | mHasFramebufferMultisample(FALSE), | ||
268 | 281 | ||
269 | mHasVertexBufferObject(FALSE), | 282 | mHasVertexBufferObject(FALSE), |
270 | mHasPBuffer(FALSE), | 283 | mHasPBuffer(FALSE), |
@@ -489,7 +502,7 @@ std::string LLGLManager::getGLInfoString() | |||
489 | info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n"); | 502 | info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n"); |
490 | info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n"); | 503 | info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n"); |
491 | 504 | ||
492 | #if !LL_MESA_HEADLESS | 505 | #if !LL_MESA_HEADLESS |
493 | all_exts = (const char *)gGLHExts.mSysExts; | 506 | all_exts = (const char *)gGLHExts.mSysExts; |
494 | LLStringUtil::replaceChar(all_exts, ' ', '\n'); | 507 | LLStringUtil::replaceChar(all_exts, ' ', '\n'); |
495 | info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n"); | 508 | info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n"); |
@@ -564,6 +577,16 @@ void LLGLManager::initExtensions() | |||
564 | # else | 577 | # else |
565 | mHasFramebufferObject = FALSE; | 578 | mHasFramebufferObject = FALSE; |
566 | # endif | 579 | # endif |
580 | # if GL_EXT_framebuffer_multisample | ||
581 | mHasFramebufferMultisample = TRUE; | ||
582 | # else | ||
583 | mHasFramebufferMultisample = FALSE; | ||
584 | # endif | ||
585 | # if GL_ARB_draw_buffers | ||
586 | mHasDrawBuffers = TRUE; | ||
587 | #else | ||
588 | mHasDrawBuffers = FALSE; | ||
589 | # endif | ||
567 | mHasMipMapGeneration = FALSE; | 590 | mHasMipMapGeneration = FALSE; |
568 | mHasSeparateSpecularColor = FALSE; | 591 | mHasSeparateSpecularColor = FALSE; |
569 | mHasAnisotropic = FALSE; | 592 | mHasAnisotropic = FALSE; |
@@ -587,6 +610,8 @@ void LLGLManager::initExtensions() | |||
587 | // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad | 610 | // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad |
588 | mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) | 611 | mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) |
589 | && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); | 612 | && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); |
613 | mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); | ||
614 | mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); | ||
590 | #if !LL_DARWIN | 615 | #if !LL_DARWIN |
591 | mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); | 616 | mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); |
592 | #endif | 617 | #endif |
@@ -596,7 +621,8 @@ void LLGLManager::initExtensions() | |||
596 | mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts); | 621 | mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts); |
597 | #endif | 622 | #endif |
598 | 623 | ||
599 | #if LL_LINUX | 624 | #if LL_LINUX || LL_SOLARIS |
625 | llinfos << "initExtensions() checking shell variables to adjust features..." << llendl; | ||
600 | // Our extension support for the Linux Client is very young with some | 626 | // Our extension support for the Linux Client is very young with some |
601 | // potential driver gotchas, so offer a semi-secret way to turn it off. | 627 | // potential driver gotchas, so offer a semi-secret way to turn it off. |
602 | if (getenv("LL_GL_NOEXT")) /* Flawfinder: ignore */ | 628 | if (getenv("LL_GL_NOEXT")) /* Flawfinder: ignore */ |
@@ -606,6 +632,8 @@ void LLGLManager::initExtensions() | |||
606 | mHasCompressedTextures = FALSE; | 632 | mHasCompressedTextures = FALSE; |
607 | mHasVertexBufferObject = FALSE; | 633 | mHasVertexBufferObject = FALSE; |
608 | mHasFramebufferObject = FALSE; | 634 | mHasFramebufferObject = FALSE; |
635 | mHasFramebufferMultisample = FALSE; | ||
636 | mHasDrawBuffers = FALSE; | ||
609 | mHasMipMapGeneration = FALSE; | 637 | mHasMipMapGeneration = FALSE; |
610 | mHasSeparateSpecularColor = FALSE; | 638 | mHasSeparateSpecularColor = FALSE; |
611 | mHasAnisotropic = FALSE; | 639 | mHasAnisotropic = FALSE; |
@@ -655,8 +683,11 @@ void LLGLManager::initExtensions() | |||
655 | if (strchr(blacklist,'o')) mHasFragmentShader = FALSE;//S | 683 | if (strchr(blacklist,'o')) mHasFragmentShader = FALSE;//S |
656 | if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S | 684 | if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S |
657 | if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S | 685 | if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S |
686 | if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S | ||
687 | if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE; | ||
688 | |||
658 | } | 689 | } |
659 | #endif // LL_LINUX | 690 | #endif // LL_LINUX || LL_SOLARIS |
660 | 691 | ||
661 | if (!mHasMultitexture) | 692 | if (!mHasMultitexture) |
662 | { | 693 | { |
@@ -719,7 +750,7 @@ void LLGLManager::initExtensions() | |||
719 | glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange); | 750 | glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange); |
720 | glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange); | 751 | glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange); |
721 | 752 | ||
722 | #if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS | 753 | #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS |
723 | LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL; | 754 | LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL; |
724 | if (mHasVertexBufferObject) | 755 | if (mHasVertexBufferObject) |
725 | { | 756 | { |
@@ -744,6 +775,7 @@ void LLGLManager::initExtensions() | |||
744 | } | 775 | } |
745 | if (mHasFramebufferObject) | 776 | if (mHasFramebufferObject) |
746 | { | 777 | { |
778 | llinfos << "initExtensions() FramebufferObject-related procs..." << llendl; | ||
747 | glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbufferEXT"); | 779 | glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbufferEXT"); |
748 | glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbufferEXT"); | 780 | glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbufferEXT"); |
749 | glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffersEXT"); | 781 | glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffersEXT"); |
@@ -762,18 +794,33 @@ void LLGLManager::initExtensions() | |||
762 | glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT"); | 794 | glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT"); |
763 | glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT"); | 795 | glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT"); |
764 | } | 796 | } |
765 | #if !LL_LINUX | 797 | if (mHasFramebufferMultisample) |
766 | // This is expected to be a static symbol on Linux GL implementations | 798 | { |
799 | glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT"); | ||
800 | glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebufferEXT"); | ||
801 | } | ||
802 | if (mHasDrawBuffers) | ||
803 | { | ||
804 | glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB"); | ||
805 | } | ||
806 | #if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS | ||
807 | // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah | ||
767 | glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); | 808 | glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); |
768 | if (!glDrawRangeElements) | 809 | if (!glDrawRangeElements) |
769 | { | 810 | { |
770 | mGLMaxVertexRange = 0; | 811 | mGLMaxVertexRange = 0; |
771 | mGLMaxIndexRange = 0; | 812 | mGLMaxIndexRange = 0; |
772 | } | 813 | } |
773 | #endif // !LL_LINUX | 814 | #endif // !LL_LINUX || LL_LINUX_NV_GL_HEADERS |
815 | #if LL_LINUX_NV_GL_HEADERS | ||
816 | // nvidia headers are critically different from mesa-esque | ||
817 | glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glActiveTextureARB"); | ||
818 | glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)GLH_EXT_GET_PROC_ADDRESS("glClientActiveTextureARB"); | ||
819 | #endif // LL_LINUX_NV_GL_HEADERS | ||
774 | 820 | ||
775 | if (mHasOcclusionQuery) | 821 | if (mHasOcclusionQuery) |
776 | { | 822 | { |
823 | llinfos << "initExtensions() OcclusionQuery-related procs..." << llendl; | ||
777 | glGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueriesARB"); | 824 | glGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueriesARB"); |
778 | glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueriesARB"); | 825 | glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueriesARB"); |
779 | glIsQueryARB = (PFNGLISQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQueryARB"); | 826 | glIsQueryARB = (PFNGLISQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQueryARB"); |
@@ -785,6 +832,7 @@ void LLGLManager::initExtensions() | |||
785 | } | 832 | } |
786 | if (mHasPointParameters) | 833 | if (mHasPointParameters) |
787 | { | 834 | { |
835 | llinfos << "initExtensions() PointParameters-related procs..." << llendl; | ||
788 | glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB"); | 836 | glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB"); |
789 | glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB"); | 837 | glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB"); |
790 | } | 838 | } |
@@ -832,6 +880,7 @@ void LLGLManager::initExtensions() | |||
832 | } | 880 | } |
833 | if (mHasVertexShader) | 881 | if (mHasVertexShader) |
834 | { | 882 | { |
883 | llinfos << "initExtensions() VertexShader-related procs..." << llendl; | ||
835 | glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); | 884 | glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB"); |
836 | glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); | 885 | glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB"); |
837 | glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB"); | 886 | glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB"); |
@@ -944,7 +993,7 @@ void assert_glerror() | |||
944 | { | 993 | { |
945 | // gluErrorString returns NULL for some extensions' error codes. | 994 | // gluErrorString returns NULL for some extensions' error codes. |
946 | // you'll probably have to grep for the number in glext.h. | 995 | // you'll probably have to grep for the number in glext.h. |
947 | LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << LL_ENDL; | 996 | LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL; |
948 | } | 997 | } |
949 | error = glGetError(); | 998 | error = glGetError(); |
950 | #endif | 999 | #endif |
@@ -980,12 +1029,14 @@ void LLGLState::initClass() | |||
980 | { | 1029 | { |
981 | sStateMap[GL_DITHER] = GL_TRUE; | 1030 | sStateMap[GL_DITHER] = GL_TRUE; |
982 | // sStateMap[GL_TEXTURE_2D] = GL_TRUE; | 1031 | // sStateMap[GL_TEXTURE_2D] = GL_TRUE; |
983 | 1032 | ||
984 | //make sure multisample defaults to disabled | 1033 | //make sure multisample defaults to disabled |
985 | sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; | 1034 | sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; |
986 | glDisable(GL_MULTISAMPLE_ARB); | 1035 | glDisable(GL_MULTISAMPLE_ARB); |
987 | 1036 | ||
988 | //default vertex arrays to enabled. | 1037 | sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; |
1038 | glDisable(GL_MULTISAMPLE_ARB); | ||
1039 | |||
989 | glEnableClientState(GL_VERTEX_ARRAY); | 1040 | glEnableClientState(GL_VERTEX_ARRAY); |
990 | } | 1041 | } |
991 | 1042 | ||
@@ -1038,7 +1089,7 @@ void LLGLState::checkStates(const std::string& msg) | |||
1038 | 1089 | ||
1039 | if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) | 1090 | if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) |
1040 | { | 1091 | { |
1041 | LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << LL_ENDL; | 1092 | LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; |
1042 | } | 1093 | } |
1043 | 1094 | ||
1044 | for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin(); | 1095 | for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin(); |
@@ -1077,7 +1128,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) | |||
1077 | if (tex_env_mode != GL_MODULATE) | 1128 | if (tex_env_mode != GL_MODULATE) |
1078 | { | 1129 | { |
1079 | error = TRUE; | 1130 | error = TRUE; |
1080 | LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << LL_ENDL; | 1131 | LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL; |
1081 | } | 1132 | } |
1082 | } | 1133 | } |
1083 | 1134 | ||
@@ -1093,7 +1144,8 @@ void LLGLState::checkTextureChannels(const std::string& msg) | |||
1093 | "GL_TEXTURE_GEN_S", | 1144 | "GL_TEXTURE_GEN_S", |
1094 | "GL_TEXTURE_GEN_T", | 1145 | "GL_TEXTURE_GEN_T", |
1095 | "GL_TEXTURE_GEN_Q", | 1146 | "GL_TEXTURE_GEN_Q", |
1096 | "GL_TEXTURE_GEN_R" | 1147 | "GL_TEXTURE_GEN_R", |
1148 | "GL_TEXTURE_RECTANGLE_ARB" | ||
1097 | }; | 1149 | }; |
1098 | 1150 | ||
1099 | static GLint value[] = | 1151 | static GLint value[] = |
@@ -1105,7 +1157,8 @@ void LLGLState::checkTextureChannels(const std::string& msg) | |||
1105 | GL_TEXTURE_GEN_S, | 1157 | GL_TEXTURE_GEN_S, |
1106 | GL_TEXTURE_GEN_T, | 1158 | GL_TEXTURE_GEN_T, |
1107 | GL_TEXTURE_GEN_Q, | 1159 | GL_TEXTURE_GEN_Q, |
1108 | GL_TEXTURE_GEN_R | 1160 | GL_TEXTURE_GEN_R, |
1161 | GL_TEXTURE_RECTANGLE_ARB | ||
1109 | }; | 1162 | }; |
1110 | 1163 | ||
1111 | GLint stackDepth = 0; | 1164 | GLint stackDepth = 0; |
@@ -1133,7 +1186,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) | |||
1133 | LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; | 1186 | LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; |
1134 | } | 1187 | } |
1135 | 1188 | ||
1136 | for (S32 j = (i == 0 ? 1 : 0); j < 8; j++) | 1189 | for (S32 j = (i == 0 ? 1 : 0); j < 9; j++) |
1137 | { | 1190 | { |
1138 | if (glIsEnabled(value[j])) | 1191 | if (glIsEnabled(value[j])) |
1139 | { | 1192 | { |
@@ -1141,6 +1194,18 @@ void LLGLState::checkTextureChannels(const std::string& msg) | |||
1141 | LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL; | 1194 | LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL; |
1142 | } | 1195 | } |
1143 | } | 1196 | } |
1197 | |||
1198 | glh::matrix4f mat; | ||
1199 | glh::matrix4f identity; | ||
1200 | identity.identity(); | ||
1201 | |||
1202 | glGetFloatv(GL_TEXTURE_MATRIX, mat.m); | ||
1203 | |||
1204 | if (mat != identity) | ||
1205 | { | ||
1206 | error = TRUE; | ||
1207 | LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL; | ||
1208 | } | ||
1144 | } | 1209 | } |
1145 | 1210 | ||
1146 | gGL.getTexUnit(0)->activate(); | 1211 | gGL.getTexUnit(0)->activate(); |
@@ -1262,6 +1327,22 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) | |||
1262 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | 1327 | glClientActiveTextureARB(GL_TEXTURE0_ARB); |
1263 | gGL.getTexUnit(0)->activate(); | 1328 | gGL.getTexUnit(0)->activate(); |
1264 | 1329 | ||
1330 | if (gGLManager.mHasVertexShader) | ||
1331 | { //make sure vertex attribs are all disabled | ||
1332 | GLint count; | ||
1333 | glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &count); | ||
1334 | for (GLint i = 0; i < count; i++) | ||
1335 | { | ||
1336 | GLint enabled; | ||
1337 | glGetVertexAttribivARB((GLuint) i, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &enabled); | ||
1338 | if (enabled) | ||
1339 | { | ||
1340 | error = TRUE; | ||
1341 | LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL; | ||
1342 | } | ||
1343 | } | ||
1344 | } | ||
1345 | |||
1265 | if (error) | 1346 | if (error) |
1266 | { | 1347 | { |
1267 | LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; | 1348 | LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; |
@@ -1647,6 +1728,7 @@ void LLGLNamePool::cleanupPools() | |||
1647 | LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, GLenum depth_func) | 1728 | LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, GLenum depth_func) |
1648 | : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled) | 1729 | : mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled) |
1649 | { | 1730 | { |
1731 | stop_glerror(); | ||
1650 | if (depth_enabled != sDepthEnabled) | 1732 | if (depth_enabled != sDepthEnabled) |
1651 | { | 1733 | { |
1652 | gGL.flush(); | 1734 | gGL.flush(); |
diff --git a/linden/indra/llrender/llgl.h b/linden/indra/llrender/llgl.h index 011fd63..00ff1e2 100644 --- a/linden/indra/llrender/llgl.h +++ b/linden/indra/llrender/llgl.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -76,7 +77,8 @@ public: | |||
76 | BOOL mHasMipMapGeneration; | 77 | BOOL mHasMipMapGeneration; |
77 | BOOL mHasCompressedTextures; | 78 | BOOL mHasCompressedTextures; |
78 | BOOL mHasFramebufferObject; | 79 | BOOL mHasFramebufferObject; |
79 | 80 | BOOL mHasFramebufferMultisample; | |
81 | |||
80 | // ARB Extensions | 82 | // ARB Extensions |
81 | BOOL mHasVertexBufferObject; | 83 | BOOL mHasVertexBufferObject; |
82 | BOOL mHasPBuffer; | 84 | BOOL mHasPBuffer; |
@@ -85,6 +87,7 @@ public: | |||
85 | BOOL mHasFragmentShader; | 87 | BOOL mHasFragmentShader; |
86 | BOOL mHasOcclusionQuery; | 88 | BOOL mHasOcclusionQuery; |
87 | BOOL mHasPointParameters; | 89 | BOOL mHasPointParameters; |
90 | BOOL mHasDrawBuffers; | ||
88 | 91 | ||
89 | // Other extensions. | 92 | // Other extensions. |
90 | BOOL mHasAnisotropic; | 93 | BOOL mHasAnisotropic; |
diff --git a/linden/indra/llrender/llgldbg.cpp b/linden/indra/llrender/llgldbg.cpp index 27b45a9..c54ab18 100644 --- a/linden/indra/llrender/llgldbg.cpp +++ b/linden/indra/llrender/llgldbg.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llrender/llgldbg.h b/linden/indra/llrender/llgldbg.h index 73ab7fc..d989091 100644 --- a/linden/indra/llrender/llgldbg.h +++ b/linden/indra/llrender/llgldbg.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llrender/llglheaders.h b/linden/indra/llrender/llglheaders.h index 20a420b..c7178a5 100644 --- a/linden/indra/llrender/llglheaders.h +++ b/linden/indra/llrender/llglheaders.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -32,11 +33,215 @@ | |||
32 | #ifndef LL_LLGLHEADERS_H | 33 | #ifndef LL_LLGLHEADERS_H |
33 | #define LL_LLGLHEADERS_H | 34 | #define LL_LLGLHEADERS_H |
34 | 35 | ||
35 | #if LL_MESA | 36 | #if LL_SOLARIS |
37 | # if defined(__sparc) | ||
38 | # define I_NEED_OS2_H // avoiding BOOL conflicts | ||
39 | # endif | ||
40 | # include "GL/gl.h" | ||
41 | # if defined(__sparc) | ||
42 | # undef I_NEED_OS2_H | ||
43 | # ifdef BOOL | ||
44 | # undef BOOL // now get rid of Xmd.h crap | ||
45 | # endif | ||
46 | # endif | ||
47 | # include "GL/glx.h" | ||
48 | # define GL_GLEXT_PROTOTYPES 1 | ||
49 | # include "GL/glext.h" | ||
50 | # include "GL/glu.h" | ||
51 | # include "GL/glx.h" | ||
52 | # define GLX_GLXEXT_PROTOTYPES 1 | ||
53 | # include "GL/glxext.h" | ||
54 | //# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p)) | ||
55 | # define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddress((const GLubyte*)(p)) | ||
56 | // the X headers define 'Status'. Undefine to avoid confusion. | ||
57 | #undef Status | ||
58 | |||
59 | // The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly | ||
60 | // This header is distributed with SL. You'll find it in linden/libraries/include/GL/ | ||
61 | # define __APPLE__ | ||
62 | # include "GL/glh_extensions.h" | ||
63 | # undef __APPLE__ | ||
64 | |||
65 | |||
66 | // GL_ARB_vertex_buffer_object | ||
67 | extern PFNGLBINDBUFFERARBPROC glBindBufferARB; | ||
68 | extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB; | ||
69 | extern PFNGLGENBUFFERSARBPROC glGenBuffersARB; | ||
70 | extern PFNGLISBUFFERARBPROC glIsBufferARB; | ||
71 | extern PFNGLBUFFERDATAARBPROC glBufferDataARB; | ||
72 | extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB; | ||
73 | extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB; | ||
74 | extern PFNGLMAPBUFFERARBPROC glMapBufferARB; | ||
75 | extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; | ||
76 | extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; | ||
77 | extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; | ||
78 | |||
79 | // GL_ATI_vertex_array_object | ||
80 | extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; | ||
81 | extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; | ||
82 | extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI; | ||
83 | extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI; | ||
84 | extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI; | ||
85 | extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI; | ||
86 | extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI; | ||
87 | extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI; | ||
88 | extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI; | ||
89 | extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI; | ||
90 | extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI; | ||
91 | extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI; | ||
92 | extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI; | ||
93 | |||
94 | // GL_ARB_occlusion_query | ||
95 | extern PFNGLGENQUERIESARBPROC glGenQueriesARB; | ||
96 | extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB; | ||
97 | extern PFNGLISQUERYARBPROC glIsQueryARB; | ||
98 | extern PFNGLBEGINQUERYARBPROC glBeginQueryARB; | ||
99 | extern PFNGLENDQUERYARBPROC glEndQueryARB; | ||
100 | extern PFNGLGETQUERYIVARBPROC glGetQueryivARB; | ||
101 | extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB; | ||
102 | extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB; | ||
103 | |||
104 | // GL_ARB_point_parameters | ||
105 | extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB; | ||
106 | extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB; | ||
107 | |||
108 | // GL_ARB_shader_objects | ||
109 | extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; | ||
110 | extern PFNGLGETHANDLEARBPROC glGetHandleARB; | ||
111 | extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB; | ||
112 | extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; | ||
113 | extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB; | ||
114 | extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB; | ||
115 | extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; | ||
116 | extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB; | ||
117 | extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB; | ||
118 | extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; | ||
119 | extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB; | ||
120 | extern PFNGLUNIFORM1FARBPROC glUniform1fARB; | ||
121 | extern PFNGLUNIFORM2FARBPROC glUniform2fARB; | ||
122 | extern PFNGLUNIFORM3FARBPROC glUniform3fARB; | ||
123 | extern PFNGLUNIFORM4FARBPROC glUniform4fARB; | ||
124 | extern PFNGLUNIFORM1IARBPROC glUniform1iARB; | ||
125 | extern PFNGLUNIFORM2IARBPROC glUniform2iARB; | ||
126 | extern PFNGLUNIFORM3IARBPROC glUniform3iARB; | ||
127 | extern PFNGLUNIFORM4IARBPROC glUniform4iARB; | ||
128 | extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB; | ||
129 | extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB; | ||
130 | extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB; | ||
131 | extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB; | ||
132 | extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB; | ||
133 | extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB; | ||
134 | extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB; | ||
135 | extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB; | ||
136 | extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB; | ||
137 | extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB; | ||
138 | extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB; | ||
139 | extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB; | ||
140 | extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; | ||
141 | extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB; | ||
142 | extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB; | ||
143 | extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; | ||
144 | extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB; | ||
145 | extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB; | ||
146 | extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB; | ||
147 | extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB; | ||
148 | |||
149 | // GL_ARB_vertex_shader | ||
150 | extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB; | ||
151 | extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB; | ||
152 | extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB; | ||
153 | extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB; | ||
154 | extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB; | ||
155 | extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB; | ||
156 | extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB; | ||
157 | extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB; | ||
158 | extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB; | ||
159 | extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB; | ||
160 | extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB; | ||
161 | extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB; | ||
162 | extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB; | ||
163 | extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB; | ||
164 | extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB; | ||
165 | extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB; | ||
166 | extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB; | ||
167 | extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB; | ||
168 | extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB; | ||
169 | extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB; | ||
170 | extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB; | ||
171 | extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB; | ||
172 | extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB; | ||
173 | extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB; | ||
174 | extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB; | ||
175 | extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB; | ||
176 | extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB; | ||
177 | extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB; | ||
178 | extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB; | ||
179 | extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB; | ||
180 | extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB; | ||
181 | extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB; | ||
182 | extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB; | ||
183 | extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB; | ||
184 | extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB; | ||
185 | extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB; | ||
186 | extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB; | ||
187 | extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB; | ||
188 | extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB; | ||
189 | extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; | ||
190 | extern PFNGLBINDPROGRAMARBPROC glBindProgramARB; | ||
191 | extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB; | ||
192 | extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB; | ||
193 | extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB; | ||
194 | extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB; | ||
195 | extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB; | ||
196 | extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB; | ||
197 | extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB; | ||
198 | extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB; | ||
199 | extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB; | ||
200 | extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB; | ||
201 | extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB; | ||
202 | extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB; | ||
203 | extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB; | ||
204 | extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB; | ||
205 | extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB; | ||
206 | extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB; | ||
207 | extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB; | ||
208 | extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB; | ||
209 | extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB; | ||
210 | extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB; | ||
211 | extern PFNGLISPROGRAMARBPROC glIsProgramARB; | ||
212 | extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB; | ||
213 | extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB; | ||
214 | extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; | ||
215 | |||
216 | extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; | ||
217 | extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; | ||
218 | |||
219 | extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; | ||
220 | |||
221 | //GL_EXT_framebuffer_object | ||
222 | extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; | ||
223 | extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; | ||
224 | extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; | ||
225 | extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; | ||
226 | extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; | ||
227 | extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; | ||
228 | extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; | ||
229 | extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; | ||
230 | extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; | ||
231 | extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; | ||
232 | extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; | ||
233 | extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; | ||
234 | extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; | ||
235 | extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; | ||
236 | extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; | ||
237 | extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; | ||
238 | extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; | ||
239 | |||
240 | #elif LL_MESA | ||
36 | //---------------------------------------------------------------------------- | 241 | //---------------------------------------------------------------------------- |
37 | // MESA headers | 242 | // MESA headers |
38 | // quotes so we get libraries/.../GL/ version | 243 | // quotes so we get libraries/.../GL/ version |
39 | #define GL_GLEXT_PROTOTYPES | 244 | #define GL_GLEXT_PROTOTYPES 1 |
40 | #include "GL/gl.h" | 245 | #include "GL/gl.h" |
41 | #include "GL/glext.h" | 246 | #include "GL/glext.h" |
42 | #include "GL/glu.h" | 247 | #include "GL/glu.h" |
@@ -46,7 +251,7 @@ | |||
46 | # include "GL/glh_extensions.h" | 251 | # include "GL/glh_extensions.h" |
47 | # undef __APPLE__ | 252 | # undef __APPLE__ |
48 | 253 | ||
49 | #elif LL_LINUX | 254 | #elif LL_LINUX |
50 | //---------------------------------------------------------------------------- | 255 | //---------------------------------------------------------------------------- |
51 | // Linux, MESA headers, but not necessarily assuming MESA runtime. | 256 | // Linux, MESA headers, but not necessarily assuming MESA runtime. |
52 | // quotes so we get libraries/.../GL/ version | 257 | // quotes so we get libraries/.../GL/ version |
@@ -76,6 +281,20 @@ | |||
76 | #undef Status | 281 | #undef Status |
77 | #endif // LL_LINUX && !LL_MESA_HEADLESS | 282 | #endif // LL_LINUX && !LL_MESA_HEADLESS |
78 | 283 | ||
284 | #if LL_LINUX && defined(WINGDIAPI) | ||
285 | // WINGDIAPI gets set if we are using the linux nvidia gl.h header which needs | ||
286 | // the functions below setting up. | ||
287 | # define LL_LINUX_NV_GL_HEADERS 1 | ||
288 | #else | ||
289 | # define LL_LINUX_NV_GL_HEADERS 0 | ||
290 | #endif // LL_LINUX && defined(WINGDIAPI) | ||
291 | |||
292 | #if LL_LINUX_NV_GL_HEADERS | ||
293 | // Missing functions when using nvidia headers: | ||
294 | extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; | ||
295 | extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB; | ||
296 | extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements; | ||
297 | #endif // LL_LINUX_NV_GL_HEADERS | ||
79 | 298 | ||
80 | // GL_ARB_vertex_buffer_object | 299 | // GL_ARB_vertex_buffer_object |
81 | extern PFNGLBINDBUFFERARBPROC glBindBufferARB; | 300 | extern PFNGLBINDBUFFERARBPROC glBindBufferARB; |
@@ -230,8 +449,6 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; | |||
230 | extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; | 449 | extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; |
231 | extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; | 450 | extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; |
232 | 451 | ||
233 | extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; | ||
234 | |||
235 | //GL_EXT_framebuffer_object | 452 | //GL_EXT_framebuffer_object |
236 | extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; | 453 | extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; |
237 | extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; | 454 | extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; |
@@ -251,6 +468,14 @@ extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; | |||
251 | extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; | 468 | extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; |
252 | extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; | 469 | extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; |
253 | 470 | ||
471 | // GL_EXT_framebuffer_multisample | ||
472 | extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; | ||
473 | |||
474 | // GL_EXT_framebuffer_blit | ||
475 | extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; | ||
476 | |||
477 | //GL_ARB_draw_buffers | ||
478 | extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; | ||
254 | 479 | ||
255 | #elif LL_WINDOWS | 480 | #elif LL_WINDOWS |
256 | 481 | ||
@@ -439,6 +664,14 @@ extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; | |||
439 | extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; | 664 | extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; |
440 | extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; | 665 | extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; |
441 | 666 | ||
667 | // GL_EXT_framebuffer_multisample | ||
668 | extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; | ||
669 | |||
670 | // GL_EXT_framebuffer_blit | ||
671 | extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; | ||
672 | |||
673 | //GL_ARB_draw_buffers | ||
674 | extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; | ||
442 | 675 | ||
443 | #elif LL_DARWIN | 676 | #elif LL_DARWIN |
444 | //---------------------------------------------------------------------------- | 677 | //---------------------------------------------------------------------------- |
@@ -475,6 +708,8 @@ extern void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenu | |||
475 | extern void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; | 708 | extern void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; |
476 | extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; | 709 | extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; |
477 | 710 | ||
711 | // GL_ARB_draw_buffers | ||
712 | extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; | ||
478 | 713 | ||
479 | #ifdef __cplusplus | 714 | #ifdef __cplusplus |
480 | extern "C" { | 715 | extern "C" { |
diff --git a/linden/indra/llrender/llglimmediate.cpp b/linden/indra/llrender/llglimmediate.cpp index bade1aa..17c2182 100644 --- a/linden/indra/llrender/llglimmediate.cpp +++ b/linden/indra/llrender/llglimmediate.cpp | |||
@@ -1,265 +1 @@ | |||
1 | <<<<<<< .working | ||
2 | #error This file has been renamed llrender.cpp | #error This file has been renamed llrender.cpp | |
3 | ======= | ||
4 | /** | ||
5 | * @file llglimmediate.cpp | ||
6 | * @brief LLGLImmediate implementation | ||
7 | * | ||
8 | * $LicenseInfo:firstyear=2001&license=viewergpl$ | ||
9 | * | ||
10 | * Copyright (c) 2001-2009, Linden Research, Inc. | ||
11 | * | ||
12 | * Second Life Viewer Source Code | ||
13 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
14 | * to you under the terms of the GNU General Public License, version 2.0 | ||
15 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
16 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
17 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
18 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
19 | * | ||
20 | * There are special exceptions to the terms and conditions of the GPL as | ||
21 | * it is applied to this Source Code. View the full text of the exception | ||
22 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
23 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
24 | * | ||
25 | * By copying, modifying or distributing this software, you acknowledge | ||
26 | * that you have read and understood your obligations described above, | ||
27 | * and agree to abide by those obligations. | ||
28 | * | ||
29 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
30 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
31 | * COMPLETENESS OR PERFORMANCE. | ||
32 | * $/LicenseInfo$ | ||
33 | */ | ||
34 | |||
35 | #include "linden_common.h" | ||
36 | |||
37 | #include "llglimmediate.h" | ||
38 | #include "llvertexbuffer.h" | ||
39 | |||
40 | LLGLImmediate gGL; | ||
41 | |||
42 | const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD; | ||
43 | |||
44 | LLGLImmediate::LLGLImmediate() | ||
45 | { | ||
46 | mCount = 0; | ||
47 | mMode = LLVertexBuffer::TRIANGLES; | ||
48 | mBuffer = new LLVertexBuffer(immediate_mask, 0); | ||
49 | mBuffer->allocateBuffer(4096, 0, TRUE); | ||
50 | mBuffer->getVertexStrider(mVerticesp); | ||
51 | mBuffer->getTexCoordStrider(mTexcoordsp); | ||
52 | mBuffer->getColorStrider(mColorsp); | ||
53 | } | ||
54 | |||
55 | void LLGLImmediate::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) | ||
56 | { | ||
57 | flush(); | ||
58 | glTranslatef(x,y,z); | ||
59 | } | ||
60 | |||
61 | void LLGLImmediate::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z) | ||
62 | { | ||
63 | flush(); | ||
64 | glScalef(x,y,z); | ||
65 | } | ||
66 | |||
67 | void LLGLImmediate::pushMatrix() | ||
68 | { | ||
69 | flush(); | ||
70 | glPushMatrix(); | ||
71 | } | ||
72 | |||
73 | void LLGLImmediate::popMatrix() | ||
74 | { | ||
75 | flush(); | ||
76 | glPopMatrix(); | ||
77 | } | ||
78 | |||
79 | void LLGLImmediate::blendFunc(GLenum sfactor, GLenum dfactor) | ||
80 | { | ||
81 | flush(); | ||
82 | glBlendFunc(sfactor, dfactor); | ||
83 | } | ||
84 | |||
85 | void LLGLImmediate::begin(const GLuint& mode) | ||
86 | { | ||
87 | if (mode != mMode) | ||
88 | { | ||
89 | if (mMode == LLVertexBuffer::QUADS || | ||
90 | mMode == LLVertexBuffer::LINES || | ||
91 | mMode == LLVertexBuffer::TRIANGLES || | ||
92 | mMode == LLVertexBuffer::POINTS) | ||
93 | { | ||
94 | flush(); | ||
95 | } | ||
96 | else if (mCount != 0) | ||
97 | { | ||
98 | llerrs << "gGL.begin() called redundantly." << llendl; | ||
99 | } | ||
100 | |||
101 | mMode = mode; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | void LLGLImmediate::end() | ||
106 | { | ||
107 | if (mCount == 0) | ||
108 | { | ||
109 | return; | ||
110 | //IMM_ERRS << "GL begin and end called with no vertices specified." << llendl; | ||
111 | } | ||
112 | |||
113 | if ((mMode != LLVertexBuffer::QUADS && | ||
114 | mMode != LLVertexBuffer::LINES && | ||
115 | mMode != LLVertexBuffer::TRIANGLES && | ||
116 | mMode != LLVertexBuffer::POINTS) || | ||
117 | mCount > 2048) | ||
118 | { | ||
119 | flush(); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | void LLGLImmediate::flush() | ||
124 | { | ||
125 | if (mCount > 0) | ||
126 | { | ||
127 | #if 0 | ||
128 | if (!glIsEnabled(GL_VERTEX_ARRAY)) | ||
129 | { | ||
130 | llerrs << "foo 1" << llendl; | ||
131 | } | ||
132 | |||
133 | if (!glIsEnabled(GL_COLOR_ARRAY)) | ||
134 | { | ||
135 | llerrs << "foo 2" << llendl; | ||
136 | } | ||
137 | |||
138 | if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY)) | ||
139 | { | ||
140 | llerrs << "foo 3" << llendl; | ||
141 | } | ||
142 | |||
143 | if (glIsEnabled(GL_NORMAL_ARRAY)) | ||
144 | { | ||
145 | llerrs << "foo 7" << llendl; | ||
146 | } | ||
147 | |||
148 | GLvoid* pointer; | ||
149 | |||
150 | glGetPointerv(GL_VERTEX_ARRAY_POINTER, &pointer); | ||
151 | if (pointer != &(mBuffer[0].v)) | ||
152 | { | ||
153 | llerrs << "foo 4" << llendl; | ||
154 | } | ||
155 | |||
156 | glGetPointerv(GL_COLOR_ARRAY_POINTER, &pointer); | ||
157 | if (pointer != &(mBuffer[0].c)) | ||
158 | { | ||
159 | llerrs << "foo 5" << llendl; | ||
160 | } | ||
161 | |||
162 | glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &pointer); | ||
163 | if (pointer != &(mBuffer[0].uv)) | ||
164 | { | ||
165 | llerrs << "foo 6" << llendl; | ||
166 | } | ||
167 | #endif | ||
168 | |||
169 | mBuffer->setBuffer(immediate_mask); | ||
170 | mBuffer->drawArrays(mMode, 0, mCount); | ||
171 | |||
172 | mVerticesp[0] = mVerticesp[mCount]; | ||
173 | mTexcoordsp[0] = mTexcoordsp[mCount]; | ||
174 | mColorsp[0] = mColorsp[mCount]; | ||
175 | mCount = 0; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | void LLGLImmediate::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) | ||
180 | { | ||
181 | if (mCount >= 4096) | ||
182 | { | ||
183 | // llwarns << "GL immediate mode overflow. Some geometry not drawn." << llendl; | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | mVerticesp[mCount] = LLVector3(x,y,z); | ||
188 | mCount++; | ||
189 | if (mCount < 4096) | ||
190 | { | ||
191 | mVerticesp[mCount] = mVerticesp[mCount-1]; | ||
192 | mColorsp[mCount] = mColorsp[mCount-1]; | ||
193 | mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | void LLGLImmediate::vertex2i(const GLint& x, const GLint& y) | ||
198 | { | ||
199 | vertex3f((GLfloat) x, (GLfloat) y, 0); | ||
200 | } | ||
201 | |||
202 | void LLGLImmediate::vertex2f(const GLfloat& x, const GLfloat& y) | ||
203 | { | ||
204 | vertex3f(x,y,0); | ||
205 | } | ||
206 | |||
207 | void LLGLImmediate::vertex2fv(const GLfloat* v) | ||
208 | { | ||
209 | vertex3f(v[0], v[1], 0); | ||
210 | } | ||
211 | |||
212 | void LLGLImmediate::vertex3fv(const GLfloat* v) | ||
213 | { | ||
214 | vertex3f(v[0], v[1], v[2]); | ||
215 | } | ||
216 | |||
217 | void LLGLImmediate::texCoord2f(const GLfloat& x, const GLfloat& y) | ||
218 | { | ||
219 | mTexcoordsp[mCount] = LLVector2(x,y); | ||
220 | } | ||
221 | |||
222 | void LLGLImmediate::texCoord2i(const GLint& x, const GLint& y) | ||
223 | { | ||
224 | texCoord2f((GLfloat) x, (GLfloat) y); | ||
225 | } | ||
226 | |||
227 | void LLGLImmediate::texCoord2fv(const GLfloat* tc) | ||
228 | { | ||
229 | texCoord2f(tc[0], tc[1]); | ||
230 | } | ||
231 | |||
232 | void LLGLImmediate::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a) | ||
233 | { | ||
234 | mColorsp[mCount] = LLColor4U(r,g,b,a); | ||
235 | } | ||
236 | |||
237 | void LLGLImmediate::color4ubv(const GLubyte* c) | ||
238 | { | ||
239 | color4ub(c[0], c[1], c[2], c[3]); | ||
240 | } | ||
241 | |||
242 | void LLGLImmediate::color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a) | ||
243 | { | ||
244 | color4ub((GLubyte) (llclamp(r, 0.f, 1.f)*255), | ||
245 | (GLubyte) (llclamp(g, 0.f, 1.f)*255), | ||
246 | (GLubyte) (llclamp(b, 0.f, 1.f)*255), | ||
247 | (GLubyte) (llclamp(a, 0.f, 1.f)*255)); | ||
248 | } | ||
249 | |||
250 | void LLGLImmediate::color4fv(const GLfloat* c) | ||
251 | { | ||
252 | color4f(c[0],c[1],c[2],c[3]); | ||
253 | } | ||
254 | |||
255 | void LLGLImmediate::color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b) | ||
256 | { | ||
257 | color4f(r,g,b,1); | ||
258 | } | ||
259 | |||
260 | void LLGLImmediate::color3fv(const GLfloat* c) | ||
261 | { | ||
262 | color4f(c[0],c[1],c[2],1); | ||
263 | } | ||
264 | |||
265 | >>>>>>> .merge-right.r88690 | ||
diff --git a/linden/indra/llrender/llglimmediate.h b/linden/indra/llrender/llglimmediate.h index 690abe0..4a7a0eb 100644 --- a/linden/indra/llrender/llglimmediate.h +++ b/linden/indra/llrender/llglimmediate.h | |||
@@ -1,98 +1 @@ | |||
1 | <<<<<<< .working | ||
2 | #error This file has been renamed llrender.h | #error This file has been renamed llrender.h | |
3 | ======= | ||
4 | /** | ||
5 | * @file llglimmediate.h | ||
6 | * @brief LLGLImmediate definition | ||
7 | * | ||
8 | * This class acts as a wrapper for OpenGL immediate calls concerning glBegin and glEnd. | ||
9 | * The goal of this class is to minimize the number of api calls due to legacy rendering | ||
10 | * code, and to define an interface for a multiple rendering API abstraction of the UI | ||
11 | * rendering. | ||
12 | * | ||
13 | * $LicenseInfo:firstyear=2001&license=viewergpl$ | ||
14 | * | ||
15 | * Copyright (c) 2001-2009, Linden Research, Inc. | ||
16 | * | ||
17 | * Second Life Viewer Source Code | ||
18 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
19 | * to you under the terms of the GNU General Public License, version 2.0 | ||
20 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
21 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
22 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
23 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
24 | * | ||
25 | * There are special exceptions to the terms and conditions of the GPL as | ||
26 | * it is applied to this Source Code. View the full text of the exception | ||
27 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
28 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
29 | * | ||
30 | * By copying, modifying or distributing this software, you acknowledge | ||
31 | * that you have read and understood your obligations described above, | ||
32 | * and agree to abide by those obligations. | ||
33 | * | ||
34 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
35 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
36 | * COMPLETENESS OR PERFORMANCE. | ||
37 | * $/LicenseInfo$ | ||
38 | */ | ||
39 | |||
40 | #ifndef LL_LLGLIMMEDIATE_H | ||
41 | #define LL_LLGLIMMEDIATE_H | ||
42 | |||
43 | #include "stdtypes.h" | ||
44 | #include "llgltypes.h" | ||
45 | #include "llglheaders.h" | ||
46 | #include "llvertexbuffer.h" | ||
47 | |||
48 | class LLGLImmediate | ||
49 | { | ||
50 | public: | ||
51 | LLGLImmediate(); | ||
52 | |||
53 | void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z); | ||
54 | void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z); | ||
55 | void pushMatrix(); | ||
56 | void popMatrix(); | ||
57 | void blendFunc(GLenum sfactor, GLenum dfactor); | ||
58 | void flush(); | ||
59 | |||
60 | void begin(const GLuint& mode); | ||
61 | void end(); | ||
62 | void vertex2i(const GLint& x, const GLint& y); | ||
63 | void vertex2f(const GLfloat& x, const GLfloat& y); | ||
64 | void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z); | ||
65 | void vertex2fv(const GLfloat* v); | ||
66 | void vertex3fv(const GLfloat* v); | ||
67 | |||
68 | void texCoord2i(const GLint& x, const GLint& y); | ||
69 | void texCoord2f(const GLfloat& x, const GLfloat& y); | ||
70 | void texCoord2fv(const GLfloat* tc); | ||
71 | |||
72 | void color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a); | ||
73 | void color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a); | ||
74 | void color4fv(const GLfloat* c); | ||
75 | void color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b); | ||
76 | void color3fv(const GLfloat* c); | ||
77 | void color4ubv(const GLubyte* c); | ||
78 | |||
79 | typedef struct | ||
80 | { | ||
81 | GLfloat v[3]; | ||
82 | GLubyte c[4]; | ||
83 | GLfloat uv[2]; | ||
84 | } Vertex; | ||
85 | |||
86 | private: | ||
87 | U32 mCount; | ||
88 | U32 mMode; | ||
89 | LLPointer<LLVertexBuffer> mBuffer; | ||
90 | LLStrider<LLVector3> mVerticesp; | ||
91 | LLStrider<LLVector2> mTexcoordsp; | ||
92 | LLStrider<LLColor4U> mColorsp; | ||
93 | }; | ||
94 | |||
95 | extern LLGLImmediate gGL; | ||
96 | |||
97 | #endif | ||
98 | >>>>>>> .merge-right.r88690 | ||
diff --git a/linden/indra/llrender/llglslshader.cpp b/linden/indra/llrender/llglslshader.cpp index 6683916..08d6548 100644 --- a/linden/indra/llrender/llglslshader.cpp +++ b/linden/indra/llrender/llglslshader.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -255,6 +256,14 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms) | |||
255 | S32 location = glGetUniformLocationARB(mProgramObject, name); | 256 | S32 location = glGetUniformLocationARB(mProgramObject, name); |
256 | if (location != -1) | 257 | if (location != -1) |
257 | { | 258 | { |
259 | //chop off "[0]" so we can always access the first element | ||
260 | //of an array by the array name | ||
261 | char* is_array = strstr(name, "[0]"); | ||
262 | if (is_array) | ||
263 | { | ||
264 | is_array[0] = 0; | ||
265 | } | ||
266 | |||
258 | mUniformMap[name] = location; | 267 | mUniformMap[name] = location; |
259 | LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; | 268 | LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; |
260 | 269 | ||
@@ -352,11 +361,17 @@ void LLGLSLShader::unbind() | |||
352 | { | 361 | { |
353 | if (gGLManager.mHasShaderObjects) | 362 | if (gGLManager.mHasShaderObjects) |
354 | { | 363 | { |
355 | for (U32 i = 0; i < mAttribute.size(); ++i) | 364 | stop_glerror(); |
365 | if (gGLManager.mIsNVIDIA) | ||
356 | { | 366 | { |
357 | vertexAttrib4f(i, 0,0,0,1); | 367 | for (U32 i = 0; i < mAttribute.size(); ++i) |
368 | { | ||
369 | vertexAttrib4f(i, 0,0,0,1); | ||
370 | stop_glerror(); | ||
371 | } | ||
358 | } | 372 | } |
359 | glUseProgramObjectARB(0); | 373 | glUseProgramObjectARB(0); |
374 | stop_glerror(); | ||
360 | } | 375 | } |
361 | } | 376 | } |
362 | 377 | ||
@@ -389,14 +404,39 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) | |||
389 | return -1; | 404 | return -1; |
390 | } | 405 | } |
391 | S32 index = mTexture[uniform]; | 406 | S32 index = mTexture[uniform]; |
392 | if (index != -1) | 407 | if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) |
393 | { | 408 | { |
394 | gGL.getTexUnit(index)->activate(); | 409 | if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) |
410 | { | ||
411 | llerrs << "Texture channel " << index << " texture type corrupted." << llendl; | ||
412 | } | ||
395 | gGL.getTexUnit(index)->disable(); | 413 | gGL.getTexUnit(index)->disable(); |
396 | } | 414 | } |
397 | return index; | 415 | return index; |
398 | } | 416 | } |
399 | 417 | ||
418 | void LLGLSLShader::uniform1i(U32 index, GLint x) | ||
419 | { | ||
420 | if (mProgramObject > 0) | ||
421 | { | ||
422 | if (mUniform.size() <= index) | ||
423 | { | ||
424 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | if (mUniform[index] >= 0) | ||
429 | { | ||
430 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
431 | if (iter == mValue.end() || iter->second.mV[0] != x) | ||
432 | { | ||
433 | glUniform1iARB(mUniform[index], x); | ||
434 | mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f); | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | |||
400 | void LLGLSLShader::uniform1f(U32 index, GLfloat x) | 440 | void LLGLSLShader::uniform1f(U32 index, GLfloat x) |
401 | { | 441 | { |
402 | if (mProgramObject > 0) | 442 | if (mProgramObject > 0) |
@@ -488,6 +528,29 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat | |||
488 | } | 528 | } |
489 | } | 529 | } |
490 | 530 | ||
531 | void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v) | ||
532 | { | ||
533 | if (mProgramObject > 0) | ||
534 | { | ||
535 | if (mUniform.size() <= index) | ||
536 | { | ||
537 | UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; | ||
538 | return; | ||
539 | } | ||
540 | |||
541 | if (mUniform[index] >= 0) | ||
542 | { | ||
543 | std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]); | ||
544 | LLVector4 vec(v[0],0.f,0.f,0.f); | ||
545 | if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1) | ||
546 | { | ||
547 | glUniform1ivARB(mUniform[index], count, v); | ||
548 | mValue[mUniform[index]] = vec; | ||
549 | } | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | |||
491 | void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) | 554 | void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) |
492 | { | 555 | { |
493 | if (mProgramObject > 0) | 556 | if (mProgramObject > 0) |
@@ -646,6 +709,22 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform) | |||
646 | return -1; | 709 | return -1; |
647 | } | 710 | } |
648 | 711 | ||
712 | void LLGLSLShader::uniform1i(const string& uniform, GLint v) | ||
713 | { | ||
714 | GLint location = getUniformLocation(uniform); | ||
715 | |||
716 | if (location >= 0) | ||
717 | { | ||
718 | std::map<GLint, LLVector4>::iterator iter = mValue.find(location); | ||
719 | LLVector4 vec(v,0.f,0.f,0.f); | ||
720 | if (iter == mValue.end() || shouldChange(iter->second,vec)) | ||
721 | { | ||
722 | glUniform1iARB(location, v); | ||
723 | mValue[location] = vec; | ||
724 | } | ||
725 | } | ||
726 | } | ||
727 | |||
649 | void LLGLSLShader::uniform1f(const string& uniform, GLfloat v) | 728 | void LLGLSLShader::uniform1f(const string& uniform, GLfloat v) |
650 | { | 729 | { |
651 | GLint location = getUniformLocation(uniform); | 730 | GLint location = getUniformLocation(uniform); |
diff --git a/linden/indra/llrender/llglslshader.h b/linden/indra/llrender/llglslshader.h index 66c53df..166d4af 100644 --- a/linden/indra/llrender/llglslshader.h +++ b/linden/indra/llrender/llglslshader.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -77,18 +78,22 @@ public: | |||
77 | BOOL mapAttributes(const std::vector<std::string> * attributes); | 78 | BOOL mapAttributes(const std::vector<std::string> * attributes); |
78 | BOOL mapUniforms(const std::vector<std::string> * uniforms); | 79 | BOOL mapUniforms(const std::vector<std::string> * uniforms); |
79 | void mapUniform(GLint index, const std::vector<std::string> * uniforms); | 80 | void mapUniform(GLint index, const std::vector<std::string> * uniforms); |
81 | void uniform1i(U32 index, GLint i); | ||
80 | void uniform1f(U32 index, GLfloat v); | 82 | void uniform1f(U32 index, GLfloat v); |
81 | void uniform2f(U32 index, GLfloat x, GLfloat y); | 83 | void uniform2f(U32 index, GLfloat x, GLfloat y); |
82 | void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z); | 84 | void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z); |
83 | void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); | 85 | void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); |
86 | void uniform1iv(U32 index, U32 count, const GLint* i); | ||
84 | void uniform1fv(U32 index, U32 count, const GLfloat* v); | 87 | void uniform1fv(U32 index, U32 count, const GLfloat* v); |
85 | void uniform2fv(U32 index, U32 count, const GLfloat* v); | 88 | void uniform2fv(U32 index, U32 count, const GLfloat* v); |
86 | void uniform3fv(U32 index, U32 count, const GLfloat* v); | 89 | void uniform3fv(U32 index, U32 count, const GLfloat* v); |
87 | void uniform4fv(U32 index, U32 count, const GLfloat* v); | 90 | void uniform4fv(U32 index, U32 count, const GLfloat* v); |
91 | void uniform1i(const std::string& uniform, GLint i); | ||
88 | void uniform1f(const std::string& uniform, GLfloat v); | 92 | void uniform1f(const std::string& uniform, GLfloat v); |
89 | void uniform2f(const std::string& uniform, GLfloat x, GLfloat y); | 93 | void uniform2f(const std::string& uniform, GLfloat x, GLfloat y); |
90 | void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z); | 94 | void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z); |
91 | void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w); | 95 | void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w); |
96 | void uniform1iv(const std::string& uniform, U32 count, const GLint* i); | ||
92 | void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v); | 97 | void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v); |
93 | void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v); | 98 | void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v); |
94 | void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v); | 99 | void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v); |
diff --git a/linden/indra/llrender/llglstates.h b/linden/indra/llrender/llglstates.h index 94d136e..4a51cac 100644 --- a/linden/indra/llrender/llglstates.h +++ b/linden/indra/llrender/llglstates.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llrender/llgltypes.h b/linden/indra/llrender/llgltypes.h index 5809b9c..9b0e81f 100644 --- a/linden/indra/llrender/llgltypes.h +++ b/linden/indra/llrender/llgltypes.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llrender/llimagegl.cpp b/linden/indra/llrender/llimagegl.cpp index 6a142a7..cdf626e 100644 --- a/linden/indra/llrender/llimagegl.cpp +++ b/linden/indra/llrender/llimagegl.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -62,7 +63,6 @@ BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; | |||
62 | F32 LLImageGL::sLastFrameTime = 0.f; | 63 | F32 LLImageGL::sLastFrameTime = 0.f; |
63 | 64 | ||
64 | std::set<LLImageGL*> LLImageGL::sImageList; | 65 | std::set<LLImageGL*> LLImageGL::sImageList; |
65 | |||
66 | //************************************************************************************** | 66 | //************************************************************************************** |
67 | //below are functions for debug use | 67 | //below are functions for debug use |
68 | //do not delete them even though they are not currently being used. | 68 | //do not delete them even though they are not currently being used. |
@@ -308,21 +308,21 @@ void LLImageGL::init(BOOL usemipmaps) | |||
308 | #endif | 308 | #endif |
309 | 309 | ||
310 | mPickMask = NULL; | 310 | mPickMask = NULL; |
311 | mTextureState = NO_DELETE ; | ||
311 | mTextureMemory = 0; | 312 | mTextureMemory = 0; |
312 | mLastBindTime = 0.f; | 313 | mLastBindTime = 0.f; |
313 | 314 | ||
314 | mTarget = GL_TEXTURE_2D; | 315 | mTarget = GL_TEXTURE_2D; |
315 | mBindTarget = LLTexUnit::TT_TEXTURE; | 316 | mBindTarget = LLTexUnit::TT_TEXTURE; |
316 | mUseMipMaps = usemipmaps; | 317 | mUseMipMaps = usemipmaps; |
317 | mHasMipMaps = FALSE; | 318 | mHasMipMaps = false; |
318 | mAutoGenMips = FALSE; | 319 | mAutoGenMips = FALSE; |
319 | mTexName = 0; | 320 | mTexName = 0; |
320 | mIsResident = 0; | 321 | mIsResident = 0; |
321 | mClampS = FALSE; | 322 | |
322 | mClampT = FALSE; | 323 | mTexOptionsDirty = true; |
323 | mClampR = FALSE; | 324 | mAddressMode = LLTexUnit::TAM_WRAP; |
324 | mMagFilterNearest = FALSE; | 325 | mFilterOption = LLTexUnit::TFO_ANISOTROPIC; |
325 | mMinFilterNearest = FALSE; | ||
326 | mWidth = 0; | 326 | mWidth = 0; |
327 | mHeight = 0; | 327 | mHeight = 0; |
328 | mComponents = 0; | 328 | mComponents = 0; |
@@ -338,6 +338,7 @@ void LLImageGL::init(BOOL usemipmaps) | |||
338 | mHasExplicitFormat = FALSE; | 338 | mHasExplicitFormat = FALSE; |
339 | 339 | ||
340 | mGLTextureCreated = FALSE ; | 340 | mGLTextureCreated = FALSE ; |
341 | mIsMask = FALSE; | ||
341 | } | 342 | } |
342 | 343 | ||
343 | void LLImageGL::cleanup() | 344 | void LLImageGL::cleanup() |
@@ -468,6 +469,11 @@ bool LLImageGL::bindDefaultImage(const S32 stage) const | |||
468 | return false; | 469 | return false; |
469 | } | 470 | } |
470 | 471 | ||
472 | //virtual | ||
473 | void LLImageGL::forceImmediateUpdate() | ||
474 | { | ||
475 | return ; | ||
476 | } | ||
471 | 477 | ||
472 | void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes ) | 478 | void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes ) |
473 | { | 479 | { |
@@ -497,17 +503,15 @@ void LLImageGL::setImage(const LLImageRaw* imageraw) | |||
497 | void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | 503 | void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) |
498 | { | 504 | { |
499 | // LLFastTimer t1(LLFastTimer::FTM_TEMP1); | 505 | // LLFastTimer t1(LLFastTimer::FTM_TEMP1); |
500 | 506 | llpushcallstacks ; | |
501 | bool is_compressed = false; | 507 | bool is_compressed = false; |
502 | if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) | 508 | if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) |
503 | { | 509 | { |
504 | is_compressed = true; | 510 | is_compressed = true; |
505 | } | 511 | } |
506 | 512 | ||
507 | { | ||
508 | // LLFastTimer t2(LLFastTimer::FTM_TEMP2); | 513 | // LLFastTimer t2(LLFastTimer::FTM_TEMP2); |
509 | llverify(gGL.getTexUnit(0)->bind(this)); | 514 | gGL.getTexUnit(0)->bind(this); |
510 | } | ||
511 | 515 | ||
512 | if (mUseMipMaps) | 516 | if (mUseMipMaps) |
513 | { | 517 | { |
@@ -518,6 +522,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
518 | // are stored BEFORE the largest image | 522 | // are stored BEFORE the largest image |
519 | for (S32 d=mCurrentDiscardLevel; d<=mMaxDiscardLevel; d++) | 523 | for (S32 d=mCurrentDiscardLevel; d<=mMaxDiscardLevel; d++) |
520 | { | 524 | { |
525 | |||
521 | S32 w = getWidth(d); | 526 | S32 w = getWidth(d); |
522 | S32 h = getHeight(d); | 527 | S32 h = getHeight(d); |
523 | S32 gl_level = d-mCurrentDiscardLevel; | 528 | S32 gl_level = d-mCurrentDiscardLevel; |
@@ -528,7 +533,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
528 | if (is_compressed) | 533 | if (is_compressed) |
529 | { | 534 | { |
530 | // LLFastTimer t2(LLFastTimer::FTM_TEMP4); | 535 | // LLFastTimer t2(LLFastTimer::FTM_TEMP4); |
531 | S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); | 536 | S32 tex_size = dataFormatBytes(mFormatPrimary, w, h); |
532 | glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); | 537 | glCompressedTexImage2DARB(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in); |
533 | stop_glerror(); | 538 | stop_glerror(); |
534 | } | 539 | } |
@@ -542,7 +547,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
542 | stop_glerror(); | 547 | stop_glerror(); |
543 | } | 548 | } |
544 | 549 | ||
545 | glTexImage2D(mTarget, gl_level, mFormatInternal, w, h, 0, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in); | 550 | LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in); |
551 | if (gl_level == 0) | ||
552 | { | ||
553 | analyzeAlpha(data_in, w, h); | ||
554 | } | ||
546 | updatePickMask(w, h, data_in); | 555 | updatePickMask(w, h, data_in); |
547 | 556 | ||
548 | if(mFormatSwapBytes) | 557 | if(mFormatSwapBytes) |
@@ -574,10 +583,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
574 | S32 w = getWidth(mCurrentDiscardLevel); | 583 | S32 w = getWidth(mCurrentDiscardLevel); |
575 | S32 h = getHeight(mCurrentDiscardLevel); | 584 | S32 h = getHeight(mCurrentDiscardLevel); |
576 | 585 | ||
577 | glTexImage2D(mTarget, 0, mFormatInternal, | 586 | LLImageGL::setManualImage(mTarget, 0, mFormatInternal, |
578 | w, h, 0, | 587 | w, h, |
579 | mFormatPrimary, mFormatType, | 588 | mFormatPrimary, mFormatType, |
580 | data_in); | 589 | data_in); |
590 | analyzeAlpha(data_in, w, h); | ||
581 | stop_glerror(); | 591 | stop_glerror(); |
582 | 592 | ||
583 | updatePickMask(w, h, data_in); | 593 | updatePickMask(w, h, data_in); |
@@ -629,7 +639,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
629 | stop_glerror(); | 639 | stop_glerror(); |
630 | } | 640 | } |
631 | 641 | ||
632 | glTexImage2D(mTarget, m, mFormatInternal, w, h, 0, mFormatPrimary, mFormatType, cur_mip_data); | 642 | LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data); |
643 | if (m == 0) | ||
644 | { | ||
645 | analyzeAlpha(data_in, w, h); | ||
646 | } | ||
633 | stop_glerror(); | 647 | stop_glerror(); |
634 | if (m == 0) | 648 | if (m == 0) |
635 | { | 649 | { |
@@ -662,7 +676,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
662 | { | 676 | { |
663 | llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; | 677 | llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl; |
664 | } | 678 | } |
665 | mHasMipMaps = TRUE; | 679 | mHasMipMaps = true; |
666 | } | 680 | } |
667 | else | 681 | else |
668 | { | 682 | { |
@@ -683,8 +697,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
683 | stop_glerror(); | 697 | stop_glerror(); |
684 | } | 698 | } |
685 | 699 | ||
686 | glTexImage2D(mTarget, 0, mFormatInternal, w, h, 0, | 700 | LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, |
687 | mFormatPrimary, mFormatType, (GLvoid *)data_in); | 701 | mFormatPrimary, mFormatType, (GLvoid *)data_in); |
702 | analyzeAlpha(data_in, w, h); | ||
703 | |||
688 | updatePickMask(w, h, data_in); | 704 | updatePickMask(w, h, data_in); |
689 | 705 | ||
690 | stop_glerror(); | 706 | stop_glerror(); |
@@ -696,14 +712,16 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) | |||
696 | } | 712 | } |
697 | 713 | ||
698 | } | 714 | } |
699 | mHasMipMaps = FALSE; | 715 | mHasMipMaps = false; |
700 | } | 716 | } |
701 | stop_glerror(); | 717 | stop_glerror(); |
702 | mGLTextureCreated = true; | 718 | mGLTextureCreated = true; |
719 | llpushcallstacks ; | ||
703 | } | 720 | } |
704 | 721 | ||
705 | BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) | 722 | BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) |
706 | { | 723 | { |
724 | llpushcallstacks ; | ||
707 | if (!width || !height) | 725 | if (!width || !height) |
708 | { | 726 | { |
709 | return TRUE; | 727 | return TRUE; |
@@ -779,6 +797,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 | |||
779 | 797 | ||
780 | glTexSubImage2D(mTarget, 0, x_pos, y_pos, | 798 | glTexSubImage2D(mTarget, 0, x_pos, y_pos, |
781 | width, height, mFormatPrimary, mFormatType, datap); | 799 | width, height, mFormatPrimary, mFormatType, datap); |
800 | gGL.getTexUnit(0)->disable(); | ||
782 | stop_glerror(); | 801 | stop_glerror(); |
783 | 802 | ||
784 | if(mFormatSwapBytes) | 803 | if(mFormatSwapBytes) |
@@ -791,6 +810,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 | |||
791 | stop_glerror(); | 810 | stop_glerror(); |
792 | mGLTextureCreated = true; | 811 | mGLTextureCreated = true; |
793 | } | 812 | } |
813 | llpushcallstacks ; | ||
794 | return TRUE; | 814 | return TRUE; |
795 | } | 815 | } |
796 | 816 | ||
@@ -815,6 +835,24 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ | |||
815 | } | 835 | } |
816 | } | 836 | } |
817 | 837 | ||
838 | // static | ||
839 | void LLImageGL::generateTextures(S32 numTextures, U32 *textures) | ||
840 | { | ||
841 | glGenTextures(numTextures, (GLuint*)textures); | ||
842 | } | ||
843 | |||
844 | // static | ||
845 | void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) | ||
846 | { | ||
847 | glDeleteTextures(numTextures, (GLuint*)textures); | ||
848 | } | ||
849 | |||
850 | // static | ||
851 | void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) | ||
852 | { | ||
853 | glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); | ||
854 | } | ||
855 | |||
818 | //create an empty GL texture: just create a texture name | 856 | //create an empty GL texture: just create a texture name |
819 | //the texture is assiciate with some image by calling glTexImage outside LLImageGL | 857 | //the texture is assiciate with some image by calling glTexImage outside LLImageGL |
820 | BOOL LLImageGL::createGLTexture() | 858 | BOOL LLImageGL::createGLTexture() |
@@ -847,6 +885,7 @@ BOOL LLImageGL::createGLTexture() | |||
847 | 885 | ||
848 | BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) | 886 | BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) |
849 | { | 887 | { |
888 | llpushcallstacks ; | ||
850 | if (gGLManager.mIsDisabled) | 889 | if (gGLManager.mIsDisabled) |
851 | { | 890 | { |
852 | llwarns << "Trying to create a texture while GL is disabled!" << llendl; | 891 | llwarns << "Trying to create a texture while GL is disabled!" << llendl; |
@@ -907,6 +946,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S | |||
907 | 946 | ||
908 | BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) | 947 | BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) |
909 | { | 948 | { |
949 | llpushcallstacks ; | ||
910 | llassert(data_in); | 950 | llassert(data_in); |
911 | 951 | ||
912 | if (discard_level < 0) | 952 | if (discard_level < 0) |
@@ -923,7 +963,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ | |||
923 | return TRUE; | 963 | return TRUE; |
924 | } | 964 | } |
925 | 965 | ||
926 | GLuint old_name = mTexName; | 966 | U32 old_name = mTexName; |
927 | // S32 old_discard = mCurrentDiscardLevel; | 967 | // S32 old_discard = mCurrentDiscardLevel; |
928 | 968 | ||
929 | if (usename != 0) | 969 | if (usename != 0) |
@@ -932,7 +972,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ | |||
932 | } | 972 | } |
933 | else | 973 | else |
934 | { | 974 | { |
935 | glGenTextures(1, (GLuint*)&mTexName); | 975 | LLImageGL::generateTextures(1, &mTexName); |
936 | stop_glerror(); | 976 | stop_glerror(); |
937 | { | 977 | { |
938 | // LLFastTimer t1(LLFastTimer::FTM_TEMP6); | 978 | // LLFastTimer t1(LLFastTimer::FTM_TEMP6); |
@@ -962,9 +1002,11 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ | |||
962 | 1002 | ||
963 | setImage(data_in, data_hasmips); | 1003 | setImage(data_in, data_hasmips); |
964 | 1004 | ||
965 | setClamp(mClampS, mClampT); | 1005 | // Set texture options to our defaults. |
966 | setMipFilterNearest(mMagFilterNearest); | 1006 | gGL.getTexUnit(0)->setHasMipMaps(mHasMipMaps); |
967 | 1007 | gGL.getTexUnit(0)->setTextureAddressMode(mAddressMode); | |
1008 | gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); | ||
1009 | |||
968 | // things will break if we don't unbind after creation | 1010 | // things will break if we don't unbind after creation |
969 | gGL.getTexUnit(0)->unbind(mBindTarget); | 1011 | gGL.getTexUnit(0)->unbind(mBindTarget); |
970 | stop_glerror(); | 1012 | stop_glerror(); |
@@ -972,16 +1014,18 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ | |||
972 | if (old_name != 0) | 1014 | if (old_name != 0) |
973 | { | 1015 | { |
974 | sGlobalTextureMemory -= mTextureMemory; | 1016 | sGlobalTextureMemory -= mTextureMemory; |
975 | glDeleteTextures(1, &old_name); | 1017 | LLImageGL::deleteTextures(1, &old_name); |
976 | stop_glerror(); | 1018 | stop_glerror(); |
977 | } | 1019 | } |
978 | 1020 | ||
979 | mTextureMemory = getMipBytes(discard_level); | 1021 | mTextureMemory = getMipBytes(discard_level); |
980 | sGlobalTextureMemory += mTextureMemory; | 1022 | sGlobalTextureMemory += mTextureMemory; |
981 | 1023 | setActive() ; | |
1024 | |||
982 | // mark this as bound at this point, so we don't throw it out immediately | 1025 | // mark this as bound at this point, so we don't throw it out immediately |
983 | mLastBindTime = sLastFrameTime; | 1026 | mLastBindTime = sLastFrameTime; |
984 | 1027 | ||
1028 | llpushcallstacks ; | ||
985 | return TRUE; | 1029 | return TRUE; |
986 | } | 1030 | } |
987 | 1031 | ||
@@ -1054,6 +1098,7 @@ BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_h | |||
1054 | 1098 | ||
1055 | BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) | 1099 | BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) |
1056 | { | 1100 | { |
1101 | llpushcallstacks ; | ||
1057 | if (discard_level < 0) | 1102 | if (discard_level < 0) |
1058 | { | 1103 | { |
1059 | discard_level = mCurrentDiscardLevel; | 1104 | discard_level = mCurrentDiscardLevel; |
@@ -1068,7 +1113,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre | |||
1068 | 1113 | ||
1069 | //explicitly unbind texture | 1114 | //explicitly unbind texture |
1070 | gGL.getTexUnit(0)->unbind(mBindTarget); | 1115 | gGL.getTexUnit(0)->unbind(mBindTarget); |
1071 | llverify(gGL.getTexUnit(0)->bind(this)); | 1116 | llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName)); |
1072 | 1117 | ||
1073 | //debug code, leave it there commented. | 1118 | //debug code, leave it there commented. |
1074 | //checkTexSize() ; | 1119 | //checkTexSize() ; |
@@ -1156,7 +1201,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre | |||
1156 | return FALSE ; | 1201 | return FALSE ; |
1157 | } | 1202 | } |
1158 | //----------------------------------------------------------------------------------------------- | 1203 | //----------------------------------------------------------------------------------------------- |
1159 | 1204 | llpushcallstacks ; | |
1160 | return TRUE ; | 1205 | return TRUE ; |
1161 | } | 1206 | } |
1162 | 1207 | ||
@@ -1178,8 +1223,10 @@ void LLImageGL::destroyGLTexture() | |||
1178 | sGlobalTextureMemory -= mTextureMemory; | 1223 | sGlobalTextureMemory -= mTextureMemory; |
1179 | mTextureMemory = 0; | 1224 | mTextureMemory = 0; |
1180 | 1225 | ||
1181 | glDeleteTextures(1, (GLuint*)&mTexName); | 1226 | LLImageGL::deleteTextures(1, &mTexName); |
1227 | mTextureState = DELETED ; | ||
1182 | mTexName = 0; | 1228 | mTexName = 0; |
1229 | mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. | ||
1183 | mGLTextureCreated = FALSE ; | 1230 | mGLTextureCreated = FALSE ; |
1184 | stop_glerror(); | 1231 | stop_glerror(); |
1185 | } | 1232 | } |
@@ -1187,89 +1234,35 @@ void LLImageGL::destroyGLTexture() | |||
1187 | 1234 | ||
1188 | //---------------------------------------------------------------------------- | 1235 | //---------------------------------------------------------------------------- |
1189 | 1236 | ||
1190 | void LLImageGL::glClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr) | 1237 | void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) |
1191 | { | 1238 | { |
1192 | glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); | 1239 | if (mAddressMode != mode) |
1193 | glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); | ||
1194 | glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); | ||
1195 | } | ||
1196 | |||
1197 | void LLImageGL::glClamp (BOOL clamps, BOOL clampt) | ||
1198 | { | ||
1199 | if (mTexName != 0) | ||
1200 | { | 1240 | { |
1201 | glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT); | 1241 | mTexOptionsDirty = true; |
1202 | glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_T, clampt ? GL_CLAMP_TO_EDGE : GL_REPEAT); | 1242 | mAddressMode = mode; |
1203 | } | 1243 | } |
1204 | } | ||
1205 | |||
1206 | void LLImageGL::setClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr) | ||
1207 | { | ||
1208 | mClampS = clamps; | ||
1209 | mClampT = clampt; | ||
1210 | mClampR = clampr; | ||
1211 | glClampCubemap (clamps, clampt, clampr); | ||
1212 | } | ||
1213 | 1244 | ||
1214 | void LLImageGL::setClamp(BOOL clamps, BOOL clampt) | 1245 | if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) |
1215 | { | 1246 | { |
1216 | mClampS = clamps; | 1247 | gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureAddressMode(mode); |
1217 | mClampT = clampt; | 1248 | mTexOptionsDirty = false; |
1218 | glClamp (clamps, clampt); | 1249 | } |
1219 | } | ||
1220 | |||
1221 | void LLImageGL::overrideClamp (BOOL clamps, BOOL clampt) | ||
1222 | { | ||
1223 | glClamp (clamps, clampt); | ||
1224 | } | ||
1225 | |||
1226 | void LLImageGL::restoreClamp (void) | ||
1227 | { | ||
1228 | glClamp (mClampS, mClampT); | ||
1229 | } | 1250 | } |
1230 | 1251 | ||
1231 | void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest) | 1252 | void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option) |
1232 | { | 1253 | { |
1233 | mMagFilterNearest = mag_nearest; | 1254 | if (mFilterOption != option) |
1234 | mMinFilterNearest = min_nearest; | 1255 | { |
1256 | mTexOptionsDirty = true; | ||
1257 | mFilterOption = option; | ||
1258 | } | ||
1235 | 1259 | ||
1236 | if (mTexName != 0) | 1260 | if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) |
1237 | { | 1261 | { |
1238 | if (mMinFilterNearest) | 1262 | gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option); |
1239 | { | 1263 | mTexOptionsDirty = false; |
1240 | glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 1264 | } |
1241 | } | 1265 | stop_glerror(); |
1242 | else if (mHasMipMaps) | ||
1243 | { | ||
1244 | glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | ||
1245 | } | ||
1246 | else | ||
1247 | { | ||
1248 | glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
1249 | } | ||
1250 | if (mMagFilterNearest) | ||
1251 | { | ||
1252 | glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_NEAREST); | ||
1253 | } | ||
1254 | else | ||
1255 | { | ||
1256 | glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
1257 | } | ||
1258 | if (gGLManager.mHasAnisotropic) | ||
1259 | { | ||
1260 | if (sGlobalUseAnisotropic && !mMagFilterNearest) | ||
1261 | { | ||
1262 | F32 largest_anisotropy; | ||
1263 | glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_anisotropy); | ||
1264 | glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_anisotropy); | ||
1265 | } | ||
1266 | else | ||
1267 | { | ||
1268 | glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); | ||
1269 | } | ||
1270 | } | ||
1271 | stop_glerror(); | ||
1272 | } | ||
1273 | } | 1266 | } |
1274 | 1267 | ||
1275 | BOOL LLImageGL::getIsResident(BOOL test_now) | 1268 | BOOL LLImageGL::getIsResident(BOOL test_now) |
@@ -1356,6 +1349,118 @@ void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType b | |||
1356 | mBindTarget = bind_target; | 1349 | mBindTarget = bind_target; |
1357 | } | 1350 | } |
1358 | 1351 | ||
1352 | void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) | ||
1353 | { | ||
1354 | if (mFormatType != GL_UNSIGNED_BYTE) | ||
1355 | { | ||
1356 | llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; | ||
1357 | } | ||
1358 | |||
1359 | U32 stride = 0; | ||
1360 | switch (mFormatPrimary) | ||
1361 | { | ||
1362 | case GL_LUMINANCE: | ||
1363 | case GL_ALPHA: | ||
1364 | stride = 1; | ||
1365 | break; | ||
1366 | case GL_LUMINANCE_ALPHA: | ||
1367 | stride = 2; | ||
1368 | break; | ||
1369 | case GL_RGB: | ||
1370 | //no alpha | ||
1371 | mIsMask = FALSE; | ||
1372 | return; | ||
1373 | case GL_RGBA: | ||
1374 | stride = 4; | ||
1375 | break; | ||
1376 | case GL_BGRA_EXT: | ||
1377 | stride = 4; | ||
1378 | break; | ||
1379 | default: | ||
1380 | llwarns << "Cannot analyze alpha of image with primary format " << std::hex << mFormatPrimary << std::dec << llendl; | ||
1381 | return; | ||
1382 | } | ||
1383 | |||
1384 | U32 length = w * h; | ||
1385 | const GLubyte* current = ((const GLubyte*) data_in)+stride-1; | ||
1386 | |||
1387 | S32 sample[16]; | ||
1388 | memset(sample, 0, sizeof(S32)*16); | ||
1389 | |||
1390 | for (U32 i = 0; i < length; i++) | ||
1391 | { | ||
1392 | ++sample[*current/16]; | ||
1393 | current += stride; | ||
1394 | } | ||
1395 | |||
1396 | U32 total = 0; | ||
1397 | for (U32 i = 4; i < 11; i++) | ||
1398 | { | ||
1399 | total += sample[i]; | ||
1400 | } | ||
1401 | |||
1402 | if (total > length/16) | ||
1403 | { | ||
1404 | mIsMask = FALSE; | ||
1405 | } | ||
1406 | else | ||
1407 | { | ||
1408 | mIsMask = TRUE; | ||
1409 | } | ||
1410 | } | ||
1411 | |||
1412 | BOOL LLImageGL::isDeleted() | ||
1413 | { | ||
1414 | return mTextureState == DELETED ; | ||
1415 | } | ||
1416 | |||
1417 | BOOL LLImageGL::isInactive() | ||
1418 | { | ||
1419 | return mTextureState == INACTIVE ; | ||
1420 | } | ||
1421 | |||
1422 | BOOL LLImageGL::isDeletionCandidate() | ||
1423 | { | ||
1424 | return mTextureState == DELETION_CANDIDATE ; | ||
1425 | } | ||
1426 | |||
1427 | void LLImageGL::setDeletionCandidate() | ||
1428 | { | ||
1429 | if(mTexName && (mTextureState == INACTIVE)) | ||
1430 | { | ||
1431 | mTextureState = DELETION_CANDIDATE ; | ||
1432 | } | ||
1433 | } | ||
1434 | |||
1435 | void LLImageGL::forceActive() | ||
1436 | { | ||
1437 | mTextureState = ACTIVE ; | ||
1438 | } | ||
1439 | |||
1440 | void LLImageGL::setActive() | ||
1441 | { | ||
1442 | if(mTextureState != NO_DELETE) | ||
1443 | { | ||
1444 | mTextureState = ACTIVE ; | ||
1445 | } | ||
1446 | } | ||
1447 | |||
1448 | //set the texture inactive | ||
1449 | void LLImageGL::setInactive() | ||
1450 | { | ||
1451 | if(mTexName && (mTextureState == ACTIVE) && !getBoundRecently()) | ||
1452 | { | ||
1453 | mTextureState = INACTIVE ; | ||
1454 | } | ||
1455 | } | ||
1456 | |||
1457 | //set the texture to stay in memory | ||
1458 | void LLImageGL::setNoDelete() | ||
1459 | { | ||
1460 | mTextureState = NO_DELETE ; | ||
1461 | } | ||
1462 | |||
1463 | //---------------------------------------------------------------------------- | ||
1359 | void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) | 1464 | void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) |
1360 | { | 1465 | { |
1361 | if (mFormatType != GL_UNSIGNED_BYTE || | 1466 | if (mFormatType != GL_UNSIGNED_BYTE || |
@@ -1468,7 +1573,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) | |||
1468 | llassert(w > 0 && h > 0 && cur_mip_data); | 1573 | llassert(w > 0 && h > 0 && cur_mip_data); |
1469 | U8 test = cur_mip_data[w*h*mComponents-1]; | 1574 | U8 test = cur_mip_data[w*h*mComponents-1]; |
1470 | { | 1575 | { |
1471 | glTexImage2D(mTarget, m, mFormatInternal, w, h, 0, mFormatPrimary, mFormatType, cur_mip_data); | 1576 | LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data); |
1472 | stop_glerror(); | 1577 | stop_glerror(); |
1473 | } | 1578 | } |
1474 | if (prev_mip_data && prev_mip_data != rawdata) | 1579 | if (prev_mip_data && prev_mip_data != rawdata) |
diff --git a/linden/indra/llrender/llimagegl.h b/linden/indra/llrender/llimagegl.h index 1965495..4f737bc 100644 --- a/linden/indra/llrender/llimagegl.h +++ b/linden/indra/llrender/llimagegl.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -45,6 +46,7 @@ | |||
45 | 46 | ||
46 | class LLImageGL : public LLRefCount | 47 | class LLImageGL : public LLRefCount |
47 | { | 48 | { |
49 | friend class LLTexUnit; | ||
48 | public: | 50 | public: |
49 | // Size calculation | 51 | // Size calculation |
50 | static S32 dataFormatBits(S32 dataformat); | 52 | static S32 dataFormatBits(S32 dataformat); |
@@ -79,17 +81,22 @@ public: | |||
79 | protected: | 81 | protected: |
80 | virtual ~LLImageGL(); | 82 | virtual ~LLImageGL(); |
81 | 83 | ||
82 | private: | 84 | void analyzeAlpha(const void* data_in, S32 w, S32 h); |
83 | void glClamp (BOOL clamps, BOOL clampt); | ||
84 | void glClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr = FALSE); | ||
85 | 85 | ||
86 | public: | 86 | public: |
87 | virtual void dump(); // debugging info to llinfos | 87 | virtual void dump(); // debugging info to llinfos |
88 | virtual bool bindError(const S32 stage = 0) const; | 88 | virtual bool bindError(const S32 stage = 0) const; |
89 | virtual bool bindDefaultImage(const S32 stage = 0) const; | 89 | virtual bool bindDefaultImage(const S32 stage = 0) const; |
90 | virtual void forceImmediateUpdate() ; | ||
90 | 91 | ||
91 | void setSize(S32 width, S32 height, S32 ncomponents); | 92 | void setSize(S32 width, S32 height, S32 ncomponents); |
92 | 93 | ||
94 | // These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() | ||
95 | // for tracking purposes and will be deprecated in the future | ||
96 | static void generateTextures(S32 numTextures, U32 *textures); | ||
97 | static void deleteTextures(S32 numTextures, U32 *textures); | ||
98 | static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); | ||
99 | |||
93 | BOOL createGLTexture() ; | 100 | BOOL createGLTexture() ; |
94 | BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); | 101 | BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); |
95 | BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); | 102 | BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); |
@@ -102,14 +109,9 @@ public: | |||
102 | // Read back a raw image for this discard level, if it exists | 109 | // Read back a raw image for this discard level, if it exists |
103 | BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); | 110 | BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); |
104 | void destroyGLTexture(); | 111 | void destroyGLTexture(); |
105 | 112 | ||
106 | void setClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr = FALSE); | ||
107 | void setClamp(BOOL clamps, BOOL clampt); | ||
108 | void overrideClamp (BOOL clamps, BOOL clampt); | ||
109 | void restoreClamp (void); | ||
110 | void setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest = FALSE); | ||
111 | void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); | 113 | void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); |
112 | void dontDiscard() { mDontDiscard = 1; } | 114 | void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } |
113 | 115 | ||
114 | S32 getDiscardLevel() const { return mCurrentDiscardLevel; } | 116 | S32 getDiscardLevel() const { return mCurrentDiscardLevel; } |
115 | S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } | 117 | S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } |
@@ -123,15 +125,12 @@ public: | |||
123 | S32 getMipBytes(S32 discard_level = -1) const; | 125 | S32 getMipBytes(S32 discard_level = -1) const; |
124 | BOOL getBoundRecently() const; | 126 | BOOL getBoundRecently() const; |
125 | LLGLenum getPrimaryFormat() const { return mFormatPrimary; } | 127 | LLGLenum getPrimaryFormat() const { return mFormatPrimary; } |
126 | 128 | ||
127 | BOOL getClampS() const { return mClampS; } | ||
128 | BOOL getClampT() const { return mClampT; } | ||
129 | BOOL getClampR() const { return mClampR; } | ||
130 | BOOL getMipFilterNearest() const { return mMagFilterNearest; } | ||
131 | |||
132 | BOOL getHasGLTexture() const { return mTexName != 0; } | 129 | BOOL getHasGLTexture() const { return mTexName != 0; } |
133 | LLGLuint getTexName() const { return mTexName; } | 130 | LLGLuint getTexName() const { return mTexName; } |
134 | 131 | ||
132 | BOOL getIsAlphaMask() const { return mIsMask; } | ||
133 | |||
135 | BOOL getIsResident(BOOL test_now = FALSE); // not const | 134 | BOOL getIsResident(BOOL test_now = FALSE); // not const |
136 | 135 | ||
137 | void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target); | 136 | void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target); |
@@ -151,6 +150,27 @@ public: | |||
151 | BOOL getMask(const LLVector2 &tc); | 150 | BOOL getMask(const LLVector2 &tc); |
152 | 151 | ||
153 | void checkTexSize() const ; | 152 | void checkTexSize() const ; |
153 | |||
154 | // Sets the addressing mode used to sample the texture | ||
155 | // (such as wrapping, mirrored wrapping, and clamp) | ||
156 | // Note: this actually gets set the next time the texture is bound. | ||
157 | void setAddressMode(LLTexUnit::eTextureAddressMode mode); | ||
158 | LLTexUnit::eTextureAddressMode getAddressMode(void) const { return mAddressMode; } | ||
159 | |||
160 | // Sets the filtering options used to sample the texture | ||
161 | // (such as point sampling, bilinear interpolation, mipmapping, and anisotropic filtering) | ||
162 | // Note: this actually gets set the next time the texture is bound. | ||
163 | void setFilteringOption(LLTexUnit::eTextureFilterOptions option); | ||
164 | LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; } | ||
165 | |||
166 | BOOL isDeleted() ; | ||
167 | BOOL isInactive() ; | ||
168 | BOOL isDeletionCandidate(); | ||
169 | void setDeletionCandidate() ; | ||
170 | void setInactive() ; | ||
171 | void setActive() ; | ||
172 | void forceActive() ; | ||
173 | void setNoDelete() ; | ||
154 | 174 | ||
155 | protected: | 175 | protected: |
156 | void init(BOOL usemipmaps); | 176 | void init(BOOL usemipmaps); |
@@ -165,9 +185,10 @@ private: | |||
165 | LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL | 185 | LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL |
166 | U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel | 186 | U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel |
167 | S8 mUseMipMaps; | 187 | S8 mUseMipMaps; |
168 | S8 mHasMipMaps; | ||
169 | S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents) | 188 | S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents) |
170 | S8 mAutoGenMips; | 189 | S8 mAutoGenMips; |
190 | |||
191 | BOOL mIsMask; | ||
171 | 192 | ||
172 | bool mGLTextureCreated ; | 193 | bool mGLTextureCreated ; |
173 | LLGLuint mTexName; | 194 | LLGLuint mTexName; |
@@ -178,6 +199,7 @@ private: | |||
178 | protected: | 199 | protected: |
179 | LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) | 200 | LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) |
180 | LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) | 201 | LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) |
202 | bool mHasMipMaps; | ||
181 | 203 | ||
182 | LLGLboolean mIsResident; | 204 | LLGLboolean mIsResident; |
183 | 205 | ||
@@ -185,17 +207,27 @@ protected: | |||
185 | S8 mMaxDiscardLevel; | 207 | S8 mMaxDiscardLevel; |
186 | S8 mDontDiscard; // Keep full res version of this image (for UI, etc) | 208 | S8 mDontDiscard; // Keep full res version of this image (for UI, etc) |
187 | 209 | ||
188 | S8 mClampS; // Need to save clamp state | 210 | bool mTexOptionsDirty; |
189 | S8 mClampT; | 211 | LLTexUnit::eTextureAddressMode mAddressMode; // Defaults to TAM_WRAP |
190 | S8 mClampR; | 212 | LLTexUnit::eTextureFilterOptions mFilterOption; // Defaults to TFO_TRILINEAR |
191 | S8 mMagFilterNearest; // if TRUE, set magfilter to GL_NEAREST | 213 | |
192 | S8 mMinFilterNearest; // if TRUE, set minfilter to GL_NEAREST | ||
193 | 214 | ||
194 | LLGLint mFormatInternal; // = GL internalformat | 215 | LLGLint mFormatInternal; // = GL internalformat |
195 | LLGLenum mFormatPrimary; // = GL format (pixel data format) | 216 | LLGLenum mFormatPrimary; // = GL format (pixel data format) |
196 | LLGLenum mFormatType; | 217 | LLGLenum mFormatType; |
197 | BOOL mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1) | 218 | BOOL mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1) |
198 | 219 | ||
220 | protected: | ||
221 | typedef enum | ||
222 | { | ||
223 | DELETED = 0, //removed from memory | ||
224 | DELETION_CANDIDATE, //ready to be removed from memory | ||
225 | INACTIVE, //not be used for the last certain period (i.e., 30 seconds). | ||
226 | ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). | ||
227 | NO_DELETE = 99 //stay in memory, can not be removed. | ||
228 | } LLGLTexureState; | ||
229 | LLGLTexureState mTextureState ; | ||
230 | |||
199 | // STATICS | 231 | // STATICS |
200 | public: | 232 | public: |
201 | static std::set<LLImageGL*> sImageList; | 233 | static std::set<LLImageGL*> sImageList; |
diff --git a/linden/indra/llrender/llpostprocess.cpp b/linden/indra/llrender/llpostprocess.cpp index 92a0854..7f4be6a 100644 --- a/linden/indra/llrender/llpostprocess.cpp +++ b/linden/indra/llrender/llpostprocess.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -207,7 +208,7 @@ void LLPostProcess::applyShaders(void) | |||
207 | /// If any of the above shaders have been called update the frame buffer; | 208 | /// If any of the above shaders have been called update the frame buffer; |
208 | if (tweaks.useColorFilter()) | 209 | if (tweaks.useColorFilter()) |
209 | { | 210 | { |
210 | GLuint tex = mSceneRenderTexture->getTexName() ; | 211 | U32 tex = mSceneRenderTexture->getTexName() ; |
211 | copyFrameBuffer(tex, screenW, screenH); | 212 | copyFrameBuffer(tex, screenW, screenH); |
212 | } | 213 | } |
213 | applyNightVisionShader(); | 214 | applyNightVisionShader(); |
@@ -217,7 +218,7 @@ void LLPostProcess::applyShaders(void) | |||
217 | /// If any of the above shaders have been called update the frame buffer; | 218 | /// If any of the above shaders have been called update the frame buffer; |
218 | if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()) | 219 | if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()) |
219 | { | 220 | { |
220 | GLuint tex = mSceneRenderTexture->getTexName() ; | 221 | U32 tex = mSceneRenderTexture->getTexName() ; |
221 | copyFrameBuffer(tex, screenW, screenH); | 222 | copyFrameBuffer(tex, screenW, screenH); |
222 | } | 223 | } |
223 | applyBloomShader(); | 224 | applyBloomShader(); |
@@ -359,7 +360,7 @@ void LLPostProcess::doEffects(void) | |||
359 | 360 | ||
360 | /// Copy the screen buffer to the render texture | 361 | /// Copy the screen buffer to the render texture |
361 | { | 362 | { |
362 | GLuint tex = mSceneRenderTexture->getTexName() ; | 363 | U32 tex = mSceneRenderTexture->getTexName() ; |
363 | copyFrameBuffer(tex, screenW, screenH); | 364 | copyFrameBuffer(tex, screenW, screenH); |
364 | } | 365 | } |
365 | 366 | ||
@@ -385,7 +386,7 @@ void LLPostProcess::doEffects(void) | |||
385 | checkError(); | 386 | checkError(); |
386 | } | 387 | } |
387 | 388 | ||
388 | void LLPostProcess::copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height) | 389 | void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height) |
389 | { | 390 | { |
390 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture); | 391 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture); |
391 | glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0); | 392 | glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0); |
@@ -502,10 +503,8 @@ void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int wi | |||
502 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName()); | 503 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName()); |
503 | glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, | 504 | glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, |
504 | GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); | 505 | GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); |
505 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR); | 506 | gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); |
506 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR); | 507 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); |
507 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
508 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
509 | } | 508 | } |
510 | } | 509 | } |
511 | 510 | ||
@@ -522,11 +521,9 @@ void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture) | |||
522 | if(texture->createGLTexture()) | 521 | if(texture->createGLTexture()) |
523 | { | 522 | { |
524 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); | 523 | gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); |
525 | glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); | 524 | LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); |
526 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); | 525 | gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); |
527 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); | 526 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); |
528 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); | ||
529 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); | ||
530 | } | 527 | } |
531 | } | 528 | } |
532 | 529 | ||
diff --git a/linden/indra/llrender/llpostprocess.h b/linden/indra/llrender/llpostprocess.h index b191e9d..009e4bd 100644 --- a/linden/indra/llrender/llpostprocess.h +++ b/linden/indra/llrender/llpostprocess.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -255,7 +256,7 @@ private: | |||
255 | /// OpenGL Helper Functions | 256 | /// OpenGL Helper Functions |
256 | void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog); | 257 | void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog); |
257 | void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height); | 258 | void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height); |
258 | void copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height); | 259 | void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height); |
259 | void createNoiseTexture(LLPointer<LLImageGL>& texture); | 260 | void createNoiseTexture(LLPointer<LLImageGL>& texture); |
260 | bool checkError(void); | 261 | bool checkError(void); |
261 | void checkShaderError(GLhandleARB shader); | 262 | void checkShaderError(GLhandleARB shader); |
diff --git a/linden/indra/llrender/llrender.cpp b/linden/indra/llrender/llrender.cpp index ff0a2db..ba95a19 100644 --- a/linden/indra/llrender/llrender.cpp +++ b/linden/indra/llrender/llrender.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -74,7 +75,7 @@ static GLenum sGLCompareFunc[] = | |||
74 | GL_GREATER | 75 | GL_GREATER |
75 | }; | 76 | }; |
76 | 77 | ||
77 | const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD; | 78 | const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; |
78 | 79 | ||
79 | static GLenum sGLBlendFactor[] = | 80 | static GLenum sGLBlendFactor[] = |
80 | { | 81 | { |
@@ -95,7 +96,8 @@ LLTexUnit::LLTexUnit(S32 index) | |||
95 | mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), | 96 | mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), |
96 | mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), | 97 | mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), |
97 | mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), | 98 | mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), |
98 | mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0) | 99 | mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), |
100 | mHasMipMaps(false) | ||
99 | { | 101 | { |
100 | llassert_always(index < LL_NUM_TEXTURE_LAYERS); | 102 | llassert_always(index < LL_NUM_TEXTURE_LAYERS); |
101 | mIndex = index; | 103 | mIndex = index; |
@@ -175,8 +177,9 @@ void LLTexUnit::disable(void) | |||
175 | } | 177 | } |
176 | } | 178 | } |
177 | 179 | ||
178 | bool LLTexUnit::bind(const LLImageGL* texture, bool forceBind) | 180 | bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) |
179 | { | 181 | { |
182 | stop_glerror(); | ||
180 | if (mIndex < 0) return false; | 183 | if (mIndex < 0) return false; |
181 | 184 | ||
182 | gGL.flush(); | 185 | gGL.flush(); |
@@ -189,14 +192,28 @@ bool LLTexUnit::bind(const LLImageGL* texture, bool forceBind) | |||
189 | 192 | ||
190 | if (!texture->getTexName()) //if texture does not exist | 193 | if (!texture->getTexName()) //if texture does not exist |
191 | { | 194 | { |
195 | //if deleted, will re-generate it immediately | ||
196 | texture->forceImmediateUpdate() ; | ||
197 | |||
192 | return texture->bindDefaultImage(mIndex); | 198 | return texture->bindDefaultImage(mIndex); |
193 | } | 199 | } |
194 | // Disabled caching of binding state. | 200 | |
195 | activate(); | 201 | if ((mCurrTexture != texture->getTexName()) || forceBind) |
196 | enable(texture->getTarget()); | 202 | { |
197 | mCurrTexture = texture->getTexName(); | 203 | activate(); |
198 | glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); | 204 | enable(texture->getTarget()); |
199 | texture->updateBindStats(); | 205 | mCurrTexture = texture->getTexName(); |
206 | glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); | ||
207 | texture->updateBindStats(); | ||
208 | texture->setActive() ; | ||
209 | mHasMipMaps = texture->mHasMipMaps; | ||
210 | if (texture->mTexOptionsDirty) | ||
211 | { | ||
212 | texture->mTexOptionsDirty = false; | ||
213 | setTextureAddressMode(texture->mAddressMode); | ||
214 | setTextureFilteringOption(texture->mFilterOption); | ||
215 | } | ||
216 | } | ||
200 | return true; | 217 | return true; |
201 | } | 218 | } |
202 | 219 | ||
@@ -206,8 +223,13 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) | |||
206 | 223 | ||
207 | gGL.flush(); | 224 | gGL.flush(); |
208 | 225 | ||
209 | // Disabled caching of binding state. | 226 | if (cubeMap == NULL) |
210 | if (cubeMap != NULL) | 227 | { |
228 | llwarns << "NULL LLTexUnit::bind cubemap" << llendl; | ||
229 | return false; | ||
230 | } | ||
231 | |||
232 | if (mCurrTexture != cubeMap->mImages[0]->getTexName()) | ||
211 | { | 233 | { |
212 | if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) | 234 | if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) |
213 | { | 235 | { |
@@ -215,18 +237,27 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap) | |||
215 | enable(LLTexUnit::TT_CUBE_MAP); | 237 | enable(LLTexUnit::TT_CUBE_MAP); |
216 | mCurrTexture = cubeMap->mImages[0]->getTexName(); | 238 | mCurrTexture = cubeMap->mImages[0]->getTexName(); |
217 | glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture); | 239 | glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture); |
240 | mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; | ||
218 | cubeMap->mImages[0]->updateBindStats(); | 241 | cubeMap->mImages[0]->updateBindStats(); |
219 | cubeMap->mImages[0]->setMipFilterNearest (FALSE, FALSE); | 242 | if (cubeMap->mImages[0]->mTexOptionsDirty) |
243 | { | ||
244 | cubeMap->mImages[0]->mTexOptionsDirty = false; | ||
245 | setTextureAddressMode(cubeMap->mImages[0]->mAddressMode); | ||
246 | setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption); | ||
247 | } | ||
220 | return true; | 248 | return true; |
221 | } | 249 | } |
222 | else | 250 | else |
223 | { | 251 | { |
224 | llwarns << "Using cube map without extension!" << llendl | 252 | llwarns << "Using cube map without extension!" << llendl; |
253 | return false; | ||
225 | } | 254 | } |
226 | } | 255 | } |
227 | return false; | 256 | return true; |
228 | } | 257 | } |
229 | 258 | ||
259 | // LLRenderTarget is unavailible on the mapserver since it uses FBOs. | ||
260 | #if !LL_MESA_HEADLESS | ||
230 | bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) | 261 | bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) |
231 | { | 262 | { |
232 | if (mIndex < 0) return false; | 263 | if (mIndex < 0) return false; |
@@ -244,23 +275,26 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) | |||
244 | 275 | ||
245 | return true; | 276 | return true; |
246 | } | 277 | } |
278 | #endif // LL_MESA_HEADLESS | ||
247 | 279 | ||
248 | bool LLTexUnit::bindManual(eTextureType type, U32 texture) | 280 | bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) |
249 | { | 281 | { |
250 | if (mIndex < 0) return false; | 282 | if (mIndex < 0 || mCurrTexture == texture) return false; |
251 | 283 | ||
252 | // Disabled caching of binding state. | ||
253 | gGL.flush(); | 284 | gGL.flush(); |
254 | 285 | ||
255 | activate(); | 286 | activate(); |
256 | enable(type); | 287 | enable(type); |
257 | mCurrTexture = texture; | 288 | mCurrTexture = texture; |
258 | glBindTexture(sGLTextureType[type], texture); | 289 | glBindTexture(sGLTextureType[type], texture); |
290 | mHasMipMaps = hasMips; | ||
259 | return true; | 291 | return true; |
260 | } | 292 | } |
261 | 293 | ||
262 | void LLTexUnit::unbind(eTextureType type) | 294 | void LLTexUnit::unbind(eTextureType type) |
263 | { | 295 | { |
296 | stop_glerror(); | ||
297 | |||
264 | if (mIndex < 0) return; | 298 | if (mIndex < 0) return; |
265 | 299 | ||
266 | // Disabled caching of binding state. | 300 | // Disabled caching of binding state. |
@@ -276,17 +310,57 @@ void LLTexUnit::unbind(eTextureType type) | |||
276 | 310 | ||
277 | void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) | 311 | void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) |
278 | { | 312 | { |
279 | if (mIndex < 0) return; | 313 | if (mIndex < 0 || mCurrTexture == 0) return; |
280 | 314 | ||
281 | if (true) | 315 | activate(); |
316 | |||
317 | glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); | ||
318 | glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); | ||
319 | if (mCurrTexType == TT_CUBE_MAP) | ||
282 | { | 320 | { |
283 | activate(); | 321 | glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); |
322 | } | ||
323 | } | ||
324 | |||
325 | void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option) | ||
326 | { | ||
327 | if (mIndex < 0 || mCurrTexture == 0) return; | ||
284 | 328 | ||
285 | glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); | 329 | if (option == TFO_POINT) |
286 | glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); | 330 | { |
287 | if (mCurrTexType == TT_CUBE_MAP) | 331 | glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
332 | } | ||
333 | else | ||
334 | { | ||
335 | glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
336 | } | ||
337 | |||
338 | if (option >= TFO_TRILINEAR && mHasMipMaps) | ||
339 | { | ||
340 | glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); | ||
341 | } | ||
342 | else if (option >= TFO_BILINEAR) | ||
343 | { | ||
344 | glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
345 | } | ||
346 | else | ||
347 | { | ||
348 | glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||
349 | } | ||
350 | |||
351 | if (gGLManager.mHasAnisotropic) | ||
352 | { | ||
353 | if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) | ||
288 | { | 354 | { |
289 | glTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); | 355 | if (gGL.mMaxAnisotropy < 1.f) |
356 | { | ||
357 | glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGL.mMaxAnisotropy); | ||
358 | } | ||
359 | glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGL.mMaxAnisotropy); | ||
360 | } | ||
361 | else | ||
362 | { | ||
363 | glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); | ||
290 | } | 364 | } |
291 | } | 365 | } |
292 | } | 366 | } |
@@ -589,12 +663,13 @@ void LLTexUnit::debugTextureUnit(void) | |||
589 | 663 | ||
590 | 664 | ||
591 | LLRender::LLRender() | 665 | LLRender::LLRender() |
592 | : mDirty(false), mCount(0), mMode(LLRender::TRIANGLES) | 666 | : mDirty(false), mCount(0), mMode(LLRender::TRIANGLES), |
667 | mMaxAnisotropy(0.f) | ||
593 | { | 668 | { |
594 | mBuffer = new LLVertexBuffer(immediate_mask, 0); | 669 | mBuffer = new LLVertexBuffer(immediate_mask, 0); |
595 | mBuffer->allocateBuffer(4096, 0, TRUE); | 670 | mBuffer->allocateBuffer(4096, 0, TRUE); |
596 | mBuffer->getVertexStrider(mVerticesp); | 671 | mBuffer->getVertexStrider(mVerticesp); |
597 | mBuffer->getTexCoordStrider(mTexcoordsp); | 672 | mBuffer->getTexCoord0Strider(mTexcoordsp); |
598 | mBuffer->getColorStrider(mColorsp); | 673 | mBuffer->getColorStrider(mColorsp); |
599 | 674 | ||
600 | mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS); | 675 | mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS); |
@@ -687,7 +762,10 @@ void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB | |||
687 | mCurrColorMask[2] = writeColorB; | 762 | mCurrColorMask[2] = writeColorB; |
688 | mCurrColorMask[3] = writeAlpha; | 763 | mCurrColorMask[3] = writeAlpha; |
689 | 764 | ||
690 | glColorMask(writeColorR, writeColorG, writeColorB, writeAlpha); | 765 | glColorMask(writeColorR ? GL_TRUE : GL_FALSE, |
766 | writeColorG ? GL_TRUE : GL_FALSE, | ||
767 | writeColorB ? GL_TRUE : GL_FALSE, | ||
768 | writeAlpha ? GL_TRUE : GL_FALSE); | ||
691 | } | 769 | } |
692 | 770 | ||
693 | void LLRender::setSceneBlendType(eBlendType type) | 771 | void LLRender::setSceneBlendType(eBlendType type) |
@@ -767,6 +845,14 @@ bool LLRender::verifyTexUnitActive(U32 unitToVerify) | |||
767 | } | 845 | } |
768 | } | 846 | } |
769 | 847 | ||
848 | void LLRender::clearErrors() | ||
849 | { | ||
850 | while (glGetError()) | ||
851 | { | ||
852 | //loop until no more error flags left | ||
853 | } | ||
854 | } | ||
855 | |||
770 | void LLRender::begin(const GLuint& mode) | 856 | void LLRender::begin(const GLuint& mode) |
771 | { | 857 | { |
772 | if (mode != mMode) | 858 | if (mode != mMode) |
@@ -852,13 +938,14 @@ void LLRender::flush() | |||
852 | 938 | ||
853 | mBuffer->setBuffer(immediate_mask); | 939 | mBuffer->setBuffer(immediate_mask); |
854 | mBuffer->drawArrays(mMode, 0, mCount); | 940 | mBuffer->drawArrays(mMode, 0, mCount); |
855 | 941 | ||
856 | mVerticesp[0] = mVerticesp[mCount]; | 942 | mVerticesp[0] = mVerticesp[mCount]; |
857 | mTexcoordsp[0] = mTexcoordsp[mCount]; | 943 | mTexcoordsp[0] = mTexcoordsp[mCount]; |
858 | mColorsp[0] = mColorsp[mCount]; | 944 | mColorsp[0] = mColorsp[mCount]; |
859 | mCount = 0; | 945 | mCount = 0; |
860 | } | 946 | } |
861 | } | 947 | } |
948 | |||
862 | void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) | 949 | void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) |
863 | { | 950 | { |
864 | //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] | 951 | //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] |
diff --git a/linden/indra/llrender/llrender.h b/linden/indra/llrender/llrender.h index e949190..437c715 100644 --- a/linden/indra/llrender/llrender.h +++ b/linden/indra/llrender/llrender.h | |||
@@ -22,7 +22,8 @@ | |||
22 | * There are special exceptions to the terms and conditions of the GPL as | 22 | * There are special exceptions to the terms and conditions of the GPL as |
23 | * it is applied to this Source Code. View the full text of the exception | 23 | * it is applied to this Source Code. View the full text of the exception |
24 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 24 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
25 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 25 | * online at |
26 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
26 | * | 27 | * |
27 | * By copying, modifying or distributing this software, you acknowledge | 28 | * By copying, modifying or distributing this software, you acknowledge |
28 | * that you have read and understood your obligations described above, | 29 | * that you have read and understood your obligations described above, |
@@ -70,6 +71,14 @@ public: | |||
70 | TAM_CLAMP // No texture type is currently enabled | 71 | TAM_CLAMP // No texture type is currently enabled |
71 | } eTextureAddressMode; | 72 | } eTextureAddressMode; |
72 | 73 | ||
74 | typedef enum | ||
75 | { // Note: If mipmapping or anisotropic are not enabled or supported it should fall back gracefully | ||
76 | TFO_POINT = 0, // Equal to: min=point, mag=point, mip=none. | ||
77 | TFO_BILINEAR, // Equal to: min=linear, mag=linear, mip=point. | ||
78 | TFO_TRILINEAR, // Equal to: min=linear, mag=linear, mip=linear. | ||
79 | TFO_ANISOTROPIC // Equal to: min=anisotropic, max=anisotropic, mip=linear. | ||
80 | } eTextureFilterOptions; | ||
81 | |||
73 | typedef enum | 82 | typedef enum |
74 | { | 83 | { |
75 | TB_REPLACE = 0, | 84 | TB_REPLACE = 0, |
@@ -130,30 +139,43 @@ public: | |||
130 | // Sets this tex unit to be the currently active one | 139 | // Sets this tex unit to be the currently active one |
131 | void activate(void); | 140 | void activate(void); |
132 | 141 | ||
133 | // Enables this texture unit for the given texture type (automatically disables any previously enabled texture type) | 142 | // Enables this texture unit for the given texture type |
143 | // (automatically disables any previously enabled texture type) | ||
134 | void enable(eTextureType type); | 144 | void enable(eTextureType type); |
145 | |||
135 | // Disables the current texture unit | 146 | // Disables the current texture unit |
136 | void disable(void); | 147 | void disable(void); |
137 | 148 | ||
138 | // Binds the LLImageGL to this texture unit | 149 | // Binds the LLImageGL to this texture unit |
139 | // (automatically enables the unit for the LLImageGL's texture type) | 150 | // (automatically enables the unit for the LLImageGL's texture type) |
140 | bool bind(const LLImageGL* texture, bool forceBind = false); | 151 | bool bind(LLImageGL* texture, bool forceBind = false); |
141 | 152 | ||
142 | // Binds a cubemap to this texture unit | 153 | // Binds a cubemap to this texture unit |
143 | // (automatically enables the texture unit for cubemaps) | 154 | // (automatically enables the texture unit for cubemaps) |
144 | bool bind(LLCubeMap* cubeMap); | 155 | bool bind(LLCubeMap* cubeMap); |
145 | 156 | ||
146 | // Binds a render target to this texture unit (automatically enables the texture unit for the RT's texture type) | 157 | // Binds a render target to this texture unit |
158 | // (automatically enables the texture unit for the RT's texture type) | ||
147 | bool bind(LLRenderTarget * renderTarget, bool bindDepth = false); | 159 | bool bind(LLRenderTarget * renderTarget, bool bindDepth = false); |
148 | 160 | ||
149 | // Manually binds a texture to the texture unit (automatically enables the tex unit for the given texture type) | 161 | // Manually binds a texture to the texture unit |
150 | bool bindManual(eTextureType type, U32 texture); | 162 | // (automatically enables the tex unit for the given texture type) |
163 | bool bindManual(eTextureType type, U32 texture, bool hasMips = false); | ||
151 | 164 | ||
152 | // Unbinds the currently bound texture of the given type (only if there's a texture of the given type currently bound) | 165 | // Unbinds the currently bound texture of the given type |
166 | // (only if there's a texture of the given type currently bound) | ||
153 | void unbind(eTextureType type); | 167 | void unbind(eTextureType type); |
154 | 168 | ||
169 | // Sets the addressing mode used to sample the texture | ||
170 | // Warning: this stays set for the bound texture forever, | ||
171 | // make sure you want to permanently change the address mode for the bound texture. | ||
155 | void setTextureAddressMode(eTextureAddressMode mode); | 172 | void setTextureAddressMode(eTextureAddressMode mode); |
156 | 173 | ||
174 | // Sets the filtering options used to sample the texture | ||
175 | // Warning: this stays set for the bound texture forever, | ||
176 | // make sure you want to permanently change the filtering for the bound texture. | ||
177 | void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option); | ||
178 | |||
157 | void setTextureBlendType(eTextureBlendType type); | 179 | void setTextureBlendType(eTextureBlendType type); |
158 | 180 | ||
159 | inline void setTextureColorBlend(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2 = TBS_PREV_COLOR) | 181 | inline void setTextureColorBlend(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2 = TBS_PREV_COLOR) |
@@ -165,6 +187,12 @@ public: | |||
165 | 187 | ||
166 | static U32 getInternalType(eTextureType type); | 188 | static U32 getInternalType(eTextureType type); |
167 | 189 | ||
190 | U32 getCurrTexture(void) { return mCurrTexture; } | ||
191 | |||
192 | eTextureType getCurrType(void) { return mCurrTexType; } | ||
193 | |||
194 | void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; } | ||
195 | |||
168 | protected: | 196 | protected: |
169 | S32 mIndex; | 197 | S32 mIndex; |
170 | U32 mCurrTexture; | 198 | U32 mCurrTexture; |
@@ -178,6 +206,7 @@ protected: | |||
178 | eTextureBlendSrc mCurrAlphaSrc2; | 206 | eTextureBlendSrc mCurrAlphaSrc2; |
179 | S32 mCurrColorScale; | 207 | S32 mCurrColorScale; |
180 | S32 mCurrAlphaScale; | 208 | S32 mCurrAlphaScale; |
209 | bool mHasMipMaps; | ||
181 | 210 | ||
182 | void debugTextureUnit(void); | 211 | void debugTextureUnit(void); |
183 | void setColorScale(S32 scale); | 212 | void setColorScale(S32 scale); |
@@ -291,6 +320,8 @@ public: | |||
291 | 320 | ||
292 | void debugTexUnits(void); | 321 | void debugTexUnits(void); |
293 | 322 | ||
323 | void clearErrors(); | ||
324 | |||
294 | struct Vertex | 325 | struct Vertex |
295 | { | 326 | { |
296 | GLfloat v[3]; | 327 | GLfloat v[3]; |
@@ -315,6 +346,8 @@ private: | |||
315 | LLStrider<LLColor4U> mColorsp; | 346 | LLStrider<LLColor4U> mColorsp; |
316 | std::vector<LLTexUnit*> mTexUnits; | 347 | std::vector<LLTexUnit*> mTexUnits; |
317 | LLTexUnit* mDummyTexUnit; | 348 | LLTexUnit* mDummyTexUnit; |
349 | |||
350 | F32 mMaxAnisotropy; | ||
318 | }; | 351 | }; |
319 | 352 | ||
320 | extern F64 gGLModelView[16]; | 353 | extern F64 gGLModelView[16]; |
diff --git a/linden/indra/llrender/llrendersphere.cpp b/linden/indra/llrender/llrendersphere.cpp index 6aaa03e..e22b753 100644 --- a/linden/indra/llrender/llrendersphere.cpp +++ b/linden/indra/llrender/llrendersphere.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llrender/llrendersphere.h b/linden/indra/llrender/llrendersphere.h index d48b917..617ee3e 100644 --- a/linden/indra/llrender/llrendersphere.h +++ b/linden/indra/llrender/llrendersphere.h | |||
@@ -2,16 +2,27 @@ | |||
2 | * @file llrendersphere.h | 2 | * @file llrendersphere.h |
3 | * @brief interface for the LLRenderSphere class. | 3 | * @brief interface for the LLRenderSphere class. |
4 | * | 4 | * |
5 | * $LicenseInfo:firstyear=2001&license=internal$ | 5 | * $LicenseInfo:firstyear=2001&license=viewergpl$ |
6 | * | 6 | * |
7 | * Copyright (c) 2001-2009, Linden Research, Inc. | 7 | * Copyright (c) 2001-2009, Linden Research, Inc. |
8 | * | 8 | * |
9 | * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of | 9 | * Second Life Viewer Source Code |
10 | * this source code is governed by the Linden Lab Source Code Disclosure | 10 | * The source code in this file ("Source Code") is provided by Linden Lab |
11 | * Agreement ("Agreement") previously entered between you and Linden | 11 | * to you under the terms of the GNU General Public License, version 2.0 |
12 | * Lab. By accessing, using, copying, modifying or distributing this | 12 | * ("GPL"), unless you have obtained a separate licensing agreement |
13 | * software, you acknowledge that you have been informed of your | 13 | * ("Other License"), formally executed by you and Linden Lab. Terms of |
14 | * obligations under the Agreement and agree to abide by those obligations. | 14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or |
15 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at | ||
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
15 | * | 26 | * |
16 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | 27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO |
17 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | 28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, |
diff --git a/linden/indra/llrender/llrendertarget.cpp b/linden/indra/llrender/llrendertarget.cpp index 392ec24..b7f3177 100644 --- a/linden/indra/llrender/llrendertarget.cpp +++ b/linden/indra/llrender/llrendertarget.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -36,6 +37,24 @@ | |||
36 | #include "llgl.h" | 37 | #include "llgl.h" |
37 | 38 | ||
38 | 39 | ||
40 | void check_framebuffer_status() | ||
41 | { | ||
42 | if (gDebugGL) | ||
43 | { | ||
44 | GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | ||
45 | switch (status) | ||
46 | { | ||
47 | case GL_FRAMEBUFFER_COMPLETE_EXT: | ||
48 | break; | ||
49 | case GL_FRAMEBUFFER_UNSUPPORTED_EXT: | ||
50 | llerrs << "WTF?" << llendl; | ||
51 | break; | ||
52 | default: | ||
53 | llerrs << "WTF?" << llendl; | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | |||
39 | BOOL LLRenderTarget::sUseFBO = FALSE; | 58 | BOOL LLRenderTarget::sUseFBO = FALSE; |
40 | 59 | ||
41 | LLRenderTarget::LLRenderTarget() : | 60 | LLRenderTarget::LLRenderTarget() : |
@@ -47,7 +66,9 @@ LLRenderTarget::LLRenderTarget() : | |||
47 | mStencil(0), | 66 | mStencil(0), |
48 | mUseDepth(FALSE), | 67 | mUseDepth(FALSE), |
49 | mRenderDepth(FALSE), | 68 | mRenderDepth(FALSE), |
50 | mUsage(LLTexUnit::TT_TEXTURE) | 69 | mUsage(LLTexUnit::TT_TEXTURE), |
70 | mSamples(0), | ||
71 | mSampleBuffer(NULL) | ||
51 | { | 72 | { |
52 | } | 73 | } |
53 | 74 | ||
@@ -56,40 +77,26 @@ LLRenderTarget::~LLRenderTarget() | |||
56 | release(); | 77 | release(); |
57 | } | 78 | } |
58 | 79 | ||
59 | void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLTexUnit::eTextureType usage, BOOL use_fbo) | 80 | |
81 | void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) | ||
82 | { | ||
83 | mSampleBuffer = buffer; | ||
84 | } | ||
85 | |||
86 | void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo) | ||
60 | { | 87 | { |
61 | stop_glerror(); | 88 | stop_glerror(); |
62 | mResX = resx; | 89 | mResX = resx; |
63 | mResY = resy; | 90 | mResY = resy; |
64 | 91 | ||
92 | mStencil = stencil; | ||
65 | mUsage = usage; | 93 | mUsage = usage; |
66 | mUseDepth = depth; | 94 | mUseDepth = depth; |
67 | release(); | ||
68 | |||
69 | glGenTextures(1, (GLuint *) &mTex); | ||
70 | gGL.getTexUnit(0)->bindManual(mUsage, mTex); | ||
71 | glTexImage2D(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, 0, color_fmt, GL_UNSIGNED_BYTE, NULL); | ||
72 | |||
73 | glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
74 | glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
75 | |||
76 | if (mUsage != LLTexUnit::TT_RECT_TEXTURE) | ||
77 | { | ||
78 | glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); | ||
79 | glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); | ||
80 | } | ||
81 | else | ||
82 | { | ||
83 | // ATI doesn't support mirrored repeat for rectangular textures. | ||
84 | glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
85 | glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
86 | } | ||
87 | 95 | ||
88 | stop_glerror(); | 96 | release(); |
89 | 97 | ||
90 | if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) | 98 | if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) |
91 | { | 99 | { |
92 | |||
93 | if (depth) | 100 | if (depth) |
94 | { | 101 | { |
95 | stop_glerror(); | 102 | stop_glerror(); |
@@ -99,37 +106,141 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLT | |||
99 | 106 | ||
100 | glGenFramebuffersEXT(1, (GLuint *) &mFBO); | 107 | glGenFramebuffersEXT(1, (GLuint *) &mFBO); |
101 | 108 | ||
109 | if (mDepth) | ||
110 | { | ||
111 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | ||
112 | if (mStencil) | ||
113 | { | ||
114 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); | ||
115 | stop_glerror(); | ||
116 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); | ||
117 | stop_glerror(); | ||
118 | } | ||
119 | else | ||
120 | { | ||
121 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); | ||
122 | stop_glerror(); | ||
123 | } | ||
124 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||
125 | } | ||
126 | |||
102 | stop_glerror(); | 127 | stop_glerror(); |
128 | } | ||
103 | 129 | ||
104 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | 130 | addColorAttachment(color_fmt); |
131 | } | ||
105 | 132 | ||
106 | stop_glerror(); | 133 | void LLRenderTarget::addColorAttachment(U32 color_fmt) |
134 | { | ||
135 | if (color_fmt == 0) | ||
136 | { | ||
137 | return; | ||
138 | } | ||
107 | 139 | ||
108 | if (mDepth) | 140 | U32 offset = mTex.size(); |
109 | { | 141 | if (offset >= 4 || |
110 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); | 142 | offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) |
111 | stop_glerror(); | 143 | { |
112 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); | 144 | llerrs << "Too many color attachments!" << llendl; |
113 | stop_glerror(); | 145 | } |
114 | } | ||
115 | 146 | ||
116 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, | 147 | U32 tex; |
117 | LLTexUnit::getInternalType(mUsage), mTex, 0); | 148 | LLImageGL::generateTextures(1, &tex); |
118 | stop_glerror(); | 149 | gGL.getTexUnit(0)->bindManual(mUsage, tex); |
150 | |||
151 | stop_glerror(); | ||
152 | |||
153 | LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | ||
119 | 154 | ||
155 | stop_glerror(); | ||
156 | |||
157 | if (offset == 0) | ||
158 | { | ||
159 | gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); | ||
160 | } | ||
161 | else | ||
162 | { //don't filter data attachments | ||
163 | gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); | ||
164 | } | ||
165 | if (mUsage != LLTexUnit::TT_RECT_TEXTURE) | ||
166 | { | ||
167 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); | ||
168 | } | ||
169 | else | ||
170 | { | ||
171 | // ATI doesn't support mirrored repeat for rectangular textures. | ||
172 | gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); | ||
173 | } | ||
174 | if (mFBO) | ||
175 | { | ||
176 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | ||
177 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, | ||
178 | LLTexUnit::getInternalType(mUsage), tex, 0); | ||
179 | stop_glerror(); | ||
180 | |||
181 | check_framebuffer_status(); | ||
182 | |||
120 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | 183 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
121 | stop_glerror(); | ||
122 | } | 184 | } |
185 | |||
186 | mTex.push_back(tex); | ||
187 | |||
123 | } | 188 | } |
124 | 189 | ||
125 | void LLRenderTarget::allocateDepth() | 190 | void LLRenderTarget::allocateDepth() |
126 | { | 191 | { |
127 | glGenTextures(1, (GLuint *) &mDepth); | 192 | if (mStencil) |
128 | gGL.getTexUnit(0)->bindManual(mUsage, mDepth); | 193 | { |
129 | U32 internal_type = LLTexUnit::getInternalType(mUsage); | 194 | //use render buffers where stencil buffers are in play |
130 | glTexParameteri(internal_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 195 | glGenRenderbuffersEXT(1, (GLuint *) &mDepth); |
131 | glTexParameteri(internal_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 196 | glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); |
132 | glTexImage2D(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); | 197 | glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); |
198 | glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); | ||
199 | } | ||
200 | else | ||
201 | { | ||
202 | LLImageGL::generateTextures(1, &mDepth); | ||
203 | gGL.getTexUnit(0)->bindManual(mUsage, mDepth); | ||
204 | U32 internal_type = LLTexUnit::getInternalType(mUsage); | ||
205 | gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); | ||
206 | LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) | ||
211 | { | ||
212 | if (!mFBO || !target.mFBO) | ||
213 | { | ||
214 | llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; | ||
215 | } | ||
216 | |||
217 | if (mDepth) | ||
218 | { | ||
219 | stop_glerror(); | ||
220 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, target.mFBO); | ||
221 | stop_glerror(); | ||
222 | |||
223 | if (mStencil) | ||
224 | { | ||
225 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); | ||
226 | stop_glerror(); | ||
227 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); | ||
228 | stop_glerror(); | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); | ||
233 | stop_glerror(); | ||
234 | if (mStencil) | ||
235 | { | ||
236 | glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); | ||
237 | stop_glerror(); | ||
238 | } | ||
239 | } | ||
240 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||
241 | |||
242 | target.mUseDepth = TRUE; | ||
243 | } | ||
133 | } | 244 | } |
134 | 245 | ||
135 | void LLRenderTarget::release() | 246 | void LLRenderTarget::release() |
@@ -140,24 +251,63 @@ void LLRenderTarget::release() | |||
140 | mFBO = 0; | 251 | mFBO = 0; |
141 | } | 252 | } |
142 | 253 | ||
143 | if (mTex) | 254 | if (mTex.size() > 0) |
144 | { | 255 | { |
145 | glDeleteTextures(1, (GLuint *) &mTex); | 256 | LLImageGL::deleteTextures(mTex.size(), &mTex[0]); |
146 | mTex = 0; | 257 | mTex.clear(); |
147 | } | 258 | } |
148 | 259 | ||
149 | if (mDepth) | 260 | if (mDepth) |
150 | { | 261 | { |
151 | glDeleteTextures(1, (GLuint *) &mDepth); | 262 | if (mStencil) |
263 | { | ||
264 | glDeleteRenderbuffersEXT(1, (GLuint*) &mDepth); | ||
265 | stop_glerror(); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | LLImageGL::deleteTextures(1, &mDepth); | ||
270 | stop_glerror(); | ||
271 | } | ||
152 | mDepth = 0; | 272 | mDepth = 0; |
153 | } | 273 | } |
274 | |||
275 | mSampleBuffer = NULL; | ||
154 | } | 276 | } |
155 | 277 | ||
156 | void LLRenderTarget::bindTarget() | 278 | void LLRenderTarget::bindTarget() |
157 | { | 279 | { |
158 | if (mFBO) | 280 | if (mFBO) |
159 | { | 281 | { |
160 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | 282 | stop_glerror(); |
283 | if (mSampleBuffer) | ||
284 | { | ||
285 | mSampleBuffer->bindTarget(this); | ||
286 | stop_glerror(); | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | ||
291 | stop_glerror(); | ||
292 | if (gGLManager.mHasDrawBuffers) | ||
293 | { //setup multiple render targets | ||
294 | GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, | ||
295 | GL_COLOR_ATTACHMENT1_EXT, | ||
296 | GL_COLOR_ATTACHMENT2_EXT, | ||
297 | GL_COLOR_ATTACHMENT3_EXT}; | ||
298 | glDrawBuffersARB(mTex.size(), drawbuffers); | ||
299 | } | ||
300 | |||
301 | if (mTex.empty()) | ||
302 | { //no color buffer to draw to | ||
303 | glDrawBuffer(GL_NONE); | ||
304 | glReadBuffer(GL_NONE); | ||
305 | } | ||
306 | |||
307 | check_framebuffer_status(); | ||
308 | |||
309 | stop_glerror(); | ||
310 | } | ||
161 | } | 311 | } |
162 | 312 | ||
163 | glViewport(0, 0, mResX, mResY); | 313 | glViewport(0, 0, mResX, mResY); |
@@ -172,7 +322,7 @@ void LLRenderTarget::unbindTarget() | |||
172 | } | 322 | } |
173 | } | 323 | } |
174 | 324 | ||
175 | void LLRenderTarget::clear() | 325 | void LLRenderTarget::clear(U32 mask_in) |
176 | { | 326 | { |
177 | U32 mask = GL_COLOR_BUFFER_BIT; | 327 | U32 mask = GL_COLOR_BUFFER_BIT; |
178 | if (mUseDepth) | 328 | if (mUseDepth) |
@@ -181,15 +331,36 @@ void LLRenderTarget::clear() | |||
181 | } | 331 | } |
182 | if (mFBO) | 332 | if (mFBO) |
183 | { | 333 | { |
184 | glClear(mask); | 334 | check_framebuffer_status(); |
335 | stop_glerror(); | ||
336 | glClear(mask & mask_in); | ||
337 | stop_glerror(); | ||
185 | } | 338 | } |
186 | else | 339 | else |
187 | { | 340 | { |
188 | LLGLEnable scissor(GL_SCISSOR_TEST); | 341 | LLGLEnable scissor(GL_SCISSOR_TEST); |
189 | glScissor(0, 0, mResX, mResY); | 342 | glScissor(0, 0, mResX, mResY); |
190 | stop_glerror(); | 343 | stop_glerror(); |
191 | glClear(mask); | 344 | glClear(mask & mask_in); |
345 | } | ||
346 | } | ||
347 | |||
348 | U32 LLRenderTarget::getTexture(U32 attachment) const | ||
349 | { | ||
350 | if (attachment > mTex.size()-1) | ||
351 | { | ||
352 | llerrs << "Invalid attachment index." << llendl; | ||
353 | } | ||
354 | return mTex[attachment]; | ||
355 | } | ||
356 | |||
357 | void LLRenderTarget::bindTexture(U32 index, S32 channel) | ||
358 | { | ||
359 | if (index > mTex.size()-1) | ||
360 | { | ||
361 | llerrs << "Invalid attachment index." << llendl; | ||
192 | } | 362 | } |
363 | gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]); | ||
193 | } | 364 | } |
194 | 365 | ||
195 | void LLRenderTarget::flush(BOOL fetch_depth) | 366 | void LLRenderTarget::flush(BOOL fetch_depth) |
@@ -210,16 +381,87 @@ void LLRenderTarget::flush(BOOL fetch_depth) | |||
210 | gGL.getTexUnit(0)->bind(this, true); | 381 | gGL.getTexUnit(0)->bind(this, true); |
211 | glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); | 382 | glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); |
212 | } | 383 | } |
384 | |||
385 | gGL.getTexUnit(0)->disable(); | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | #if !LL_DARWIN | ||
390 | |||
391 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||
392 | |||
393 | if (mSampleBuffer) | ||
394 | { | ||
395 | LLGLEnable multisample(GL_MULTISAMPLE_ARB); | ||
396 | stop_glerror(); | ||
397 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | ||
398 | stop_glerror(); | ||
399 | check_framebuffer_status(); | ||
400 | glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO); | ||
401 | check_framebuffer_status(); | ||
402 | |||
403 | stop_glerror(); | ||
404 | glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); | ||
405 | stop_glerror(); | ||
406 | |||
407 | if (mTex.size() > 1) | ||
408 | { | ||
409 | for (U32 i = 1; i < mTex.size(); ++i) | ||
410 | { | ||
411 | glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, | ||
412 | LLTexUnit::getInternalType(mUsage), mTex[i], 0); | ||
413 | stop_glerror(); | ||
414 | glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); | ||
415 | stop_glerror(); | ||
416 | glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); | ||
417 | stop_glerror(); | ||
418 | } | ||
419 | |||
420 | for (U32 i = 0; i < mTex.size(); ++i) | ||
421 | { | ||
422 | glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, | ||
423 | LLTexUnit::getInternalType(mUsage), mTex[i], 0); | ||
424 | stop_glerror(); | ||
425 | glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); | ||
426 | stop_glerror(); | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | #endif | ||
431 | |||
432 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||
433 | glFlush(); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, | ||
438 | S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) | ||
439 | { | ||
440 | #if !LL_DARWIN | ||
441 | if (!source.mFBO || !mFBO) | ||
442 | { | ||
443 | llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; | ||
444 | } | ||
445 | |||
446 | if (mSampleBuffer) | ||
447 | { | ||
448 | mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); | ||
213 | } | 449 | } |
214 | else | 450 | else |
215 | { | 451 | { |
452 | glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); | ||
453 | glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); | ||
454 | |||
455 | glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); | ||
456 | |||
216 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | 457 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
217 | } | 458 | } |
459 | #endif | ||
218 | } | 460 | } |
219 | 461 | ||
220 | BOOL LLRenderTarget::isComplete() const | 462 | BOOL LLRenderTarget::isComplete() const |
221 | { | 463 | { |
222 | return (mTex || mDepth) ? TRUE : FALSE; | 464 | return (!mTex.empty() || mDepth) ? TRUE : FALSE; |
223 | } | 465 | } |
224 | 466 | ||
225 | void LLRenderTarget::getViewport(S32* viewport) | 467 | void LLRenderTarget::getViewport(S32* viewport) |
@@ -230,3 +472,191 @@ void LLRenderTarget::getViewport(S32* viewport) | |||
230 | viewport[3] = mResY; | 472 | viewport[3] = mResY; |
231 | } | 473 | } |
232 | 474 | ||
475 | //================================================== | ||
476 | // LLMultisampleBuffer implementation | ||
477 | //================================================== | ||
478 | LLMultisampleBuffer::LLMultisampleBuffer() | ||
479 | { | ||
480 | |||
481 | } | ||
482 | |||
483 | LLMultisampleBuffer::~LLMultisampleBuffer() | ||
484 | { | ||
485 | releaseSampleBuffer(); | ||
486 | } | ||
487 | |||
488 | void LLMultisampleBuffer::releaseSampleBuffer() | ||
489 | { | ||
490 | if (mFBO) | ||
491 | { | ||
492 | glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); | ||
493 | mFBO = 0; | ||
494 | } | ||
495 | |||
496 | if (mTex.size() > 0) | ||
497 | { | ||
498 | glDeleteRenderbuffersEXT(mTex.size(), (GLuint *) &mTex[0]); | ||
499 | mTex.clear(); | ||
500 | } | ||
501 | |||
502 | if (mDepth) | ||
503 | { | ||
504 | glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth); | ||
505 | mDepth = 0; | ||
506 | } | ||
507 | } | ||
508 | |||
509 | void LLMultisampleBuffer::bindTarget() | ||
510 | { | ||
511 | bindTarget(this); | ||
512 | } | ||
513 | |||
514 | void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) | ||
515 | { | ||
516 | if (!ref) | ||
517 | { | ||
518 | ref = this; | ||
519 | } | ||
520 | |||
521 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | ||
522 | if (gGLManager.mHasDrawBuffers) | ||
523 | { //setup multiple render targets | ||
524 | GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, | ||
525 | GL_COLOR_ATTACHMENT1_EXT, | ||
526 | GL_COLOR_ATTACHMENT2_EXT, | ||
527 | GL_COLOR_ATTACHMENT3_EXT}; | ||
528 | glDrawBuffersARB(ref->mTex.size(), drawbuffers); | ||
529 | } | ||
530 | |||
531 | check_framebuffer_status(); | ||
532 | |||
533 | glViewport(0, 0, mResX, mResY); | ||
534 | |||
535 | } | ||
536 | |||
537 | void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo ) | ||
538 | { | ||
539 | allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); | ||
540 | } | ||
541 | |||
542 | void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples ) | ||
543 | { | ||
544 | stop_glerror(); | ||
545 | mResX = resx; | ||
546 | mResY = resy; | ||
547 | |||
548 | mUsage = usage; | ||
549 | mUseDepth = depth; | ||
550 | mStencil = stencil; | ||
551 | |||
552 | releaseSampleBuffer(); | ||
553 | |||
554 | if (!gGLManager.mHasFramebufferMultisample) | ||
555 | { | ||
556 | llerrs << "Attempting to allocate unsupported render target type!" << llendl; | ||
557 | } | ||
558 | |||
559 | mSamples = samples; | ||
560 | |||
561 | if (mSamples <= 1) | ||
562 | { | ||
563 | llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl; | ||
564 | } | ||
565 | |||
566 | stop_glerror(); | ||
567 | |||
568 | if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) | ||
569 | { | ||
570 | |||
571 | if (depth) | ||
572 | { | ||
573 | stop_glerror(); | ||
574 | allocateDepth(); | ||
575 | stop_glerror(); | ||
576 | } | ||
577 | |||
578 | glGenFramebuffersEXT(1, (GLuint *) &mFBO); | ||
579 | |||
580 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | ||
581 | |||
582 | if (mDepth) | ||
583 | { | ||
584 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); | ||
585 | if (mStencil) | ||
586 | { | ||
587 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); | ||
588 | } | ||
589 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||
590 | } | ||
591 | |||
592 | stop_glerror(); | ||
593 | |||
594 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||
595 | stop_glerror(); | ||
596 | } | ||
597 | |||
598 | addColorAttachment(color_fmt); | ||
599 | } | ||
600 | |||
601 | void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) | ||
602 | { | ||
603 | #if !LL_DARWIN | ||
604 | if (color_fmt == 0) | ||
605 | { | ||
606 | return; | ||
607 | } | ||
608 | |||
609 | U32 offset = mTex.size(); | ||
610 | if (offset >= 4 || | ||
611 | offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers)) | ||
612 | { | ||
613 | llerrs << "Too many color attachments!" << llendl; | ||
614 | } | ||
615 | |||
616 | U32 tex; | ||
617 | glGenRenderbuffersEXT(1, &tex); | ||
618 | |||
619 | glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tex); | ||
620 | glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, color_fmt, mResX, mResY); | ||
621 | stop_glerror(); | ||
622 | |||
623 | if (mFBO) | ||
624 | { | ||
625 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); | ||
626 | glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, GL_RENDERBUFFER_EXT, tex); | ||
627 | stop_glerror(); | ||
628 | GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | ||
629 | switch (status) | ||
630 | { | ||
631 | case GL_FRAMEBUFFER_COMPLETE_EXT: | ||
632 | break; | ||
633 | case GL_FRAMEBUFFER_UNSUPPORTED_EXT: | ||
634 | llerrs << "WTF?" << llendl; | ||
635 | break; | ||
636 | default: | ||
637 | llerrs << "WTF?" << llendl; | ||
638 | } | ||
639 | |||
640 | glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | ||
641 | } | ||
642 | |||
643 | mTex.push_back(tex); | ||
644 | #endif | ||
645 | } | ||
646 | |||
647 | void LLMultisampleBuffer::allocateDepth() | ||
648 | { | ||
649 | #if !LL_DARWIN | ||
650 | glGenRenderbuffersEXT(1, (GLuint* ) &mDepth); | ||
651 | glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); | ||
652 | if (mStencil) | ||
653 | { | ||
654 | glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); | ||
655 | } | ||
656 | else | ||
657 | { | ||
658 | glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); | ||
659 | } | ||
660 | #endif | ||
661 | } | ||
662 | |||
diff --git a/linden/indra/llrender/llrendertarget.h b/linden/indra/llrender/llrendertarget.h index 38a41cb..d5d809b 100644 --- a/linden/indra/llrender/llrendertarget.h +++ b/linden/indra/llrender/llrendertarget.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -32,6 +33,9 @@ | |||
32 | #ifndef LL_LLRENDERTARGET_H | 33 | #ifndef LL_LLRENDERTARGET_H |
33 | #define LL_LLRENDERTARGET_H | 34 | #define LL_LLRENDERTARGET_H |
34 | 35 | ||
36 | // LLRenderTarget is unavailible on the mapserver since it uses FBOs. | ||
37 | #if !LL_MESA_HEADLESS | ||
38 | |||
35 | #include "llgl.h" | 39 | #include "llgl.h" |
36 | #include "llrender.h" | 40 | #include "llrender.h" |
37 | 41 | ||
@@ -59,6 +63,7 @@ | |||
59 | 63 | ||
60 | */ | 64 | */ |
61 | 65 | ||
66 | class LLMultisampleBuffer; | ||
62 | 67 | ||
63 | class LLRenderTarget | 68 | class LLRenderTarget |
64 | { | 69 | { |
@@ -67,15 +72,25 @@ public: | |||
67 | static BOOL sUseFBO; | 72 | static BOOL sUseFBO; |
68 | 73 | ||
69 | LLRenderTarget(); | 74 | LLRenderTarget(); |
70 | ~LLRenderTarget(); | 75 | virtual ~LLRenderTarget(); |
71 | 76 | ||
72 | //allocate resources for rendering | 77 | //allocate resources for rendering |
73 | //must be called before use | 78 | //must be called before use |
74 | //multiple calls will release previously allocated resources | 79 | //multiple calls will release previously allocated resources |
75 | void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, BOOL use_fbo = FALSE); | 80 | void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, BOOL use_fbo = FALSE); |
81 | |||
82 | //provide this render target with a multisample resource. | ||
83 | void setSampleBuffer(LLMultisampleBuffer* buffer); | ||
84 | |||
85 | //add color buffer attachment | ||
86 | //limit of 4 color attachments per render target | ||
87 | virtual void addColorAttachment(U32 color_fmt); | ||
76 | 88 | ||
77 | //allocate a depth texture | 89 | //allocate a depth texture |
78 | void allocateDepth(); | 90 | virtual void allocateDepth(); |
91 | |||
92 | //share depth buffer with provided render target | ||
93 | virtual void shareDepthBuffer(LLRenderTarget& target); | ||
79 | 94 | ||
80 | //free any allocated resources | 95 | //free any allocated resources |
81 | //safe to call redundantly | 96 | //safe to call redundantly |
@@ -83,14 +98,14 @@ public: | |||
83 | 98 | ||
84 | //bind target for rendering | 99 | //bind target for rendering |
85 | //applies appropriate viewport | 100 | //applies appropriate viewport |
86 | void bindTarget(); | 101 | virtual void bindTarget(); |
87 | 102 | ||
88 | //unbind target for rendering | 103 | //unbind target for rendering |
89 | static void unbindTarget(); | 104 | static void unbindTarget(); |
90 | 105 | ||
91 | //clear render targer, clears depth buffer if present, | 106 | //clear render targer, clears depth buffer if present, |
92 | //uses scissor rect if in copy-to-texture mode | 107 | //uses scissor rect if in copy-to-texture mode |
93 | void clear(); | 108 | void clear(U32 mask = 0xFFFFFFFF); |
94 | 109 | ||
95 | //get applied viewport | 110 | //get applied viewport |
96 | void getViewport(S32* viewport); | 111 | void getViewport(S32* viewport); |
@@ -103,10 +118,12 @@ public: | |||
103 | 118 | ||
104 | LLTexUnit::eTextureType getUsage(void) const { return mUsage; } | 119 | LLTexUnit::eTextureType getUsage(void) const { return mUsage; } |
105 | 120 | ||
106 | U32 getTexture(void) const { return mTex; } | 121 | U32 getTexture(U32 attachment = 0) const; |
107 | 122 | ||
108 | U32 getDepth(void) const { return mDepth; } | 123 | U32 getDepth(void) const { return mDepth; } |
109 | 124 | ||
125 | void bindTexture(U32 index, S32 channel); | ||
126 | |||
110 | //flush rendering operations | 127 | //flush rendering operations |
111 | //must be called when rendering is complete | 128 | //must be called when rendering is complete |
112 | //should be used 1:1 with bindTarget | 129 | //should be used 1:1 with bindTarget |
@@ -115,23 +132,47 @@ public: | |||
115 | // the current depth texture. A depth texture will be allocated if needed. | 132 | // the current depth texture. A depth texture will be allocated if needed. |
116 | void flush(BOOL fetch_depth = FALSE); | 133 | void flush(BOOL fetch_depth = FALSE); |
117 | 134 | ||
135 | void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, | ||
136 | S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); | ||
137 | |||
118 | //Returns TRUE if target is ready to be rendered into. | 138 | //Returns TRUE if target is ready to be rendered into. |
119 | //That is, if the target has been allocated with at least | 139 | //That is, if the target has been allocated with at least |
120 | //one renderable attachment (i.e. color buffer, depth buffer). | 140 | //one renderable attachment (i.e. color buffer, depth buffer). |
121 | BOOL isComplete() const; | 141 | BOOL isComplete() const; |
122 | 142 | ||
123 | private: | 143 | protected: |
144 | friend class LLMultisampleBuffer; | ||
124 | U32 mResX; | 145 | U32 mResX; |
125 | U32 mResY; | 146 | U32 mResY; |
126 | U32 mTex; | 147 | std::vector<U32> mTex; |
127 | U32 mFBO; | 148 | U32 mFBO; |
128 | U32 mDepth; | 149 | U32 mDepth; |
129 | U32 mStencil; | 150 | BOOL mStencil; |
130 | BOOL mUseDepth; | 151 | BOOL mUseDepth; |
131 | BOOL mRenderDepth; | 152 | BOOL mRenderDepth; |
132 | LLTexUnit::eTextureType mUsage; | 153 | LLTexUnit::eTextureType mUsage; |
154 | U32 mSamples; | ||
155 | LLMultisampleBuffer* mSampleBuffer; | ||
133 | 156 | ||
134 | }; | 157 | }; |
135 | 158 | ||
159 | class LLMultisampleBuffer : public LLRenderTarget | ||
160 | { | ||
161 | public: | ||
162 | LLMultisampleBuffer(); | ||
163 | virtual ~LLMultisampleBuffer(); | ||
164 | |||
165 | void releaseSampleBuffer(); | ||
166 | |||
167 | virtual void bindTarget(); | ||
168 | void bindTarget(LLRenderTarget* ref); | ||
169 | virtual void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo); | ||
170 | void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples); | ||
171 | virtual void addColorAttachment(U32 color_fmt); | ||
172 | virtual void allocateDepth(); | ||
173 | }; | ||
174 | |||
175 | #endif //!LL_MESA_HEADLESS | ||
176 | |||
136 | #endif | 177 | #endif |
137 | 178 | ||
diff --git a/linden/indra/llrender/llshadermgr.cpp b/linden/indra/llrender/llshadermgr.cpp index 3046d19..1286e91 100644 --- a/linden/indra/llrender/llshadermgr.cpp +++ b/linden/indra/llrender/llshadermgr.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -363,7 +364,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade | |||
363 | 364 | ||
364 | 365 | ||
365 | //copy file into memory | 366 | //copy file into memory |
366 | while(fgets((char *)buff, 1024, file) != NULL && count < (sizeof(buff)/sizeof(buff[0]))) | 367 | while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) ) |
367 | { | 368 | { |
368 | text[count++] = (GLcharARB *)strdup((char *)buff); | 369 | text[count++] = (GLcharARB *)strdup((char *)buff); |
369 | } | 370 | } |
diff --git a/linden/indra/llrender/llshadermgr.h b/linden/indra/llrender/llshadermgr.h index 1f78e30..2488c7a 100644 --- a/linden/indra/llrender/llshadermgr.h +++ b/linden/indra/llrender/llshadermgr.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
diff --git a/linden/indra/llrender/llvertexbuffer.cpp b/linden/indra/llrender/llvertexbuffer.cpp index cb7f352..461edbe 100644 --- a/linden/indra/llrender/llvertexbuffer.cpp +++ b/linden/indra/llrender/llvertexbuffer.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -68,8 +69,10 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = | |||
68 | { | 69 | { |
69 | sizeof(LLVector3), // TYPE_VERTEX, | 70 | sizeof(LLVector3), // TYPE_VERTEX, |
70 | sizeof(LLVector3), // TYPE_NORMAL, | 71 | sizeof(LLVector3), // TYPE_NORMAL, |
71 | sizeof(LLVector2), // TYPE_TEXCOORD, | 72 | sizeof(LLVector2), // TYPE_TEXCOORD0, |
73 | sizeof(LLVector2), // TYPE_TEXCOORD1, | ||
72 | sizeof(LLVector2), // TYPE_TEXCOORD2, | 74 | sizeof(LLVector2), // TYPE_TEXCOORD2, |
75 | sizeof(LLVector2), // TYPE_TEXCOORD3, | ||
73 | sizeof(LLColor4U), // TYPE_COLOR, | 76 | sizeof(LLColor4U), // TYPE_COLOR, |
74 | sizeof(LLVector3), // TYPE_BINORMAL, | 77 | sizeof(LLVector3), // TYPE_BINORMAL, |
75 | sizeof(F32), // TYPE_WEIGHT, | 78 | sizeof(F32), // TYPE_WEIGHT, |
@@ -102,8 +105,8 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) | |||
102 | { | 105 | { |
103 | MAP_VERTEX, | 106 | MAP_VERTEX, |
104 | MAP_NORMAL, | 107 | MAP_NORMAL, |
105 | MAP_TEXCOORD, | 108 | MAP_TEXCOORD0, |
106 | MAP_COLOR | 109 | MAP_COLOR, |
107 | }; | 110 | }; |
108 | 111 | ||
109 | GLenum array[] = | 112 | GLenum array[] = |
@@ -111,7 +114,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) | |||
111 | GL_VERTEX_ARRAY, | 114 | GL_VERTEX_ARRAY, |
112 | GL_NORMAL_ARRAY, | 115 | GL_NORMAL_ARRAY, |
113 | GL_TEXTURE_COORD_ARRAY, | 116 | GL_TEXTURE_COORD_ARRAY, |
114 | GL_COLOR_ARRAY | 117 | GL_COLOR_ARRAY, |
115 | }; | 118 | }; |
116 | 119 | ||
117 | for (U32 i = 0; i < 4; ++i) | 120 | for (U32 i = 0; i < 4; ++i) |
@@ -122,7 +125,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) | |||
122 | { //needs to be disabled | 125 | { //needs to be disabled |
123 | glDisableClientState(array[i]); | 126 | glDisableClientState(array[i]); |
124 | } | 127 | } |
125 | else | 128 | else if (gDebugGL) |
126 | { //needs to be enabled, make sure it was (DEBUG TEMPORARY) | 129 | { //needs to be enabled, make sure it was (DEBUG TEMPORARY) |
127 | if (i > 0 && !glIsEnabled(array[i])) | 130 | if (i > 0 && !glIsEnabled(array[i])) |
128 | { | 131 | { |
@@ -136,29 +139,55 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) | |||
136 | { //needs to be enabled | 139 | { //needs to be enabled |
137 | glEnableClientState(array[i]); | 140 | glEnableClientState(array[i]); |
138 | } | 141 | } |
139 | else if (glIsEnabled(array[i])) | 142 | else if (gDebugGL && glIsEnabled(array[i])) |
140 | { //needs to be disabled, make sure it was (DEBUG TEMPORARY) | 143 | { //needs to be disabled, make sure it was (DEBUG TEMPORARY) |
141 | llerrs << "Bad client state! " << array[i] << " enabled." << llendl; | 144 | llerrs << "Bad client state! " << array[i] << " enabled." << llendl; |
142 | } | 145 | } |
143 | } | 146 | } |
144 | } | 147 | } |
145 | 148 | ||
146 | if (sLastMask & MAP_TEXCOORD2) | 149 | U32 map_tc[] = |
147 | { | 150 | { |
148 | if (!(data_mask & MAP_TEXCOORD2)) | 151 | MAP_TEXCOORD1, |
152 | MAP_TEXCOORD2, | ||
153 | MAP_TEXCOORD3 | ||
154 | }; | ||
155 | |||
156 | for (U32 i = 0; i < 3; i++) | ||
157 | { | ||
158 | if (sLastMask & map_tc[i]) | ||
149 | { | 159 | { |
150 | glClientActiveTextureARB(GL_TEXTURE1_ARB); | 160 | if (!(data_mask & map_tc[i])) |
161 | { | ||
162 | glClientActiveTextureARB(GL_TEXTURE1_ARB+i); | ||
163 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | ||
164 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
165 | } | ||
166 | } | ||
167 | else if (data_mask & map_tc[i]) | ||
168 | { | ||
169 | glClientActiveTextureARB(GL_TEXTURE1_ARB+i); | ||
170 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
171 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | if (sLastMask & MAP_BINORMAL) | ||
176 | { | ||
177 | if (!(data_mask & MAP_BINORMAL)) | ||
178 | { | ||
179 | glClientActiveTextureARB(GL_TEXTURE2_ARB); | ||
151 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); | 180 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
152 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | 181 | glClientActiveTextureARB(GL_TEXTURE0_ARB); |
153 | } | 182 | } |
154 | } | 183 | } |
155 | else if (data_mask & MAP_TEXCOORD2) | 184 | else if (data_mask & MAP_BINORMAL) |
156 | { | 185 | { |
157 | glClientActiveTextureARB(GL_TEXTURE1_ARB); | 186 | glClientActiveTextureARB(GL_TEXTURE2_ARB); |
158 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); | 187 | glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
159 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | 188 | glClientActiveTextureARB(GL_TEXTURE0_ARB); |
160 | } | 189 | } |
161 | 190 | ||
162 | sLastMask = data_mask; | 191 | sLastMask = data_mask; |
163 | } | 192 | } |
164 | } | 193 | } |
@@ -193,6 +222,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi | |||
193 | return; | 222 | return; |
194 | } | 223 | } |
195 | 224 | ||
225 | stop_glerror(); | ||
196 | glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, | 226 | glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, |
197 | ((U16*) getIndicesPointer()) + indices_offset); | 227 | ((U16*) getIndicesPointer()) + indices_offset); |
198 | stop_glerror(); | 228 | stop_glerror(); |
@@ -222,13 +252,14 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const | |||
222 | return; | 252 | return; |
223 | } | 253 | } |
224 | 254 | ||
255 | stop_glerror(); | ||
225 | glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, | 256 | glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, |
226 | ((U16*) getIndicesPointer()) + indices_offset); | 257 | ((U16*) getIndicesPointer()) + indices_offset); |
258 | stop_glerror(); | ||
227 | } | 259 | } |
228 | 260 | ||
229 | void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const | 261 | void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const |
230 | { | 262 | { |
231 | |||
232 | if (first >= (U32) mRequestedNumVerts || | 263 | if (first >= (U32) mRequestedNumVerts || |
233 | first + count > (U32) mRequestedNumVerts) | 264 | first + count > (U32) mRequestedNumVerts) |
234 | { | 265 | { |
@@ -246,6 +277,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const | |||
246 | return; | 277 | return; |
247 | } | 278 | } |
248 | 279 | ||
280 | stop_glerror(); | ||
249 | glDrawArrays(sGLMode[mode], first, count); | 281 | glDrawArrays(sGLMode[mode], first, count); |
250 | stop_glerror(); | 282 | stop_glerror(); |
251 | } | 283 | } |
@@ -766,11 +798,7 @@ U8* LLVertexBuffer::mapBuffer(S32 access) | |||
766 | stop_glerror(); | 798 | stop_glerror(); |
767 | mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); | 799 | mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); |
768 | stop_glerror(); | 800 | stop_glerror(); |
769 | /*if (sMapped) | 801 | |
770 | { | ||
771 | llerrs << "Mapped two VBOs at the same time!" << llendl; | ||
772 | } | ||
773 | sMapped = TRUE;*/ | ||
774 | if (!mMappedData) | 802 | if (!mMappedData) |
775 | { | 803 | { |
776 | //-------------------- | 804 | //-------------------- |
@@ -895,14 +923,22 @@ bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index) | |||
895 | { | 923 | { |
896 | return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index); | 924 | return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index); |
897 | } | 925 | } |
898 | bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index) | 926 | bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index) |
927 | { | ||
928 | return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index); | ||
929 | } | ||
930 | bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index) | ||
899 | { | 931 | { |
900 | return VertexBufferStrider<LLVector2,TYPE_TEXCOORD>::get(*this, strider, index); | 932 | return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index); |
901 | } | 933 | } |
902 | bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index) | 934 | /*bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index) |
903 | { | 935 | { |
904 | return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index); | 936 | return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index); |
905 | } | 937 | } |
938 | bool LLVertexBuffer::getTexCoord3Strider(LLStrider<LLVector2>& strider, S32 index) | ||
939 | { | ||
940 | return VertexBufferStrider<LLVector2,TYPE_TEXCOORD3>::get(*this, strider, index); | ||
941 | }*/ | ||
906 | bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index) | 942 | bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index) |
907 | { | 943 | { |
908 | return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index); | 944 | return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index); |
@@ -1100,24 +1136,39 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const | |||
1100 | { | 1136 | { |
1101 | glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); | 1137 | glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); |
1102 | } | 1138 | } |
1139 | if (data_mask & MAP_TEXCOORD3) | ||
1140 | { | ||
1141 | glClientActiveTextureARB(GL_TEXTURE3_ARB); | ||
1142 | glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD3])); | ||
1143 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
1144 | } | ||
1103 | if (data_mask & MAP_TEXCOORD2) | 1145 | if (data_mask & MAP_TEXCOORD2) |
1104 | { | 1146 | { |
1105 | glClientActiveTextureARB(GL_TEXTURE1_ARB); | 1147 | glClientActiveTextureARB(GL_TEXTURE2_ARB); |
1106 | glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); | 1148 | glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); |
1107 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | 1149 | glClientActiveTextureARB(GL_TEXTURE0_ARB); |
1108 | } | 1150 | } |
1109 | if (data_mask & MAP_TEXCOORD) | 1151 | if (data_mask & MAP_TEXCOORD1) |
1110 | { | 1152 | { |
1111 | glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD])); | 1153 | glClientActiveTextureARB(GL_TEXTURE1_ARB); |
1154 | glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD1])); | ||
1155 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
1112 | } | 1156 | } |
1113 | if (data_mask & MAP_COLOR) | 1157 | if (data_mask & MAP_BINORMAL) |
1114 | { | 1158 | { |
1115 | glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); | 1159 | glClientActiveTextureARB(GL_TEXTURE2_ARB); |
1160 | glTexCoordPointer(3,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); | ||
1161 | glClientActiveTextureARB(GL_TEXTURE0_ARB); | ||
1116 | } | 1162 | } |
1117 | if (data_mask & MAP_BINORMAL) | 1163 | if (data_mask & MAP_TEXCOORD0) |
1118 | { | 1164 | { |
1119 | glVertexAttribPointerARB(6, 3, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); | 1165 | glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); |
1120 | } | 1166 | } |
1167 | if (data_mask & MAP_COLOR) | ||
1168 | { | ||
1169 | glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); | ||
1170 | } | ||
1171 | |||
1121 | if (data_mask & MAP_WEIGHT) | 1172 | if (data_mask & MAP_WEIGHT) |
1122 | { | 1173 | { |
1123 | glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT])); | 1174 | glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT])); |
diff --git a/linden/indra/llrender/llvertexbuffer.h b/linden/indra/llrender/llvertexbuffer.h index aa1aafc..aad948e 100644 --- a/linden/indra/llrender/llvertexbuffer.h +++ b/linden/indra/llrender/llvertexbuffer.h | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -99,8 +100,10 @@ public: | |||
99 | enum { | 100 | enum { |
100 | TYPE_VERTEX, | 101 | TYPE_VERTEX, |
101 | TYPE_NORMAL, | 102 | TYPE_NORMAL, |
102 | TYPE_TEXCOORD, | 103 | TYPE_TEXCOORD0, |
104 | TYPE_TEXCOORD1, | ||
103 | TYPE_TEXCOORD2, | 105 | TYPE_TEXCOORD2, |
106 | TYPE_TEXCOORD3, | ||
104 | TYPE_COLOR, | 107 | TYPE_COLOR, |
105 | // These use VertexAttribPointer and should possibly be made generic | 108 | // These use VertexAttribPointer and should possibly be made generic |
106 | TYPE_BINORMAL, | 109 | TYPE_BINORMAL, |
@@ -112,16 +115,15 @@ public: | |||
112 | enum { | 115 | enum { |
113 | MAP_VERTEX = (1<<TYPE_VERTEX), | 116 | MAP_VERTEX = (1<<TYPE_VERTEX), |
114 | MAP_NORMAL = (1<<TYPE_NORMAL), | 117 | MAP_NORMAL = (1<<TYPE_NORMAL), |
115 | MAP_TEXCOORD = (1<<TYPE_TEXCOORD), | 118 | MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0), |
119 | MAP_TEXCOORD1 = (1<<TYPE_TEXCOORD1), | ||
116 | MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2), | 120 | MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2), |
121 | MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3), | ||
117 | MAP_COLOR = (1<<TYPE_COLOR), | 122 | MAP_COLOR = (1<<TYPE_COLOR), |
118 | // These use VertexAttribPointer and should possibly be made generic | 123 | // These use VertexAttribPointer and should possibly be made generic |
119 | MAP_BINORMAL = (1<<TYPE_BINORMAL), | 124 | MAP_BINORMAL = (1<<TYPE_BINORMAL), |
120 | MAP_WEIGHT = (1<<TYPE_WEIGHT), | 125 | MAP_WEIGHT = (1<<TYPE_WEIGHT), |
121 | MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), | 126 | MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), |
122 | MAP_DRAW = 0x2000, // Buffer is in draw (read-only) mode | ||
123 | MAP_MAPPED = 0x4000, // Indicates that buffer has been mapped, but not to any type of data | ||
124 | MAP_UNMAPPED = 0x8000 // Indicates that buffer has been logically un-mapped | ||
125 | }; | 127 | }; |
126 | 128 | ||
127 | protected: | 129 | protected: |
@@ -164,8 +166,8 @@ public: | |||
164 | // vb->unmapBuffer(); | 166 | // vb->unmapBuffer(); |
165 | bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0); | 167 | bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0); |
166 | bool getIndexStrider(LLStrider<U16>& strider, S32 index=0); | 168 | bool getIndexStrider(LLStrider<U16>& strider, S32 index=0); |
167 | bool getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index=0); | 169 | bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0); |
168 | bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0); | 170 | bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0); |
169 | bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0); | 171 | bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0); |
170 | bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0); | 172 | bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0); |
171 | bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0); | 173 | bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0); |