viewer#2411 LLFontGL::render optimizations

master
Andrey Kleshchev 2024-08-28 23:05:58 +03:00 committed by Andrey Kleshchev
parent 36423bd660
commit 4ae1de1f8a
20 changed files with 629 additions and 79 deletions

View File

@ -17,6 +17,7 @@ set(llrender_SOURCE_FILES
llfontfreetype.cpp
llfontfreetypesvg.cpp
llfontgl.cpp
llfontvertexbuffer.cpp
llfontregistry.cpp
llgl.cpp
llglslshader.cpp
@ -43,6 +44,7 @@ set(llrender_HEADER_FILES
llcubemap.h
llcubemaparray.h
llfontgl.h
llfontvertexbuffer.h
llfontfreetype.h
llfontfreetypesvg.h
llfontbitmapcache.h

View File

@ -34,6 +34,7 @@
#include "llfontbitmapcache.h"
#include "llfontregistry.h"
#include "llgl.h"
#include "llglslshader.h"
#include "llimagegl.h"
#include "llrender.h"
#include "llstl.h"
@ -41,6 +42,7 @@
#include "lltexture.h"
#include "lldir.h"
#include "llstring.h"
#include "llvertexbuffer.h"
// Third party library includes
#include <boost/tokenizer.hpp>
@ -143,7 +145,8 @@ 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) const
ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, bool use_ellipses, bool use_color,
std::list<LLVertexBufferData> *buffer_list) const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
@ -157,6 +160,7 @@ 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);
@ -270,10 +274,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
const LLFontGlyphInfo* next_glyph = NULL;
const S32 GLYPH_BATCH_SIZE = 30;
LLVector3 vertices[GLYPH_BATCH_SIZE * 4];
LLVector2 uvs[GLYPH_BATCH_SIZE * 4];
LLColor4U colors[GLYPH_BATCH_SIZE * 4];
static constexpr S32 GLYPH_BATCH_SIZE = 30;
static thread_local LLVector3 vertices[GLYPH_BATCH_SIZE * 4];
static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 4];
static thread_local LLColor4U colors[GLYPH_BATCH_SIZE * 4];
LLColor4U text_color(color);
// Preserve the transparency to render fading emojis in fading text (e.g.
@ -282,6 +286,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
std::pair<EFontGlyphType, S32> 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];
@ -305,16 +312,35 @@ 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)
{
gGL.begin(LLRender::QUADS);
if (buffer_list)
{
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;
LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
gGL.getTexUnit(0)->bind(font_image);
}
@ -338,11 +364,28 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (glyph_count >= GLYPH_BATCH_SIZE)
{
gGL.begin(LLRender::QUADS);
if (buffer_list)
{
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;
}
@ -376,11 +419,28 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
cur_render_y = cur_y;
}
gGL.begin(LLRender::QUADS);
if (buffer_list)
{
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)
@ -394,15 +454,42 @@ 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);
gGL.begin(LLRender::LINES);
gGL.vertex2f(start_x, cur_y - descender);
gGL.vertex2f(cur_x, cur_y - descender);
gGL.end();
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);
}
}
if (draw_ellipses)
{
// recursively render ellipses at end of string
// we've already reserved enough room
gGL.pushUIMatrix();
@ -417,7 +504,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
S32_MAX, max_pixels,
right_x,
false,
use_color);
use_color,
buffer_list);
gGL.popUIMatrix();
}

View File

@ -33,6 +33,7 @@
#include "llimagegl.h"
#include "llpointer.h"
#include "llrect.h"
#include "llvertexbuffer.h"
#include "v2math.h"
class LLColor4;
@ -42,6 +43,7 @@ class LLFontFreetype;
// Structure used to store previously requested fonts.
class LLFontRegistry;
class LLVertexBuffer;
class LLFontGL
{
@ -79,6 +81,16 @@ 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<LLVertexBuffer> mBuffer;
LLPointer <LLImageGL> mImage; // might be a better idea to store
U8 mMode;
U32 mCount;
};
LLFontGL();
~LLFontGL();
@ -119,7 +131,8 @@ public:
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x=NULL,
bool use_ellipses = false,
bool use_color = true) const;
bool use_color = true,
std::list<LLVertexBufferData>* buffer_list = nullptr) const;
S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;

View File

