From 5c64e5e13d9a75cac510aac3128fc6ee780ab243 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 30 Aug 2024 18:51:48 +0300 Subject: viewer#2411 LLFontGL::render optimizations #3 --- indra/llrender/llfontgl.cpp | 118 +++-------------------- indra/llrender/llfontgl.h | 15 +-- indra/llrender/llfontvertexbuffer.cpp | 75 +++++---------- indra/llrender/llfontvertexbuffer.h | 12 ++- indra/llrender/llrender.cpp | 175 +++++++++++++++++++++------------- indra/llrender/llrender.h | 9 +- indra/llrender/llvertexbuffer.cpp | 47 +++++++++ indra/llrender/llvertexbuffer.h | 31 ++++++ indra/newview/llhudnametag.h | 4 +- 9 files changed, 241 insertions(+), 245 deletions(-) diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 701ab4d060..7d74bb3e46 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -42,7 +42,6 @@ #include "lltexture.h" #include "lldir.h" #include "llstring.h" -#include "llvertexbuffer.h" // Third party library includes #include @@ -145,8 +144,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rec S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, - ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color, - std::list *buffer_list) const + ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; @@ -160,7 +158,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons return 0; } - gGL.flush(); // deliberately empty pending verts gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); @@ -286,9 +283,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons std::pair bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1); S32 glyph_count = 0; - S32 buffer_count = 0; - LLVertexBuffer* vb; - LLImageGL* font_image = nullptr; for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; @@ -312,35 +306,16 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // otherwise the queued glyphs will be taken from wrong textures. if (glyph_count > 0) { - if (buffer_list) + gGL.begin(LLRender::QUADS); { - vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - - vb = gGL.getBuffer(buffer_count); // instead of endNoCache to draw now - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - } - else - { - gGL.begin(LLRender::QUADS); - { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - } - gGL.end(); } + gGL.end(); glyph_count = 0; } bitmap_entry = next_bitmap_entry; - font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); + LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); gGL.getTexUnit(0)->bind(font_image); } @@ -364,28 +339,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (glyph_count >= GLYPH_BATCH_SIZE) { - if (buffer_list) + gGL.begin(LLRender::QUADS); { - vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - vb = gGL.endNoCache(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - } - else - { - gGL.begin(LLRender::QUADS); - { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - } - gGL.end(); } + gGL.end(); glyph_count = 0; } @@ -418,29 +376,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_x = cur_x; cur_render_y = cur_y; } - - if (buffer_list) + gGL.begin(LLRender::QUADS); { - vb = gGL.beginNoCache(LLRender::QUADS, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - vb = gGL.endNoCache(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, LLRender::QUADS, buffer_count); - } - } - else - { - gGL.begin(LLRender::QUADS); - { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); - } - gGL.end(); } + gGL.end(); if (right_x) @@ -454,45 +394,14 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight()); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (buffer_list) - { - vb = gGL.beginNoCache(LLRender::LINES, buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, nullptr, LLRender::QUADS, buffer_count); - } - - gGL.vertex2f(start_x, cur_y - descender); - gGL.vertex2f(cur_x, cur_y - descender); - - vb = gGL.getBuffer(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, nullptr, LLRender::LINES, buffer_count); - } - } - else - { - gGL.begin(LLRender::LINES); - gGL.vertex2f(start_x, cur_y - descender); - gGL.vertex2f(cur_x, cur_y - descender); - gGL.end(); - } - } - else if (buffer_list) - { - vb = gGL.getBuffer(buffer_count); - if (vb) - { - buffer_list->emplace_back(vb, font_image, gGL.getMode(), buffer_count); - } + gGL.begin(LLRender::LINES); + gGL.vertex2f(start_x, cur_y - descender); + gGL.vertex2f(cur_x, cur_y - descender); + gGL.end(); } if (draw_ellipses) { - // signal a separate context - buffer_list->emplace_back(nullptr, nullptr, 0, 0); - // recursively render ellipses at end of string // we've already reserved enough room gGL.pushUIMatrix(); @@ -507,8 +416,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons S32_MAX, max_pixels, right_x, false, - use_color, - buffer_list); + use_color); gGL.popUIMatrix(); } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 5015601cf6..de7529a583 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -33,7 +33,6 @@ #include "llimagegl.h" #include "llpointer.h" #include "llrect.h" -#include "llvertexbuffer.h" #include "v2math.h" class LLColor4; @@ -43,7 +42,6 @@ class LLFontFreetype; // Structure used to store previously requested fonts. class LLFontRegistry; -class LLVertexBuffer; class LLFontGL { @@ -81,16 +79,6 @@ public: DROP_SHADOW_SOFT }; - struct LLVertexBufferData - { - LLVertexBufferData() : mBuffer(nullptr), mImage(nullptr), mMode(0), mCount(0) {} - LLVertexBufferData(LLVertexBuffer* buffer, LLImageGL* image, U8 mode, U32 count) : mBuffer(buffer), mImage(image), mMode(mode), mCount(count) {} - LLPointer mBuffer; - LLPointer mImage; // might be a better idea to store - U8 mMode; - U32 mCount; - }; - LLFontGL(); ~LLFontGL(); @@ -131,8 +119,7 @@ public: S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, bool use_ellipses = false, - bool use_color = true, - std::list* buffer_list = nullptr) const; + bool use_color = true) const; S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const; diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index c4b68c4a6c..284762dc94 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -60,12 +60,17 @@ S32 LLFontVertexBuffer::render( bool use_ellipses, bool use_color ) { + if (!LLFontGL::sDisplayFont) //do not display texts + { + return static_cast(text.length()); + } if (mBufferList.empty()) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); } - else if (mLastX != x || mLastY != y + else if (mLastX != x + || mLastY != y || mLastFont != fontp || mLastColor != color // alphas change often || mLastHalign != halign @@ -74,7 +79,10 @@ S32 LLFontVertexBuffer::render( || mLastMaxChars != max_chars || mLastMaxPixels != max_pixels || mLastStyle != style - || mLastShadow != shadow) // ex: buttons change shadow state + || mLastShadow != shadow // ex: buttons change shadow state + || mLastScaleX != LLFontGL::sScaleX + || mLastScaleY != LLFontGL::sScaleY + || mLastOrigin != LLFontGL::sCurOrigin) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); @@ -110,8 +118,11 @@ void LLFontVertexBuffer::genBuffers( bool use_color) { mBufferList.clear(); + + gGL.beginList(&mBufferList); mChars = fontp->render(text, begin_offset, x, y, color, halign, valign, - style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color, &mBufferList); + style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); + gGL.endList(); mLastFont = fontp; mLastOffset = begin_offset; @@ -126,67 +137,25 @@ void LLFontVertexBuffer::genBuffers( mLastStyle = style; mLastShadow = shadow; + mLastScaleX = LLFontGL::sScaleX; + mLastScaleY = LLFontGL::sScaleY; + mLastOrigin = LLFontGL::sCurOrigin; + if (right_x) { mLastRightX = *right_x; } } -void render_buffers(LLFontVertexBuffer::buffer_list_t::iterator iter, LLFontVertexBuffer::buffer_list_t::iterator end) +void LLFontVertexBuffer::renderBuffers() { + gGL.flush(); // deliberately empty pending verts gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); gGL.pushUIMatrix(); - - gGL.loadUIIdentity(); - - // Depth translation, so that floating text appears 'in-world' - // and is correctly occluded. - gGL.translatef(0.f, 0.f, LLFontGL::sCurDepth); - - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - while (iter != end) - { - if (iter->mBuffer == nullptr) - { - // elipses indicator - iter++; - break; - } - if (iter->mImage) - { - gGL.getTexUnit(0)->bind(iter->mImage); - } - else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - iter->mBuffer->setBuffer(); - - if (LLRender::sGLCoreProfile && iter->mMode == LLRender::QUADS) - { - iter->mBuffer->drawArrays(LLRender::TRIANGLES, 0, iter->mCount); - } - else - { - iter->mBuffer->drawArrays(iter->mMode, 0, iter->mCount); - } - iter++; - } - - if (iter != end) + for (LLVertexBufferData& buffer : mBufferList) { - gGL.pushUIMatrix(); - render_buffers(iter, end); - gGL.popUIMatrix(); + buffer.draw(); } - gGL.popUIMatrix(); } -void LLFontVertexBuffer::renderBuffers() -{ - gGL.flush(); // deliberately empty pending verts - render_buffers(mBufferList.begin(), mBufferList.end()); -} - diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index 458b0a91bb..7c29e1097b 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -30,7 +30,7 @@ #include "llfontgl.h" -class LLVertexBuffer; +class LLVertexBufferData; class LLFontVertexBuffer { @@ -52,8 +52,6 @@ public: F32* right_x = NULL, bool use_ellipses = false, bool use_color = true); - - typedef std::list buffer_list_t; private: void genBuffers(const LLFontGL* fontp, @@ -71,7 +69,7 @@ private: void renderBuffers(); - buffer_list_t mBufferList; + std::list mBufferList; S32 mChars = 0; const LLFontGL *mLastFont = nullptr; S32 mLastOffset = 0; @@ -86,6 +84,12 @@ private: U8 mLastStyle = LLFontGL::NORMAL; LLFontGL::ShadowType mLastShadow = LLFontGL::NO_SHADOW; F32 mLastRightX = 0.f; + + // LLFontGL's statics + F32 mLastScaleX = 1.f; + F32 mLastScaleY = 1.f; + LLCoordGL mLastOrigin; + bool mTrackStringChanges = true; static std::hash sStringHasher; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 8cd2d9cc15..182f61f907 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -77,6 +77,7 @@ struct LLVBCache }; static std::unordered_map sVBCache; +static thread_local std::list *sBufferDataList = nullptr; static const GLenum sGLTextureType[] = { @@ -1528,6 +1529,25 @@ void LLRender::clearErrors() } } +void LLRender::beginList(std::list *list) +{ + flush(); + sBufferDataList = list; +} + +void LLRender::endList() +{ + if (sBufferDataList) + { + flush(); + sBufferDataList = nullptr; + } + else + { + llassert(false); // something failed to provide a list or closed it twice + } +} + void LLRender::begin(const GLuint& mode) { if (mode != mMode) @@ -1663,78 +1683,26 @@ void LLRender::flush() if (mBuffer) { - HBXXH64 hash; - U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; + LLVertexBuffer *vb; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hash"); - - hash.update((U8*)mVerticesp.get(), count * sizeof(LLVector4a)); - if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) - { - hash.update((U8*)mTexcoordsp.get(), count * sizeof(LLVector2)); - } - - if (attribute_mask & LLVertexBuffer::MAP_COLOR) - { - hash.update((U8*)mColorsp.get(), count * sizeof(LLColor4U)); - } - - hash.finalize(); - } - - - U64 vhash = hash.digest(); - - // check the VB cache before making a new vertex buffer - // This is a giant hack to deal with (mostly) our terrible UI rendering code - // that was built on top of OpenGL immediate mode. Huge performance wins - // can be had by not uploading geometry to VRAM unless absolutely necessary. - // Most of our usage of the "immediate mode" style draw calls is actually - // sending the same geometry over and over again. - // To leverage this, we maintain a running hash of the vertex stream being - // built up before a flush, and then check that hash against a VB - // cache just before creating a vertex buffer in VRAM - std::unordered_map::iterator cache = sVBCache.find(vhash); - - LLPointer vb; + U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask; - if (cache != sVBCache.end()) + if (sBufferDataList) { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hit"); - // cache hit, just use the cached buffer - vb = cache->second.vb; - cache->second.touched = std::chrono::steady_clock::now(); + vb = genBuffer(attribute_mask, count); + sBufferDataList->emplace_back( + vb, + mMode, + count, + gGL.getTexUnit(0)->mCurrTexture, + mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]], + mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]], + mMatrix[MM_TEXTURE0][mMatIdx[MM_TEXTURE0]] + ); } else { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); - vb = genBuffer(attribute_mask, count); - - sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; - - static U32 miss_count = 0; - miss_count++; - if (miss_count > 1024) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache clean"); - miss_count = 0; - auto now = std::chrono::steady_clock::now(); - - using namespace std::chrono_literals; - // every 1024 misses, clean the cache of any VBs that haven't been touched in the last second - for (std::unordered_map::iterator iter = sVBCache.begin(); iter != sVBCache.end(); ) - { - if (now - iter->second.touched > 1s) - { - iter = sVBCache.erase(iter); - } - else - { - ++iter; - } - } - } + vb = bufferfromCache(attribute_mask, count); } drawBuffer(vb, mMode, count); @@ -1749,6 +1717,81 @@ void LLRender::flush() } } +LLVertexBuffer* LLRender::bufferfromCache(U32 attribute_mask, U32 count) +{ + LLVertexBuffer *vb = nullptr; + HBXXH64 hash; + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hash"); + + hash.update((U8*)mVerticesp.get(), count * sizeof(LLVector4a)); + if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) + { + hash.update((U8*)mTexcoordsp.get(), count * sizeof(LLVector2)); + } + + if (attribute_mask & LLVertexBuffer::MAP_COLOR) + { + hash.update((U8*)mColorsp.get(), count * sizeof(LLColor4U)); + } + + hash.finalize(); + } + + U64 vhash = hash.digest(); + + // check the VB cache before making a new vertex buffer + // This is a giant hack to deal with (mostly) our terrible UI rendering code + // that was built on top of OpenGL immediate mode. Huge performance wins + // can be had by not uploading geometry to VRAM unless absolutely necessary. + // Most of our usage of the "immediate mode" style draw calls is actually + // sending the same geometry over and over again. + // To leverage this, we maintain a running hash of the vertex stream being + // built up before a flush, and then check that hash against a VB + // cache just before creating a vertex buffer in VRAM + std::unordered_map::iterator cache = sVBCache.find(vhash); + + if (cache != sVBCache.end()) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache hit"); + // cache hit, just use the cached buffer + vb = cache->second.vb; + cache->second.touched = std::chrono::steady_clock::now(); + } + else + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss"); + vb = genBuffer(attribute_mask, count); + + sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; + + static U32 miss_count = 0; + miss_count++; + if (miss_count > 1024) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache clean"); + miss_count = 0; + auto now = std::chrono::steady_clock::now(); + + using namespace std::chrono_literals; + // every 1024 misses, clean the cache of any VBs that haven't been touched in the last second + for (std::unordered_map::iterator iter = sVBCache.begin(); iter != sVBCache.end(); ) + { + if (now - iter->second.touched > 1s) + { + iter = sVBCache.erase(iter); + } + else + { + ++iter; + } + } + } + } + return vb; +} + LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count) { LLVertexBuffer * vb = new LLVertexBuffer(attribute_mask); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 5f84a4a275..aeee8685ab 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -50,7 +50,8 @@ class LLVertexBuffer; class LLCubeMap; class LLImageGL; class LLRenderTarget; -class LLTexture ; +class LLTexture; +class LLVertexBufferData; #define LL_MATRIX_STACK_DEPTH 32 @@ -415,6 +416,10 @@ public: void flush(); + // if list is set, will store buffers in list for later use, if list isn't set, will use cache + void beginList(std::list *list); + void endList(); + void begin(const GLuint& mode); void end(); @@ -491,6 +496,7 @@ public: private: friend class LLLightState; + LLVertexBuffer* bufferfromCache(U32 attribute_mask, U32 count); LLVertexBuffer* genBuffer(U32 attribute_mask, S32 count); void drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count); void resetStriders(S32 count); @@ -525,7 +531,6 @@ private: std::vector mUIOffset; std::vector mUIScale; - }; extern F32 gGLModelView[16]; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 02afcf12c6..11b41730aa 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -570,6 +570,53 @@ public: static LLVBOPool* sVBOPool = nullptr; +void LLVertexBufferData::draw() +{ + if (!mVB) + { + // signal for pushUIMatrix + return; // todo: find a better way? + } + + if (mTexName) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTexName); + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadMatrix(mModelView.m); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(mProjection.m); + gGL.matrixMode(LLRender::MM_TEXTURE0); + gGL.pushMatrix(); + gGL.loadMatrix(mTexture0.m); + + mVB->setBuffer(); + + if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) + { + mVB->drawArrays(LLRender::TRIANGLES, 0, mCount); + } + else + { + mVB->drawArrays(mMode, 0, mCount); + } + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); +} + +//============================================================================ + //static U64 LLVertexBuffer::getBytesAllocated() { diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 4ada0c335b..2a4affdc60 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -53,6 +53,37 @@ //============================================================================ // base class class LLPrivateMemoryPool; +class LLVertexBuffer; + +class LLVertexBufferData +{ +public: + LLVertexBufferData() + : mVB(nullptr) + , mMode(0) + , mCount(0) + , mTexName(0) + {} + LLVertexBufferData(LLVertexBuffer* buffer, U8 mode, U32 count, U32 tex_name, glh::matrix4f model_view, glh::matrix4f projection, glh::matrix4f texture0) + : mVB(buffer) + , mMode(mode) + , mCount(count) + , mTexName(tex_name) + , mProjection(model_view) + , mModelView(projection) + , mTexture0(texture0) + {} + void draw(); + LLPointer mVB; + U8 mMode; + U32 mCount; + U32 mTexName; + glh::matrix4f mProjection; + glh::matrix4f mModelView; + glh::matrix4f mTexture0; +}; +typedef std::list buffer_data_list_t; + class LLVertexBuffer final : public LLRefCount { public: diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index b48a606982..0a882ac273 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -59,7 +59,9 @@ protected: : mColor(color), mStyle(style), mText(text), - mFont(font) + mFont(font), + mFontBufferLabel(false), + mFontBufferText(false) {} F32 getWidth(const LLFontGL* font); const LLWString& getText() const { return mText; } -- cgit v1.2.3