summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2024-11-02 20:55:56 +0800
committerErik Kundiman <erik@megapahit.org>2024-11-03 19:33:18 +0800
commit3f72f9a202bed628f838cc24fe58a0511ca0d161 (patch)
tree0684cfff91551d9b6aabdb825981b46a5cb53fe8 /indra/llrender
parentd302bf3c96666cfd46d7585cb3d8b6ec27bb83bf (diff)
parent9c0a6d1b0e5e9d6da6a63ff367f40ab08c064bbe (diff)
Merge remote-tracking branch 'secondlife/release/maint-c' into maint-c
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/CMakeLists.txt4
-rw-r--r--indra/llrender/llatmosphere.cpp290
-rw-r--r--indra/llrender/llatmosphere.h173
-rw-r--r--indra/llrender/llfontfreetype.cpp201
-rw-r--r--indra/llrender/llfontfreetype.h23
-rw-r--r--indra/llrender/llfontgl.cpp8
-rw-r--r--indra/llrender/llfontgl.h2
-rw-r--r--indra/llrender/llfontvertexbuffer.cpp11
-rw-r--r--indra/llrender/llgl.cpp24
-rw-r--r--indra/llrender/llgl.h6
-rw-r--r--indra/llrender/llglslshader.cpp22
-rw-r--r--indra/llrender/llglslshader.h2
-rw-r--r--indra/llrender/llgltexture.cpp80
-rw-r--r--indra/llrender/llgltexture.h3
-rw-r--r--indra/llrender/llimagegl.cpp2
-rw-r--r--indra/llrender/llpostprocess.cpp466
-rw-r--r--indra/llrender/llpostprocess.h267
-rw-r--r--indra/llrender/llrender.cpp379
-rw-r--r--indra/llrender/llrender.h18
-rw-r--r--indra/llrender/llrender2dutils.cpp2
-rw-r--r--indra/llrender/llrendertarget.cpp9
-rw-r--r--indra/llrender/llrendertarget.h9
-rw-r--r--indra/llrender/llshadermgr.cpp14
-rw-r--r--indra/llrender/llshadermgr.h14
-rw-r--r--indra/llrender/llvertexbuffer.cpp24
-rw-r--r--indra/llrender/llvertexbuffer.h1
26 files changed, 520 insertions, 1534 deletions
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index d48b508ddc..6cd85daa6f 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -10,7 +10,6 @@ include(LLImage)
include(LLWindow)
set(llrender_SOURCE_FILES
- llatmosphere.cpp
llcubemap.cpp
llcubemaparray.cpp
llfontbitmapcache.cpp
@@ -23,7 +22,6 @@ set(llrender_SOURCE_FILES
llglslshader.cpp
llgltexture.cpp
llimagegl.cpp
- llpostprocess.cpp
llrender.cpp
llrender2dutils.cpp
llrendernavprim.cpp
@@ -40,7 +38,6 @@ set(llrender_SOURCE_FILES
set(llrender_HEADER_FILES
CMakeLists.txt
- llatmosphere.h
llcubemap.h
llcubemaparray.h
llfontgl.h
@@ -56,7 +53,6 @@ set(llrender_HEADER_FILES
llgltexture.h
llgltypes.h
llimagegl.h
- llpostprocess.h
llrender.h
llrender2dutils.h
llrendernavprim.h
diff --git a/indra/llrender/llatmosphere.cpp b/indra/llrender/llatmosphere.cpp
deleted file mode 100644
index eae5623a3c..0000000000
--- a/indra/llrender/llatmosphere.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/**
- * @file llatmosphere.cpp
- * @brief LLAtmosphere integration impl
- *
- * $LicenseInfo:firstyear=2018&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2018, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llatmosphere.h"
-#include "llfasttimer.h"
-#include "llsys.h"
-#include "llglheaders.h"
-#include "llrender.h"
-#include "llshadermgr.h"
-#include "llglslshader.h"
-
-LLAtmosphere* gAtmosphere = nullptr;
-
-// Values from "Reference Solar Spectral Irradiance: ASTM G-173", ETR column
-// (see http://rredc.nrel.gov/solar/spectra/am1.5/ASTMG173/ASTMG173.html),
-// summed and averaged in each bin (e.g. the value for 360nm is the average
-// of the ASTM G-173 values for all wavelengths between 360 and 370nm).
-// Values in W.m^-2.
-const int kLambdaMin = 360;
-const int kLambdaMax = 830;
-const double kSolarIrradiance[48] = {
- 1.11776, 1.14259, 1.01249, 1.14716, 1.72765, 1.73054, 1.6887, 1.61253,
- 1.91198, 2.03474, 2.02042, 2.02212, 1.93377, 1.95809, 1.91686, 1.8298,
- 1.8685, 1.8931, 1.85149, 1.8504, 1.8341, 1.8345, 1.8147, 1.78158, 1.7533,
- 1.6965, 1.68194, 1.64654, 1.6048, 1.52143, 1.55622, 1.5113, 1.474, 1.4482,
- 1.41018, 1.36775, 1.34188, 1.31429, 1.28303, 1.26758, 1.2367, 1.2082,
- 1.18737, 1.14683, 1.12362, 1.1058, 1.07124, 1.04992
-};
-
-// Values from http://www.iup.uni-bremen.de/gruppen/molspec/databases/
-// referencespectra/o3spectra2011/index.html for 233K, summed and averaged in
-// each bin (e.g. the value for 360nm is the average of the original values
-// for all wavelengths between 360 and 370nm). Values in m^2.
-const double kOzoneCrossSection[48] = {
- 1.18e-27, 2.182e-28, 2.818e-28, 6.636e-28, 1.527e-27, 2.763e-27, 5.52e-27,
- 8.451e-27, 1.582e-26, 2.316e-26, 3.669e-26, 4.924e-26, 7.752e-26, 9.016e-26,
- 1.48e-25, 1.602e-25, 2.139e-25, 2.755e-25, 3.091e-25, 3.5e-25, 4.266e-25,
- 4.672e-25, 4.398e-25, 4.701e-25, 5.019e-25, 4.305e-25, 3.74e-25, 3.215e-25,
- 2.662e-25, 2.238e-25, 1.852e-25, 1.473e-25, 1.209e-25, 9.423e-26, 7.455e-26,
- 6.566e-26, 5.105e-26, 4.15e-26, 4.228e-26, 3.237e-26, 2.451e-26, 2.801e-26,
- 2.534e-26, 1.624e-26, 1.465e-26, 2.078e-26, 1.383e-26, 7.105e-27
-};
-
-// From https://en.wikipedia.org/wiki/Dobson_unit, in molecules.m^-2.
-const double kDobsonUnit = 2.687e20;
-// Maximum number density of ozone molecules, in m^-3 (computed so at to get
-// 300 Dobson units of ozone - for this we divide 300 DU by the integral of
-// the ozone density profile defined below, which is equal to 15km).
-const double kMaxOzoneNumberDensity = 300.0 * kDobsonUnit / 15000.0;
-const double kRayleigh = 1.24062e-6;
-const double kRayleighScaleHeight = 8000.0;
-const double kMieScaleHeight = 1200.0;
-const double kMieAngstromAlpha = 0.0;
-const double kMieAngstromBeta = 5.328e-3;
-const double kMieSingleScatteringAlbedo = 0.9;
-const double kGroundAlbedo = 0.1;
-
-AtmosphericModelSettings::AtmosphericModelSettings()
- : m_skyBottomRadius(6360.0f)
- , m_skyTopRadius(6420.0f)
- , m_sunArcRadians(0.00045f)
- , m_mieAnisotropy(0.8f)
-{
- DensityLayer rayleigh_density(0.0, 1.0, -1.0 / kRayleighScaleHeight, 0.0, 0.0);
- DensityLayer mie_density(0.0, 1.0, -1.0 / kMieScaleHeight, 0.0, 0.0);
-
- m_rayleighProfile.push_back(rayleigh_density);
- m_mieProfile.push_back(mie_density);
-
- // Density profile increasing linearly from 0 to 1 between 10 and 25km, and
- // decreasing linearly from 1 to 0 between 25 and 40km. This is an approximate
- // profile from http://www.kln.ac.lk/science/Chemistry/Teaching_Resources/
- // Documents/Introduction%20to%20atmospheric%20chemistry.pdf (page 10).
- m_absorptionProfile.push_back(DensityLayer(25000.0, 0.0, 0.0, 1.0 / 15000.0, -2.0 / 3.0));
- m_absorptionProfile.push_back(DensityLayer(0.0, 0.0, 0.0, -1.0 / 15000.0, 8.0 / 3.0));
-}
-
-AtmosphericModelSettings::AtmosphericModelSettings(
- DensityProfile& rayleighProfile,
- DensityProfile& mieProfile,
- DensityProfile& absorptionProfile)
-: m_skyBottomRadius(6360.0f)
-, m_skyTopRadius(6420.0f)
-, m_rayleighProfile(rayleighProfile)
-, m_mieProfile(mieProfile)
-, m_absorptionProfile(absorptionProfile)
-, m_sunArcRadians(0.00045f)
-, m_mieAnisotropy(0.8f)
-{
-}
-
-AtmosphericModelSettings::AtmosphericModelSettings(
- F32 skyBottomRadius,
- F32 skyTopRadius,
- DensityProfile& rayleighProfile,
- DensityProfile& mieProfile,
- DensityProfile& absorptionProfile,
- F32 sunArcRadians,
- F32 mieAniso)
-: m_skyBottomRadius(skyBottomRadius)
-, m_skyTopRadius(skyTopRadius)
-, m_rayleighProfile(rayleighProfile)
-, m_mieProfile(mieProfile)
-, m_absorptionProfile(absorptionProfile)
-, m_sunArcRadians(sunArcRadians)
-, m_mieAnisotropy(mieAniso)
-{
-}
-
-bool AtmosphericModelSettings::operator==(const AtmosphericModelSettings& rhs) const
-{
- if (m_skyBottomRadius != rhs.m_skyBottomRadius)
- {
- return false;
- }
-
- if (m_skyTopRadius != rhs.m_skyTopRadius)
- {
- return false;
- }
-
- if (m_sunArcRadians != rhs.m_sunArcRadians)
- {
- return false;
- }
-
- if (m_mieAnisotropy != rhs.m_mieAnisotropy)
- {
- return false;
- }
-
- if (m_rayleighProfile != rhs.m_rayleighProfile)
- {
- return false;
- }
-
- if (m_mieProfile != rhs.m_mieProfile)
- {
- return false;
- }
-
- if (m_absorptionProfile != rhs.m_absorptionProfile)
- {
- return false;
- }
-
- return true;
-}
-
-void LLAtmosphere::initClass()
-{
- if (!gAtmosphere)
- {
- gAtmosphere = new LLAtmosphere;
- }
-}
-
-void LLAtmosphere::cleanupClass()
-{
- if(gAtmosphere)
- {
- delete gAtmosphere;
- }
- gAtmosphere = NULL;
-}
-
-LLAtmosphere::LLAtmosphere()
-{
- for (int l = kLambdaMin; l <= kLambdaMax; l += 10)
- {
- double lambda = static_cast<double>(l) * 1e-3; // micro-meters
- double mie = kMieAngstromBeta / kMieScaleHeight * pow(lambda, -kMieAngstromAlpha);
- m_wavelengths.push_back(l);
- m_solar_irradiance.push_back(kSolarIrradiance[(l - kLambdaMin) / 10]);
- m_rayleigh_scattering.push_back(kRayleigh * pow(lambda, -4));
- m_mie_scattering.push_back(mie * kMieSingleScatteringAlbedo);
- m_mie_extinction.push_back(mie);
- m_absorption_extinction.push_back(kMaxOzoneNumberDensity * kOzoneCrossSection[(l - kLambdaMin) / 10]);
- m_ground_albedo.push_back(kGroundAlbedo);
- }
-
- AtmosphericModelSettings defaults;
- configureAtmosphericModel(defaults);
-}
-
-LLAtmosphere::~LLAtmosphere()
-{
- // Cease referencing textures from atmosphere::model from our LLGLTextures wrappers for same.
- if (m_transmittance)
- {
- m_transmittance->setTexName(0);
- }
-
- if (m_scattering)
- {
- m_scattering->setTexName(0);
- }
-
- if (m_mie_scatter_texture)
- {
- m_mie_scatter_texture->setTexName(0);
- }
-}
-
-bool LLAtmosphere::configureAtmosphericModel(AtmosphericModelSettings& settings)
-{
- // TBD
- return true;
-}
-
-LLGLTexture* LLAtmosphere::getTransmittance()
-{
- if (!m_transmittance)
- {
- m_transmittance = new LLGLTexture;
- m_transmittance->generateGLTexture();
- m_transmittance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
- m_transmittance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_transmittance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT);
- m_transmittance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
- }
- return m_transmittance;
-}
-
-LLGLTexture* LLAtmosphere::getScattering()
-{
- if (!m_scattering)
- {
- m_scattering = new LLGLTexture;
- m_scattering->generateGLTexture();
- m_scattering->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
- m_scattering->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_scattering->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT);
- m_scattering->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
- }
- return m_scattering;
-}
-
-LLGLTexture* LLAtmosphere::getMieScattering()
-{
- if (!m_mie_scatter_texture)
- {
- m_mie_scatter_texture = new LLGLTexture;
- m_mie_scatter_texture->generateGLTexture();
- m_mie_scatter_texture->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
- m_mie_scatter_texture->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_mie_scatter_texture->setExplicitFormat(GL_RGB16F, GL_RGB, GL_FLOAT);
- m_mie_scatter_texture->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
- }
- return m_mie_scatter_texture;
-}
-
-LLGLTexture* LLAtmosphere::getIlluminance()
-{
- if (!m_illuminance)
- {
- m_illuminance = new LLGLTexture;
- m_illuminance->generateGLTexture();
- m_illuminance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
- m_illuminance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
- m_illuminance->setExplicitFormat(GL_RGB32F, GL_RGB, GL_FLOAT);
- m_illuminance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
- }
- return m_illuminance;
-}
diff --git a/indra/llrender/llatmosphere.h b/indra/llrender/llatmosphere.h
deleted file mode 100644
index 4b8c7d0819..0000000000
--- a/indra/llrender/llatmosphere.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * @file llatmosphere.h
- * @brief LLAtmosphere class
- *
- * $LicenseInfo:firstyear=2018&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2018, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_ATMOSPHERE_H
-#define LL_ATMOSPHERE_H
-
-#include "llglheaders.h"
-#include "llgltexture.h"
-
-// An atmosphere layer of width 'width' (in m), and whose density is defined as
-// 'exp_term' * exp('exp_scale' * h) + 'linear_term' * h + 'constant_term',
-// clamped to [0,1], and where h is the altitude (in m). 'exp_term' and
-// 'constant_term' are unitless, while 'exp_scale' and 'linear_term' are in
-// m^-1.
-class DensityLayer {
- public:
- DensityLayer()
- : width(0.0f)
- , exp_term(0.0f)
- , exp_scale(0.0f)
- , linear_term(0.0f)
- , constant_term(0.0f)
- {
- }
-
- DensityLayer(float width, float exp_term, float exp_scale, float linear_term, float constant_term)
- : width(width)
- , exp_term(exp_term)
- , exp_scale(exp_scale)
- , linear_term(linear_term)
- , constant_term(constant_term)
- {
- }
-
- bool operator==(const DensityLayer& rhs) const
- {
- if (width != rhs.width)
- {
- return false;
- }
-
- if (exp_term != rhs.exp_term)
- {
- return false;
- }
-
- if (exp_scale != rhs.exp_scale)
- {
- return false;
- }
-
- if (linear_term != rhs.linear_term)
- {
- return false;
- }
-
- if (constant_term != rhs.constant_term)
- {
- return false;
- }
-
- return true;
- }
-
- float width = 1024.0f;
- float exp_term = 1.0f;
- float exp_scale = 1.0f;
- float linear_term = 1.0f;
- float constant_term = 0.0f;
-};
-
-typedef std::vector<DensityLayer> DensityProfile;
-
-class AtmosphericModelSettings
-{
-public:
- AtmosphericModelSettings();
-
- AtmosphericModelSettings(
- DensityProfile& rayleighProfile,
- DensityProfile& mieProfile,
- DensityProfile& absorptionProfile);
-
- AtmosphericModelSettings(
- F32 skyBottomRadius,
- F32 skyTopRadius,
- DensityProfile& rayleighProfile,
- DensityProfile& mieProfile,
- DensityProfile& absorptionProfile,
- F32 sunArcRadians,
- F32 mieAniso);
-
- bool operator==(const AtmosphericModelSettings& rhs) const;
-
- F32 m_skyBottomRadius;
- F32 m_skyTopRadius;
- DensityProfile m_rayleighProfile;
- DensityProfile m_mieProfile;
- DensityProfile m_absorptionProfile;
- F32 m_sunArcRadians;
- F32 m_mieAnisotropy;
-};
-
-class LLAtmosphere
-{
-public:
- LLAtmosphere();
- ~LLAtmosphere();
-
- static void initClass();
- static void cleanupClass();
-
- const LLAtmosphere& operator=(const LLAtmosphere& rhs)
- {
- LL_ERRS() << "Illegal operation!" << LL_ENDL;
- return *this;
- }
-
- LLGLTexture* getTransmittance();
- LLGLTexture* getScattering();
- LLGLTexture* getMieScattering();
- LLGLTexture* getIlluminance();
-
- bool configureAtmosphericModel(AtmosphericModelSettings& settings);
-
-protected:
- LLAtmosphere(const LLAtmosphere& rhs)
- {
- *this = rhs;
- }
-
- LLPointer<LLGLTexture> m_transmittance;
- LLPointer<LLGLTexture> m_scattering;
- LLPointer<LLGLTexture> m_mie_scatter_texture;
- LLPointer<LLGLTexture> m_illuminance;
-
- std::vector<double> m_wavelengths;
- std::vector<double> m_solar_irradiance;
- std::vector<double> m_rayleigh_scattering;
- std::vector<double> m_mie_scattering;
- std::vector<double> m_mie_extinction;
- std::vector<double> m_absorption_extinction;
- std::vector<double> m_ground_albedo;
-
- AtmosphericModelSettings m_settings;
-};
-
-extern LLAtmosphere* gAtmosphere;
-
-#endif // LL_ATMOSPHERE_H
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 94daba0817..97be43cf86 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -270,7 +270,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
const LLFontGlyphInfo* next_glyph = NULL;
- static constexpr S32 GLYPH_BATCH_SIZE = 30;
+ static constexpr U32 GLYPH_BATCH_SIZE = 30;
static thread_local LLVector4a vertices[GLYPH_BATCH_SIZE * 6];
static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 6];
static thread_local LLColor4U colors[GLYPH_BATCH_SIZE * 6];
@@ -281,7 +281,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
LLColor4U emoji_color(255, 255, 255, text_color.mV[VALPHA]);
std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
- S32 glyph_count = 0;
+ U32 glyph_count = 0;
for (i = begin_offset; i < begin_offset + length; i++)
{
llwchar wch = wstr[i];
@@ -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();
@@ -1262,7 +1260,7 @@ void LLFontGL::renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor
colors_out[index] = color;
}
-void LLFontGL::drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
+void LLFontGL::drawGlyph(U32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
{
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index 4bb6c55c65..a257d94512 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -239,7 +239,7 @@ private:
LLPointer<LLFontFreetype> mFontFreetype;
void renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const;
- void drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
+ void drawGlyph(U32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
// Registry holds all instantiated fonts.
static LLFontRegistry* sFontRegistry;
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 6988e55034..273871678c 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;
@@ -1001,9 +1002,6 @@ LLGLManager::LLGLManager() :
mIsAMD(false),
mIsNVIDIA(false),
mIsIntel(false),
-#if LL_DARWIN
- mIsMobileGF(false),
-#endif
mHasRequirements(true),
mDriverVersionMajor(1),
mDriverVersionMinor(0),
@@ -1045,7 +1043,6 @@ void LLGLManager::initWGL()
GLH_EXT_NAME(wglGetGPUIDsAMD) = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
GLH_EXT_NAME(wglGetGPUInfoAMD) = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD");
}
- mHasNVXGpuMemoryInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts))
{
@@ -1153,7 +1150,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?
@@ -1219,8 +1220,10 @@ bool LLGLManager::initGL()
{
LL_WARNS("RenderInit") << "VRAM Detected (AMDAssociations):" << mVRAM << LL_ENDL;
}
- }
- else if (mHasNVXGpuMemoryInfo)
+ } else
+#endif
+#if LL_WINDOWS || LL_LINUX
+ if (mHasNVXGpuMemoryInfo)
{
GLint mem_kb = 0;
glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &mem_kb);
@@ -1440,6 +1443,13 @@ void LLGLManager::initExtensions()
mHasTransformFeedback = mGLVersion >= 3.99f;
mHasDebugOutput = mGLVersion >= 4.29f;
+#if LL_WINDOWS || LL_LINUX
+ if( gGLHExts.mSysExts )
+ mHasNVXGpuMemoryInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
+ else
+ LL_WARNS() << "gGLHExts.mSysExts is not set.?" << LL_ENDL;
+#endif
+
// Misc
glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index f5b1e8d786..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")
@@ -107,11 +108,6 @@ public:
// hints to the render pipe
U32 mDownScaleMethod = 0; // see settings.xml RenderDownScaleMethod
-#if LL_DARWIN
- // Needed to distinguish problem cards on older Macs that break with Materials
- bool mIsMobileGF;
-#endif
-
// Whether this version of GL is good enough for SL to use
bool mHasRequirements;
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index e79d67c5c7..147d3a5de2 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -1176,6 +1176,28 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextu
return uniform;
}
+// For LLImageGL-wrapped textures created via GL elsewhere with our API only. Use with caution.
+S32 LLGLSLShader::bindTextureImageGL(S32 uniform, LLImageGL* texture, LLTexUnit::eTextureType mode)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << uniform << LL_ENDL;
+ llassert(false);
+ return -1;
+ }
+
+ uniform = mTexture[uniform];
+
+ if (uniform > -1)
+ {
+ gGL.getTexUnit(uniform)->bind(texture);
+ }
+
+ return uniform;
+}
+
S32 LLGLSLShader::bindTexture(S32 uniform, LLRenderTarget* texture, bool depth, LLTexUnit::eTextureFilterOptions mode, U32 index)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 2d669c70a9..c24daaf686 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -264,6 +264,8 @@ public:
// You can reuse the return value to unbind a texture when required.
S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ // For LLImageGL-wrapped textures created via GL elsewhere with our API only. Use with caution.
+ S32 bindTextureImageGL(S32 uniform, LLImageGL* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
S32 bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR);
S32 bindTexture(S32 uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR, U32 index = 0);
S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
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/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 1d39786c2a..e6522ee418 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1855,7 +1855,7 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
ref();
LL::WorkQueue::postMaybe(
mMainQueue,
- [=]()
+ [=, this]()
{
LL_PROFILE_ZONE_NAMED("cglt - delete callback");
syncTexName(new_tex_name);
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
deleted file mode 100644
index 2e70c6953d..0000000000
--- a/indra/llrender/llpostprocess.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-/**
- * @file llpostprocess.cpp
- * @brief LLPostProcess class implementation
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llpostprocess.h"
-#include "llglslshader.h"
-#include "llsdserialize.h"
-#include "llrender.h"
-
-static LLStaticHashedString sRenderTexture("RenderTexture");
-static LLStaticHashedString sBrightness("brightness");
-static LLStaticHashedString sContrast("contrast");
-static LLStaticHashedString sContrastBase("contrastBase");
-static LLStaticHashedString sSaturation("saturation");
-static LLStaticHashedString sLumWeights("lumWeights");
-static LLStaticHashedString sNoiseTexture("NoiseTexture");
-static LLStaticHashedString sBrightMult("brightMult");
-static LLStaticHashedString sNoiseStrength("noiseStrength");
-static LLStaticHashedString sExtractLow("extractLow");
-static LLStaticHashedString sExtractHigh("extractHigh");
-static LLStaticHashedString sBloomStrength("bloomStrength");
-static LLStaticHashedString sTexelSize("texelSize");
-static LLStaticHashedString sBlurDirection("blurDirection");
-static LLStaticHashedString sBlurWidth("blurWidth");
-
-LLPostProcess * gPostProcess = NULL;
-
-static const unsigned int NOISE_SIZE = 512;
-
-LLPostProcess::LLPostProcess(void) :
- initialized(false),
- mAllEffects(LLSD::emptyMap()),
- screenW(1), screenH(1)
-{
- mSceneRenderTexture = NULL ;
- mNoiseTexture = NULL ;
- mTempBloomTexture = NULL ;
-
- noiseTextureScale = 1.0f;
-
- /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
- std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
- LL_DEBUGS("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL;
-
- llifstream effectsXML(pathName);
-
- if (effectsXML)
- {
- LLPointer<LLSDParser> parser = new LLSDXMLParser();
-
- parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED);
- }
-
- if (!mAllEffects.has("default"))
- {
- LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
-
- defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
- defaultEffect["enable_bloom"] = LLSD::Boolean(false);
- defaultEffect["enable_color_filter"] = LLSD::Boolean(false);
-
- /// NVG Defaults
- defaultEffect["brightness_multiplier"] = 3.0;
- defaultEffect["noise_size"] = 25.0;
- defaultEffect["noise_strength"] = 0.4;
-
- // TODO BTest potentially add this to tweaks?
- noiseTextureScale = 1.0f;
-
- /// Bloom Defaults
- defaultEffect["extract_low"] = 0.95;
- defaultEffect["extract_high"] = 1.0;
- defaultEffect["bloom_width"] = 2.25;
- defaultEffect["bloom_strength"] = 1.5;
-
- /// Color Filter Defaults
- defaultEffect["brightness"] = 1.0;
- defaultEffect["contrast"] = 1.0;
- defaultEffect["saturation"] = 1.0;
-
- LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray());
- contrastBase.append(1.0);
- contrastBase.append(1.0);
- contrastBase.append(1.0);
- contrastBase.append(0.5);
- }
-
- setSelectedEffect("default");
- */
-}
-
-LLPostProcess::~LLPostProcess(void)
-{
- invalidate() ;
-}
-
-// static
-void LLPostProcess::initClass(void)
-{
- //this will cause system to crash at second time login
- //if first time login fails due to network connection --- bao
- //***llassert_always(gPostProcess == NULL);
- //replaced by the following line:
- if(gPostProcess)
- return ;
-
-
- gPostProcess = new LLPostProcess();
-}
-
-// static
-void LLPostProcess::cleanupClass()
-{
- delete gPostProcess;
- gPostProcess = NULL;
-}
-
-void LLPostProcess::setSelectedEffect(std::string const & effectName)
-{
- mSelectedEffectName = effectName;
- static_cast<LLSD &>(tweaks) = mAllEffects[effectName];
-}
-
-void LLPostProcess::saveEffect(std::string const & effectName)
-{
- /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
- mAllEffects[effectName] = tweaks;
-
- std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
- //LL_INFOS() << "Saving PostProcess Effects settings to " << pathName << LL_ENDL;
-
- llofstream effectsXML(pathName);
-
- LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
-
- formatter->format(mAllEffects, effectsXML);
- */
-}
-void LLPostProcess::invalidate()
-{
- mSceneRenderTexture = NULL ;
- mNoiseTexture = NULL ;
- mTempBloomTexture = NULL ;
- initialized = false ;
-}
-
-void LLPostProcess::apply(unsigned int width, unsigned int height)
-{
- if (!initialized || width != screenW || height != screenH){
- initialize(width, height);
- }
- if (shadersEnabled()){
- doEffects();
- }
-}
-
-void LLPostProcess::initialize(unsigned int width, unsigned int height)
-{
- screenW = width;
- screenH = height;
- createTexture(mSceneRenderTexture, screenW, screenH);
- initialized = true;
-
- checkError();
- createNightVisionShader();
- createBloomShader();
- createColorFilterShader();
- checkError();
-}
-
-inline bool LLPostProcess::shadersEnabled(void)
-{
- return (tweaks.useColorFilter().asBoolean() ||
- tweaks.useNightVisionShader().asBoolean() ||
- tweaks.useBloomShader().asBoolean() );
-
-}
-
-void LLPostProcess::applyShaders(void)
-{
- if (tweaks.useColorFilter()){
- applyColorFilterShader();
- checkError();
- }
- if (tweaks.useNightVisionShader()){
- /// If any of the above shaders have been called update the frame buffer;
- if (tweaks.useColorFilter())
- {
- U32 tex = mSceneRenderTexture->getTexName() ;
- copyFrameBuffer(tex, screenW, screenH);
- }
- applyNightVisionShader();
- checkError();
- }
- if (tweaks.useBloomShader()){
- /// If any of the above shaders have been called update the frame buffer;
- if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean())
- {
- U32 tex = mSceneRenderTexture->getTexName() ;
- copyFrameBuffer(tex, screenW, screenH);
- }
- applyBloomShader();
- checkError();
- }
-}
-
-void LLPostProcess::applyColorFilterShader(void)
-{
-
-}
-
-void LLPostProcess::createColorFilterShader(void)
-{
- /// Define uniform names
- colorFilterUniforms[sRenderTexture] = 0;
- colorFilterUniforms[sBrightness] = 0;
- colorFilterUniforms[sContrast] = 0;
- colorFilterUniforms[sContrastBase] = 0;
- colorFilterUniforms[sSaturation] = 0;
- colorFilterUniforms[sLumWeights] = 0;
-}
-
-void LLPostProcess::applyNightVisionShader(void)
-{
-
-}
-
-void LLPostProcess::createNightVisionShader(void)
-{
- /// Define uniform names
- nightVisionUniforms[sRenderTexture] = 0;
- nightVisionUniforms[sNoiseTexture] = 0;
- nightVisionUniforms[sBrightMult] = 0;
- nightVisionUniforms[sNoiseStrength] = 0;
- nightVisionUniforms[sLumWeights] = 0;
-
- createNoiseTexture(mNoiseTexture);
-}
-
-void LLPostProcess::applyBloomShader(void)
-{
-
-}
-
-void LLPostProcess::createBloomShader(void)
-{
- createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
-
- /// Create Bloom Extract Shader
- bloomExtractUniforms[sRenderTexture] = 0;
- bloomExtractUniforms[sExtractLow] = 0;
- bloomExtractUniforms[sExtractHigh] = 0;
- bloomExtractUniforms[sLumWeights] = 0;
-
- /// Create Bloom Blur Shader
- bloomBlurUniforms[sRenderTexture] = 0;
- bloomBlurUniforms[sBloomStrength] = 0;
- bloomBlurUniforms[sTexelSize] = 0;
- bloomBlurUniforms[sBlurDirection] = 0;
- bloomBlurUniforms[sBlurWidth] = 0;
-}
-
-void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLuint & prog)
-{
- /// Find uniform locations and insert into map
- glslUniforms::iterator i;
- for (i = uniforms.begin(); i != uniforms.end(); ++i){
- i->second = glGetUniformLocation(prog, i->first.String().c_str());
- }
-}
-
-void LLPostProcess::doEffects(void)
-{
- /// Save GL State
-#if GL_VERSION_1_1
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glPushClientAttrib(GL_ALL_ATTRIB_BITS);
-#endif
-
- /// Copy the screen buffer to the render texture
- {
- U32 tex = mSceneRenderTexture->getTexName() ;
- copyFrameBuffer(tex, screenW, screenH);
- }
-
- /// Clear the frame buffer.
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- /// Change to an orthogonal view
- viewOrthogonal(screenW, screenH);
-
- checkError();
- applyShaders();
-
- LLGLSLShader::unbind();
- checkError();
-
- /// Change to a perspective view
- viewPerspective();
-
- /// Reset GL State
-#if GL_VERSION_1_1
- glPopClientAttrib();
- glPopAttrib();
-#endif
- checkError();
-}
-
-void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height)
-{
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture);
-#if GL_VERSION_3_1
- glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, width, height, 0);
-#endif
-}
-
-void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
-{
-
-}
-
-void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
-{
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.ortho( 0.f, (GLfloat) width , (GLfloat) height , 0.f, -1.f, 1.f );
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
-}
-
-void LLPostProcess::viewPerspective(void)
-{
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-}
-
-void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height)
-{
- viewPerspective();
- viewOrthogonal(width, height);
-}
-
-void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height)
-{
- std::vector<GLubyte> data(width * height * 4, 0) ;
-
- texture = new LLImageGL(false) ;
- if(texture->createGLTexture())
- {
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
-#if GL_VERSION_3_1
- glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, width, height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
-#endif
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- }
-}
-
-void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture)
-{
- std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
- for (unsigned int i = 0; i < NOISE_SIZE; i++){
- for (unsigned int k = 0; k < NOISE_SIZE; k++){
- buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
- }
- }
-
- texture = new LLImageGL(false) ;
- if(texture->createGLTexture())
- {
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
- LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
- }
-}
-
-bool LLPostProcess::checkError(void)
-{
- GLenum glErr;
- bool retCode = false;
-
- glErr = glGetError();
- while (glErr != GL_NO_ERROR)
- {
- // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
-#if GLU_VERSION_1_1
- char const * err_str_raw = (const char *) gluErrorString(glErr);
-
- if(err_str_raw == NULL)
- {
-#endif
- std::ostringstream err_builder;
- err_builder << "unknown error number " << glErr;
- mShaderErrorString = err_builder.str();
-#if GLU_VERSION_1_1
- }
- else
- {
- mShaderErrorString = err_str_raw;
- }
-#endif
-
- retCode = true;
- glErr = glGetError();
- }
- return retCode;
-}
-
-void LLPostProcess::checkShaderError(GLuint shader)
-{
- GLint infologLength = 0;
- GLint charsWritten = 0;
- GLchar *infoLog;
-
- checkError(); // Check for OpenGL errors
-
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
-
- checkError(); // Check for OpenGL errors
-
- if (infologLength > 0)
- {
- infoLog = (GLchar *)malloc(infologLength);
- if (infoLog == NULL)
- {
- /// Could not allocate infolog buffer
- return;
- }
- glGetProgramInfoLog(shader, infologLength, &charsWritten, infoLog);
- // shaderErrorLog << (char *) infoLog << std::endl;
- mShaderErrorString = (char *) infoLog;
- free(infoLog);
- }
- checkError(); // Check for OpenGL errors
-}
diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h
deleted file mode 100644
index b5b7549efb..0000000000
--- a/indra/llrender/llpostprocess.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- * @file llpostprocess.h
- * @brief LLPostProcess class definition
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_POSTPROCESS_H
-#define LL_POSTPROCESS_H
-
-#include <map>
-#include <fstream>
-#include "llgl.h"
-#include "llglheaders.h"
-#include "llstaticstringtable.h"
-
-class LLPostProcess
-{
-public:
-
- typedef enum _QuadType {
- QUAD_NORMAL,
- QUAD_NOISE,
- QUAD_BLOOM_EXTRACT,
- QUAD_BLOOM_COMBINE
- } QuadType;
-
- /// GLSL Shader Encapsulation Struct
- typedef LLStaticStringTable<GLuint> glslUniforms;
-
- struct PostProcessTweaks : public LLSD {
- inline PostProcessTweaks() : LLSD(LLSD::emptyMap())
- {
- }
-
- inline LLSD & brightMult() {
- return (*this)["brightness_multiplier"];
- }
-
- inline LLSD & noiseStrength() {
- return (*this)["noise_strength"];
- }
-
- inline LLSD & noiseSize() {
- return (*this)["noise_size"];
- }
-
- inline LLSD & extractLow() {
- return (*this)["extract_low"];
- }
-
- inline LLSD & extractHigh() {
- return (*this)["extract_high"];
- }
-
- inline LLSD & bloomWidth() {
- return (*this)["bloom_width"];
- }
-
- inline LLSD & bloomStrength() {
- return (*this)["bloom_strength"];
- }
-
- inline LLSD & brightness() {
- return (*this)["brightness"];
- }
-
- inline LLSD & contrast() {
- return (*this)["contrast"];
- }
-
- inline LLSD & contrastBaseR() {
- return (*this)["contrast_base"][0];
- }
-
- inline LLSD & contrastBaseG() {
- return (*this)["contrast_base"][1];
- }
-
- inline LLSD & contrastBaseB() {
- return (*this)["contrast_base"][2];
- }
-
- inline LLSD & contrastBaseIntensity() {
- return (*this)["contrast_base"][3];
- }
-
- inline LLSD & saturation() {
- return (*this)["saturation"];
- }
-
- inline LLSD & useNightVisionShader() {
- return (*this)["enable_night_vision"];
- }
-
- inline LLSD & useBloomShader() {
- return (*this)["enable_bloom"];
- }
-
- inline LLSD & useColorFilter() {
- return (*this)["enable_color_filter"];
- }
-
-
- inline F32 getBrightMult() const {
- return F32((*this)["brightness_multiplier"].asReal());
- }
-
- inline F32 getNoiseStrength() const {
- return F32((*this)["noise_strength"].asReal());
- }
-
- inline F32 getNoiseSize() const {
- return F32((*this)["noise_size"].asReal());
- }
-
- inline F32 getExtractLow() const {
- return F32((*this)["extract_low"].asReal());
- }
-
- inline F32 getExtractHigh() const {
- return F32((*this)["extract_high"].asReal());
- }
-
- inline F32 getBloomWidth() const {
- return F32((*this)["bloom_width"].asReal());
- }
-
- inline F32 getBloomStrength() const {
- return F32((*this)["bloom_strength"].asReal());
- }
-
- inline F32 getBrightness() const {
- return F32((*this)["brightness"].asReal());
- }
-
- inline F32 getContrast() const {
- return F32((*this)["contrast"].asReal());
- }
-
- inline F32 getContrastBaseR() const {
- return F32((*this)["contrast_base"][0].asReal());
- }
-
- inline F32 getContrastBaseG() const {
- return F32((*this)["contrast_base"][1].asReal());
- }
-
- inline F32 getContrastBaseB() const {
- return F32((*this)["contrast_base"][2].asReal());
- }
-
- inline F32 getContrastBaseIntensity() const {
- return F32((*this)["contrast_base"][3].asReal());
- }
-
- inline F32 getSaturation() const {
- return F32((*this)["saturation"].asReal());
- }
-
- };
-
- bool initialized;
- PostProcessTweaks tweaks;
-
- // the map of all availible effects
- LLSD mAllEffects;
-
-private:
- LLPointer<LLImageGL> mSceneRenderTexture ;
- LLPointer<LLImageGL> mNoiseTexture ;
- LLPointer<LLImageGL> mTempBloomTexture ;
-
-public:
- LLPostProcess(void);
-
- ~LLPostProcess(void);
-
- void apply(unsigned int width, unsigned int height);
- void invalidate() ;
-
- /// Perform global initialization for this class.
- static void initClass(void);
-
- // Cleanup of global data that's only inited once per class.
- static void cleanupClass();
-
- void setSelectedEffect(std::string const & effectName);
-
- inline std::string const & getSelectedEffect(void) const {
- return mSelectedEffectName;
- }
-
- void saveEffect(std::string const & effectName);
-
-private:
- /// read in from file
- std::string mShaderErrorString;
- unsigned int screenW;
- unsigned int screenH;
-
- float noiseTextureScale;
-
- /// Shader Uniforms
- glslUniforms nightVisionUniforms;
- glslUniforms bloomExtractUniforms;
- glslUniforms bloomBlurUniforms;
- glslUniforms colorFilterUniforms;
-
- // the name of currently selected effect in mAllEffects
- // invariant: tweaks == mAllEffects[mSelectedEffectName]
- std::string mSelectedEffectName;
-
- /// General functions
- void initialize(unsigned int width, unsigned int height);
- void doEffects(void);
- void applyShaders(void);
- bool shadersEnabled(void);
-
- /// Night Vision Functions
- void createNightVisionShader(void);
- void applyNightVisionShader(void);
-
- /// Bloom Functions
- void createBloomShader(void);
- void applyBloomShader(void);
-
- /// Color Filter Functions
- void createColorFilterShader(void);
- void applyColorFilterShader(void);
-
- /// OpenGL Helper Functions
- void getShaderUniforms(glslUniforms & uniforms, GLuint & prog);
- void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height);
- void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height);
- void createNoiseTexture(LLPointer<LLImageGL>& texture);
- bool checkError(void);
- void checkShaderError(GLuint shader);
- void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
- void viewOrthogonal(unsigned int width, unsigned int height);
- void changeOrthogonal(unsigned int width, unsigned int height);
- void viewPerspective(void);
-};
-
-extern LLPostProcess * gPostProcess;
-
-
-#endif // LL_POSTPROCESS_H
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 9178fc16b9..a0025968f7 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -38,7 +38,7 @@
#include "hbxxh.h"
#include "glm/gtc/type_ptr.hpp"
-#if LL_WINDOWS
+#if GL_ARB_debug_output && !LL_DARWIN
extern void APIENTRY gl_debug_callback(GLenum source,
GLenum type,
GLuint id,
@@ -157,7 +157,8 @@ void LLTexUnit::refreshState(void)
void LLTexUnit::activate(void)
{
- if (mIndex < 0) return;
+ if (mIndex < 0)
+ return;
if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
{
@@ -169,7 +170,8 @@ void LLTexUnit::activate(void)
void LLTexUnit::enable(eTextureType type)
{
- if (mIndex < 0) return;
+ if (mIndex < 0)
+ return;
if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )
{
@@ -186,7 +188,8 @@ void LLTexUnit::enable(eTextureType type)
void LLTexUnit::disable(void)
{
- if (mIndex < 0) return;
+ if (mIndex < 0)
+ return;
if (mCurrTexType != TT_NONE)
{
@@ -222,7 +225,7 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
{
gGL.flush();
- LLImageGL* gl_tex = NULL ;
+ LLImageGL* gl_tex = NULL;
if (texture != NULL && (gl_tex = texture->getGLTexture()))
{
@@ -237,8 +240,8 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
if(gl_tex->updateBindStats())
{
- texture->setActive() ;
- texture->updateBindStatsForTester() ;
+ texture->setActive();
+ texture->updateBindStatsForTester();
}
mHasMipMaps = gl_tex->mHasMipMaps;
if (gl_tex->mTexOptionsDirty)
@@ -252,9 +255,9 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
else
{
//if deleted, will re-generate it immediately
- texture->forceImmediateUpdate() ;
+ texture->forceImmediateUpdate();
- gl_tex->forceUpdateBindStats() ;
+ gl_tex->forceUpdateBindStats();
return texture->bindDefaultImage(mIndex);
}
}
@@ -282,24 +285,27 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 usename)
{
stop_glerror();
- if (mIndex < 0) return false;
+ if (mIndex < 0)
+ {
+ return false;
+ }
U32 texname = usename ? usename : texture->getTexName();
- if(!texture)
+ if (!texture)
{
LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
return false;
}
- if(!texname)
+ if (!texname)
{
if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName())
{
- return bind(LLImageGL::sDefaultGLTexture) ;
+ return bind(LLImageGL::sDefaultGLTexture);
}
stop_glerror();
- return false ;
+ return false;
}
if ((mCurrTexture != texname) || forceBind)
@@ -332,7 +338,10 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32
bool LLTexUnit::bind(LLCubeMap* cubeMap)
{
- if (mIndex < 0) return false;
+ if (mIndex < 0)
+ {
+ return false;
+ }
gGL.flush();
@@ -372,7 +381,10 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
// LLRenderTarget is unavailible on the mapserver since it uses FBOs.
bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
{
- if (mIndex < 0) return false;
+ if (mIndex < 0)
+ {
+ return false;
+ }
gGL.flush();
@@ -397,7 +409,7 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
return false;
}
- if(mCurrTexture != texture)
+ if (mCurrTexture != texture)
{
gGL.flush();
@@ -407,6 +419,7 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
glBindTexture(sGLTextureType[type], texture);
mHasMipMaps = hasMips;
}
+
return true;
}
@@ -414,7 +427,8 @@ void LLTexUnit::unbind(eTextureType type)
{
stop_glerror();
- if (mIndex < 0) return;
+ if (mIndex < 0)
+ return;
//always flush and activate for consistency
// some code paths assume unbind always flushes and sets the active texture
@@ -460,7 +474,8 @@ void LLTexUnit::unbindFast(eTextureType type)
void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
{
- if (mIndex < 0 || mCurrTexture == 0) return;
+ if (mIndex < 0 || mCurrTexture == 0)
+ return;
gGL.flush();
@@ -476,7 +491,8 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
- if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
+ if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE)
+ return;
gGL.flush();
@@ -532,7 +548,7 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
{
#if GL_VERSION_1_3
- switch(src)
+ switch (src)
{
// All four cases should return the same value.
case TBS_PREV_COLOR:
@@ -573,14 +589,14 @@ GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
{
- switch(src)
+ switch (src)
{
// All four cases should return the same value.
case TBS_PREV_COLOR:
case TBS_TEX_COLOR:
case TBS_VERT_COLOR:
case TBS_CONST_COLOR:
- return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
+ return isAlpha ? GL_SRC_ALPHA : GL_SRC_COLOR;
// All four cases should return the same value.
case TBS_PREV_ALPHA:
@@ -594,7 +610,7 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
case TBS_ONE_MINUS_TEX_COLOR:
case TBS_ONE_MINUS_VERT_COLOR:
case TBS_ONE_MINUS_CONST_COLOR:
- return (isAlpha) ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE_MINUS_SRC_COLOR;
+ return isAlpha ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE_MINUS_SRC_COLOR;
// All four cases should return the same value.
case TBS_ONE_MINUS_PREV_ALPHA:
@@ -605,7 +621,7 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
default:
LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Source Color or Alpha instead." << LL_ENDL;
- return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
+ return isAlpha ? GL_SRC_ALPHA : GL_SRC_COLOR;
}
}
@@ -616,7 +632,7 @@ void LLTexUnit::setColorScale(S32 scale)
mCurrColorScale = scale;
gGL.flush();
#if GL_VERSION_1_1
- glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
+ glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, scale);
#endif
}
}
@@ -628,7 +644,7 @@ void LLTexUnit::setAlphaScale(S32 scale)
mCurrAlphaScale = scale;
gGL.flush();
#if GL_VERSION_1_1
- glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
+ glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
#endif
}
}
@@ -637,7 +653,8 @@ void LLTexUnit::setAlphaScale(S32 scale)
// texture unit based on the currently set active texture in opengl.
void LLTexUnit::debugTextureUnit(void)
{
- if (mIndex < 0) return;
+ if (mIndex < 0)
+ return;
GLint activeTexture;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
@@ -659,16 +676,16 @@ LLLightState::LLLightState(S32 index)
{
if (mIndex == 0)
{
- mDiffuse.set(1,1,1,1);
- mDiffuseB.set(0,0,0,0);
- mSpecular.set(1,1,1,1);
+ mDiffuse.set(1, 1, 1, 1);
+ mDiffuseB.set(0, 0, 0, 0);
+ mSpecular.set(1, 1, 1, 1);
}
mSunIsPrimary = true;
- mAmbient.set(0,0,0,1);
- mPosition.set(0,0,1,0);
- mSpotDirection.set(0,0,-1);
+ mAmbient.set(0, 0, 0, 1);
+ mPosition.set(0, 0, 1, 0);
+ mSpotDirection.set(0, 0, -1);
}
void LLLightState::enable()
@@ -863,7 +880,7 @@ LLRender::~LLRender()
bool LLRender::init(bool needs_vertex_buffer)
{
-#if LL_WINDOWS
+#if GL_ARB_debug_output && !LL_DARWIN
if (gGLManager.mHasDebugOutput && gDebugGL)
{ //setup debug output callback
//glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);
@@ -902,6 +919,7 @@ bool LLRender::init(bool needs_vertex_buffer)
{
initVertexBuffer();
}
+
return true;
}
@@ -1135,7 +1153,6 @@ void LLRender::syncMatrices()
}
}
-
if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics)
{ //also sync light state
syncLightState();
@@ -1148,91 +1165,78 @@ void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
flush();
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::translate(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::vec3(x, y, z));
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::translate(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::vec3(x, y, z));
+ mMatHash[mMatrixMode]++;
}
void LLRender::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
flush();
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::scale(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::vec3(x, y, z));
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::scale(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::vec3(x, y, z));
+ mMatHash[mMatrixMode]++;
}
void LLRender::ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar)
{
flush();
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] *= glm::ortho(left, right, bottom, top, zNear, zFar);
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] *= glm::ortho(left, right, bottom, top, zNear, zFar);
+ mMatHash[mMatrixMode]++;
}
void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
flush();
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::rotate(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::radians(a), glm::vec3(x,y,z));
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::rotate(mMatrix[mMatrixMode][mMatIdx[mMatrixMode]], glm::radians(a), glm::vec3(x,y,z));
+ mMatHash[mMatrixMode]++;
}
void LLRender::pushMatrix()
{
flush();
+ if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1)
{
- if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1)
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]];
- ++mMatIdx[mMatrixMode];
- }
- else
- {
- LL_WARNS() << "Matrix stack overflow." << LL_ENDL;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]];
+ ++mMatIdx[mMatrixMode];
+ }
+ else
+ {
+ LL_WARNS() << "Matrix stack overflow." << LL_ENDL;
}
}
void LLRender::popMatrix()
{
flush();
+
+ if (mMatIdx[mMatrixMode] > 0)
{
- if (mMatIdx[mMatrixMode] > 0)
- {
- --mMatIdx[mMatrixMode];
- mMatHash[mMatrixMode]++;
- }
- else
- {
- LL_WARNS() << "Matrix stack underflow." << LL_ENDL;
- }
+ --mMatIdx[mMatrixMode];
+ mMatHash[mMatrixMode]++;
+ }
+ else
+ {
+ LL_WARNS() << "Matrix stack underflow." << LL_ENDL;
}
}
void LLRender::loadMatrix(const GLfloat* m)
{
flush();
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::make_mat4((GLfloat*) m);
- mMatHash[mMatrixMode]++;
- }
+
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::make_mat4((GLfloat*) m);
+ mMatHash[mMatrixMode]++;
}
void LLRender::multMatrix(const GLfloat* m)
{
flush();
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] *= glm::make_mat4(m);
- mMatHash[mMatrixMode]++;
- }
+
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] *= glm::make_mat4(m);
+ mMatHash[mMatrixMode]++;
}
void LLRender::matrixMode(eMatrixMode mode)
@@ -1270,12 +1274,10 @@ void LLRender::loadIdentity()
{
flush();
- {
- llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
+ llassert_always(mMatrixMode < NUM_MATRIX_MODES);
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::identity<glm::mat4>();
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]] = glm::identity<glm::mat4>();
+ mMatHash[mMatrixMode]++;
}
const glm::mat4& LLRender::getModelviewMatrix()
@@ -1295,9 +1297,7 @@ void LLRender::translateUI(F32 x, F32 y, F32 z)
LL_ERRS() << "Need to push a UI translation frame before offsetting" << LL_ENDL;
}
- mUIOffset.back().mV[0] += x;
- mUIOffset.back().mV[1] += y;
- mUIOffset.back().mV[2] += z;
+ mUIOffset.back().add(LLVector4a(x, y, z));
}
void LLRender::scaleUI(F32 x, F32 y, F32 z)
@@ -1307,14 +1307,14 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z)
LL_ERRS() << "Need to push a UI transformation frame before scaling." << LL_ENDL;
}
- mUIScale.back().scaleVec(LLVector3(x,y,z));
+ mUIScale.back().mul(LLVector4a(x, y, z));
}
void LLRender::pushUIMatrix()
{
if (mUIOffset.empty())
{
- mUIOffset.emplace_back(0.f,0.f,0.f);
+ mUIOffset.emplace_back(0.f);
}
else
{
@@ -1323,7 +1323,7 @@ void LLRender::pushUIMatrix()
if (mUIScale.empty())
{
- mUIScale.emplace_back(1.f,1.f,1.f);
+ mUIScale.emplace_back(1.f);
}
else
{
@@ -1345,18 +1345,20 @@ LLVector3 LLRender::getUITranslation()
{
if (mUIOffset.empty())
{
- return LLVector3(0,0,0);
+ return LLVector3::zero;
}
- return mUIOffset.back();
+
+ return LLVector3(mUIOffset.back().getF32ptr());
}
LLVector3 LLRender::getUIScale()
{
if (mUIScale.empty())
{
- return LLVector3(1,1,1);
+ return LLVector3::all_one;
}
- return mUIScale.back();
+
+ return LLVector3(mUIScale.back().getF32ptr());
}
@@ -1366,8 +1368,9 @@ void LLRender::loadUIIdentity()
{
LL_ERRS() << "Need to push UI translation frame before clearing offset." << LL_ENDL;
}
- mUIOffset.back().setVec(0,0,0);
- mUIScale.back().setVec(1,1,1);
+
+ mUIOffset.back().clear();
+ mUIScale.back().splat(1);
}
void LLRender::setColorMask(bool writeColor, bool writeAlpha)
@@ -1461,7 +1464,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
flush();
glBlendFuncSeparate(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
- sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
+ sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
}
}
@@ -1471,11 +1474,9 @@ LLTexUnit* LLRender::getTexUnit(U32 index)
{
return &mTexUnits[index];
}
- else
- {
- LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL;
- return &mDummyTexUnit;
- }
+
+ LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL;
+ return &mDummyTexUnit;
}
LLLightState* LLRender::getLight(U32 index)
@@ -1504,11 +1505,9 @@ bool LLRender::verifyTexUnitActive(U32 unitToVerify)
{
return true;
}
- else
- {
- LL_WARNS() << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << LL_ENDL;
- return false;
- }
+
+ LL_WARNS() << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << LL_ENDL;
+ return false;
}
void LLRender::clearErrors()
@@ -1525,6 +1524,7 @@ void LLRender::beginList(std::list<LLVertexBufferData> *list)
{
LL_ERRS() << "beginList called while another list is open." << LL_ENDL;
}
+
llassert(LLGLSLShader::sCurBoundShaderPtr == &gUIProgram);
flush();
sBufferDataList = list;
@@ -1597,7 +1597,7 @@ void LLRender::flush()
if (mMode == LLRender::TRIANGLES)
{
- if (mCount%3 != 0)
+ if (mCount % 3 != 0)
{
count -= (mCount % 3);
LL_WARNS() << "Incomplete triangle requested." << LL_ENDL;
@@ -1606,7 +1606,7 @@ void LLRender::flush()
if (mMode == LLRender::LINES)
{
- if (mCount%2 != 0)
+ if (mCount % 2 != 0)
{
count -= (mCount % 2);
LL_WARNS() << "Incomplete line requested." << LL_ENDL;
@@ -1617,7 +1617,6 @@ void LLRender::flush()
if (mBuffer)
{
-
LLVertexBuffer *vb;
U32 attribute_mask = LLGLSLShader::sCurBoundShaderPtr->mAttributeMask;
@@ -1724,6 +1723,7 @@ LLVertexBuffer* LLRender::bufferfromCache(U32 attribute_mask, U32 count)
}
}
}
+
return vb;
}
@@ -1771,14 +1771,26 @@ void LLRender::resetStriders(S32 count)
void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
- //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095]
+ // the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095]
if (mCount > 2048)
- { //break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below
+ { // break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below
switch (mMode)
{
- case LLRender::POINTS: flush(); break;
- case LLRender::TRIANGLES: if (mCount%3==0) flush(); break;
- case LLRender::LINES: if (mCount%2 == 0) flush(); break;
+ case LLRender::POINTS:
+ flush();
+ break;
+ case LLRender::TRIANGLES:
+ if (mCount % 3 == 0)
+ {
+ flush();
+ }
+ break;
+ case LLRender::LINES:
+ if (mCount % 2 == 0)
+ {
+ flush();
+ }
+ break;
}
}
@@ -1788,23 +1800,64 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
return;
}
- if (mUIOffset.empty())
+ LLVector4a vert(x, y, z);
+ transform(vert);
+ mVerticesp[mCount] = vert;
+
+ mCount++;
+ mVerticesp[mCount] = vert;
+ mColorsp[mCount] = mColorsp[mCount-1];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+}
+
+void LLRender::transform(LLVector3& vert)
+{
+ if (!mUIOffset.empty())
{
- mVerticesp[mCount].set(x,y,z);
+ vert += LLVector3(mUIOffset.back().getF32ptr());
+ vert *= LLVector3(mUIScale.back().getF32ptr());
}
- else
+}
+
+void LLRender::transform(LLVector4a& vert)
+{
+ if (!mUIOffset.empty())
{
- LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back());
- mVerticesp[mCount].set(vert.mV[VX], vert.mV[VY], vert.mV[VZ]);
+ vert.add(mUIOffset.back());
+ vert.mul(mUIScale.back());
}
+}
- mCount++;
- mVerticesp[mCount] = mVerticesp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+void LLRender::untransform(LLVector3& vert)
+{
+ if (!mUIOffset.empty())
+ {
+ vert /= LLVector3(mUIScale.back().getF32ptr());
+ vert -= LLVector3(mUIOffset.back().getF32ptr());
+ }
}
-void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count)
+void LLRender::batchTransform(LLVector4a* verts, U32 vert_count)
+{
+ if (!mUIOffset.empty())
+ {
+ const LLVector4a& offset = mUIOffset.back();
+ const LLVector4a& scale = mUIScale.back();
+
+ for (U32 i = 0; i < vert_count; ++i)
+ {
+ verts[i].add(offset);
+ verts[i].mul(scale);
+ }
+ }
+}
+
+void LLRender::vertexBatchPreTransformed(const std::vector<LLVector4a>& verts)
+{
+ vertexBatchPreTransformed(verts.data(), verts.size());
+}
+
+void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, std::size_t vert_count)
{
if (mCount + vert_count > 4094)
{
@@ -1817,15 +1870,17 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count)
mVerticesp[mCount] = verts[i];
mCount++;
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount - 1];
+ mColorsp[mCount] = mColorsp[mCount - 1];
}
- if( mCount > 0 ) // ND: Guard against crashes if mCount is zero, yes it can happen
- mVerticesp[mCount] = mVerticesp[mCount-1];
+ if (mCount > 0) // ND: Guard against crashes if mCount is zero, yes it can happen
+ {
+ mVerticesp[mCount] = mVerticesp[mCount - 1];
+ }
}
-void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count)
+void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, std::size_t vert_count)
{
if (mCount + vert_count > 4094)
{
@@ -1849,7 +1904,7 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32
}
}
-void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count)
+void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U* colors, std::size_t vert_count)
{
if (mCount + vert_count > 4094)
{
@@ -1876,27 +1931,27 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLCo
void LLRender::vertex2i(const GLint& x, const GLint& y)
{
- vertex3f((GLfloat) x, (GLfloat) y, 0);
+ vertex3f((GLfloat)x, (GLfloat)y, 0);
}
void LLRender::vertex2f(const GLfloat& x, const GLfloat& y)
{
- vertex3f(x,y,0);
+ vertex3f(x, y, 0);
}
void LLRender::vertex2fv(const GLfloat* v)
{
- vertex3f(v[0], v[1], 0);
+ vertex3f(v[VX], v[VY], 0);
}
void LLRender::vertex3fv(const GLfloat* v)
{
- vertex3f(v[0], v[1], v[2]);
+ vertex3f(v[VX], v[VY], v[VZ]);
}
void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y)
{
- mTexcoordsp[mCount] = LLVector2(x,y);
+ mTexcoordsp[mCount].set(x,y);
}
void LLRender::texCoord2i(const GLint& x, const GLint& y)
@@ -1906,46 +1961,47 @@ void LLRender::texCoord2i(const GLint& x, const GLint& y)
void LLRender::texCoord2fv(const GLfloat* tc)
{
- texCoord2f(tc[0], tc[1]);
+ texCoord2f(tc[VX], tc[VY]);
}
void LLRender::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a)
{
- if (!LLGLSLShader::sCurBoundShaderPtr || LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
+ if (!LLGLSLShader::sCurBoundShaderPtr ||
+ LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
{
- mColorsp[mCount] = LLColor4U(r,g,b,a);
+ mColorsp[mCount].set(r, g, b, a);
}
else
{ //not using shaders or shader reads color from a uniform
- diffuseColor4ub(r,g,b,a);
+ diffuseColor4ub(r, g, b, a);
}
}
void LLRender::color4ubv(const GLubyte* c)
{
- color4ub(c[0], c[1], c[2], c[3]);
+ color4ub(c[VX], c[VY], c[VZ], c[VW]);
}
void LLRender::color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a)
{
- color4ub((GLubyte) (llclamp(r, 0.f, 1.f)*255),
- (GLubyte) (llclamp(g, 0.f, 1.f)*255),
- (GLubyte) (llclamp(b, 0.f, 1.f)*255),
- (GLubyte) (llclamp(a, 0.f, 1.f)*255));
+ color4ub((GLubyte) (llclamp(r, 0.f, 1.f) * 255),
+ (GLubyte) (llclamp(g, 0.f, 1.f) * 255),
+ (GLubyte) (llclamp(b, 0.f, 1.f) * 255),
+ (GLubyte) (llclamp(a, 0.f, 1.f) * 255));
}
void LLRender::color4fv(const GLfloat* c)
{
- color4f(c[0],c[1],c[2],c[3]);
+ color4f(c[VX], c[VY], c[VZ], c[VW]);
}
void LLRender::color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b)
{
- color4f(r,g,b,1);
+ color4f(r, g, b, 1);
}
void LLRender::color3fv(const GLfloat* c)
{
- color4f(c[0],c[1],c[2],1);
+ color4f(c[VX], c[VY], c[VZ], 1);
}
void LLRender::diffuseColor3f(F32 r, F32 g, F32 b)
@@ -1955,7 +2011,7 @@ void LLRender::diffuseColor3f(F32 r, F32 g, F32 b)
if (shader)
{
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f);
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r, g, b, 1.f);
}
}
@@ -1966,7 +2022,7 @@ void LLRender::diffuseColor3fv(const F32* c)
if (shader)
{
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f);
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[VX], c[VY], c[VZ], 1.f);
}
}
@@ -1977,7 +2033,7 @@ void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a)
if (shader)
{
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a);
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r, g, b, a);
}
}
@@ -1999,7 +2055,7 @@ void LLRender::diffuseColor4ubv(const U8* c)
if (shader)
{
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f);
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, c[3] / 255.f);
}
}
@@ -2010,11 +2066,10 @@ void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a)
if (shader)
{
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f);
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r / 255.f, g / 255.f, b / 255.f, a / 255.f);
}
}
-
void LLRender::debugTexUnits(void)
{
LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL;
@@ -2025,7 +2080,7 @@ void LLRender::debugTexUnits(void)
{
if (i == mCurrTextureUnitIndex) active_enabled = "true";
LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL;
- LL_INFOS("TextureUnit") << "Enabled As: " ;
+ LL_INFOS("TextureUnit") << "Enabled As: ";
switch (getTexUnit(i)->mCurrTexType)
{
case LLTexUnit::TT_TEXTURE:
@@ -2112,10 +2167,10 @@ glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec)
y.splat(vec.y);
z.splat(vec.z);
- s.splat<3>(mat[0].data);
- t.splat<3>(mat[1].data);
- p.splat<3>(mat[2].data);
- q.splat<3>(mat[3].data);
+ s.splat<3>(mat[VX].data);
+ t.splat<3>(mat[VY].data);
+ p.splat<3>(mat[VZ].data);
+ q.splat<3>(mat[VW].data);
s.mul(x);
t.mul(y);
@@ -2124,12 +2179,12 @@ glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec)
t.add(p);
q.add(t);
- x.mul(mat[0].data);
- y.mul(mat[1].data);
- z.mul(mat[2].data);
+ x.mul(mat[VX].data);
+ y.mul(mat[VY].data);
+ z.mul(mat[VZ].data);
x.add(y);
- z.add(mat[3].data);
+ z.add(mat[VW].data);
LLVector4a res;
res.load3(glm::value_ptr(vec));
res.setAdd(x, z);
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 7162ce51a4..410ef6f560 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -47,6 +47,7 @@
#include <array>
#include <list>
+#include <vector>
class LLVertexBuffer;
class LLCubeMap;
@@ -456,9 +457,16 @@ public:
void diffuseColor4ubv(const U8* c);
void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);
- void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count);
- void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count);
- void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count);
+ void transform(LLVector3& vert);
+ void transform(LLVector4a& vert);
+ void untransform(LLVector3& vert);
+
+ void batchTransform(LLVector4a* verts, U32 vert_count);
+
+ void vertexBatchPreTransformed(const std::vector<LLVector4a>& verts);
+ void vertexBatchPreTransformed(const LLVector4a* verts, std::size_t vert_count);
+ void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, std::size_t vert_count);
+ void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U*, std::size_t vert_count);
void setColorMask(bool writeColor, bool writeAlpha);
void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha);
@@ -532,8 +540,8 @@ private:
eBlendFactor mCurrBlendAlphaSFactor;
eBlendFactor mCurrBlendAlphaDFactor;
- std::vector<LLVector3> mUIOffset;
- std::vector<LLVector3> mUIScale;
+ std::vector<LLVector4a> mUIOffset;
+ std::vector<LLVector4a> mUIScale;
};
extern F32 gGLModelView[16];
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
index 9144ce6d62..90c1caba79 100644
--- a/indra/llrender/llrender2dutils.cpp
+++ b/indra/llrender/llrender2dutils.cpp
@@ -450,7 +450,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
gGL.color4fv(color.mV);
- constexpr S32 NUM_VERTICES = 9 * 2 * 3; // 9 quads, 2 triangles per quad, 3 vertices per triangle
+ constexpr U32 NUM_VERTICES = 9 * 2 * 3; // 9 quads, 2 triangles per quad, 3 vertices per triangle
static thread_local LLVector2 uv[NUM_VERTICES];
static thread_local LLVector4a pos[NUM_VERTICES];
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 0e4aa2ee7a..f39615a37d 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -51,6 +51,7 @@ void check_framebuffer_status()
}
bool LLRenderTarget::sUseFBO = false;
+bool LLRenderTarget::sClearOnInvalidate = false;
U32 LLRenderTarget::sCurFBO = 0;
@@ -476,6 +477,13 @@ void LLRenderTarget::clear(U32 mask_in)
}
}
+void LLRenderTarget::invalidate(U32 mask_in)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ if (!sClearOnInvalidate) { return; }
+ clear(mask_in);
+}
+
U32 LLRenderTarget::getTexture(U32 attachment) const
{
if (attachment >= mTex.size())
@@ -590,7 +598,6 @@ void LLRenderTarget::swapFBORefs(LLRenderTarget& other)
llassert(!other.isBoundInStack());
// Must be same type
- llassert(sUseFBO == other.sUseFBO);
llassert(mResX == other.mResX);
llassert(mResY == other.mResY);
llassert(mInternalFormat == other.mInternalFormat);
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index cd3290cf66..f066534cf4 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -63,6 +63,7 @@ class LLRenderTarget
public:
// Whether or not to use FBO implementation
static bool sUseFBO;
+ static bool sClearOnInvalidate;
static U32 sBytesAllocated;
static U32 sCurFBO;
static U32 sCurResX;
@@ -128,11 +129,17 @@ public:
// Asserts that this target is not currently bound in the stack
void bindTarget();
- //clear render targer, clears depth buffer if present,
+ //clear render target, clears depth buffer if present,
//uses scissor rect if in copy-to-texture mode
// asserts that this target is currently bound
void clear(U32 mask = 0xFFFFFFFF);
+ //same as clear, except may be a no-op depending on configuration
+ //useful to indicate the buffer is about to be overwritten and we
+ //don't care about its previous contents
+ //depending on the GPU, one may be more expensive than the other
+ void invalidate(U32 mask = 0xFFFFFFFF);
+
//get applied viewport
void getViewport(S32* viewport);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 150277c8df..796805e2a5 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1190,8 +1190,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("gltf_material_id"); // (GLTF)
mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF)
+ mReservedUniforms.push_back("terrain_stamp_scale");
- llassert(mReservedUniforms.size() == LLShaderMgr::TERRAIN_TEXTURE_TRANSFORMS +1);
+ llassert(mReservedUniforms.size() == LLShaderMgr::TERRAIN_STAMP_SCALE +1);
mReservedUniforms.push_back("viewport");
@@ -1300,9 +1301,6 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("shadow_matrix");
mReservedUniforms.push_back("env_mat");
mReservedUniforms.push_back("shadow_clip");
- mReservedUniforms.push_back("sun_wash");
- mReservedUniforms.push_back("shadow_noise");
- mReservedUniforms.push_back("blur_size");
mReservedUniforms.push_back("ssao_radius");
mReservedUniforms.push_back("ssao_max_radius");
mReservedUniforms.push_back("ssao_factor");
@@ -1318,8 +1316,6 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("moon_dir");
mReservedUniforms.push_back("shadow_res");
mReservedUniforms.push_back("proj_shadow_res");
- mReservedUniforms.push_back("depth_cutoff");
- mReservedUniforms.push_back("norm_cutoff");
mReservedUniforms.push_back("shadow_target_width");
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH + 1);
@@ -1369,9 +1365,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("noiseMap");
mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");
- mReservedUniforms.push_back("bloomMap");
mReservedUniforms.push_back("projectionMap");
- mReservedUniforms.push_back("norm_mat");
mReservedUniforms.push_back("specular_color");
mReservedUniforms.push_back("env_intensity");
@@ -1450,10 +1444,6 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("sun_size");
mReservedUniforms.push_back("fog_color");
- mReservedUniforms.push_back("transmittance_texture");
- mReservedUniforms.push_back("scattering_texture");
- mReservedUniforms.push_back("single_mie_scattering_texture");
- mReservedUniforms.push_back("irradiance_texture");
mReservedUniforms.push_back("blend_factor");
mReservedUniforms.push_back("moisture_level");
mReservedUniforms.push_back("droplet_radius");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 0eb9db6715..ff07ce454b 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -67,6 +67,7 @@ public:
GLTF_MATERIAL_ID, // "gltf_material_id" (GLTF)
TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF)
+ TERRAIN_STAMP_SCALE, // "terrain_stamp_scale"
VIEWPORT, // "viewport"
LIGHT_POSITION, // "light_position"
@@ -157,9 +158,6 @@ public:
DEFERRED_SHADOW_MATRIX, // "shadow_matrix"
DEFERRED_ENV_MAT, // "env_mat"
DEFERRED_SHADOW_CLIP, // "shadow_clip"
- DEFERRED_SUN_WASH, // "sun_wash"
- DEFERRED_SHADOW_NOISE, // "shadow_noise"
- DEFERRED_BLUR_SIZE, // "blur_size"
DEFERRED_SSAO_RADIUS, // "ssao_radius"
DEFERRED_SSAO_MAX_RADIUS, // "ssao_max_radius"
DEFERRED_SSAO_FACTOR, // "ssao_factor"
@@ -175,8 +173,6 @@ public:
DEFERRED_MOON_DIR, // "moon_dir"
DEFERRED_SHADOW_RES, // "shadow_res"
DEFERRED_PROJ_SHADOW_RES, // "proj_shadow_res"
- DEFERRED_DEPTH_CUTOFF, // "depth_cutoff"
- DEFERRED_NORM_CUTOFF, // "norm_cutoff"
DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width"
DEFERRED_SSR_ITR_COUNT, // "iterationCount"
@@ -221,9 +217,7 @@ public:
DEFERRED_NOISE, // "noiseMap"
DEFERRED_LIGHTFUNC, // "lightFunc"
DEFERRED_LIGHT, // "lightMap"
- DEFERRED_BLOOM, // "bloomMap"
DEFERRED_PROJECTION, // "projectionMap"
- DEFERRED_NORM_MATRIX, // "norm_mat"
SPECULAR_COLOR, // "specular_color"
ENVIRONMENT_INTENSITY, // "env_intensity"
@@ -301,13 +295,7 @@ public:
SUN_SIZE, // "sun_size"
FOG_COLOR, // "fog_color"
- // precomputed textures
- TRANSMITTANCE_TEX, // "transmittance_texture"
- SCATTER_TEX, // "scattering_texture"
- SINGLE_MIE_SCATTER_TEX, // "single_mie_scattering_texture"
- ILLUMINANCE_TEX, // "irradiance_texture"
BLEND_FACTOR, // "blend_factor"
-
MOISTURE_LEVEL, // "moisture_level"
DROPLET_RADIUS, // "droplet_radius"
ICE_LEVEL, // "ice_level"
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;