@ -0,0 +1,157 @@
/**
* @file llfontvertexbuffer.cpp
* @brief Buffer storage for font rendering.
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2024, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llfontvertexbuffer.h"
#include "llvertexbuffer.h"
LLFontVertexBuffer::LLFontVertexBuffer(bool track_changes)
: mTrackStringChanges(track_changes)
{
}
LLFontVertexBuffer::~LLFontVertexBuffer()
{
reset();
}
void LLFontVertexBuffer::reset()
{
mBufferList.clear();
}
S32 LLFontVertexBuffer::render(
const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style, LLFontGL::ShadowType shadow,
S32 max_chars , S32 max_pixels,
F32* right_x,
bool use_ellipses,
bool use_color )
{
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 || mLastColor != color) // always track position and alphs
{
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
else if (true //mTrackStringChanges
&& (mLastOffset != begin_offset
|| mLastMaxChars != max_chars
|| mLastMaxPixels != max_pixels
|| mLastStringHash != sStringHasher._Do_hash(text))) // todo, track all parameters?
{
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
else
{
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);
for (auto &buf_data : mBufferList)
{
if (buf_data.mImage)
{
gGL.getTexUnit(0)->bind(buf_data.mImage);
}
else
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
buf_data.mBuffer->setBuffer();
if (LLRender::sGLCoreProfile && buf_data.mMode == LLRender::QUADS)
{
buf_data.mBuffer->drawArrays(LLRender::TRIANGLES, 0, buf_data.mCount);
}
else
{
buf_data.mBuffer->drawArrays(buf_data.mMode, 0, buf_data.mCount);
}
}
if (right_x)
{
*right_x = mLastRightX;
}
gGL.popUIMatrix();
}
return mChars;
}
void LLFontVertexBuffer::genBuffers(
const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style, LLFontGL::ShadowType shadow,
S32 max_chars, S32 max_pixels,
F32* right_x,
bool use_ellipses,
bool use_color)
{
mBufferList.clear();
mChars = fontp->render(text, begin_offset, x, y, color, halign, valign,
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color, &mBufferList);
mLastOffset = begin_offset;
mLastMaxChars = max_chars;
mLastMaxPixels = max_pixels;
mLastStringHash = sStringHasher._Do_hash(text);
mLastX = x;
mLastY = y;
mLastColor = color;
if (right_x)
{
mLastRightX = *right_x;
}
}

View File

@ -0,0 +1,85 @@
/**
* @file llfontgl.h
* @author Andrii Kleshchev
* @brief Buffer storage for font rendering.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLFONTVERTEXBUFFER_H
#define LL_LLFONTVERTEXBUFFER_H
#include "llfontgl.h"
class LLVertexBuffer;
class LLFontVertexBuffer
{
public:
LLFontVertexBuffer(bool track_changes = true);
~LLFontVertexBuffer();
void reset();
S32 render(const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE,
U8 style = LLFontGL::NORMAL, LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW,
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x = NULL,
bool use_ellipses = false,
bool use_color = true);
private:
void genBuffers(const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style, LLFontGL::ShadowType shadow,
S32 max_chars, S32 max_pixels,
F32* right_x,
bool use_ellipses,
bool use_color);
std::list<LLFontGL::LLVertexBufferData> mBufferList;
S32 mChars = 0;
S32 mLastOffset = 0;
S32 mLastMaxChars = 0;
S32 mLastMaxPixels = 0;
size_t mLastStringHash = 0;
F32 mLastX = 0.f;
F32 mLastY = 0.f;
LLColor4 mLastColor;
F32 mLastRightX = 0.f;
bool mTrackStringChanges = true;
static std::hash<LLWString> sStringHasher;
};
#endif

View File

@ -1570,6 +1570,51 @@ void LLRender::end()
flush();
}
}
LLVertexBuffer* LLRender::beginNoCache(const GLuint& mode, S32& count)
{
if (mode != mMode)
{
if (mode == LLRender::QUADS)
{
mQuadCycle = 1;
}
if (mMode == LLRender::QUADS ||
mMode == LLRender::LINES ||
mMode == LLRender::TRIANGLES ||
mMode == LLRender::POINTS)
{
return getBuffer(count);
}
else if (mCount != 0)
{
LL_ERRS() << "gGL.begin() called redundantly." << LL_ENDL;
}
mMode = mode;
}
return nullptr;
}
LLVertexBuffer* LLRender::endNoCache(S32& count)
{
if (mCount == 0)
{
return nullptr;
//IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL;
}
if ((mMode != LLRender::QUADS &&
mMode != LLRender::LINES &&
mMode != LLRender::TRIANGLES &&
mMode != LLRender::POINTS) ||
mCount > 2048)
{
return getBuffer(count);
}
return nullptr;
}
void LLRender::flush()
{
STOP_GLERROR;
@ -1664,27 +1709,7 @@ void LLRender::flush()
else
{
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss");
vb = new LLVertexBuffer(attribute_mask);
vb->allocateBuffer(count, 0);
vb->setBuffer();
vb->setPositionData((LLVector4a*) mVerticesp.get());
if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
{
vb->setTexCoord0Data(mTexcoordsp.get());
}
if (attribute_mask & LLVertexBuffer::MAP_COLOR)
{
vb->setColorData(mColorsp.get());
}
#if LL_DARWIN
vb->unmapBuffer();
#endif
vb->unbind();
vb = genBuffer(attribute_mask, count);
sVBCache[vhash] = { vb , std::chrono::steady_clock::now() };
@ -1712,17 +1737,7 @@ void LLRender::flush()
}
}
vb->setBuffer();
if (mMode == LLRender::QUADS && sGLCoreProfile)
{
vb->drawArrays(LLRender::TRIANGLES, 0, count);
mQuadCycle = 1;
}
else
{
vb->drawArrays(mMode, 0, count);
}
drawBuffer(vb, mMode, count);
}
else
{
@ -1730,13 +1745,129 @@ void LLRender::flush()
LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL;
}
resetStriders(count);
}
}
mVerticesp[0] = mVerticesp[count];
mTexcoordsp[0] = mTexcoordsp[count];
mColorsp[0] = mColorsp[count];
LLVertexBuffer* LLRender::genBuffer(U32 attribute_mask, S32 count)
{
LLVertexBuffer * vb = new LLVertexBuffer(attribute_mask);
vb->allocateBuffer(count, 0);
vb->setBuffer();
vb->setPositionData((LLVector4a*)mVerticesp.get());
if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
{
vb->setTexCoord0Data(mTexcoordsp.get());
}
if (attribute_mask & LLVertexBuffer::MAP_COLOR)
{
vb->setColorData(mColorsp.get());
}
#if LL_DARWIN
vb->unmapBuffer();
#endif
vb->unbind();
return vb;
}
void LLRender::drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count)
{
vb->setBuffer();
if (mode == LLRender::QUADS && sGLCoreProfile)
{
vb->drawArrays(LLRender::TRIANGLES, 0, count);
mQuadCycle = 1;
}
else
{
vb->drawArrays(mode, 0, count);
}
}
void LLRender::resetStriders(S32 count)
{
mVerticesp[0] = mVerticesp[count];
mTexcoordsp[0] = mTexcoordsp[count];
mColorsp[0] = mColorsp[count];
mCount = 0;
}
LLVertexBuffer* LLRender::getBuffer(S32 & count)
{
STOP_GLERROR;
LLVertexBuffer *vb;
if (mCount > 0)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
llassert(LLGLSLShader::sCurBoundShaderPtr != nullptr);
if (!mUIOffset.empty())
{
sUICalls++;
sUIVerts += mCount;
}
//store mCount in a local variable to avoid re-entrance (drawArrays may call flush)
count = mCount;
if (mMode == LLRender::QUADS && !sGLCoreProfile)
{
if (mCount % 4 != 0)
{
count -= (mCount % 4);
LL_WARNS() << "Incomplete quad requested." << LL_ENDL;
}
}
if (mMode == LLRender::TRIANGLES)
{
if (mCount % 3 != 0)
{
count -= (mCount % 3);
LL_WARNS() << "Incomplete triangle requested." << LL_ENDL;
}
}
if (mMode == LLRender::LINES)
{
if (mCount % 2 != 0)
{
count -= (mCount % 2);
LL_WARNS() << "Incomplete line requested." << LL_ENDL;
}
}
mCount = 0;
if (mBuffer)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb cache miss");
U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
vb = genBuffer(attribute_mask, count);
drawBuffer(vb, mMode, count);
}
else
{
// mBuffer is present in main thread and not present in an image thread
LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL;
}
resetStriders(count);
}
else
{
count = 0;
}
return vb;
}
void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)

View File

@ -417,6 +417,12 @@ public:
void begin(const GLuint& mode);
void end();
LLVertexBuffer* beginNoCache(const GLuint& mode, S32& count);
LLVertexBuffer* endNoCache(S32& count);
LLVertexBuffer* getBuffer(S32& count);
U8 getMode() const { return mMode; }
void vertex2i(const GLint& x, const GLint& y);
void vertex2f(const GLfloat& x, const GLfloat& y);
void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z);
@ -485,6 +491,10 @@ public:
private:
friend class LLLightState;
LLVertexBuffer* genBuffer(U32 attribute_mask, S32 count);
void drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count);
void resetStriders(S32 count);
eMatrixMode mMatrixMode;
U32 mMatIdx[NUM_MATRIX_MODES];
U32 mMatHash[NUM_MATRIX_MODES];

View File

@ -120,8 +120,9 @@ LLButton::Params::Params()
LLButton::LLButton(const LLButton::Params& p)
: LLUICtrl(p),
: LLUICtrl(p),
LLBadgeOwner(getHandle()),
mFontBuffer(false),
mMouseDownFrame(0),
mMouseHeldDownCount(0),
mBorderEnabled( false ),
@ -329,6 +330,30 @@ void LLButton::onCommit()
LLUICtrl::onCommit();
}
void LLButton::setUnselectedLabelColor(const LLUIColor& c)
{
mUnselectedLabelColor = c;
mFontBuffer.reset();
}
void LLButton::setSelectedLabelColor(const LLUIColor& c)
{
mSelectedLabelColor = c;
mFontBuffer.reset();
}
void LLButton::setUseEllipses(bool use_ellipses)
{
mUseEllipses = use_ellipses;
mFontBuffer.reset();
}
void LLButton::setUseFontColor(bool use_font_color)
{
mUseFontColor = use_font_color;
mFontBuffer.reset();
}
boost::signals2::connection LLButton::setClickedCallback(const CommitCallbackParam& cb)
{
return setClickedCallback(initCommitCallback(cb));
@ -396,6 +421,15 @@ bool LLButton::postBuild()
return LLUICtrl::postBuild();
}
void LLButton::onVisibilityChange(bool new_visibility)
{
if (!new_visibility)
{
mFontBuffer.reset();
}
return LLUICtrl::onVisibilityChange(new_visibility);
}
bool LLButton::handleUnicodeCharHere(llwchar uni_char)
{
bool handled = false;
@ -954,7 +988,7 @@ void LLButton::draw()
// LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value.
// Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode.
// Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.
mLastDrawCharsCount = mGLFont->render(label, 0,
mLastDrawCharsCount = mFontBuffer.render(mGLFont, label, 0,
(F32)x,
(F32)(getRect().getHeight() / 2 + mBottomVPad),
label_color % alpha,
@ -996,6 +1030,7 @@ void LLButton::setToggleState(bool b)
setFlashing(false); // stop flash state whenever the selected/unselected state if reset
// Unselected label assignments
autoResize();
mFontBuffer.reset();
}
}
@ -1025,11 +1060,13 @@ bool LLButton::toggleState()
void LLButton::setLabel( const std::string& label )
{
mUnselectedLabel = mSelectedLabel = label;
mFontBuffer.reset();
}
void LLButton::setLabel( const LLUIString& label )
{
mUnselectedLabel = mSelectedLabel = label;
mFontBuffer.reset();
}
void LLButton::setLabel( const LLStringExplicit& label )
@ -1043,17 +1080,20 @@ bool LLButton::setLabelArg( const std::string& key, const LLStringExplicit& text
{
mUnselectedLabel.setArg(key, text);
mSelectedLabel.setArg(key, text);
mFontBuffer.reset();
return true;
}
void LLButton::setLabelUnselected( const LLStringExplicit& label )
{
mUnselectedLabel = label;
mFontBuffer.reset();
}
void LLButton::setLabelSelected( const LLStringExplicit& label )
{
mSelectedLabel = label;
mFontBuffer.reset();
}
bool LLButton::labelIsTruncated() const
@ -1113,6 +1153,7 @@ void LLButton::resize(const LLUIString& label)
if (btn_width < min_width)
{
reshape(min_width, getRect().getHeight());
mFontBuffer.reset();
}
}
}

View File

@ -35,6 +35,7 @@
#include "v4color.h"
#include "llframetimer.h"
#include "llfontgl.h"
#include "llfontvertexbuffer.h"
#include "lluiimage.h"
#include "lluistring.h"
@ -167,15 +168,17 @@ public:
virtual void draw();
/*virtual*/ bool postBuild();
/*virtual*/ void onVisibilityChange(bool visible);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual void onMouseCaptureLost();
virtual void onCommit();
void setUnselectedLabelColor( const LLUIColor& c ) { mUnselectedLabelColor = c; }
void setSelectedLabelColor( const LLUIColor& c ) { mSelectedLabelColor = c; }
void setUseEllipses( bool use_ellipses ) { mUseEllipses = use_ellipses; }
void setUseFontColor( bool use_font_color) { mUseFontColor = use_font_color; }
void setUnselectedLabelColor(const LLUIColor& c);
void setSelectedLabelColor(const LLUIColor& c);
void setUseEllipses(bool use_ellipses);
void setUseFontColor(bool use_font_color);
boost::signals2::connection setClickedCallback(const CommitCallbackParam& cb);
@ -223,7 +226,6 @@ public:
const std::string getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); }
const std::string getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); }
void setImageColor(const std::string& color_control);
void setImageColor(const LLUIColor& c);
/*virtual*/ void setColor(const LLUIColor& c);
@ -278,7 +280,6 @@ public:
void setCommitOnReturn(bool commit) { mCommitOnReturn = commit; }
bool getCommitOnReturn() const { return mCommitOnReturn; }
static void onHeldDown(void *userdata); // to be called by gIdleCallbacks
static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname);
static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
static void setDockableFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname);
@ -306,6 +307,7 @@ protected:
commit_signal_t* mHeldDownSignal;
const LLFontGL* mGLFont;
LLFontVertexBuffer mFontBuffer;
S32 mMouseDownFrame;
S32 mMouseHeldDownCount; // Counter for parameter passed to held-down callback

