aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llrender/CMakeLists.txt14
-rw-r--r--linden/indra/llrender/llcubemap.cpp15
-rw-r--r--linden/indra/llrender/llcubemap.h3
-rw-r--r--linden/indra/llrender/llfont.cpp187
-rw-r--r--linden/indra/llrender/llfont.h52
-rw-r--r--linden/indra/llrender/llfontbitmapcache.cpp169
-rw-r--r--linden/indra/llrender/llfontbitmapcache.h79
-rw-r--r--linden/indra/llrender/llfontgl.cpp673
-rw-r--r--linden/indra/llrender/llfontgl.h74
-rw-r--r--linden/indra/llrender/llfontregistry.cpp651
-rw-r--r--linden/indra/llrender/llfontregistry.h114
-rw-r--r--linden/indra/llrender/llgl.cpp132
-rw-r--r--linden/indra/llrender/llgl.h7
-rw-r--r--linden/indra/llrender/llgldbg.cpp3
-rw-r--r--linden/indra/llrender/llgldbg.h3
-rw-r--r--linden/indra/llrender/llglheaders.h247
-rw-r--r--linden/indra/llrender/llglimmediate.cpp264
-rw-r--r--linden/indra/llrender/llglimmediate.h97
-rw-r--r--linden/indra/llrender/llglslshader.cpp89
-rw-r--r--linden/indra/llrender/llglslshader.h7
-rw-r--r--linden/indra/llrender/llglstates.h3
-rw-r--r--linden/indra/llrender/llgltypes.h3
-rw-r--r--linden/indra/llrender/llimagegl.cpp315
-rw-r--r--linden/indra/llrender/llimagegl.h78
-rw-r--r--linden/indra/llrender/llpostprocess.cpp25
-rw-r--r--linden/indra/llrender/llpostprocess.h5
-rw-r--r--linden/indra/llrender/llrender.cpp145
-rw-r--r--linden/indra/llrender/llrender.h47
-rw-r--r--linden/indra/llrender/llrendersphere.cpp3
-rw-r--r--linden/indra/llrender/llrendersphere.h25
-rw-r--r--linden/indra/llrender/llrendertarget.cpp536
-rw-r--r--linden/indra/llrender/llrendertarget.h61
-rw-r--r--linden/indra/llrender/llshadermgr.cpp5
-rw-r--r--linden/indra/llrender/llshadermgr.h3
-rw-r--r--linden/indra/llrender/llvertexbuffer.cpp109
-rw-r--r--linden/indra/llrender/llvertexbuffer.h18
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)
9include(LLMath) 9include(LLMath)
10include(LLRender) 10include(LLRender)
11include(LLWindow) 11include(LLWindow)
12include(LLXML)
13include(LLVFS)
12 14
13include_directories( 15include_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
22set(llrender_SOURCE_FILES 26set(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})
63if (SERVER AND NOT WINDOWS AND NOT DARWIN) 68if (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)
78else (SERVER AND NOT WINDOWS AND NOT DARWIN) 84else (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 )
82endif (SERVER AND NOT WINDOWS AND NOT DARWIN) 90endif (SERVER AND NOT WINDOWS AND NOT DARWIN)
83add_library (llrender ${llrender_SOURCE_FILES}) 91add_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()
311void LLCubeMap::setReflection (void) 312void 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
318LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const 319LLVector3 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
56FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; 59FT_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
127LLFont::LLFont(LLImageRaw *imagep) 130LLFont::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
147LLFont::~LLFont() 150LLFont::~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
160void 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 256void LLFont::resetBitmapCache()
297void 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
343BOOL LLFont::addChar(const llwchar wch) 298BOOL 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
398BOOL LLFont::addGlyphFromFont(LLFont *fontp, const llwchar wch, const U32 glyph_index) 352BOOL 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
519BOOL LLFont::addGlyph(const llwchar wch, const U32 glyph_index) 453BOOL 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
597void LLFont::renderGlyph(const U32 glyph_index) 531void 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
629void LLFont::setSubImageLuminanceAlpha(const U32 x, 566void 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
40class LLImageRaw; 44class LLImageRaw;
41class LLFontManager; 45class LLFontManager;
42class LLFont; 46class 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
95class LLFont 99class LLFont
96{ 100{
97public: 101public:
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
148protected: 154protected:
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
160protected: 167protected:
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;
190private: 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
38LLFontBitmapCache::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
50LLFontBitmapCache::~LLFontBitmapCache()
51{
52}
53
54void 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
65LLImageRaw *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
73LLImageGL *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
82BOOL 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
149void 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
158void 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.
40class LLFontBitmapCache: public LLRefCount
41{
42public:
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
65private:
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;
50BOOL LLFontGL::sDisplayFont = TRUE ; 53BOOL LLFontGL::sDisplayFont = TRUE ;
51std::string LLFontGL::sAppDir; 54std::string LLFontGL::sAppDir;
52 55
53LLFontGL* LLFontGL::sMonospace = NULL;
54LLFontGL* LLFontGL::sSansSerifSmall = NULL;
55LLFontGL* LLFontGL::sSansSerif = NULL;
56LLFontGL* LLFontGL::sSansSerifBig = NULL;
57LLFontGL* LLFontGL::sSansSerifHuge = NULL;
58LLFontGL* LLFontGL::sSansSerifBold = NULL;
59LLFontList* LLFontGL::sMonospaceFallback = NULL;
60LLFontList* LLFontGL::sSSFallback = NULL;
61LLFontList* LLFontGL::sSSSmallFallback = NULL;
62LLFontList* LLFontGL::sSSBigFallback = NULL;
63LLFontList* LLFontGL::sSSHugeFallback = NULL;
64LLFontList* LLFontGL::sSSBoldFallback = NULL;
65LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f); 56LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f);
57LLFontRegistry* LLFontGL::sFontRegistry = NULL;
66 58
67LLCoordFont LLFontGL::sCurOrigin; 59LLCoordFont LLFontGL::sCurOrigin;
68std::vector<LLCoordFont> LLFontGL::sOriginStack; 60std::vector<LLCoordFont> LLFontGL::sOriginStack;
69 61
70LLFontGL*& gExtCharFont = LLFontGL::sSansSerif;
71
72const F32 EXT_X_BEARING = 1.f; 62const F32 EXT_X_BEARING = 1.f;
73const F32 EXT_Y_BEARING = 0.f; 63const F32 EXT_Y_BEARING = 0.f;
74const F32 EXT_KERNING = 1.f; 64const F32 EXT_KERNING = 1.f;
75const F32 PIXEL_BORDER_THRESHOLD = 0.0001f; 65const F32 PIXEL_BORDER_THRESHOLD = 0.0001f;
76const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; 66const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
77 67
78const F32 PAD_AMT = 0.5f; 68const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture
79const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; 69const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
80 70
81F32 llfont_round_x(F32 x) 71F32 llfont_round_x(F32 x)
@@ -126,7 +116,6 @@ U8 LLFontGL::getStyleFromString(const std::string &style)
126LLFontGL::LLFontGL() 116LLFontGL::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
138LLFontGL::~LLFontGL() 127LLFontGL::~LLFontGL()
139{ 128{
140 mImageGLp = NULL;
141 mRawImageGLp = NULL;
142 clearEmbeddedChars(); 129 clearEmbeddedChars();
143} 130}
144 131
145void LLFontGL::init() 132void 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
162void 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 209bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc)
223bool 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
261bool 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
282BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, 218BOOL 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
464void LLFontGL::destroyDefaultFonts() 256void 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
504void LLFontGL::destroyGL() 264void 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(); 272void 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
541BOOL LLFontGL::addChar(const llwchar wch) 296//static
297LLFontGL* LLFontGL::getFontMonospace()
298{
299 return getFont(LLFontDescriptor("Monospace","Monospace",0));
300}
301
302//static
303LLFontGL* LLFontGL::getFontSansSerifSmall()
304{
305 return getFont(LLFontDescriptor("SansSerif","Small",0));
306}
307
308//static
309LLFontGL* LLFontGL::getFontSansSerif()
310{
311 return getFont(LLFontDescriptor("SansSerif","Medium",0));
312}
313
314//static
315LLFontGL* LLFontGL::getFontSansSerifBig()
316{
317 return getFont(LLFontDescriptor("SansSerif","Large",0));
318}
319
320//static
321LLFontGL* LLFontGL::getFontSansSerifHuge()
322{
323 return getFont(LLFontDescriptor("SansSerif","Huge",0));
324}
325
326//static
327LLFontGL* LLFontGL::getFontSansSerifBold()
328{
329 return getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
330}
331
332//static
333LLFontGL* LLFontGL::getFontExtChar()
334{
335 return getFontSansSerif();
336}
337
338//static
339LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
340{
341 return sFontRegistry->getFont(desc);
342}
343
344BOOL 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
570S32 LLFontGL::render(const LLWString &wstr, 375S32 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
900LLImageGL *LLFontGL::getImageGL() const
901{
902 return mImageGLp;
903}
904 685
905S32 LLFontGL::getWidth(const std::string& utf8text) const 686S32 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
1315void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const std::string& label ) 1069void 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
1321void LLFontGL::addEmbeddedChar( llwchar wc, LLImageGL* image, const LLWString& wlabel ) 1075void 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
1327void LLFontGL::removeEmbeddedChar( llwchar wc ) 1081void 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
1432std::string LLFontGL::nameFromFont(const LLFontGL* fontp) 1185std::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
1465LLFontGL* 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
42class LLColor4; 45class LLColor4;
43 46
47// Key used to request a font.
48class LLFontDescriptor;
49
50// Structure used to store previously requested fonts.
51class LLFontRegistry;
52
44class LLFontGL : public LLFont 53class LLFontGL : public LLFont
45{ 54{
46public: 55public:
@@ -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
250protected: 247protected:
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
255protected: 250protected:
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
261public: 259public:
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
43extern LLControlGroup gSavedSettings;
44
45using std::string;
46using std::map;
47
48bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc);
49
50LLFontDescriptor::LLFontDescriptor():
51 mStyle(0)
52{
53}
54
55LLFontDescriptor::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
66LLFontDescriptor::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
76bool 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
94static const std::string s_template_string("TEMPLATE");
95
96bool LLFontDescriptor::isTemplate() const
97{
98 return getSize() == s_template_string;
99}
100
101// Look for substring match and remove substring if matched.
102bool 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.
114bool 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 }
133LLFontDescriptor 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
171LLFontRegistry::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
182LLFontRegistry::~LLFontRegistry()
183{
184 clear();
185}
186
187bool 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
225std::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
238bool 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
278bool 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
334bool 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
346LLFontGL *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
474void 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
486void 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
498void 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
510LLFontGL *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
530const 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
541static 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.
564const 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
625void 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
39class LLFontGL;
40
41typedef std::vector<std::string> string_vec_t;
42
43class LLFontDescriptor
44{
45public:
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
64private:
65 std::string mName;
66 std::string mSize;
67 string_vec_t mFileNames;
68 U8 mStyle;
69};
70
71class LLFontRegistry
72{
73public:
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
100private:
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
65LLGLNamePool::pool_list_t LLGLNamePool::sInstances; 66LLGLNamePool::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
70PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL; 71PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL;
@@ -132,6 +133,15 @@ PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
132PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; 133PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
133PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; 134PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL;
134 135
136// GL_EXT_framebuffer_multisample
137PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL;
138
139// GL_EXT_framebuffer_blit
140PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL;
141
142// GL_ARB_draw_buffers
143PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL;
144
135//shader object prototypes 145//shader object prototypes
136PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL; 146PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
137PFNGLGETHANDLEARBPROC glGetHandleARB = NULL; 147PFNGLGETHANDLEARBPROC glGetHandleARB = NULL;
@@ -174,7 +184,7 @@ PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
174PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL; 184PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
175 185
176// vertex shader prototypes 186// vertex shader prototypes
177#if LL_LINUX 187#if LL_LINUX || LL_SOLARIS
178PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL; 188PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL;
179PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL; 189PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL;
180PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL; 190PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL;
@@ -193,7 +203,7 @@ PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB = NULL;
193PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL; 203PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL;
194PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL; 204PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL;
195PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL; 205PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL;
196#endif // LL_LINUX 206#endif // LL_LINUX || LL_SOLARIS
197PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL; 207PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL;
198PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL; 208PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL;
199PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL; 209PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL;
@@ -201,7 +211,7 @@ PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB = NULL;
201PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL; 211PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL;
202PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL; 212PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL;
203PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL; 213PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL;
204#if LL_LINUX 214#if LL_LINUX || LL_SOLARIS
205PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL; 215PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL;
206PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL; 216PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL;
207PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL; 217PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL;
@@ -239,7 +249,7 @@ PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB = NULL;
239PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL; 249PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL;
240PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL; 250PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL;
241PFNGLISPROGRAMARBPROC glIsProgramARB = NULL; 251PFNGLISPROGRAMARBPROC glIsProgramARB = NULL;
242#endif // LL_LINUX 252#endif // LL_LINUX || LL_SOLARIS
243PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL; 253PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL;
244PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL; 254PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL;
245PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL; 255PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
@@ -248,10 +258,12 @@ PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
248PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; 258PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
249#endif 259#endif
250 260
251#if LL_LINUX 261#if LL_LINUX_NV_GL_HEADERS
252PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL; 262// linux nvidia headers. these define these differently to mesa's. ugh.
253#endif // LL_LINUX 263PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
254 264PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL;
265PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL;
266#endif // LL_LINUX_NV_GL_HEADERS
255#endif 267#endif
256 268
257LLGLManager gGLManager; 269LLGLManager 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()
1647LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, GLenum depth_func) 1728LLGLDepthTest::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
67extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
68extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
69extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
70extern PFNGLISBUFFERARBPROC glIsBufferARB;
71extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
72extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
73extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
74extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
75extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
76extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
77extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
78
79// GL_ATI_vertex_array_object
80extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
81extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
82extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI;
83extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI;
84extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI;
85extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI;
86extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI;
87extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI;
88extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI;
89extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI;
90extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI;
91extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI;
92extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI;
93
94// GL_ARB_occlusion_query
95extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
96extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
97extern PFNGLISQUERYARBPROC glIsQueryARB;
98extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
99extern PFNGLENDQUERYARBPROC glEndQueryARB;
100extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
101extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
102extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
103
104// GL_ARB_point_parameters
105extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
106extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
107
108// GL_ARB_shader_objects
109extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
110extern PFNGLGETHANDLEARBPROC glGetHandleARB;
111extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
112extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
113extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
114extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
115extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
116extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
117extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
118extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
119extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
120extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
121extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
122extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
123extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
124extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
125extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
126extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
127extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
128extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
129extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
130extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
131extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
132extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
133extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
134extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
135extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
136extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
137extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
138extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
139extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
140extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
141extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
142extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
143extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
144extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
145extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
146extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
147extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
148
149// GL_ARB_vertex_shader
150extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
151extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
152extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
153extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
154extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
155extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
156extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
157extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
158extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
159extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
160extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
161extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
162extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
163extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
164extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
165extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
166extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
167extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
168extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
169extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
170extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
171extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
172extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
173extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
174extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
175extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
176extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
177extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
178extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
179extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
180extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
181extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
182extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
183extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
184extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
185extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
186extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
187extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
188extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
189extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
190extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
191extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
192extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
193extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
194extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
195extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
196extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
197extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
198extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
199extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
200extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
201extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
202extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
203extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
204extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
205extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
206extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
207extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
208extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
209extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
210extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
211extern PFNGLISPROGRAMARBPROC glIsProgramARB;
212extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
213extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
214extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
215
216extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
217extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
218
219extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
220
221//GL_EXT_framebuffer_object
222extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
223extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
224extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
225extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT;
226extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
227extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT;
228extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT;
229extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
230extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
231extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
232extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
233extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT;
234extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
235extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
236extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
237extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
238extern 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:
294extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
295extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB;
296extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements;
297#endif // LL_LINUX_NV_GL_HEADERS
79 298
80// GL_ARB_vertex_buffer_object 299// GL_ARB_vertex_buffer_object
81extern PFNGLBINDBUFFERARBPROC glBindBufferARB; 300extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
@@ -230,8 +449,6 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
230extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB; 449extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
231extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; 450extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
232 451
233extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
234
235//GL_EXT_framebuffer_object 452//GL_EXT_framebuffer_object
236extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; 453extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
237extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; 454extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
@@ -251,6 +468,14 @@ extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
251extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; 468extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
252extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; 469extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
253 470
471// GL_EXT_framebuffer_multisample
472extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
473
474// GL_EXT_framebuffer_blit
475extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;
476
477//GL_ARB_draw_buffers
478extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
254 479
255#elif LL_WINDOWS 480#elif LL_WINDOWS
256 481
@@ -439,6 +664,14 @@ extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
439extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; 664extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
440extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; 665extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
441 666
667// GL_EXT_framebuffer_multisample
668extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
669
670// GL_EXT_framebuffer_blit
671extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;
672
673//GL_ARB_draw_buffers
674extern 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
475extern void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; 708extern void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
476extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; 709extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
477 710
711// GL_ARB_draw_buffers
712extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
478 713
479#ifdef __cplusplus 714#ifdef __cplusplus
480extern "C" { 715extern "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
40LLGLImmediate gGL;
41
42const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD;
43
44LLGLImmediate::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
55void LLGLImmediate::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
56{
57 flush();
58 glTranslatef(x,y,z);
59}
60
61void LLGLImmediate::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
62{
63 flush();
64 glScalef(x,y,z);
65}
66
67void LLGLImmediate::pushMatrix()
68{
69 flush();
70 glPushMatrix();
71}
72
73void LLGLImmediate::popMatrix()
74{
75 flush();
76 glPopMatrix();
77}
78
79void LLGLImmediate::blendFunc(GLenum sfactor, GLenum dfactor)
80{
81 flush();
82 glBlendFunc(sfactor, dfactor);
83}
84
85void 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
105void 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
123void 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
179void 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
197void LLGLImmediate::vertex2i(const GLint& x, const GLint& y)
198{
199 vertex3f((GLfloat) x, (GLfloat) y, 0);
200}
201
202void LLGLImmediate::vertex2f(const GLfloat& x, const GLfloat& y)
203{
204 vertex3f(x,y,0);
205}
206
207void LLGLImmediate::vertex2fv(const GLfloat* v)
208{
209 vertex3f(v[0], v[1], 0);
210}
211
212void LLGLImmediate::vertex3fv(const GLfloat* v)
213{
214 vertex3f(v[0], v[1], v[2]);
215}
216
217void LLGLImmediate::texCoord2f(const GLfloat& x, const GLfloat& y)
218{
219 mTexcoordsp[mCount] = LLVector2(x,y);
220}
221
222void LLGLImmediate::texCoord2i(const GLint& x, const GLint& y)
223{
224 texCoord2f((GLfloat) x, (GLfloat) y);
225}
226
227void LLGLImmediate::texCoord2fv(const GLfloat* tc)
228{
229 texCoord2f(tc[0], tc[1]);
230}
231
232void 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
237void LLGLImmediate::color4ubv(const GLubyte* c)
238{
239 color4ub(c[0], c[1], c[2], c[3]);
240}
241
242void 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
250void LLGLImmediate::color4fv(const GLfloat* c)
251{
252 color4f(c[0],c[1],c[2],c[3]);
253}
254
255void LLGLImmediate::color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b)
256{
257 color4f(r,g,b,1);
258}
259
260void 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
48class LLGLImmediate
49{
50public:
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
86private:
87 U32 mCount;
88 U32 mMode;
89 LLPointer<LLVertexBuffer> mBuffer;
90 LLStrider<LLVector3> mVerticesp;
91 LLStrider<LLVector2> mTexcoordsp;
92 LLStrider<LLColor4U> mColorsp;
93};
94
95extern 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
418void 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
400void LLGLSLShader::uniform1f(U32 index, GLfloat x) 440void 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
531void 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
491void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v) 554void 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
712void 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
649void LLGLSLShader::uniform1f(const string& uniform, GLfloat v) 728void 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;
62F32 LLImageGL::sLastFrameTime = 0.f; 63F32 LLImageGL::sLastFrameTime = 0.f;
63 64
64std::set<LLImageGL*> LLImageGL::sImageList; 65std::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
343void LLImageGL::cleanup() 344void 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
473void LLImageGL::forceImmediateUpdate()
474{
475 return ;
476}
471 477
472void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes ) 478void 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)
497void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) 503void 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
705BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) 722BOOL 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
839void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
840{
841 glGenTextures(numTextures, (GLuint*)textures);
842}
843
844// static
845void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
846{
847 glDeleteTextures(numTextures, (GLuint*)textures);
848}
849
850// static
851void 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
820BOOL LLImageGL::createGLTexture() 858BOOL LLImageGL::createGLTexture()
@@ -847,6 +885,7 @@ BOOL LLImageGL::createGLTexture()
847 885
848BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) 886BOOL 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
908BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename) 947BOOL 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
1055BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) 1099BOOL 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
1190void LLImageGL::glClampCubemap (BOOL clamps, BOOL clampt, BOOL clampr) 1237void 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
1197void 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
1206void 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
1214void 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
1221void LLImageGL::overrideClamp (BOOL clamps, BOOL clampt)
1222{
1223 glClamp (clamps, clampt);
1224}
1225
1226void LLImageGL::restoreClamp (void)
1227{
1228 glClamp (mClampS, mClampT);
1229} 1250}
1230 1251
1231void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest) 1252void 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
1275BOOL LLImageGL::getIsResident(BOOL test_now) 1268BOOL 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
1352void 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
1412BOOL LLImageGL::isDeleted()
1413{
1414 return mTextureState == DELETED ;
1415}
1416
1417BOOL LLImageGL::isInactive()
1418{
1419 return mTextureState == INACTIVE ;
1420}
1421
1422BOOL LLImageGL::isDeletionCandidate()
1423{
1424 return mTextureState == DELETION_CANDIDATE ;
1425}
1426
1427void LLImageGL::setDeletionCandidate()
1428{
1429 if(mTexName && (mTextureState == INACTIVE))
1430 {
1431 mTextureState = DELETION_CANDIDATE ;
1432 }
1433}
1434
1435void LLImageGL::forceActive()
1436{
1437 mTextureState = ACTIVE ;
1438}
1439
1440void LLImageGL::setActive()
1441{
1442 if(mTextureState != NO_DELETE)
1443 {
1444 mTextureState = ACTIVE ;
1445 }
1446}
1447
1448//set the texture inactive
1449void LLImageGL::setInactive()
1450{
1451 if(mTexName && (mTextureState == ACTIVE) && !getBoundRecently())
1452 {
1453 mTextureState = INACTIVE ;
1454 }
1455}
1456
1457//set the texture to stay in memory
1458void LLImageGL::setNoDelete()
1459{
1460 mTextureState = NO_DELETE ;
1461}
1462
1463//----------------------------------------------------------------------------
1359void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) 1464void 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
46class LLImageGL : public LLRefCount 47class LLImageGL : public LLRefCount
47{ 48{
49 friend class LLTexUnit;
48public: 50public:
49 // Size calculation 51 // Size calculation
50 static S32 dataFormatBits(S32 dataformat); 52 static S32 dataFormatBits(S32 dataformat);
@@ -79,17 +81,22 @@ public:
79protected: 81protected:
80 virtual ~LLImageGL(); 82 virtual ~LLImageGL();
81 83
82private: 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
86public: 86public:
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
155protected: 175protected:
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:
178protected: 199protected:
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
220protected:
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
200public: 232public:
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
388void LLPostProcess::copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height) 389void 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
77const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD; 78const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0;
78 79
79static GLenum sGLBlendFactor[] = 80static GLenum sGLBlendFactor[] =
80{ 81{
@@ -95,7 +96,8 @@ LLTexUnit::LLTexUnit(S32 index)
95mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), 96mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
96mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), 97mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
97mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), 98mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
98mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0) 99mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0),
100mHasMipMaps(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
178bool LLTexUnit::bind(const LLImageGL* texture, bool forceBind) 180bool 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
230bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) 261bool 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
248bool LLTexUnit::bindManual(eTextureType type, U32 texture) 280bool 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
262void LLTexUnit::unbind(eTextureType type) 294void 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
277void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) 311void 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
325void 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
591LLRender::LLRender() 665LLRender::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
693void LLRender::setSceneBlendType(eBlendType type) 771void LLRender::setSceneBlendType(eBlendType type)
@@ -767,6 +845,14 @@ bool LLRender::verifyTexUnitActive(U32 unitToVerify)
767 } 845 }
768} 846}
769 847
848void LLRender::clearErrors()
849{
850 while (glGetError())
851 {
852 //loop until no more error flags left
853 }
854}
855
770void LLRender::begin(const GLuint& mode) 856void 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
862void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) 949void 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
168protected: 196protected:
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
320extern F64 gGLModelView[16]; 353extern 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
40void 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
39BOOL LLRenderTarget::sUseFBO = FALSE; 58BOOL LLRenderTarget::sUseFBO = FALSE;
40 59
41LLRenderTarget::LLRenderTarget() : 60LLRenderTarget::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
59void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLTexUnit::eTextureType usage, BOOL use_fbo) 80
81void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer)
82{
83 mSampleBuffer = buffer;
84}
85
86void 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(); 133void 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
125void LLRenderTarget::allocateDepth() 190void 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
210void 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
135void LLRenderTarget::release() 246void 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
156void LLRenderTarget::bindTarget() 278void 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
175void LLRenderTarget::clear() 325void 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
348U32 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
357void 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
195void LLRenderTarget::flush(BOOL fetch_depth) 366void 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
437void 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
220BOOL LLRenderTarget::isComplete() const 462BOOL LLRenderTarget::isComplete() const
221{ 463{
222 return (mTex || mDepth) ? TRUE : FALSE; 464 return (!mTex.empty() || mDepth) ? TRUE : FALSE;
223} 465}
224 466
225void LLRenderTarget::getViewport(S32* viewport) 467void 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//==================================================
478LLMultisampleBuffer::LLMultisampleBuffer()
479{
480
481}
482
483LLMultisampleBuffer::~LLMultisampleBuffer()
484{
485 releaseSampleBuffer();
486}
487
488void 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
509void LLMultisampleBuffer::bindTarget()
510{
511 bindTarget(this);
512}
513
514void 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
537void 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
542void 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
601void 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
647void 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
66class LLMultisampleBuffer;
62 67
63class LLRenderTarget 68class 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
123private: 143protected:
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
159class LLMultisampleBuffer : public LLRenderTarget
160{
161public:
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
229void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const 261void 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}
898bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index) 926bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index)
927{
928 return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index);
929}
930bool 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}
902bool 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}
938bool LLVertexBuffer::getTexCoord3Strider(LLStrider<LLVector2>& strider, S32 index)
939{
940 return VertexBufferStrider<LLVector2,TYPE_TEXCOORD3>::get(*this, strider, index);
941}*/
906bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index) 942bool 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
127protected: 129protected:
@@ -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);