summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llfontfreetype.cpp201
-rw-r--r--indra/llrender/llfontfreetype.h23
-rw-r--r--indra/llrender/llfontgl.cpp2
-rw-r--r--indra/llrender/llfontvertexbuffer.cpp11
-rw-r--r--indra/llrender/llgl.cpp7
-rw-r--r--indra/llrender/llgl.h1
-rw-r--r--indra/llrender/llgltexture.cpp80
-rw-r--r--indra/llrender/llgltexture.h3
-rw-r--r--indra/llrender/llvertexbuffer.cpp24
-rw-r--r--indra/llrender/llvertexbuffer.h1
10 files changed, 230 insertions, 123 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index fa76669258..019fb07152 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -58,9 +58,9 @@
FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL;
-LLFontManager *gFontManagerp = NULL;
+LLFontManager *gFontManagerp = nullptr;
-FT_Library gFTLibrary = NULL;
+FT_Library gFTLibrary = nullptr;
//static
void LLFontManager::initClass()
@@ -75,7 +75,7 @@ void LLFontManager::initClass()
void LLFontManager::cleanupClass()
{
delete gFontManagerp;
- gFontManagerp = NULL;
+ gFontManagerp = nullptr;
}
LLFontManager::LLFontManager()
@@ -103,6 +103,7 @@ LLFontManager::LLFontManager()
LLFontManager::~LLFontManager()
{
FT_Done_FreeType(gFTLibrary);
+ unloadAllFonts();
}
@@ -141,12 +142,8 @@ LLFontFreetype::LLFontFreetype()
mAscender(0.f),
mDescender(0.f),
mLineHeight(0.f),
-#ifdef LL_WINDOWS
- pFileStream(NULL),
- pFtStream(NULL),
-#endif
mIsFallback(false),
- mFTFace(NULL),
+ mFTFace(nullptr),
mRenderGlyphCount(0),
mAddGlyphCount(0),
mStyle(0),
@@ -160,35 +157,16 @@ LLFontFreetype::~LLFontFreetype()
// Clean up freetype libs.
if (mFTFace)
FT_Done_Face(mFTFace);
- mFTFace = NULL;
+ mFTFace = nullptr;
// Delete glyph info
std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
mCharGlyphInfoMap.clear();
-#ifdef LL_WINDOWS
- delete pFileStream; // closed by FT_Done_Face
- delete pFtStream;
-#endif
delete mFontBitmapCachep;
// mFallbackFonts cleaned up by LLPointer destructor
}
-#ifdef LL_WINDOWS
-unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) {
- if (count <= 0) return count;
- llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer);
- file_stream->seekg(offset, std::ios::beg);
- file_stream->read((char*)buffer, count);
- return (unsigned long)file_stream->gcount();
-}
-
-void ft_close_cb(FT_Stream stream) {
- llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer);
- file_stream->close();
-}
-#endif
-
bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n)
{
// Don't leak face objects. This is also needed to deal with
@@ -196,26 +174,21 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
if (mFTFace)
{
FT_Done_Face(mFTFace);
- mFTFace = NULL;
+ mFTFace = nullptr;
}
- int error;
-#ifdef LL_WINDOWS
- error = ftOpenFace(filename, face_n);
-#else
- error = FT_New_Face( gFTLibrary,
- filename.c_str(),
- 0,
- &mFTFace);
-#endif
+ FT_Open_Args openArgs;
+ memset( &openArgs, 0, sizeof( openArgs ) );
+ openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size );
+
+ if( !openArgs.memory_base )
+ return false;
+
+ openArgs.flags = FT_OPEN_MEMORY;
+ int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace );
if (error)
- {
-#ifdef LL_WINDOWS
- clearFontStreams();
-#endif
return false;
- }
mIsFallback = is_fallback;
F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
@@ -230,10 +203,8 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
{
// Clean up freetype libs.
FT_Done_Face(mFTFace);
-#ifdef LL_WINDOWS
- clearFontStreams();
-#endif
- mFTFace = NULL;
+
+ mFTFace = nullptr;
return false;
}
@@ -289,73 +260,30 @@ S32 LLFontFreetype::getNumFaces(const std::string& filename)
if (mFTFace)
{
FT_Done_Face(mFTFace);
- mFTFace = NULL;
+ mFTFace = nullptr;
}
S32 num_faces = 1;
-#ifdef LL_WINDOWS
- int error = ftOpenFace(filename, 0);
+ FT_Open_Args openArgs;
+ memset( &openArgs, 0, sizeof( openArgs ) );
+ openArgs.memory_base = gFontManagerp->loadFont( filename, openArgs.memory_size );
+ if( !openArgs.memory_base )
+ return 0;
+ openArgs.flags = FT_OPEN_MEMORY;
+ int error = FT_Open_Face( gFTLibrary, &openArgs, 0, &mFTFace );
if (error)
- {
return 0;
- }
else
- {
num_faces = mFTFace->num_faces;
- }
FT_Done_Face(mFTFace);
- clearFontStreams();
- mFTFace = NULL;
-#endif
+ mFTFace = nullptr;
return num_faces;
}
-#ifdef LL_WINDOWS
-S32 LLFontFreetype::ftOpenFace(const std::string& filename, S32 face_n)
-{
- S32 error = -1;
- pFileStream = new llifstream(filename, std::ios::binary);
- if (pFileStream->is_open())
- {
- std::streampos beg = pFileStream->tellg();
- pFileStream->seekg(0, std::ios::end);
- std::streampos end = pFileStream->tellg();
- std::size_t file_size = end - beg;
- pFileStream->seekg(0, std::ios::beg);
-
- pFtStream = new LLFT_Stream();
- pFtStream->base = 0;
- pFtStream->pos = 0;
- pFtStream->size = static_cast<unsigned long>(file_size);
- pFtStream->descriptor.pointer = pFileStream;
- pFtStream->read = ft_read_cb;
- pFtStream->close = ft_close_cb;
-
- FT_Open_Args args;
- args.flags = FT_OPEN_STREAM;
- args.stream = (FT_StreamRec*)pFtStream;
- error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace);
- }
- return error;
-}
-
-void LLFontFreetype::clearFontStreams()
-{
- if (pFileStream)
- {
- pFileStream->close();
- }
- delete pFileStream;
- delete pFtStream;
- pFileStream = NULL;
- pFtStream = NULL;
-}
-#endif
-
void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font,
const char_functor_t& functor)
{
@@ -379,7 +307,7 @@ F32 LLFontFreetype::getDescenderHeight() const
F32 LLFontFreetype::getXAdvance(llwchar wch) const
{
- if (mFTFace == NULL)
+ if (mFTFace == nullptr)
return 0.0;
// Return existing info only if it is current
@@ -403,7 +331,7 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
{
- if (mFTFace == NULL)
+ if (mFTFace == nullptr)
return 0.0;
return glyph->mXAdvance;
@@ -411,7 +339,7 @@ F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
{
- if (mFTFace == NULL)
+ if (mFTFace == nullptr)
return 0.0;
//llassert(!mIsFallback);
@@ -430,7 +358,7 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
{
- if (mFTFace == NULL)
+ if (mFTFace == nullptr)
return 0.0;
U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
@@ -453,7 +381,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type
{
if (!mFTFace)
{
- return NULL;
+ return nullptr;
}
llassert(!mIsFallback);
@@ -544,14 +472,14 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type
{
return addGlyphFromFont(this, wch, glyph_index, glyph_type);
}
- return NULL;
+ return nullptr;
}
LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const
{
LL_PROFILE_ZONE_SCOPED;
- if (mFTFace == NULL)
- return NULL;
+ if (mFTFace == nullptr)
+ return nullptr;
llassert(!mIsFallback);
fontp->renderGlyph(requested_glyph_type, glyph_index);
@@ -604,7 +532,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l
{
U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer;
S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch;
- U8 *tmp_graydata = NULL;
+ U8 *tmp_graydata = nullptr;
if (fontp->mFTFace->glyph->bitmap.pixel_mode
== FT_PIXEL_MODE_MONO)
@@ -701,7 +629,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const
{
- if (mFTFace == NULL)
+ if (mFTFace == nullptr)
return;
FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT;
@@ -886,3 +814,58 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32
}
}
+
+namespace ll
+{
+ namespace fonts
+ {
+ class LoadedFont
+ {
+ public:
+ LoadedFont( std::string aName , std::string const &aAddress, std::size_t aSize )
+ : mAddress( aAddress )
+ {
+ mName = aName;
+ mSize = aSize;
+ mRefs = 1;
+ }
+ std::string mName;
+ std::string mAddress;
+ std::size_t mSize;
+ U32 mRefs;
+ };
+ }
+}
+
+U8 const* LLFontManager::loadFont( std::string const &aFilename, long &a_Size)
+{
+ a_Size = 0;
+ std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> >::iterator itr = m_LoadedFonts.find( aFilename );
+ if( itr != m_LoadedFonts.end() )
+ {
+ ++itr->second->mRefs;
+ // A possible overflow cannot happen here, as it is asserted that the size is less than std::numeric_limits<long>::max() a few lines below.
+ a_Size = static_cast<long>(itr->second->mSize);
+ return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str());
+ }
+
+ auto strContent = LLFile::getContents(aFilename);
+
+ if( strContent.empty() )
+ return nullptr;
+
+ // For fontconfig a type of long is required, std::string::size() returns size_t. I think it is safe to limit this to 2GiB and not support fonts that huge (can that even be a thing?)
+ llassert_always( strContent.size() < std::numeric_limits<long>::max() );
+
+ a_Size = static_cast<long>(strContent.size());
+
+ auto pCache = std::make_shared<ll::fonts::LoadedFont>( aFilename, strContent, a_Size );
+ itr = m_LoadedFonts.insert( std::make_pair( aFilename, pCache ) ).first;
+
+ return reinterpret_cast<U8 const*>(itr->second->mAddress.c_str());
+}
+
+void LLFontManager::unloadAllFonts()
+{
+ m_LoadedFonts.clear();
+}
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index eba89f5def..7173da5238 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -43,15 +43,28 @@ typedef struct FT_FaceRec_* LLFT_Face;
struct FT_StreamRec_;
typedef struct FT_StreamRec_ LLFT_Stream;
+namespace ll
+{
+ namespace fonts
+ {
+ class LoadedFont;
+ }
+}
+
class LLFontManager
{
public:
static void initClass();
static void cleanupClass();
+ U8 const *loadFont( std::string const &aFilename, long &a_Size );
+
private:
LLFontManager();
~LLFontManager();
+
+ void unloadAllFonts();
+ std::map< std::string, std::shared_ptr<ll::fonts::LoadedFont> > m_LoadedFonts;
};
struct LLFontGlyphInfo
@@ -90,11 +103,6 @@ public:
S32 getNumFaces(const std::string& filename);
-#ifdef LL_WINDOWS
- S32 ftOpenFace(const std::string& filename, S32 face_n);
- void clearFontStreams();
-#endif
-
typedef std::function<bool(llwchar)> char_functor_t;
void addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor = nullptr);
@@ -170,11 +178,6 @@ private:
LLFT_Face mFTFace;
-#ifdef LL_WINDOWS
- llifstream *pFileStream;
- LLFT_Stream *pFtStream;
-#endif
-
bool mIsFallback;
typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t;
typedef std::vector<fallback_font_t> fallback_font_vector_t;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index a012d57b5a..97be43cf86 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -404,7 +404,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
{
// recursively render ellipses at end of string
// we've already reserved enough room
- gGL.pushUIMatrix();
static LLWString elipses_wstr(utf8string_to_wstring(std::string("...")));
render(elipses_wstr,
0,
@@ -417,7 +416,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
right_x,
false,
use_color);
- gGL.popUIMatrix();
}
gGL.popUIMatrix();
diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp
index f5d6b03cd6..963aab7121 100644
--- a/indra/llrender/llfontvertexbuffer.cpp
+++ b/indra/llrender/llfontvertexbuffer.cpp
@@ -209,6 +209,17 @@ 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);
+
+ // Note: ellipses should technically be covered by push/load/translate of their own
+ // but it's more complexity, values do not change, skipping doesn't appear to break
+ // anything, so we can skip that until it proves to cause issues.
for (LLVertexBufferData& buffer : mBufferList)
{
buffer.draw();
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index a9627a87d3..798b605f08 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -65,6 +65,7 @@
bool gDebugSession = false;
bool gDebugGLSession = false;
+bool gDebugTextureLabelLocalFilesSession = false;
bool gClothRipple = false;
bool gHeadlessClient = false;
bool gNonInteractive = false;
@@ -1140,7 +1141,11 @@ bool LLGLManager::initGL()
// Trailing space necessary to keep "nVidia Corpor_ati_on" cards
// from being recognized as ATI.
// NOTE: AMD has been pretty good about not breaking this check, do not rename without good reason
- if (mGLVendor.substr(0,4) == "ATI ")
+ if (mGLVendor.substr(0,4) == "ATI "
+#if LL_LINUX
+ || mGLVendor.find("AMD") != std::string::npos
+#endif //LL_LINUX
+ )
{
mGLVendorShort = "AMD";
// *TODO: Fix this?
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 08cf662526..0e26961588 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -48,6 +48,7 @@
extern bool gDebugGL;
extern bool gDebugSession;
extern bool gDebugGLSession;
+extern bool gDebugTextureLabelLocalFilesSession;
extern llofstream gFailLog;
#define LL_GL_ERRS LL_ERRS("RenderState")
diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp
index 4dcca5a726..c2298d5377 100644
--- a/indra/llrender/llgltexture.cpp
+++ b/indra/llrender/llgltexture.cpp
@@ -168,6 +168,86 @@ bool LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw,
return ret ;
}
+void LLGLTexture::getGLObjectLabel(std::string& label, bool& error) const
+{
+ // GL_VERSION_4_3
+ if (gGLManager.mGLVersion < 4.29f)
+ {
+ error = true;
+ label.clear();
+ return;
+ }
+ if (!mGLTexturep)
+ {
+ error = true;
+ label.clear();
+ return;
+ }
+ LLGLuint texname = mGLTexturep->getTexName();
+ if (!texname)
+ {
+ error = true;
+ label.clear();
+ return;
+ }
+
+#if LL_DARWIN
+ // apple doesn't support GL after 4.1 so should have hit the above early out, but make the compiler happy here
+ error = true;
+ label.clear();
+ return;
+#else
+ static GLsizei max_length = 0;
+ if (max_length == 0) { glGetIntegerv(GL_MAX_LABEL_LENGTH, &max_length); }
+ static char * clabel = new char[max_length+1];
+ GLsizei length;
+ glGetObjectLabel(GL_TEXTURE, texname, max_length+1, &length, clabel);
+ error = false;
+ label.assign(clabel, length);
+#endif
+}
+
+std::string LLGLTexture::setGLObjectLabel(const std::string& prefix, bool append_texname) const
+{
+#ifndef LL_DARWIN // apple doesn't support GL > 4.1
+ if (gGLManager.mGLVersion < 4.29f) { return ""; } // GL_VERSION_4_3
+ llassert(mGLTexturep);
+ if (mGLTexturep)
+ {
+ LLGLuint texname = mGLTexturep->getTexName();
+ llassert(texname);
+ if (texname)
+ {
+ static GLsizei max_length = 0;
+ if (max_length == 0) { glGetIntegerv(GL_MAX_LABEL_LENGTH, &max_length); }
+
+ if (append_texname)
+ {
+ std::string label_with_texname = prefix + "_" + std::to_string(texname);
+ label_with_texname.resize(std::min(size_t(max_length), label_with_texname.size()));
+ glObjectLabel(GL_TEXTURE, texname, (GLsizei)label_with_texname.size(), label_with_texname.c_str());
+ return label_with_texname;
+ }
+ else
+ {
+ if (prefix.size() <= max_length)
+ {
+ glObjectLabel(GL_TEXTURE, texname, (GLsizei)prefix.size(), prefix.c_str());
+ return prefix;
+ }
+ else
+ {
+ const std::string label(prefix.c_str(), max_length);
+ glObjectLabel(GL_TEXTURE, texname, (GLsizei)label.size(), label.c_str());
+ return label;
+ }
+ }
+ }
+ }
+#endif
+ return "";
+}
+
void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, bool swap_bytes)
{
llassert(mGLTexturep.notNull()) ;
diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h
index 122d2a7f9c..22f2ed5131 100644
--- a/indra/llrender/llgltexture.h
+++ b/indra/llrender/llgltexture.h
@@ -118,6 +118,9 @@ public:
LLGLuint getTexName() const ;
bool createGLTexture() ;
+ void getGLObjectLabel(std::string& label, bool& error) const;
+ std::string setGLObjectLabel(const std::string& prefix, bool append_texname = false) const;
+
// Create a GL Texture from an image raw
// discard_level - mip level, 0 for highest resultion mip
// imageraw - the image to copy from
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 6f4828397a..12ae36f4bb 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -604,7 +604,7 @@ public:
static LLVBOPool* sVBOPool = nullptr;
-void LLVertexBufferData::draw()
+void LLVertexBufferData::drawWithMatrix()
{
if (!mVB)
{
@@ -642,6 +642,28 @@ void LLVertexBufferData::draw()
gGL.popMatrix();
}
+void LLVertexBufferData::draw()
+{
+ if (!mVB)
+ {
+ llassert(false);
+ // Not supposed to happen, check buffer generation
+ return;
+ }
+
+ if (mTexName)
+ {
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTexName);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+
+ mVB->setBuffer();
+ mVB->drawArrays(mMode, 0, mCount);
+}
+
//============================================================================
//static
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index d4c6fbaf18..375ad76fb8 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -77,6 +77,7 @@ public:
, mModelView(projection)
, mTexture0(texture0)
{}
+ void drawWithMatrix();
void draw();
LLPointer<LLVertexBuffer> mVB;
U8 mMode;