View File

@ -3710,6 +3710,10 @@ S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 t
//
// "This is why I'm doing it this way, instead of what you would think would be more obvious..."
// (C) Nat Goodspeed
if (!IsWindow(sWindowHandleForMessageBox))
{
sWindowHandleForMessageBox = NULL;
}
int retval_win = MessageBoxW(sWindowHandleForMessageBox, // HWND
ll_convert_string_to_wide(text).c_str(),
ll_convert_string_to_wide(caption).c_str(),

View File

@ -328,7 +328,7 @@ void LLHUDNameTag::renderText()
}
LLColor4 label_color(0.f, 0.f, 0.f, alpha_factor);
hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, false);
hud_render_text(segment_iter->getText(), render_position, &segment_iter->mFontBufferLabel, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, false);
}
}
@ -373,7 +373,7 @@ void LLHUDNameTag::renderText()
text_color = segment_iter->mColor;
text_color.mV[VALPHA] *= alpha_factor;
hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, false);
hud_render_text(segment_iter->getText(), render_position, &segment_iter->mFontBufferText, *fontp, style, shadow, x_offset, y_offset, text_color, false);
}
}
/// Reset the default color to white. The renderer expects this to be the default.

View File

@ -37,6 +37,7 @@
#include "llrect.h"
//#include "llframetimer.h"
#include "llfontgl.h"
#include "llfontvertexbuffer.h"
#include <set>
#include <vector>
@ -67,6 +68,8 @@ protected:
LLColor4 mColor;
LLFontGL::StyleFlags mStyle;
const LLFontGL* mFont;
LLFontVertexBuffer mFontBufferLabel;
LLFontVertexBuffer mFontBufferText;
private:
LLWString mText;
std::map<const LLFontGL*, F32> mFontWidthMap;

