llrender and lldir merge. Removed duplicate assets from skins. cleaned up skin textures.xml files to only include changes from default.
This commit is contained in:
@@ -104,7 +104,6 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
|
||||
|
||||
LLFontFreetype::LLFontFreetype()
|
||||
: mFontBitmapCachep(new LLFontBitmapCache),
|
||||
mValid(FALSE),
|
||||
mAscender(0.f),
|
||||
mDescender(0.f),
|
||||
mLineHeight(0.f),
|
||||
@@ -112,6 +111,7 @@ LLFontFreetype::LLFontFreetype()
|
||||
mFTFace(NULL),
|
||||
mRenderGlyphCount(0),
|
||||
mAddGlyphCount(0),
|
||||
mStyle(0),
|
||||
mPointSize(0)
|
||||
{
|
||||
}
|
||||
@@ -204,6 +204,19 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, const F32 point_size,
|
||||
mName = filename;
|
||||
mPointSize = point_size;
|
||||
|
||||
mStyle = LLFontGL::NORMAL;
|
||||
if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD)
|
||||
{
|
||||
mStyle |= LLFontGL::BOLD;
|
||||
mStyle &= ~LLFontGL::NORMAL;
|
||||
}
|
||||
|
||||
if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
|
||||
{
|
||||
mStyle |= LLFontGL::ITALIC;
|
||||
mStyle &= ~LLFontGL::NORMAL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -536,6 +549,15 @@ const LLPointer<LLFontBitmapCache> LLFontFreetype::getFontBitmapCache() const
|
||||
return mFontBitmapCachep;
|
||||
}
|
||||
|
||||
void LLFontFreetype::setStyle(U8 style)
|
||||
{
|
||||
mStyle = style;
|
||||
}
|
||||
|
||||
U8 LLFontFreetype::getStyle() const
|
||||
{
|
||||
return mStyle;
|
||||
}
|
||||
void LLFontFreetype::setSubImageLuminanceAlpha(const U32 x, const U32 y, const U32 bitmap_num, const U32 width, const U32 height, const U8 *data, S32 stride) const
|
||||
{
|
||||
LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num);
|
||||
|
||||
@@ -93,8 +93,6 @@ public:
|
||||
void setFallbackFonts(const font_vector_t &font);
|
||||
const font_vector_t &getFallbackFonts() const;
|
||||
|
||||
void setCharToGlyphMap(llwchar wch, U32 glyph_index) const;
|
||||
|
||||
// Global font metrics - in units of pixels
|
||||
F32 getLineHeight() const;
|
||||
F32 getAscenderHeight() const;
|
||||
@@ -140,6 +138,9 @@ public:
|
||||
const std::string& getName() const;
|
||||
|
||||
const LLPointer<LLFontBitmapCache> getFontBitmapCache() const;
|
||||
|
||||
void setStyle(U8 style);
|
||||
U8 getStyle() const;
|
||||
|
||||
static bool sOpenGLcrashOnRestart;
|
||||
|
||||
@@ -154,6 +155,8 @@ private:
|
||||
|
||||
std::string mName;
|
||||
|
||||
U8 mStyle;
|
||||
|
||||
F32 mPointSize;
|
||||
F32 mAscender;
|
||||
F32 mDescender;
|
||||
@@ -164,8 +167,6 @@ private:
|
||||
BOOL mIsFallback;
|
||||
font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
|
||||
|
||||
BOOL mValid;
|
||||
|
||||
typedef boost::unordered_map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
|
||||
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "llfontregistry.h"
|
||||
#include "llgl.h"
|
||||
#include "llrender.h"
|
||||
#include "lltexture.h"
|
||||
#include "v4color.h"
|
||||
#include "llstl.h"
|
||||
#include "llfasttimer.h"
|
||||
@@ -69,20 +70,6 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
|
||||
const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture
|
||||
const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f;
|
||||
|
||||
F32 llfont_round_x(F32 x)
|
||||
{
|
||||
//return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX;
|
||||
//return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY;
|
||||
return x;
|
||||
}
|
||||
|
||||
F32 llfont_round_y(F32 y)
|
||||
{
|
||||
//return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY;
|
||||
//return llfloor(y+0.5f);
|
||||
return y;
|
||||
}
|
||||
|
||||
LLFontGL::LLFontGL()
|
||||
{
|
||||
clearEmbeddedChars();
|
||||
@@ -166,8 +153,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
||||
|
||||
S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
|
||||
|
||||
// Strip off any style bits that are already accounted for by the font.
|
||||
style = style & (~getFontDesc().getStyle());
|
||||
// determine which style flags need to be added programmatically by stripping off the
|
||||
// style bits that are drawn by the underlying Freetype font
|
||||
U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();
|
||||
|
||||
F32 drop_shadow_strength = 0.f;
|
||||
if (shadow != NO_SHADOW)
|
||||
@@ -412,7 +400,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
||||
glyph_count = 0;
|
||||
}
|
||||
|
||||
drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style, shadow, drop_shadow_strength);
|
||||
drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength);
|
||||
|
||||
chars_drawn++;
|
||||
cur_x += fgi->mXAdvance;
|
||||
@@ -453,7 +441,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
||||
*right_x = (cur_x - origin.mV[VX]) / sScaleX;
|
||||
}
|
||||
|
||||
if (style & UNDERLINE)
|
||||
//FIXME: add underline as glyph?
|
||||
if (style_to_add & UNDERLINE)
|
||||
{
|
||||
F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight());
|
||||
|
||||
@@ -475,7 +464,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
||||
(cur_x - origin.mV[VX]) / sScaleX, (F32)y,
|
||||
color,
|
||||
LEFT, valign,
|
||||
style,
|
||||
style_to_add,
|
||||
shadow,
|
||||
S32_MAX, max_pixels,
|
||||
right_x,
|
||||
@@ -940,7 +929,7 @@ void LLFontGL::removeEmbeddedChar( llwchar wc ) const
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures)
|
||||
void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures)
|
||||
{
|
||||
sVertDPI = (F32)llfloor(screen_dpi * y_scale);
|
||||
sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
|
||||
@@ -951,7 +940,7 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st
|
||||
// Font registry init
|
||||
if (!sFontRegistry)
|
||||
{
|
||||
sFontRegistry = new LLFontRegistry(xui_paths,create_gl_textures);
|
||||
sFontRegistry = new LLFontRegistry(create_gl_textures);
|
||||
sFontRegistry->parseFontInfo("fonts.xml");
|
||||
}
|
||||
else
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "llcoord.h"
|
||||
#include "llfontregistry.h"
|
||||
#include "lltexture.h"
|
||||
#include "llimagegl.h"
|
||||
#include "llpointer.h"
|
||||
#include "llrect.h"
|
||||
#include "v2math.h"
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const;
|
||||
void removeEmbeddedChar( llwchar wc ) const;
|
||||
|
||||
static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures = true);
|
||||
static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true);
|
||||
|
||||
// Load sans-serif, sans-serif-small, etc.
|
||||
// Slow, requires multiple seconds to load fonts.
|
||||
|
||||
@@ -34,13 +34,15 @@
|
||||
#include "llcontrol.h"
|
||||
#include "lldir.h"
|
||||
#include "llwindow.h"
|
||||
#include "llxmlnode.h"
|
||||
|
||||
extern LLControlGroup gSavedSettings;
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
|
||||
bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc);
|
||||
bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc);
|
||||
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);
|
||||
|
||||
LLFontDescriptor::LLFontDescriptor():
|
||||
mStyle(0)
|
||||
@@ -163,14 +165,9 @@ LLFontDescriptor LLFontDescriptor::normalize() const
|
||||
return LLFontDescriptor(new_name,new_size,new_style,getFileNames());
|
||||
}
|
||||
|
||||
LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths,
|
||||
bool create_gl_textures)
|
||||
LLFontRegistry::LLFontRegistry(bool create_gl_textures)
|
||||
: mCreateGLTextures(create_gl_textures)
|
||||
{
|
||||
// Propagate this down from LLUICtrlFactory so LLRender doesn't
|
||||
// need an upstream dependency on LLUI.
|
||||
mXUIPaths = xui_paths;
|
||||
|
||||
// This is potentially a slow directory traversal, so we want to
|
||||
// cache the result.
|
||||
mUltimateFallbackList = LLWindow::getDynamicFallbackFontList();
|
||||
@@ -183,23 +180,27 @@ LLFontRegistry::~LLFontRegistry()
|
||||
|
||||
bool LLFontRegistry::parseFontInfo(const std::string& xml_filename)
|
||||
{
|
||||
bool success = false; // Succeed if we find at least one XUI file
|
||||
const string_vec_t& xml_paths = mXUIPaths;
|
||||
bool success = false; // Succeed if we find and read at least one XUI file
|
||||
const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename);
|
||||
if (xml_paths.empty())
|
||||
{
|
||||
// We didn't even find one single XUI file
|
||||
return false;
|
||||
}
|
||||
|
||||
for (string_vec_t::const_iterator path_it = xml_paths.begin();
|
||||
path_it != xml_paths.end();
|
||||
++path_it)
|
||||
{
|
||||
LLXMLNodePtr root;
|
||||
std::string full_filename = gDirUtilp->findSkinnedFilename(*path_it, xml_filename);
|
||||
bool parsed_file = LLXMLNode::parseFile(full_filename, root, NULL);
|
||||
bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL);
|
||||
|
||||
if (!parsed_file)
|
||||
continue;
|
||||
|
||||
if ( root.isNull() || ! root->hasName( "fonts" ) )
|
||||
{
|
||||
LL_WARNS() << "Bad font info file: "
|
||||
<< full_filename << LL_ENDL;
|
||||
LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -208,12 +209,12 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename)
|
||||
if (root->hasName("fonts"))
|
||||
{
|
||||
// Expect a collection of children consisting of "font" or "font_size" entries
|
||||
bool init_succ = initFromXML(root);
|
||||
bool init_succ = init_from_xml(this, root);
|
||||
success = success || init_succ;
|
||||
}
|
||||
}
|
||||
if (success)
|
||||
dump();
|
||||
//if (success)
|
||||
// dump();
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -231,7 +232,7 @@ std::string currentOsName()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc)
|
||||
bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
|
||||
{
|
||||
if (node->hasName("font"))
|
||||
{
|
||||
@@ -264,14 +265,14 @@ bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc)
|
||||
{
|
||||
if (child_name == currentOsName())
|
||||
{
|
||||
fontDescInitFromXML(child, desc);
|
||||
font_desc_init_from_xml(child, desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLFontRegistry::initFromXML(LLXMLNodePtr node)
|
||||
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node)
|
||||
{
|
||||
LLXMLNodePtr child;
|
||||
|
||||
@@ -282,17 +283,17 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node)
|
||||
if (child->hasName("font"))
|
||||
{
|
||||
LLFontDescriptor desc;
|
||||
bool font_succ = fontDescInitFromXML(child, desc);
|
||||
bool font_succ = font_desc_init_from_xml(child, desc);
|
||||
LLFontDescriptor norm_desc = desc.normalize();
|
||||
if (font_succ)
|
||||
{
|
||||
// if this is the first time we've seen this font name,
|
||||
// create a new template map entry for it.
|
||||
const LLFontDescriptor *match_desc = getMatchingFontDesc(desc);
|
||||
const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc);
|
||||
if (match_desc == NULL)
|
||||
{
|
||||
// Create a new entry (with no corresponding font).
|
||||
mFontMap[norm_desc] = NULL;
|
||||
registry->mFontMap[norm_desc] = NULL;
|
||||
}
|
||||
// otherwise, find the existing entry and combine data.
|
||||
else
|
||||
@@ -307,8 +308,8 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node)
|
||||
desc.getFileNames().end());
|
||||
LLFontDescriptor new_desc = *match_desc;
|
||||
new_desc.getFileNames() = match_file_names;
|
||||
mFontMap.erase(*match_desc);
|
||||
mFontMap[new_desc] = NULL;
|
||||
registry->mFontMap.erase(*match_desc);
|
||||
registry->mFontMap[new_desc] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,7 +320,7 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node)
|
||||
if (child->getAttributeString("name",size_name) &&
|
||||
child->getAttributeF32("size",size_value))
|
||||
{
|
||||
mFontSizes[size_name] = size_value;
|
||||
registry->mFontSizes[size_name] = size_value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#ifndef LL_LLFONTREGISTRY_H
|
||||
#define LL_LLFONTREGISTRY_H
|
||||
|
||||
#include "llxmlnode.h"
|
||||
#include "llpointer.h"
|
||||
|
||||
class LLFontGL;
|
||||
|
||||
@@ -65,15 +65,14 @@ private:
|
||||
class LLFontRegistry
|
||||
{
|
||||
public:
|
||||
friend bool init_from_xml(LLFontRegistry*, LLPointer<class LLXMLNode>);
|
||||
// create_gl_textures - set to false for test apps with no OpenGL window,
|
||||
// such as llui_libtest
|
||||
LLFontRegistry(const string_vec_t& xui_paths,
|
||||
bool create_gl_textures);
|
||||
LLFontRegistry(bool create_gl_textures);
|
||||
~LLFontRegistry();
|
||||
|
||||
// Load standard font info from XML file(s).
|
||||
bool parseFontInfo(const std::string& xml_filename);
|
||||
bool initFromXML(LLXMLNodePtr node);
|
||||
|
||||
// Clear cached glyphs for all fonts.
|
||||
void reset();
|
||||
@@ -95,6 +94,7 @@ public:
|
||||
const string_vec_t& getUltimateFallbackList() const;
|
||||
|
||||
private:
|
||||
LLFontRegistry(const LLFontRegistry& other); // no-copy
|
||||
LLFontGL *createFont(const LLFontDescriptor& desc);
|
||||
typedef std::map<LLFontDescriptor,LLFontGL*> font_reg_map_t;
|
||||
typedef std::map<std::string,F32> font_size_map_t;
|
||||
@@ -105,7 +105,6 @@ private:
|
||||
font_size_map_t mFontSizes;
|
||||
|
||||
string_vec_t mUltimateFallbackList;
|
||||
string_vec_t mXUIPaths;
|
||||
bool mCreateGLTextures;
|
||||
};
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@ PFNGLENDQUERYARBPROC glEndQueryARB = NULL;
|
||||
PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL;
|
||||
PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL;
|
||||
PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL;
|
||||
PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64vEXT = NULL;
|
||||
|
||||
// GL_ARB_point_parameters
|
||||
PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL;
|
||||
@@ -443,6 +444,7 @@ LLGLManager::LLGLManager() :
|
||||
mHasCubeMap(FALSE),
|
||||
mHasDebugOutput(FALSE),
|
||||
|
||||
mHasGpuShader5(FALSE),
|
||||
mHasAdaptiveVsync(FALSE),
|
||||
mHasTextureSwizzle(FALSE),
|
||||
|
||||
@@ -938,6 +940,9 @@ void LLGLManager::initExtensions()
|
||||
mHasVertexShader = FALSE;
|
||||
mHasFragmentShader = FALSE;
|
||||
mHasTextureRectangle = FALSE;
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
mHasGpuShader5 = FALSE;
|
||||
#endif
|
||||
#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called
|
||||
mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
|
||||
mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);
|
||||
@@ -982,7 +987,9 @@ void LLGLManager::initExtensions()
|
||||
&& (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
|
||||
mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
|
||||
#endif
|
||||
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
mHasGpuShader5 = ExtensionExists("GL_ARB_gpu_shader5", gGLHExts.mSysExts);;
|
||||
#endif
|
||||
#if LL_WINDOWS
|
||||
mHasAdaptiveVsync = ExtensionExists("WGL_EXT_swap_control_tear", gGLHExts.mSysExts);
|
||||
#elif LL_LINUX
|
||||
@@ -1262,6 +1269,9 @@ void LLGLManager::initExtensions()
|
||||
glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectivARB");
|
||||
glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuivARB");
|
||||
}
|
||||
#if !LL_DARWIN
|
||||
glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectui64vEXT");
|
||||
#endif
|
||||
if (mHasPointParameters)
|
||||
{
|
||||
LL_INFOS() << "initExtensions() PointParameters-related procs..." << LL_ENDL;
|
||||
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
BOOL mHasARBEnvCombine;
|
||||
BOOL mHasCubeMap;
|
||||
BOOL mHasDebugOutput;
|
||||
|
||||
BOOL mHasGpuShader5;
|
||||
BOOL mHasAdaptiveVsync;
|
||||
BOOL mHasTextureSwizzle;
|
||||
|
||||
|
||||
@@ -620,6 +620,8 @@ extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
|
||||
extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
|
||||
extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
|
||||
|
||||
extern PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64vEXT;
|
||||
|
||||
// GL_ARB_point_parameters
|
||||
extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
|
||||
extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
|
||||
|
||||
@@ -38,6 +38,11 @@
|
||||
#include "OpenGL/OpenGL.h"
|
||||
#endif
|
||||
|
||||
#ifdef LL_RELEASE_FOR_DOWNLOAD
|
||||
#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
|
||||
#else
|
||||
#define UNIFORM_ERRS LL_ERRS("Shader")
|
||||
#endif
|
||||
// Lots of STL stuff in here, using namespace std to keep things more readable
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
@@ -48,6 +53,12 @@ GLhandleARB LLGLSLShader::sCurBoundShader = 0;
|
||||
LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL;
|
||||
S32 LLGLSLShader::sIndexedTextureChannels = 0;
|
||||
bool LLGLSLShader::sNoFixedFunction = false;
|
||||
bool LLGLSLShader::sProfileEnabled = false;
|
||||
std::set<LLGLSLShader*> LLGLSLShader::sInstances;
|
||||
U64 LLGLSLShader::sTotalTimeElapsed = 0;
|
||||
U32 LLGLSLShader::sTotalTrianglesDrawn = 0;
|
||||
U64 LLGLSLShader::sTotalSamplesDrawn = 0;
|
||||
U32 LLGLSLShader::sTotalDrawCalls = 0;
|
||||
|
||||
//UI shader -- declared here so llui_libtest will link properly
|
||||
//Singu note: Not using llui_libtest... and LLViewerShaderMgr is a part of newview. So,
|
||||
@@ -77,13 +88,221 @@ LLShaderFeatures::LLShaderFeatures()
|
||||
, hasGamma(false)
|
||||
, mIndexedTextureChannels(0)
|
||||
, disableTextureIndex(false)
|
||||
, hasAlphaMask(false)
|
||||
, hasAlphaMask(false)
|
||||
, attachNothing(false)
|
||||
{
|
||||
}
|
||||
|
||||
//===============================
|
||||
// LLGLSL Shader implementation
|
||||
//===============================
|
||||
|
||||
//static
|
||||
void LLGLSLShader::initProfile()
|
||||
{
|
||||
sProfileEnabled = true;
|
||||
sTotalTimeElapsed = 0;
|
||||
sTotalTrianglesDrawn = 0;
|
||||
sTotalSamplesDrawn = 0;
|
||||
sTotalDrawCalls = 0;
|
||||
|
||||
for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
|
||||
{
|
||||
(*iter)->clearStats();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct LLGLSLShaderCompareTimeElapsed
|
||||
{
|
||||
bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs)
|
||||
{
|
||||
return lhs->mTimeElapsed < rhs->mTimeElapsed;
|
||||
}
|
||||
};
|
||||
|
||||
//static
|
||||
void LLGLSLShader::finishProfile(bool emit_report)
|
||||
{
|
||||
sProfileEnabled = false;
|
||||
|
||||
if (emit_report)
|
||||
{
|
||||
std::vector<LLGLSLShader*> sorted;
|
||||
|
||||
for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
|
||||
{
|
||||
sorted.push_back(*iter);
|
||||
}
|
||||
|
||||
std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed());
|
||||
|
||||
for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
|
||||
{
|
||||
(*iter)->dumpStats();
|
||||
}
|
||||
|
||||
LL_INFOS() << "-----------------------------------" << LL_ENDL;
|
||||
LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL;
|
||||
LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL;
|
||||
LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::clearStats()
|
||||
{
|
||||
mTrianglesDrawn = 0;
|
||||
mTimeElapsed = 0;
|
||||
mSamplesDrawn = 0;
|
||||
mDrawCalls = 0;
|
||||
mTextureStateFetched = false;
|
||||
mTextureMagFilter.clear();
|
||||
mTextureMinFilter.clear();
|
||||
}
|
||||
|
||||
void LLGLSLShader::dumpStats()
|
||||
{
|
||||
if (mDrawCalls > 0)
|
||||
{
|
||||
LL_INFOS() << "=============================================" << LL_ENDL;
|
||||
LL_INFOS() << mName << LL_ENDL;
|
||||
for (U32 i = 0; i < mShaderFiles.size(); ++i)
|
||||
{
|
||||
LL_INFOS() << mShaderFiles[i].first << LL_ENDL;
|
||||
}
|
||||
for (U32 i = 0; i < mTexture.size(); ++i)
|
||||
{
|
||||
GLint idx = mTexture[i];
|
||||
|
||||
if (idx >= 0)
|
||||
{
|
||||
GLint uniform_idx = getUniformLocation(i);
|
||||
LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL;
|
||||
}
|
||||
}
|
||||
LL_INFOS() << "=============================================" << LL_ENDL;
|
||||
|
||||
F32 ms = mTimeElapsed/1000000.f;
|
||||
F32 seconds = ms/1000.f;
|
||||
|
||||
F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f;
|
||||
F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0);
|
||||
tris_sec /= seconds;
|
||||
|
||||
F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f;
|
||||
F32 samples_sec = (F32) mSamplesDrawn/1000000000.0;
|
||||
samples_sec /= seconds;
|
||||
|
||||
F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f;
|
||||
U32 avg_batch = mTrianglesDrawn/mDrawCalls;
|
||||
|
||||
LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL;
|
||||
LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL;
|
||||
LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL;
|
||||
LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLGLSLShader::startProfile()
|
||||
{
|
||||
if (sProfileEnabled && sCurBoundShaderPtr)
|
||||
{
|
||||
sCurBoundShaderPtr->placeProfileQuery();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//static
|
||||
void LLGLSLShader::stopProfile(U32 count, U32 mode)
|
||||
{
|
||||
if (sProfileEnabled && sCurBoundShaderPtr)
|
||||
{
|
||||
sCurBoundShaderPtr->readProfileQuery(count, mode);
|
||||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::placeProfileQuery()
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
if (mTimerQuery == 0)
|
||||
{
|
||||
glGenQueriesARB(1, &mSamplesQuery);
|
||||
glGenQueriesARB(1, &mTimerQuery);
|
||||
}
|
||||
|
||||
if (!mTextureStateFetched)
|
||||
{
|
||||
mTextureStateFetched = true;
|
||||
mTextureMagFilter.resize(mTexture.size());
|
||||
mTextureMinFilter.resize(mTexture.size());
|
||||
|
||||
U32 cur_active = gGL.getCurrentTexUnitIndex();
|
||||
|
||||
for (U32 i = 0; i < mTexture.size(); ++i)
|
||||
{
|
||||
GLint idx = mTexture[i];
|
||||
|
||||
if (idx >= 0)
|
||||
{
|
||||
gGL.getTexUnit(idx)->activate();
|
||||
|
||||
U32 mag = 0xFFFFFFFF;
|
||||
U32 min = 0xFFFFFFFF;
|
||||
|
||||
U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType());
|
||||
|
||||
glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag);
|
||||
glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min);
|
||||
|
||||
mTextureMagFilter[i] = mag;
|
||||
mTextureMinFilter[i] = min;
|
||||
}
|
||||
}
|
||||
|
||||
gGL.getTexUnit(cur_active)->activate();
|
||||
}
|
||||
|
||||
|
||||
glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery);
|
||||
glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLGLSLShader::readProfileQuery(U32 count, U32 mode)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
glEndQueryARB(GL_TIME_ELAPSED);
|
||||
glEndQueryARB(GL_SAMPLES_PASSED);
|
||||
|
||||
GLuint64 time_elapsed = 0;
|
||||
glGetQueryObjectui64vEXT(mTimerQuery, GL_QUERY_RESULT, &time_elapsed);
|
||||
|
||||
GLuint64 samples_passed = 0;
|
||||
glGetQueryObjectui64vEXT(mSamplesQuery, GL_QUERY_RESULT, &samples_passed);
|
||||
|
||||
sTotalTimeElapsed += time_elapsed;
|
||||
mTimeElapsed += time_elapsed;
|
||||
|
||||
sTotalSamplesDrawn += samples_passed;
|
||||
mSamplesDrawn += samples_passed;
|
||||
|
||||
U32 tri_count = 0;
|
||||
switch (mode)
|
||||
{
|
||||
case LLRender::TRIANGLES: tri_count = count/3; break;
|
||||
case LLRender::TRIANGLE_FAN: tri_count = count-2; break;
|
||||
case LLRender::TRIANGLE_STRIP: tri_count = count-2; break;
|
||||
default: tri_count = count; break; //points lines etc just use primitive count
|
||||
}
|
||||
|
||||
mTrianglesDrawn += tri_count;
|
||||
sTotalTrianglesDrawn += tri_count;
|
||||
|
||||
sTotalDrawCalls++;
|
||||
mDrawCalls++;
|
||||
#endif
|
||||
}
|
||||
LLGLSLShader::LLGLSLShader(S32 shader_class)
|
||||
: mProgramObject(0),
|
||||
mShaderClass(shader_class),
|
||||
@@ -91,20 +310,25 @@ LLGLSLShader::LLGLSLShader(S32 shader_class)
|
||||
mTotalUniformSize(0),
|
||||
mActiveTextureChannels(0),
|
||||
mShaderLevel(0),
|
||||
mShaderGroup(SG_DEFAULT),
|
||||
mUniformsDirty(FALSE)
|
||||
mShaderGroup(SG_DEFAULT),
|
||||
mUniformsDirty(FALSE),
|
||||
mTimerQuery(0),
|
||||
mSamplesQuery(0)
|
||||
|
||||
{
|
||||
LLShaderMgr::getGlobalShaderList().push_back(this);
|
||||
}
|
||||
|
||||
LLGLSLShader::~LLGLSLShader()
|
||||
{
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
void LLGLSLShader::unload()
|
||||
{
|
||||
stop_glerror();
|
||||
mAttribute.clear();
|
||||
sInstances.erase(this);
|
||||
|
||||
stop_glerror();
|
||||
mAttribute.clear();
|
||||
mTexture.clear();
|
||||
mUniform.clear();
|
||||
mShaderFiles.clear();
|
||||
@@ -126,10 +350,22 @@ void LLGLSLShader::unload()
|
||||
glDeleteObjectARB(mProgramObject);
|
||||
mProgramObject = 0;
|
||||
}
|
||||
|
||||
//hack to make apple not complain
|
||||
glGetError();
|
||||
|
||||
|
||||
if (mTimerQuery)
|
||||
{
|
||||
glDeleteQueriesARB(1, &mTimerQuery);
|
||||
mTimerQuery = 0;
|
||||
}
|
||||
|
||||
if (mSamplesQuery)
|
||||
{
|
||||
glDeleteQueriesARB(1, &mSamplesQuery);
|
||||
mSamplesQuery = 0;
|
||||
}
|
||||
|
||||
//hack to make apple not complain
|
||||
glGetError();
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
@@ -138,9 +374,11 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
|
||||
U32 varying_count,
|
||||
const char** varyings)
|
||||
{
|
||||
//reloading, reset matrix hash values
|
||||
for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i)
|
||||
{
|
||||
sInstances.insert(this);
|
||||
|
||||
//reloading, reset matrix hash values
|
||||
for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i)
|
||||
{
|
||||
mMatHash[i] = 0xFFFFFFFF;
|
||||
}
|
||||
mLightHash = 0xFFFFFFFF;
|
||||
@@ -243,9 +481,18 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
|
||||
}
|
||||
}
|
||||
unbind();
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
if (LLShaderMgr::instance()->mProgramObjects.find(mName) == LLShaderMgr::instance()->mProgramObjects.end())
|
||||
{
|
||||
LLShaderMgr::instance()->mProgramObjects.emplace(mName, mProgramObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ShaderLoading") << "Attempting to create shader program with duplicate name: " << mName << LL_ENDL;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLGLSLShader::attachObject(std::string object)
|
||||
@@ -425,6 +672,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
|
||||
}
|
||||
|
||||
LLStaticHashedString hashedName(name);
|
||||
mUniformNameMap[location] = name;
|
||||
mUniformMap[hashedName] = location;
|
||||
|
||||
LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
|
||||
@@ -489,6 +737,7 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
|
||||
mActiveTextureChannels = 0;
|
||||
mUniform.clear();
|
||||
mUniformMap.clear();
|
||||
mUniformNameMap.clear();
|
||||
mTexture.clear();
|
||||
mValueVec4.clear();
|
||||
mValueMat3.clear();
|
||||
|
||||
@@ -56,6 +56,7 @@ public:
|
||||
S32 mIndexedTextureChannels;
|
||||
bool disableTextureIndex;
|
||||
bool hasAlphaMask;
|
||||
bool attachNothing;
|
||||
|
||||
// char numLights;
|
||||
|
||||
@@ -73,6 +74,9 @@ public:
|
||||
SG_WATER
|
||||
};
|
||||
|
||||
static std::set<LLGLSLShader*> sInstances;
|
||||
static bool sProfileEnabled;
|
||||
|
||||
LLGLSLShader(S32 shader_class);
|
||||
~LLGLSLShader();
|
||||
|
||||
@@ -81,7 +85,18 @@ public:
|
||||
static S32 sIndexedTextureChannels;
|
||||
static bool sNoFixedFunction;
|
||||
|
||||
static void initProfile();
|
||||
static void finishProfile(bool emit_report = true);
|
||||
|
||||
static void startProfile();
|
||||
static void stopProfile(U32 count, U32 mode);
|
||||
|
||||
void unload();
|
||||
void clearStats();
|
||||
void dumpStats();
|
||||
void placeProfileQuery();
|
||||
void readProfileQuery(U32 count, U32 mode);
|
||||
|
||||
BOOL createShader(std::vector<LLStaticHashedString> * attributes,
|
||||
std::vector<LLStaticHashedString> * uniforms,
|
||||
U32 varying_count = 0,
|
||||
@@ -379,6 +394,7 @@ public:
|
||||
U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
|
||||
std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
|
||||
LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
|
||||
std::map<GLint, std::string> mUniformNameMap; //lookup map of uniform location to uniform name
|
||||
//There are less naive ways to do this than just having several vectors for the differing types, but this method is of least complexity and has some inherent type-safety.
|
||||
std::vector<std::pair<GLint, LLVector4> > mValueVec4; //lookup map of uniform location to last known value
|
||||
std::vector<std::pair<GLint, LLMatrix3> > mValueMat3; //lookup map of uniform location to last known value
|
||||
@@ -395,6 +411,23 @@ public:
|
||||
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
|
||||
std::string mName;
|
||||
std::map<std::string, std::string> mDefines;
|
||||
|
||||
//statistcis for profiling shader performance
|
||||
U32 mTimerQuery;
|
||||
U32 mSamplesQuery;
|
||||
U64 mTimeElapsed;
|
||||
static U64 sTotalTimeElapsed;
|
||||
U32 mTrianglesDrawn;
|
||||
static U32 sTotalTrianglesDrawn;
|
||||
U64 mSamplesDrawn;
|
||||
static U64 sTotalSamplesDrawn;
|
||||
U32 mDrawCalls;
|
||||
static U32 sTotalDrawCalls;
|
||||
|
||||
bool mTextureStateFetched;
|
||||
std::vector<U32> mTextureMagFilter;
|
||||
std::vector<U32> mTextureMinFilter;
|
||||
|
||||
};
|
||||
|
||||
//UI shader (declared here so llui_libtest will link properly)
|
||||
|
||||
@@ -2204,26 +2204,10 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
|
||||
U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
|
||||
{
|
||||
if(!mNeedsAlphaAndPickMask)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
delete [] mPickMask;
|
||||
mPickMask = NULL;
|
||||
mPickMaskWidth = mPickMaskHeight = 0;
|
||||
|
||||
if (mFormatType != GL_UNSIGNED_BYTE ||
|
||||
mFormatPrimary != GL_RGBA)
|
||||
{
|
||||
//cannot generate a pick mask for this texture
|
||||
return;
|
||||
}
|
||||
|
||||
U32 pick_width = width/2 + 1;
|
||||
U32 pick_height = height/2 + 1;
|
||||
U32 pick_width = pWidth/2 + 1;
|
||||
U32 pick_height = pHeight/2 + 1;
|
||||
|
||||
U32 size = pick_width * pick_height;
|
||||
size = (size + 7) / 8; // pixelcount-to-bits
|
||||
@@ -2233,6 +2217,44 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
|
||||
|
||||
memset(mPickMask, 0, sizeof(U8) * size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void LLImageGL::freePickMask()
|
||||
{
|
||||
// pickmask validity depends on old image size, delete it
|
||||
if (mPickMask != NULL)
|
||||
{
|
||||
delete [] mPickMask;
|
||||
}
|
||||
mPickMask = NULL;
|
||||
mPickMaskWidth = mPickMaskHeight = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
|
||||
{
|
||||
if(!mNeedsAlphaAndPickMask)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
freePickMask();
|
||||
|
||||
if (mFormatType != GL_UNSIGNED_BYTE ||
|
||||
mFormatPrimary != GL_RGBA)
|
||||
{
|
||||
//cannot generate a pick mask for this texture
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
const U32 pickSize = createPickMask(width, height);
|
||||
#else // SHOW_ASSERT
|
||||
createPickMask(width, height);
|
||||
#endif // SHOW_ASSERT
|
||||
|
||||
U32 pick_bit = 0;
|
||||
|
||||
for (S32 y = 0; y < height; y += 2)
|
||||
@@ -2245,7 +2267,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
|
||||
{
|
||||
U32 pick_idx = pick_bit/8;
|
||||
U32 pick_offset = pick_bit%8;
|
||||
llassert(pick_idx < size);
|
||||
llassert(pick_idx < pickSize);
|
||||
|
||||
mPickMask[pick_idx] |= 1 << pick_offset;
|
||||
}
|
||||
|
||||
@@ -177,6 +177,9 @@ public:
|
||||
mutable F32 mLastBindTime; // last time this was bound, by discard level
|
||||
|
||||
private:
|
||||
U32 createPickMask(S32 pWidth, S32 pHeight);
|
||||
void freePickMask();
|
||||
|
||||
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
|
||||
S32 mSaveDiscardLevel;
|
||||
U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
|
||||
|
||||
@@ -56,7 +56,7 @@ bool LLRender::sGLCoreProfile = false;
|
||||
static const U32 LL_NUM_TEXTURE_LAYERS = 32;
|
||||
static const U32 LL_NUM_LIGHT_UNITS = 8;
|
||||
|
||||
static GLenum sGLTextureType[] =
|
||||
static const GLenum sGLTextureType[] =
|
||||
{
|
||||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE_RECTANGLE_ARB,
|
||||
@@ -64,14 +64,14 @@ static GLenum sGLTextureType[] =
|
||||
//,GL_TEXTURE_2D_MULTISAMPLE Don't use.
|
||||
};
|
||||
|
||||
static GLint sGLAddressMode[] =
|
||||
static const GLint sGLAddressMode[] =
|
||||
{
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_CLAMP_TO_EDGE
|
||||
};
|
||||
|
||||
static GLenum sGLCompareFunc[] =
|
||||
static const GLenum sGLCompareFunc[] =
|
||||
{
|
||||
GL_NEVER,
|
||||
GL_ALWAYS,
|
||||
@@ -85,7 +85,7 @@ static GLenum sGLCompareFunc[] =
|
||||
|
||||
const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0;
|
||||
|
||||
static GLenum sGLBlendFactor[] =
|
||||
static const GLenum sGLBlendFactor[] =
|
||||
{
|
||||
GL_ONE,
|
||||
GL_ZERO,
|
||||
@@ -102,15 +102,15 @@ static GLenum sGLBlendFactor[] =
|
||||
};
|
||||
|
||||
LLTexUnit::LLTexUnit(S32 index)
|
||||
: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT),
|
||||
mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
|
||||
mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
|
||||
mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
|
||||
mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0),
|
||||
mHasMipMaps(false)
|
||||
: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT),
|
||||
mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
|
||||
mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
|
||||
mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
|
||||
mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0),
|
||||
mHasMipMaps(false),
|
||||
mIndex(index)
|
||||
{
|
||||
llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS);
|
||||
mIndex = index;
|
||||
}
|
||||
|
||||
//static
|
||||
@@ -228,53 +228,66 @@ void LLTexUnit::disable(void)
|
||||
bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
|
||||
{
|
||||
stop_glerror();
|
||||
if (mIndex < 0) return false;
|
||||
|
||||
LLImageGL* gl_tex = NULL ;
|
||||
if (texture == NULL || !(gl_tex = texture->getGLTexture()))
|
||||
if (mIndex >= 0)
|
||||
{
|
||||
LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
|
||||
gGL.flush();
|
||||
|
||||
LLImageGL* gl_tex = NULL ;
|
||||
|
||||
if (texture != NULL && (gl_tex = texture->getGLTexture()))
|
||||
{
|
||||
if (gl_tex->getTexName()) //if texture exists
|
||||
{
|
||||
//in audit, replace the selected texture by the default one.
|
||||
if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0)
|
||||
{
|
||||
if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize)
|
||||
{
|
||||
gl_tex->updateBindStats(gl_tex->mTextureMemory);
|
||||
return bind(LLImageGL::sHighlightTexturep.get());
|
||||
}
|
||||
}
|
||||
if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
|
||||
{
|
||||
gGL.flush();
|
||||
activate();
|
||||
enable(gl_tex->getTarget());
|
||||
mCurrTexture = gl_tex->getTexName();
|
||||
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
|
||||
if(gl_tex->updateBindStats(gl_tex->mTextureMemory))
|
||||
{
|
||||
texture->setActive() ;
|
||||
texture->updateBindStatsForTester() ;
|
||||
}
|
||||
mHasMipMaps = gl_tex->mHasMipMaps;
|
||||
if (gl_tex->mTexOptionsDirty)
|
||||
{
|
||||
gl_tex->mTexOptionsDirty = false;
|
||||
setTextureAddressMode(gl_tex->mAddressMode);
|
||||
setTextureFilteringOption(gl_tex->mFilterOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if deleted, will re-generate it immediately
|
||||
texture->forceImmediateUpdate() ;
|
||||
|
||||
gl_tex->forceUpdateBindStats() ;
|
||||
return texture->bindDefaultImage(mIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // mIndex < 0
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gl_tex->getTexName()) //if texture does not exist
|
||||
{
|
||||
//if deleted, will re-generate it immediately
|
||||
texture->forceImmediateUpdate() ;
|
||||
|
||||
gl_tex->forceUpdateBindStats() ;
|
||||
return texture->bindDefaultImage(mIndex);
|
||||
}
|
||||
|
||||
//in audit, replace the selected texture by the default one.
|
||||
if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0)
|
||||
{
|
||||
if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize)
|
||||
{
|
||||
gl_tex->updateBindStats(gl_tex->mTextureMemory);
|
||||
return bind(LLImageGL::sHighlightTexturep.get());
|
||||
}
|
||||
}
|
||||
if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
|
||||
{
|
||||
gGL.flush();
|
||||
activate();
|
||||
enable(gl_tex->getTarget());
|
||||
mCurrTexture = gl_tex->getTexName();
|
||||
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
|
||||
if(gl_tex->updateBindStats(gl_tex->mTextureMemory))
|
||||
{
|
||||
texture->setActive() ;
|
||||
texture->updateBindStatsForTester() ;
|
||||
}
|
||||
mHasMipMaps = gl_tex->mHasMipMaps;
|
||||
if (gl_tex->mTexOptionsDirty)
|
||||
{
|
||||
gl_tex->mTexOptionsDirty = false;
|
||||
setTextureAddressMode(gl_tex->mAddressMode);
|
||||
setTextureFilteringOption(gl_tex->mFilterOption);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1763,7 +1776,7 @@ void LLRender::pushUIMatrix()
|
||||
{
|
||||
if (mUIOffset.empty())
|
||||
{
|
||||
mUIOffset.push_back(LLVector4a(0.f));
|
||||
mUIOffset.emplace_back(LLVector4a(0.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1772,7 +1785,7 @@ void LLRender::pushUIMatrix()
|
||||
|
||||
if (mUIScale.empty())
|
||||
{
|
||||
mUIScale.push_back(LLVector4a(1.f));
|
||||
mUIScale.emplace_back(LLVector4a(1.f));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1782,9 +1795,9 @@ void LLRender::pushUIMatrix()
|
||||
|
||||
void LLRender::popUIMatrix()
|
||||
{
|
||||
if (mUIOffset.empty())
|
||||
if (mUIOffset.empty() || mUIScale.empty())
|
||||
{
|
||||
LL_ERRS() << "UI offset stack blown." << LL_ENDL;
|
||||
LL_ERRS() << "UI offset or scale stack blown." << LL_ENDL;
|
||||
}
|
||||
mUIOffset.pop_back();
|
||||
mUIScale.pop_back();
|
||||
|
||||
@@ -38,12 +38,13 @@
|
||||
#include "v3math.h"
|
||||
#include "v4coloru.h"
|
||||
#include "v4math.h"
|
||||
#include "llmatrix4a.h"
|
||||
#include "llalignedarray.h"
|
||||
#include "llstrider.h"
|
||||
#include "llpointer.h"
|
||||
#include "llglheaders.h"
|
||||
#include "llmatrix4a.h"
|
||||
#include "llrect.h"
|
||||
#include "llvector4a.h"
|
||||
#include <boost/align/aligned_allocator.hpp>
|
||||
|
||||
class LLVertexBuffer;
|
||||
class LLCubeMap;
|
||||
@@ -200,7 +201,7 @@ public:
|
||||
void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; }
|
||||
|
||||
protected:
|
||||
S32 mIndex;
|
||||
const S32 mIndex;
|
||||
U32 mCurrTexture;
|
||||
eTextureType mCurrTexType;
|
||||
eTextureBlendType mCurrBlendType;
|
||||
@@ -493,8 +494,8 @@ private:
|
||||
|
||||
F32 mMaxAnisotropy;
|
||||
|
||||
LLAlignedArray<LLVector4a, 64> mUIOffset;
|
||||
LLAlignedArray<LLVector4a, 64> mUIScale;
|
||||
std::vector<LLVector4a, boost::alignment::aligned_allocator<LLVector4a, 64> > mUIOffset;
|
||||
std::vector<LLVector4a, boost::alignment::aligned_allocator<LLVector4a, 64> > mUIScale;
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
|
||||
|
||||
@@ -348,6 +348,11 @@ void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const
|
||||
gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
|
||||
}
|
||||
|
||||
void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color, const LLRectf& uv_rect)
|
||||
{
|
||||
gl_draw_scaled_rotated_image(x, y, width, height, 0.f, NULL, color, uv_rect, target);
|
||||
}
|
||||
|
||||
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
|
||||
{
|
||||
if (NULL == image)
|
||||
@@ -358,7 +363,7 @@ void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image,
|
||||
gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
|
||||
}
|
||||
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, bool scale_inner)
|
||||
{
|
||||
if (NULL == image)
|
||||
{
|
||||
@@ -371,10 +376,10 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
|
||||
F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
|
||||
|
||||
LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
|
||||
gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
|
||||
gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect, scale_inner);
|
||||
}
|
||||
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect)
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect, bool scale_inner)
|
||||
{
|
||||
stop_glerror();
|
||||
|
||||
@@ -384,56 +389,6 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
|
||||
return;
|
||||
}
|
||||
|
||||
// add in offset of current image to current UI translation
|
||||
const LLVector3 ui_scale = gGL.getUIScale();
|
||||
const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
|
||||
|
||||
F32 uv_width = uv_outer_rect.getWidth();
|
||||
F32 uv_height = uv_outer_rect.getHeight();
|
||||
|
||||
// shrink scaling region to be proportional to clipped image region
|
||||
LLRectf uv_center_rect(
|
||||
uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
|
||||
uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
|
||||
uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
|
||||
uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
|
||||
|
||||
F32 image_width = image->getWidth(0);
|
||||
F32 image_height = image->getHeight(0);
|
||||
|
||||
S32 image_natural_width = ll_round(image_width * uv_width);
|
||||
S32 image_natural_height = ll_round(image_height * uv_height);
|
||||
|
||||
LLRectf draw_center_rect( uv_center_rect.mLeft * image_width,
|
||||
uv_center_rect.mTop * image_height,
|
||||
uv_center_rect.mRight * image_width,
|
||||
uv_center_rect.mBottom * image_height);
|
||||
|
||||
{ // scale fixed region of image to drawn region
|
||||
draw_center_rect.mRight += width - image_natural_width;
|
||||
draw_center_rect.mTop += height - image_natural_height;
|
||||
|
||||
F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
|
||||
F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
|
||||
|
||||
F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
|
||||
F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
|
||||
|
||||
F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
|
||||
|
||||
draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]);
|
||||
draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]);
|
||||
draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]);
|
||||
draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]);
|
||||
}
|
||||
|
||||
LLRectf draw_outer_rect(ui_translation.mV[VX],
|
||||
ui_translation.mV[VY] + height * ui_scale.mV[VY],
|
||||
ui_translation.mV[VX] + width * ui_scale.mV[VX],
|
||||
ui_translation.mV[VY]);
|
||||
|
||||
LLGLSUIDefault gls_ui;
|
||||
|
||||
if (solid_color)
|
||||
{
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
@@ -447,7 +402,79 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
|
||||
}
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->bind(image, true);
|
||||
if (center_rect.mLeft == 0.f
|
||||
&& center_rect.mRight == 1.f
|
||||
&& center_rect.mBottom == 0.f
|
||||
&& center_rect.mTop == 1.f)
|
||||
{
|
||||
gl_draw_scaled_image(x, y, width, height, image, color, uv_outer_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add in offset of current image to current UI translation
|
||||
const LLVector3 ui_scale = gGL.getUIScale();
|
||||
const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
|
||||
|
||||
F32 uv_width = uv_outer_rect.getWidth();
|
||||
F32 uv_height = uv_outer_rect.getHeight();
|
||||
|
||||
// shrink scaling region to be proportional to clipped image region
|
||||
LLRectf uv_center_rect( uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
|
||||
uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
|
||||
uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
|
||||
uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
|
||||
|
||||
F32 image_width = image->getWidth(0);
|
||||
F32 image_height = image->getHeight(0);
|
||||
|
||||
S32 image_natural_width = ll_round(image_width * uv_width);
|
||||
S32 image_natural_height = ll_round(image_height * uv_height);
|
||||
|
||||
LLRectf draw_center_rect( uv_center_rect.mLeft * image_width,
|
||||
uv_center_rect.mTop * image_height,
|
||||
uv_center_rect.mRight * image_width,
|
||||
uv_center_rect.mBottom * image_height);
|
||||
|
||||
if (scale_inner)
|
||||
{
|
||||
// scale center region of image to drawn region
|
||||
draw_center_rect.mRight += width - image_natural_width;
|
||||
draw_center_rect.mTop += height - image_natural_height;
|
||||
|
||||
const F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
|
||||
const F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
|
||||
|
||||
const F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
|
||||
const F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
|
||||
|
||||
const F32 border_shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
|
||||
draw_center_rect.mLeft *= border_shrink_scale;
|
||||
draw_center_rect.mTop = lerp((F32)height, (F32)draw_center_rect.mTop, border_shrink_scale);
|
||||
draw_center_rect.mRight = lerp((F32)width, (F32)draw_center_rect.mRight, border_shrink_scale);
|
||||
draw_center_rect.mBottom *= border_shrink_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep center region of image at fixed scale, but in same relative position
|
||||
F32 scale_factor = llmin((F32)width / draw_center_rect.getWidth(), (F32)height / draw_center_rect.getHeight(), 1.f);
|
||||
F32 scaled_width = draw_center_rect.getWidth() * scale_factor;
|
||||
F32 scaled_height = draw_center_rect.getHeight() * scale_factor;
|
||||
draw_center_rect.setCenterAndSize(uv_center_rect.getCenterX() * width, uv_center_rect.getCenterY() * height, scaled_width, scaled_height);
|
||||
}
|
||||
|
||||
draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * ui_scale.mV[VX]);
|
||||
draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mTop * ui_scale.mV[VY]);
|
||||
draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mRight * ui_scale.mV[VX]);
|
||||
draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * ui_scale.mV[VY]);
|
||||
|
||||
LLRectf draw_outer_rect(ui_translation.mV[VX],
|
||||
ui_translation.mV[VY] + height * ui_scale.mV[VY],
|
||||
ui_translation.mV[VX] + width * ui_scale.mV[VX],
|
||||
ui_translation.mV[VY]);
|
||||
|
||||
LLGLSUIDefault gls_ui;
|
||||
|
||||
gGL.getTexUnit(0)->bind(image, true);
|
||||
|
||||
gGL.color4fv(color.mV);
|
||||
gGL.diffuseColor4fv(color.mV); //workaround: Intel HD 4000
|
||||
@@ -611,11 +638,12 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
|
||||
|
||||
uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
|
||||
pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
|
||||
index++;
|
||||
index++;
|
||||
|
||||
gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
|
||||
gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
gGL.end();
|
||||
|
||||
if (solid_color)
|
||||
{
|
||||
@@ -635,9 +663,9 @@ void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LL
|
||||
gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
|
||||
}
|
||||
|
||||
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
|
||||
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect, LLRenderTarget* target)
|
||||
{
|
||||
if (NULL == image)
|
||||
if (!image && !target)
|
||||
{
|
||||
LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
|
||||
return;
|
||||
@@ -645,8 +673,14 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
|
||||
|
||||
LLGLSUIDefault gls_ui;
|
||||
|
||||
|
||||
gGL.getTexUnit(0)->bind(image, true);
|
||||
if(image != NULL)
|
||||
{
|
||||
gGL.getTexUnit(0)->bind(image, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->bind(target);
|
||||
}
|
||||
|
||||
gGL.color4fv(color.mV);
|
||||
|
||||
@@ -698,11 +732,18 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
|
||||
gGL.translateUI(offset_x, offset_y, 0.f);
|
||||
|
||||
LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
|
||||
|
||||
gGL.getTexUnit(0)->bind(image, true);
|
||||
|
||||
if(image != NULL)
|
||||
{
|
||||
gGL.getTexUnit(0)->bind(image, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->bind(target);
|
||||
}
|
||||
|
||||
gGL.color4fv(color.mV);
|
||||
|
||||
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
LLVector3 v;
|
||||
@@ -1202,18 +1243,18 @@ void gl_segmented_rect_2d_tex(const S32 left,
|
||||
gGL.popUIMatrix();
|
||||
}
|
||||
|
||||
//FIXME: rewrite to use scissor?
|
||||
void gl_segmented_rect_2d_fragment_tex(const S32 left,
|
||||
const S32 top,
|
||||
const S32 right,
|
||||
const S32 bottom,
|
||||
const S32 texture_width,
|
||||
const S32 texture_height,
|
||||
const S32 border_size,
|
||||
const F32 start_fragment,
|
||||
const F32 end_fragment,
|
||||
const U32 edges)
|
||||
void gl_segmented_rect_2d_fragment_tex(const LLRect& rect,
|
||||
const S32 texture_width,
|
||||
const S32 texture_height,
|
||||
const S32 border_size,
|
||||
const F32 start_fragment,
|
||||
const F32 end_fragment,
|
||||
const U32 edges)
|
||||
{
|
||||
const S32 left = rect.mLeft;
|
||||
const S32 right = rect.mRight;
|
||||
const S32 top = rect.mTop;
|
||||
const S32 bottom = rect.mBottom;
|
||||
S32 width = llabs(right - left);
|
||||
S32 height = llabs(top - bottom);
|
||||
|
||||
@@ -1343,10 +1384,10 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,
|
||||
|
||||
if (end_fragment > middle_end)
|
||||
{
|
||||
u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX];
|
||||
u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX];
|
||||
x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right);
|
||||
x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
|
||||
u_min = 1.f - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]);
|
||||
u_max = 1.f - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]);
|
||||
x_min = width_vec - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_width_right);
|
||||
x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
|
||||
|
||||
// draw bottom right
|
||||
gGL.texCoord2f(u_min, 0.f);
|
||||
@@ -1393,145 +1434,132 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,
|
||||
gGL.popUIMatrix();
|
||||
}
|
||||
|
||||
void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width,
|
||||
const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec,
|
||||
const U32 edges)
|
||||
void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect,
|
||||
const LLVector3& width_vec, const LLVector3& height_vec)
|
||||
{
|
||||
LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero;
|
||||
LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero;
|
||||
|
||||
LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero;
|
||||
LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero;
|
||||
|
||||
|
||||
gGL.begin(LLRender::QUADS);
|
||||
{
|
||||
// draw bottom left
|
||||
gGL.texCoord2f(0.f, 0.f);
|
||||
gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);
|
||||
gGL.vertex3f(0.f, 0.f, 0.f);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], 0.f);
|
||||
gGL.vertex3fv(left_border_width.mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(0.f, border_scale.mV[VY]);
|
||||
gGL.vertex3fv(bottom_border_height.mV);
|
||||
gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
// draw bottom middle
|
||||
gGL.texCoord2f(border_scale.mV[VX], 0.f);
|
||||
gGL.vertex3fv(left_border_width.mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f);
|
||||
gGL.vertex3fv((width_vec - right_border_width).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
// draw bottom right
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f);
|
||||
gGL.vertex3fv((width_vec - right_border_width).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f, 0.f);
|
||||
gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);
|
||||
gGL.vertex3fv(width_vec.mV);
|
||||
|
||||
gGL.texCoord2f(1.f, border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec + bottom_border_height).mV);
|
||||
gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
// draw left
|
||||
gGL.texCoord2f(0.f, border_scale.mV[VY]);
|
||||
gGL.vertex3fv(bottom_border_height.mV);
|
||||
gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
// draw middle
|
||||
gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
// draw right
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f, border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec + bottom_border_height).mV);
|
||||
gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
|
||||
gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
// draw top left
|
||||
gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], 1.f);
|
||||
gGL.vertex3fv((left_border_width + height_vec).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(0.f, 1.f);
|
||||
gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);
|
||||
gGL.vertex3fv((height_vec).mV);
|
||||
|
||||
// draw top middle
|
||||
gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f);
|
||||
gGL.vertex3fv((width_vec - right_border_width + height_vec).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(border_scale.mV[VX], 1.f);
|
||||
gGL.vertex3fv((left_border_width + height_vec).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
|
||||
|
||||
// draw top right
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]);
|
||||
gGL.vertex3fv((width_vec + height_vec - top_border_height).mV);
|
||||
gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
|
||||
gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f, 1.f);
|
||||
gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);
|
||||
gGL.vertex3fv((width_vec + height_vec).mV);
|
||||
|
||||
gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f);
|
||||
gGL.vertex3fv((width_vec - right_border_width + height_vec).mV);
|
||||
gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
|
||||
gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
|
||||
}
|
||||
gGL.end();
|
||||
|
||||
}
|
||||
|
||||
void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec)
|
||||
{
|
||||
gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP);
|
||||
}
|
||||
|
||||
// static
|
||||
void LLRender2D::initClass(LLImageProviderInterface* image_provider,
|
||||
const LLVector2* scale_factor)
|
||||
|
||||
@@ -71,11 +71,12 @@ void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4&
|
||||
void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
|
||||
void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color);
|
||||
void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
|
||||
void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
|
||||
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
|
||||
void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
|
||||
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
|
||||
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), LLRenderTarget* target = NULL);
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
|
||||
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
|
||||
|
||||
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
|
||||
|
||||
@@ -105,9 +106,8 @@ typedef enum e_rounded_edge
|
||||
|
||||
|
||||
void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);
|
||||
void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
|
||||
void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL);
|
||||
void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec);
|
||||
void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
|
||||
void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);
|
||||
|
||||
inline void gl_rect_2d( const LLRect& rect, BOOL filled )
|
||||
{
|
||||
|
||||
@@ -80,7 +80,11 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
||||
{
|
||||
llassert_always(shader != NULL);
|
||||
LLShaderFeatures *features = & shader->mFeatures;
|
||||
|
||||
|
||||
if (features->attachNothing)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
//////////////////////////////////////
|
||||
// Attach Vertex Shader Features First
|
||||
//////////////////////////////////////
|
||||
@@ -640,11 +644,14 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
// before any non-preprocessor directives (per spec)
|
||||
text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n");
|
||||
text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n");
|
||||
|
||||
|
||||
if (minor_version == 50 && gGLManager.mHasGpuShader5)
|
||||
{
|
||||
text[count++] = strdup("#extension GL_ARB_gpu_shader5 : enable\n");
|
||||
}
|
||||
//some implementations of GLSL 1.30 require integer precision be explicitly declared
|
||||
text[count++] = strdup("precision mediump int;\n");
|
||||
text[count++] = strdup("precision highp float;\n");
|
||||
text[count++] = strdup("#define FXAA_GLSL_130 1\n");
|
||||
}
|
||||
else
|
||||
{ //set version to 400
|
||||
@@ -653,11 +660,11 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
// before any non-preprocessor directives (per spec)
|
||||
text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n");
|
||||
text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n");
|
||||
text[count++] = strdup("#define FXAA_GLSL_400 1\n");
|
||||
}
|
||||
|
||||
|
||||
text[count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n");
|
||||
text[count++] = strdup("#define FXAA_GLSL_130 1\n");
|
||||
|
||||
text[count++] = strdup("#define ATTRIBUTE in\n");
|
||||
|
||||
@@ -875,8 +882,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
{ //dump every 128 lines
|
||||
|
||||
LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL;
|
||||
ostr.clear();
|
||||
ostr.str(LLStringUtil::null);
|
||||
ostr = std::stringstream();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -943,6 +949,63 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLShaderMgr::unloadShaders()
|
||||
{
|
||||
//Instead of manually unloading, shaders are now automatically accumulated in a list.
|
||||
//Simply iterate and unload.
|
||||
std::vector<LLGLSLShader *> &shader_list = LLShaderMgr::getGlobalShaderList();
|
||||
for (std::vector<LLGLSLShader *>::iterator it = shader_list.begin(); it != shader_list.end(); ++it)
|
||||
(*it)->unload();
|
||||
mShaderObjects.clear();
|
||||
mProgramObjects.clear();
|
||||
}
|
||||
|
||||
void LLShaderMgr::unloadShaderObjects()
|
||||
{
|
||||
std::multimap<std::string, LLShaderMgr::CachedObjectInfo >::iterator it = mShaderObjects.begin();
|
||||
for (; it != mShaderObjects.end(); ++it)
|
||||
if (it->second.mHandle)
|
||||
glDeleteObjectARB(it->second.mHandle);
|
||||
mShaderObjects.clear();
|
||||
cleanupShaderSources();
|
||||
}
|
||||
|
||||
void LLShaderMgr::cleanupShaderSources()
|
||||
{
|
||||
if (!mProgramObjects.empty())
|
||||
{
|
||||
for (auto iter = mProgramObjects.cbegin(),
|
||||
iter_end = mProgramObjects.cend(); iter != iter_end; ++iter)
|
||||
{
|
||||
GLuint program = iter->second;
|
||||
if (program > 0)
|
||||
{
|
||||
GLhandleARB shaders[1024] = {};
|
||||
GLsizei count = -1;
|
||||
glGetAttachedObjectsARB(program, 1024, &count, shaders);
|
||||
if (count > 0)
|
||||
{
|
||||
for (GLsizei i = 0; i < count; ++i)
|
||||
{
|
||||
std::multimap<std::string, LLShaderMgr::CachedObjectInfo>::iterator it = mShaderObjects.begin();
|
||||
for (; it != LLShaderMgr::instance()->mShaderObjects.end(); it++)
|
||||
{
|
||||
if ((*it).second.mHandle == shaders[i])
|
||||
{
|
||||
glDetachObjectARB(program, shaders[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the linked program list as its no longer needed
|
||||
mProgramObjects.clear();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
|
||||
{
|
||||
//check for errors
|
||||
|
||||
@@ -232,6 +232,8 @@ DISPLAY_GAMMA,
|
||||
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
|
||||
BOOL validateProgramObject(GLhandleARB obj);
|
||||
GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
|
||||
void unloadShaders();
|
||||
void unloadShaderObjects();
|
||||
|
||||
// Implemented in the application to actually point to the shader directory.
|
||||
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
|
||||
@@ -252,6 +254,9 @@ public:
|
||||
// Map of shader names to compiled
|
||||
std::multimap<std::string, CachedObjectInfo > mShaderObjects; //Singu Note: Packing more info here. Doing such provides capability to skip unneeded duplicate loading..
|
||||
|
||||
// Map of program names linked
|
||||
std::map<std::string, GLuint> mProgramObjects;
|
||||
|
||||
//global (reserved slot) shader parameters
|
||||
std::vector<std::string> mReservedAttribs;
|
||||
|
||||
@@ -261,6 +266,7 @@ public:
|
||||
std::map<std::string, std::string> mDefinitions;
|
||||
|
||||
protected:
|
||||
void cleanupShaderSources();
|
||||
|
||||
// our parameter manager singleton instance
|
||||
static LLShaderMgr * sInstance;
|
||||
|
||||
@@ -38,11 +38,9 @@ LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
|
||||
mImage(image),
|
||||
mScaleRegion(0.f, 1.f, 1.f, 0.f),
|
||||
mClipRegion(0.f, 1.f, 1.f, 0.f),
|
||||
mUniformScaling(TRUE),
|
||||
mNoClip(TRUE),
|
||||
mImageLoaded(NULL)
|
||||
{
|
||||
}
|
||||
mImageLoaded(NULL),
|
||||
mScaleStyle(SCALE_INNER)
|
||||
{}
|
||||
|
||||
LLUIImage::~LLUIImage()
|
||||
{
|
||||
@@ -52,44 +50,35 @@ LLUIImage::~LLUIImage()
|
||||
void LLUIImage::setClipRegion(const LLRectf& region)
|
||||
{
|
||||
mClipRegion = region;
|
||||
mNoClip = mClipRegion.mLeft == 0.f
|
||||
&& mClipRegion.mRight == 1.f
|
||||
&& mClipRegion.mBottom == 0.f
|
||||
&& mClipRegion.mTop == 1.f;
|
||||
}
|
||||
|
||||
void LLUIImage::setScaleRegion(const LLRectf& region)
|
||||
{
|
||||
mScaleRegion = region;
|
||||
mUniformScaling = mScaleRegion.mLeft == 0.f
|
||||
&& mScaleRegion.mRight == 1.f
|
||||
&& mScaleRegion.mBottom == 0.f
|
||||
&& mScaleRegion.mTop == 1.f;
|
||||
}
|
||||
|
||||
void LLUIImage::setScaleStyle(LLUIImage::EScaleStyle style)
|
||||
{
|
||||
mScaleStyle = style;
|
||||
}
|
||||
|
||||
//TODO: move drawing implementation inside class
|
||||
void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
|
||||
{
|
||||
gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion);
|
||||
draw(x, y, getWidth(), getHeight(), color);
|
||||
}
|
||||
|
||||
void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
|
||||
{
|
||||
if (mUniformScaling)
|
||||
{
|
||||
gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_draw_scaled_image_with_border(
|
||||
x, y,
|
||||
width, height,
|
||||
mImage,
|
||||
color,
|
||||
FALSE,
|
||||
mClipRegion,
|
||||
mScaleRegion);
|
||||
}
|
||||
gl_draw_scaled_image_with_border(
|
||||
x, y,
|
||||
width, height,
|
||||
mImage,
|
||||
color,
|
||||
FALSE,
|
||||
mClipRegion,
|
||||
mScaleRegion,
|
||||
mScaleStyle == SCALE_INNER);
|
||||
}
|
||||
|
||||
void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
|
||||
@@ -101,7 +90,8 @@ void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& c
|
||||
color,
|
||||
TRUE,
|
||||
mClipRegion,
|
||||
mScaleRegion);
|
||||
mScaleRegion,
|
||||
mScaleStyle == SCALE_INNER);
|
||||
}
|
||||
|
||||
void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
|
||||
@@ -112,6 +102,50 @@ void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4&
|
||||
drawSolid(border_rect, color);
|
||||
}
|
||||
|
||||
void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis,
|
||||
const LLRect& rect, const LLColor4& color)
|
||||
{
|
||||
F32 border_scale = 1.f;
|
||||
F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight();
|
||||
F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth();
|
||||
if (rect.getHeight() < border_height || rect.getWidth() < border_width)
|
||||
{
|
||||
if(border_height - rect.getHeight() > border_width - rect.getWidth())
|
||||
{
|
||||
border_scale = (F32)rect.getHeight() / border_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
border_scale = (F32)rect.getWidth() / border_width;
|
||||
}
|
||||
}
|
||||
|
||||
LLRender2D::pushMatrix();
|
||||
{
|
||||
LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);
|
||||
LLRender2D::translate(rect_origin.mV[VX],
|
||||
rect_origin.mV[VY],
|
||||
rect_origin.mV[VZ]);
|
||||
gGL.getTexUnit(0)->bind(getImage());
|
||||
gGL.color4fv(color.mV);
|
||||
|
||||
LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(),
|
||||
mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(),
|
||||
mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(),
|
||||
mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight());
|
||||
gl_segmented_rect_3d_tex(mClipRegion,
|
||||
center_uv_rect,
|
||||
LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(),
|
||||
(rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(),
|
||||
(rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(),
|
||||
(border_height * border_scale * 0.5f) / (F32)rect.getHeight()),
|
||||
rect.getWidth() * x_axis,
|
||||
rect.getHeight() * y_axis);
|
||||
|
||||
} LLRender2D::popMatrix();
|
||||
}
|
||||
|
||||
|
||||
S32 LLUIImage::getWidth() const
|
||||
{
|
||||
// return clipped dimensions of actual image area
|
||||
|
||||
@@ -45,6 +45,12 @@ extern const LLColor4 UI_VERTEX_COLOR;
|
||||
class LLUIImage : public LLRefCount
|
||||
{
|
||||
public:
|
||||
enum EScaleStyle
|
||||
{
|
||||
SCALE_INNER,
|
||||
SCALE_OUTER
|
||||
};
|
||||
|
||||
typedef boost::signals2::signal<void (void)> image_loaded_signal_t;
|
||||
|
||||
LLUIImage(const std::string& name, LLPointer<LLTexture> image);
|
||||
@@ -52,6 +58,7 @@ public:
|
||||
|
||||
void setClipRegion(const LLRectf& region);
|
||||
void setScaleRegion(const LLRectf& region);
|
||||
void setScaleStyle(EScaleStyle style);
|
||||
|
||||
LLPointer<LLTexture> getImage() { return mImage; }
|
||||
const LLPointer<LLTexture>& getImage() const { return mImage; }
|
||||
@@ -67,7 +74,9 @@ public:
|
||||
void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
|
||||
void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
|
||||
void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
|
||||
|
||||
|
||||
void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color);
|
||||
|
||||
const std::string& getName() const { return mName; }
|
||||
|
||||
virtual S32 getWidth() const;
|
||||
@@ -84,12 +93,11 @@ public:
|
||||
protected:
|
||||
image_loaded_signal_t* mImageLoaded;
|
||||
|
||||
std::string mName;
|
||||
LLRectf mScaleRegion;
|
||||
LLRectf mClipRegion;
|
||||
LLPointer<LLTexture> mImage;
|
||||
BOOL mUniformScaling;
|
||||
BOOL mNoClip;
|
||||
std::string mName;
|
||||
LLRectf mScaleRegion;
|
||||
LLRectf mClipRegion;
|
||||
LLPointer<LLTexture> mImage;
|
||||
EScaleStyle mScaleStyle;
|
||||
};
|
||||
|
||||
namespace LLInitParam
|
||||
|
||||
Reference in New Issue
Block a user