View File

@ -39,6 +39,7 @@
#include "llui.h"
void hud_render_utf8text(const std::string &str, const LLVector3 &pos_agent,
LLFontVertexBuffer *font_buffer,
const LLFontGL &font,
const U8 style,
const LLFontGL::ShadowType shadow,
@ -47,10 +48,11 @@ void hud_render_utf8text(const std::string &str, const LLVector3 &pos_agent,
const bool orthographic)
{
LLWString wstr(utf8str_to_wstring(str));
hud_render_text(wstr, pos_agent, font, style, shadow, x_offset, y_offset, color, orthographic);
hud_render_text(wstr, pos_agent, font_buffer, font, style, shadow, x_offset, y_offset, color, orthographic);
}
void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
LLFontVertexBuffer *font_buffer,
const LLFontGL &font,
const U8 style,
const LLFontGL::ShadowType shadow,
@ -138,7 +140,14 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,
LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));
F32 right_x;
font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, static_cast<S32>(wstr.length()), 1000, &right_x, /*use_ellipses*/false, /*use_color*/true);
if (font_buffer)
{
font_buffer->render(&font, wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, static_cast<S32>(wstr.length()), 1000, &right_x, /*use_ellipses*/false, /*use_color*/true);
}
else
{
font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, static_cast<S32>(wstr.length()), 1000, &right_x, /*use_ellipses*/false, /*use_color*/true);
}
LLUI::popMatrix();
gGL.popMatrix();

View File

@ -28,6 +28,7 @@
#define LL_LLHUDRENDER_H
#include "llfontgl.h"
#include "llfontvertexbuffer.h"
class LLVector3;
class LLFontGL;
@ -35,6 +36,7 @@ class LLFontGL;
// Utility classes for rendering HUD elements
void hud_render_text(const LLWString &wstr,
const LLVector3 &pos_agent,
LLFontVertexBuffer *font_buffer,
const LLFontGL &font,
const U8 style,
const LLFontGL::ShadowType,
@ -46,9 +48,10 @@ void hud_render_text(const LLWString &wstr,
// Legacy, slower
void hud_render_utf8text(const std::string &str,
const LLVector3 &pos_agent,
LLFontVertexBuffer *font_buffer,
const LLFontGL &font,
const U8 style,
const LLFontGL::ShadowType,
const LLFontGL::ShadowType,
const F32 x_offset,
const F32 y_offset,
const LLColor4& color,

View File

@ -231,7 +231,7 @@ void LLHUDText::renderText()
}
text_color.mV[VALPHA] *= alpha_factor;
hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment);
hud_render_text(segment_iter->getText(), render_position, &mFontBuffer, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment);
}
}
/// Reset the default color to white. The renderer expects this to be the default.

View File

@ -35,6 +35,7 @@
#include "v2math.h"
#include "llrect.h"
#include "llfontgl.h"
#include "llfontvertexbuffer.h"
#include <set>
#include <vector>
@ -161,6 +162,7 @@ private:
ETextAlignment mTextAlignment;
EVertAlignment mVertAlignment;
bool mHidden;
LLFontVertexBuffer mFontBuffer;
static bool sDisplayText ;
static std::set<LLPointer<LLHUDText> > sTextObjects;

View File

@ -519,9 +519,9 @@ void LLManip::renderTickText(const LLVector3& pos, const std::string& text, cons
LLColor4 shadow_color = LLColor4::black;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
gViewerWindow->setup3DViewport(1, -1);
hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
hud_render_utf8text(text, render_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
gViewerWindow->setup3DViewport();
hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
hud_render_utf8text(text, render_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
gGL.popMatrix();
}
@ -581,12 +581,12 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string
{
fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str());
hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, 1.f, 3.f, color, hud_selection);
hud_render_utf8text(val_string, render_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
hud_render_utf8text(fraction_string, render_pos, nullptr, *small_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, 1.f, 3.f, color, hud_selection);
}
else
{
hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
hud_render_utf8text(val_string, render_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection);
}
}
gGL.popMatrix();

View File

@ -1169,10 +1169,10 @@ void LLManipRotate::renderSnapGuides()
std::string help_text = LLTrans::getString("manip_hint1");
LLColor4 help_text_color = LLColor4::white;
help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f);
hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
hud_render_utf8text(help_text, help_text_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
help_text = LLTrans::getString("manip_hint2");
help_text_pos -= offset_dir * mRadiusMeters * 0.4f;
hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
hud_render_utf8text(help_text, help_text_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
}
}
}

View File

@ -1865,10 +1865,10 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
std::string help_text = LLTrans::getString("manip_hint1");
LLColor4 help_text_color = LLColor4::white;
help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, grid_alpha, 0.f);
hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
hud_render_utf8text(help_text, help_text_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
help_text = LLTrans::getString("manip_hint2");
help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapRegimeOffset * 0.4f;
hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
hud_render_utf8text(help_text, help_text_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
}
}
}

View File

@ -1449,10 +1449,10 @@ void LLManipTranslate::renderSnapGuides()
std::string help_text = LLTrans::getString("manip_hint1");
LLColor4 help_text_color = LLColor4::white;
help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f);
hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
hud_render_utf8text(help_text, help_text_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
help_text = LLTrans::getString("manip_hint2");
help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapOffsetMeters * 0.2f;
hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
hud_render_utf8text(help_text, help_text_pos, nullptr, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false);
}
}
}