Apertura del repositorio

This commit is contained in:
2025-05-24 18:09:39 -03:00
parent 76e6359dad
commit d883ddd0d0
35253 changed files with 2891973 additions and 2 deletions
+112
View File
@@ -0,0 +1,112 @@
# -*- cmake -*-
project(llrender)
include(00-Common)
include(OpenGL)
include(FreeType)
include(LLCommon)
include(LLImage)
include(LLWindow)
set(llrender_SOURCE_FILES
llatmosphere.cpp
llcubemap.cpp
llcubemaparray.cpp
llfontbitmapcache.cpp
llfontfreetype.cpp
llfontfreetypesvg.cpp
llfontgl.cpp
llfontvertexbuffer.cpp
llfontregistry.cpp
llgl.cpp
llglslshader.cpp
llgltexture.cpp
llimagegl.cpp
llpostprocess.cpp
llrender.cpp
llrender2dutils.cpp
llrendernavprim.cpp
llrendersphere.cpp
llrendertarget.cpp
llshadermgr.cpp
lltexture.cpp
lltexturemanagerbridge.cpp
lluiimage.cpp
llvertexbuffer.cpp
llglcommonfunc.cpp
)
set(llrender_HEADER_FILES
CMakeLists.txt
llatmosphere.h
llcubemap.h
llcubemaparray.h
llfontgl.h
llfontvertexbuffer.h
llfontfreetype.h
llfontfreetypesvg.h
llfontbitmapcache.h
llfontregistry.h
llgl.h
llglheaders.h
llglslshader.h
llglstates.h
llgltexture.h
llgltypes.h
llimagegl.h
llpostprocess.h
llrender.h
llrender2dutils.h
llrendernavprim.h
llrendersphere.h
llshadermgr.h
lltexture.h
lltexturemanagerbridge.h
lluiimage.h
lluiimage.inl
llvertexbuffer.h
llglcommonfunc.h
)
list(APPEND llrender_SOURCE_FILES ${llrender_HEADER_FILES})
if (BUILD_HEADLESS)
add_library (llrenderheadless
${llrender_SOURCE_FILES}
)
set_property(TARGET llrenderheadless
PROPERTY COMPILE_DEFINITIONS LL_MESA=1 LL_MESA_HEADLESS=1
)
target_link_libraries(llrenderheadless
llcommon
llimage
llmath
llrender
llxml
llfilesystem
)
endif (BUILD_HEADLESS)
add_library (llrender ${llrender_SOURCE_FILES})
target_include_directories( llrender INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
set_property(TARGET llrender PROPERTY POSITION_INDEPENDENT_CODE ON)
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
target_link_libraries(llrender
llcommon
llimage
llmath
llfilesystem
llxml
llwindow
ll::freetype
OpenGL::GL
OpenGL::GLU
)
+290
View File
@@ -0,0 +1,290 @@
/**
* @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.0f, 1.0f, -1.0f / (F32)kRayleighScaleHeight, 0.0f, 0.0f);
DensityLayer mie_density(0.0f, 1.0f, -1.0f / (F32)kMieScaleHeight, 0.0f, 0.0f);
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.0f, 0.0f, 0.0f, 1.0f / 15000.0f, -2.0f / 3.0f));
m_absorptionProfile.push_back(DensityLayer(0.0f, 0.0f, 0.0f, -1.0f / 15000.0f, 8.0f / 3.0f));
}
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;
}
+173
View File
@@ -0,0 +1,173 @@
/**
* @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
+337
View File
@@ -0,0 +1,337 @@
/**
* @file llcubemap.cpp
* @brief LLCubeMap class implementation
*
* $LicenseInfo:firstyear=2002&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 "llworkerthread.h"
#include "llcubemap.h"
#include "v4coloru.h"
#include "v3math.h"
#include "v3dmath.h"
#include "m3math.h"
#include "m4math.h"
#include "llrender.h"
#include "llglslshader.h"
#include "llglheaders.h"
namespace {
const U16 RESOLUTION = 64;
}
bool LLCubeMap::sUseCubeMaps = true;
LLCubeMap::LLCubeMap(bool init_as_srgb)
: mTextureStage(0),
mMatrixStage(0),
mIssRGB(init_as_srgb)
{
mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
}
LLCubeMap::~LLCubeMap()
{
}
void LLCubeMap::initGL()
{
llassert(gGLManager.mInited);
if (LLCubeMap::sUseCubeMaps)
{
// Not initialized, do stuff.
if (mImages[0].isNull())
{
U32 texname = 0;
LLImageGL::generateTextures(1, &texname);
for (int i = 0; i < 6; i++)
{
mImages[i] = new LLImageGL(RESOLUTION, RESOLUTION, 4, false);
#if USE_SRGB_DECODE
if (mIssRGB) {
mImages[i]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA);
}
#endif
mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4);
mImages[i]->createGLTexture(0, mRawImages[i], texname);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
}
gGL.getTexUnit(0)->disable();
}
disable();
}
else
{
LL_WARNS() << "Using cube map without extension!" << LL_ENDL;
}
}
void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages)
{
bool flip_x[6] = { false, true, false, false, true, false };
bool flip_y[6] = { true, true, true, false, true, true };
bool transpose[6] = { false, false, false, false, true, true };
// Yes, I know that this is inefficient! - djs 08/08/02
for (int i = 0; i < 6; i++)
{
LLImageDataSharedLock lockIn(rawimages[i]);
LLImageDataLock lockOut(mRawImages[i]);
const U8 *sd = rawimages[i]->getData();
U8 *td = mRawImages[i]->getData();
S32 offset = 0;
S32 sx, sy, so;
for (int y = 0; y < 64; y++)
{
for (int x = 0; x < 64; x++)
{
sx = x;
sy = y;
if (flip_y[i])
{
sy = 63 - y;
}
if (flip_x[i])
{
sx = 63 - x;
}
if (transpose[i])
{
S32 temp = sx;
sx = sy;
sy = temp;
}
so = 64*sy + sx;
so *= 4;
*(td + offset++) = *(sd + so++);
*(td + offset++) = *(sd + so++);
*(td + offset++) = *(sd + so++);
*(td + offset++) = *(sd + so++);
}
}
}
}
void LLCubeMap::initGLData()
{
LL_PROFILE_ZONE_SCOPED;
for (int i = 0; i < 6; i++)
{
mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION);
}
}
void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
{
if (!gGLManager.mIsDisabled)
{
initGL();
initRawData(rawimages);
initGLData();
}
}
void LLCubeMap::initReflectionMap(U32 resolution, U32 components)
{
U32 texname = 0;
LLImageGL::generateTextures(1, &texname);
mImages[0] = new LLImageGL(resolution, resolution, components, true);
mImages[0]->setTexName(texname);
mImages[0]->setTarget(mTargets[0], LLTexUnit::TT_CUBE_MAP);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
}
void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages)
{
llassert(rawimages.size() == 6);
U32 texname = 0;
LLImageGL::generateTextures(1, &texname);
U32 resolution = rawimages[0]->getWidth();
U32 components = rawimages[0]->getComponents();
for (int i = 0; i < 6; i++)
{
llassert(rawimages[i]->getWidth() == resolution);
llassert(rawimages[i]->getHeight() == resolution);
llassert(rawimages[i]->getComponents() == components);
mImages[i] = new LLImageGL(resolution, resolution, components, true);
mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
mRawImages[i] = rawimages[i];
mImages[i]->createGLTexture(0, mRawImages[i], texname);
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
mImages[i]->setSubImage(mRawImages[i], 0, 0, resolution, resolution);
}
enableTexture(0);
bind();
mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
gGL.getTexUnit(0)->disable();
disable();
}
void LLCubeMap::generateMipMaps()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
mImages[0]->setUseMipMaps(true);
mImages[0]->setHasMipMaps(true);
enableTexture(0);
bind();
mImages[0]->setFilteringOption(LLTexUnit::TFO_BILINEAR);
{
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cmgmm - glGenerateMipmap");
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
}
gGL.getTexUnit(0)->disable();
disable();
}
GLuint LLCubeMap::getGLName()
{
return mImages[0]->getTexName();
}
void LLCubeMap::bind()
{
gGL.getTexUnit(mTextureStage)->bind(this);
}
void LLCubeMap::enable(S32 stage)
{
enableTexture(stage);
}
void LLCubeMap::enableTexture(S32 stage)
{
mTextureStage = stage;
if (stage >= 0 && LLCubeMap::sUseCubeMaps)
{
gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
}
}
void LLCubeMap::disable(void)
{
disableTexture();
}
void LLCubeMap::disableTexture(void)
{
if (mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
{
gGL.getTexUnit(mTextureStage)->disable();
if (mTextureStage == 0)
{
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
}
}
}
void LLCubeMap::setMatrix(S32 stage)
{
mMatrixStage = stage;
if (mMatrixStage < 0) return;
//if (stage > 0)
{
gGL.getTexUnit(stage)->activate();
}
LLVector3 x(gGLModelView+0);
LLVector3 y(gGLModelView+4);
LLVector3 z(gGLModelView+8);
LLMatrix3 mat3;
mat3.setRows(x,y,z);
LLMatrix4 trans(mat3);
trans.transpose();
gGL.matrixMode(LLRender::MM_TEXTURE);
gGL.pushMatrix();
gGL.loadMatrix((F32 *)trans.mMatrix);
gGL.matrixMode(LLRender::MM_MODELVIEW);
/*if (stage > 0)
{
gGL.getTexUnit(0)->activate();
}*/
}
void LLCubeMap::restoreMatrix()
{
if (mMatrixStage < 0) return;
//if (mMatrixStage > 0)
{
gGL.getTexUnit(mMatrixStage)->activate();
}
gGL.matrixMode(LLRender::MM_TEXTURE);
gGL.popMatrix();
gGL.matrixMode(LLRender::MM_MODELVIEW);
/*if (mMatrixStage > 0)
{
gGL.getTexUnit(0)->activate();
}*/
}
void LLCubeMap::destroyGL()
{
for (S32 i = 0; i < 6; i++)
{
mImages[i] = NULL;
}
}
+92
View File
@@ -0,0 +1,92 @@
/**
* @file llcubemap.h
* @brief LLCubeMap class definition
*
* $LicenseInfo:firstyear=2002&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_LLCUBEMAP_H
#define LL_LLCUBEMAP_H
#include "llgl.h"
#include <vector>
class LLVector3;
// Environment map hack!
class LLCubeMap : public LLRefCount
{
bool mIssRGB;
public:
LLCubeMap(bool init_as_srgb);
void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
// initialize as an undefined cubemap at the given resolution
// used for render-to-cubemap operations
// avoids usage of LLImageRaw
void initReflectionMap(U32 resolution, U32 components = 3);
// init from environment map images
// Similar to init, but takes ownership of rawimages and makes this cubemap
// respect the resolution of rawimages
// Raw images must point to array of six square images that are all the same resolution
void initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGL();
void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGLData();
void bind();
void enable(S32 stage);
void enableTexture(S32 stage);
S32 getStage(void) { return mTextureStage; }
void disable(void);
void disableTexture(void);
void setMatrix(S32 stage);
void restoreMatrix();
U32 getResolution() { return mImages[0].notNull() ? mImages[0]->getWidth(0) : 0; }
// generate mip maps for this Cube Map using GL
// NOTE: Cube Map MUST already be resident in VRAM
void generateMipMaps();
GLuint getGLName();
void destroyGL();
public:
static bool sUseCubeMaps;
protected:
friend class LLTexUnit;
~LLCubeMap();
LLGLenum mTargets[6];
LLPointer<LLImageGL> mImages[6];
LLPointer<LLImageRaw> mRawImages[6];
S32 mTextureStage;
S32 mMatrixStage;
};
#endif
+219
View File
@@ -0,0 +1,219 @@
/**
* @file llcubemaparray.cpp
* @brief LLCubeMap class implementation
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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 "llworkerthread.h"
#include "llcubemaparray.h"
#include "v4coloru.h"
#include "v3math.h"
#include "v3dmath.h"
#include "m3math.h"
#include "m4math.h"
#include "llrender.h"
#include "llglslshader.h"
#include "llglheaders.h"
//#pragma optimize("", off)
using namespace LLImageGLMemory;
// MUST match order of OpenGL face-layers
GLenum LLCubeMapArray::sTargets[6] =
{
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};
LLVector3 LLCubeMapArray::sLookVecs[6] =
{
LLVector3(1, 0, 0),
LLVector3(-1, 0, 0),
LLVector3(0, 1, 0),
LLVector3(0, -1, 0),
LLVector3(0, 0, 1),
LLVector3(0, 0, -1)
};
LLVector3 LLCubeMapArray::sUpVecs[6] =
{
LLVector3(0, -1, 0),
LLVector3(0, -1, 0),
LLVector3(0, 0, 1),
LLVector3(0, 0, -1),
LLVector3(0, -1, 0),
LLVector3(0, -1, 0)
};
LLVector3 LLCubeMapArray::sClipToCubeLookVecs[6] =
{
LLVector3(0, 0, -1), //GOOD
LLVector3(0, 0, 1), //GOOD
LLVector3(1, 0, 0), // GOOD
LLVector3(1, 0, 0), // GOOD
LLVector3(1, 0, 0),
LLVector3(-1, 0, 0),
};
LLVector3 LLCubeMapArray::sClipToCubeUpVecs[6] =
{
LLVector3(-1, 0, 0), //GOOD
LLVector3(1, 0, 0), //GOOD
LLVector3(0, 1, 0), // GOOD
LLVector3(0, -1, 0), // GOOD
LLVector3(0, 0, -1),
LLVector3(0, 0, 1)
};
LLCubeMapArray::LLCubeMapArray()
: mTextureStage(0)
{
}
LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTextureStage(0)
{
mWidth = width;
mCount = count;
// Allocate a new cubemap array with the same criteria as the incoming cubemap array
allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR);
// Copy each cubemap from the incoming array to the new array
U32 min_count = std::min(count, lhs.mCount);
for (U32 i = 0; i < min_count * 6; ++i)
{
U32 src_resolution = lhs.mWidth;
U32 dst_resolution = mWidth;
{
GLint components = GL_RGB;
if (mImage->getComponents() == 4)
components = GL_RGBA;
GLint format = GL_RGB;
// Handle different resolutions by scaling the image
LLPointer<LLImageRaw> src_image = new LLImageRaw(lhs.mWidth, lhs.mWidth, lhs.mImage->getComponents());
glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, components, GL_UNSIGNED_BYTE, src_image->getData());
LLPointer<LLImageRaw> scaled_image = src_image->scaled(mWidth, mWidth);
glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData());
}
}
}
LLCubeMapArray::~LLCubeMapArray()
{
}
void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool use_mips, bool hdr)
{
U32 texname = 0;
mWidth = resolution;
mCount = count;
mHDR = hdr;
LLImageGL::generateTextures(1, &texname);
mImage = new LLImageGL(resolution, resolution, components, use_mips);
mImage->setTexName(texname);
mImage->setTarget(sTargets[0], LLTexUnit::TT_CUBE_MAP_ARRAY);
mImage->setUseMipMaps(use_mips);
mImage->setHasMipMaps(use_mips);
bind(0);
free_cur_tex_image();
U32 format = components == 4 ? GL_RGBA16F : GL_R11F_G11F_B10F;
if (!hdr)
{
format = components == 4 ? GL_RGBA8 : GL_RGB8;
}
U32 mip = 0;
U32 mip_resolution = resolution;
while (mip_resolution >= 1)
{
glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, mip_resolution, mip_resolution, count * 6, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
if (!use_mips)
{
break;
}
mip_resolution /= 2;
++mip;
}
alloc_tex_image(resolution, resolution, format, count * 6);
mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
if (use_mips)
{
mImage->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
//glGenerateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY); // <=== latest AMD drivers do not appreciate this method of allocating mipmaps
}
else
{
mImage->setFilteringOption(LLTexUnit::TFO_BILINEAR);
}
unbind();
}
void LLCubeMapArray::bind(S32 stage)
{
mTextureStage = stage;
gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_CUBE_MAP_ARRAY, getGLName(), mImage->getUseMipMaps());
}
void LLCubeMapArray::unbind()
{
gGL.getTexUnit(mTextureStage)->unbind(LLTexUnit::TT_CUBE_MAP_ARRAY);
mTextureStage = -1;
}
GLuint LLCubeMapArray::getGLName()
{
return mImage->getTexName();
}
void LLCubeMapArray::destroyGL()
{
mImage = NULL;
}
+78
View File
@@ -0,0 +1,78 @@
/**
* @file llcubemaparray.h
* @brief LLCubeMap class definition
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, 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$
*/
#pragma once
#include "llgl.h"
#include <vector>
class LLVector3;
class LLCubeMapArray : public LLRefCount
{
public:
LLCubeMapArray();
LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count);
static GLenum sTargets[6];
// look and up vectors for each cube face (agent space)
static LLVector3 sLookVecs[6];
static LLVector3 sUpVecs[6];
// look and up vectors for each cube face (clip space)
static LLVector3 sClipToCubeLookVecs[6];
static LLVector3 sClipToCubeUpVecs[6];
// allocate a cube map array
// res - resolution of each cube face
// components - number of components per pixel
// count - number of cube maps in the array
// use_mips - if true, mipmaps will be allocated for this cube map array and anisotropic filtering will be used
void allocate(U32 res, U32 components, U32 count, bool use_mips = true, bool hdr = true);
void bind(S32 stage);
void unbind();
GLuint getGLName();
void destroyGL();
// get width of cubemaps in array (they're cubes, so this is also the height)
U32 getWidth() const { return mWidth; }
// get number of cubemaps in the array
U32 getCount() const { return mCount; }
protected:
friend class LLTexUnit;
~LLCubeMapArray();
LLPointer<LLImageGL> mImage;
U32 mWidth = 0;
U32 mCount = 0;
S32 mTextureStage;
bool mHDR;
};
+188
View File
@@ -0,0 +1,188 @@
/**
* @file llfontbitmapcache.cpp
* @brief Storage for previously rendered glyphs.
*
* $LicenseInfo:firstyear=2008&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 "llgl.h"
#include "llfontbitmapcache.h"
LLFontBitmapCache::LLFontBitmapCache()
{
}
LLFontBitmapCache::~LLFontBitmapCache()
{
}
void LLFontBitmapCache::init(S32 max_char_width,
S32 max_char_height)
{
reset();
mMaxCharWidth = max_char_width;
mMaxCharHeight = max_char_height;
S32 image_width = mMaxCharWidth * 20;
S32 pow_iw = 2;
while (pow_iw < image_width)
{
pow_iw <<= 1;
}
image_width = pow_iw;
image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
mBitmapWidth = image_width;
mBitmapHeight = image_width;
}
LLImageRaw *LLFontBitmapCache::getImageRaw(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
const U32 bitmap_idx = static_cast<U32>(bitmap_type);
if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageRawVec[bitmap_idx].size())
return nullptr;
return mImageRawVec[bitmap_idx][bitmap_num];
}
LLImageGL *LLFontBitmapCache::getImageGL(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
const U32 bitmap_idx = static_cast<U32>(bitmap_type);
if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageGLVec[bitmap_idx].size())
return nullptr;
return mImageGLVec[bitmap_idx][bitmap_num];
}
bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyphType bitmap_type, U32& bitmap_num)
{
if (bitmap_type >= EFontGlyphType::Count)
{
return false;
}
const U32 bitmap_idx = static_cast<U32>(bitmap_type);
if (mImageRawVec[bitmap_idx].empty() || (mCurrentOffsetX[bitmap_idx] + width + 1) > mBitmapWidth)
{
if ((mImageRawVec[bitmap_idx].empty()) || (mCurrentOffsetY[bitmap_idx] + 2*mMaxCharHeight + 2) > mBitmapHeight)
{
// We're out of space in the current image, or no image
// has been allocated yet. Make a new one.
S32 image_width = mMaxCharWidth * 20;
S32 pow_iw = 2;
while (pow_iw < image_width)
{
pow_iw *= 2;
}
image_width = pow_iw;
image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
S32 image_height = image_width;
mBitmapWidth = image_width;
mBitmapHeight = image_height;
S32 num_components = getNumComponents(bitmap_type);
mImageRawVec[bitmap_idx].emplace_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
bitmap_num = static_cast<U32>(mImageRawVec[bitmap_idx].size()) - 1;
LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
if (EFontGlyphType::Grayscale == bitmap_type)
{
image_raw->clear(255, 0);
}
// Make corresponding GL image.
mImageGLVec[bitmap_idx].emplace_back(new LLImageGL(image_raw, false, false));
LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
// Start at beginning of the new image.
mCurrentOffsetX[bitmap_idx] = 1;
mCurrentOffsetY[bitmap_idx] = 1;
// Attach corresponding GL texture. (*TODO: is this needed?)
gGL.getTexUnit(0)->bind(image_gl);
image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(true, true);
}
else
{
// Move to next row in current image.
mCurrentOffsetX[bitmap_idx] = 1;
mCurrentOffsetY[bitmap_idx] += mMaxCharHeight + 1;
}
}
pos_x = mCurrentOffsetX[bitmap_idx];
pos_y = mCurrentOffsetY[bitmap_idx];
bitmap_num = getNumBitmaps(bitmap_type) - 1;
mCurrentOffsetX[bitmap_idx] += width + 1;
mGeneration++;
return true;
}
void LLFontBitmapCache::destroyGL()
{
for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
{
for (LLImageGL* image_gl : mImageGLVec[idx])
{
image_gl->destroyGLTexture();
}
}
}
void LLFontBitmapCache::reset()
{
for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
{
mImageRawVec[idx].clear();
mImageGLVec[idx].clear();
mCurrentOffsetX[idx] = 1;
mCurrentOffsetY[idx] = 1;
}
mBitmapWidth = 0;
mBitmapHeight = 0;
mGeneration++;
}
//static
U32 LLFontBitmapCache::getNumComponents(EFontGlyphType bitmap_type)
{
switch (bitmap_type)
{
case EFontGlyphType::Grayscale:
return 2;
case EFontGlyphType::Color:
return 4;
default:
llassert(false);
return 2;
}
}
+83
View File
@@ -0,0 +1,83 @@
/**
* @file llfontbitmapcache.h
* @brief Storage for previously rendered glyphs.
*
* $LicenseInfo:firstyear=2008&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_LLFONTBITMAPCACHE_H
#define LL_LLFONTBITMAPCACHE_H
#include <vector>
#include "lltrace.h"
enum class EFontGlyphType : U32
{
Grayscale = 0,
Color,
Count,
Unspecified,
};
// Maintain a collection of bitmaps containing rendered glyphs.
// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL.
class LLFontBitmapCache
{
public:
LLFontBitmapCache();
~LLFontBitmapCache();
// Need to call this once, before caching any glyphs.
void init(S32 max_char_width,
S32 max_char_height);
void reset();
bool nextOpenPos(S32 width, S32& posX, S32& posY, EFontGlyphType bitmapType, U32& bitmapNum);
void destroyGL();
LLImageRaw* getImageRaw(EFontGlyphType bitmapType, U32 bitmapNum) const;
LLImageGL* getImageGL(EFontGlyphType bitmapType, U32 bitmapNum) const;
S32 getMaxCharWidth() const { return mMaxCharWidth; }
U32 getNumBitmaps(EFontGlyphType bitmapType) const { return (bitmapType < EFontGlyphType::Count) ? static_cast<U32>(mImageRawVec[static_cast<U32>(bitmapType)].size()) : 0U; }
S32 getBitmapWidth() const { return mBitmapWidth; }
S32 getBitmapHeight() const { return mBitmapHeight; }
S32 getCacheGeneration() const { return mGeneration; }
protected:
static U32 getNumComponents(EFontGlyphType bitmap_type);
private:
S32 mBitmapWidth = 0;
S32 mBitmapHeight = 0;
S32 mCurrentOffsetX[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
S32 mCurrentOffsetY[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
S32 mMaxCharWidth = 0;
S32 mMaxCharHeight = 0;
S32 mGeneration = 0;
std::vector<LLPointer<LLImageRaw>> mImageRawVec[static_cast<U32>(EFontGlyphType::Count)];
std::vector<LLPointer<LLImageGL>> mImageGLVec[static_cast<U32>(EFontGlyphType::Count)];
};
#endif //LL_LLFONTBITMAPCACHE_H
File diff suppressed because it is too large Load Diff
+216
View File
@@ -0,0 +1,216 @@
/**
* @file llfontfreetype.h
* @brief Font library wrapper
*
* $LicenseInfo:firstyear=2002&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_LLFONTFREETYPE_H
#define LL_LLFONTFREETYPE_H
#include <boost/unordered_map.hpp>
#include "llpointer.h"
#include "llstl.h"
#include "llimagegl.h"
#include "llfontbitmapcache.h"
// Hack. FT_Face is just a typedef for a pointer to a struct,
// but there's no simple forward declarations file for FreeType,
// and the main include file is 200K.
// We'll forward declare the struct here. JC
struct FT_FaceRec_;
typedef struct FT_FaceRec_* LLFT_Face;
struct FT_StreamRec_;
typedef struct FT_StreamRec_ LLFT_Stream;
// <FS:ND> FIRE-7570. Only load/mmap fonts once.
namespace nd
{
namespace fonts
{
class LoadedFont;
}
}
// </FS:ND>
class LLFontManager
{
public:
static void initClass();
static void cleanupClass();
private:
LLFontManager();
~LLFontManager();
// <FS:ND> FIRE-7570. Only load/mmap fonts once.
public:
U8 const *loadFont( std::string const &aFilename, long &a_Size );
private:
void unloadAllFonts();
std::map< std::string, std::shared_ptr<nd::fonts::LoadedFont> > m_LoadedFonts;
// </FS:ND>
};
struct LLFontGlyphInfo
{
LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type);
LLFontGlyphInfo(const LLFontGlyphInfo& fgi);
U32 mGlyphIndex;
EFontGlyphType mGlyphType;
// Metrics
S32 mWidth; // In pixels
S32 mHeight; // In pixels
F32 mXAdvance; // In pixels
F32 mYAdvance; // In pixels
// Information for actually rendering
S32 mXBitmapOffset; // Offset to the origin in the bitmap
S32 mYBitmapOffset; // Offset to the origin in the bitmap
S32 mXBearing; // Distance from baseline to left in pixels
S32 mYBearing; // Distance from baseline to top in pixels
std::pair<EFontGlyphType, S32> mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph
};
extern LLFontManager *gFontManagerp;
class LLFontFreetype : public LLRefCount
{
public:
LLFontFreetype();
~LLFontFreetype();
// is_fallback should be true for fallback fonts that aren't used
// to render directly (Unicode backup, primarily)
bool loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n);
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);
// Global font metrics - in units of pixels
F32 getLineHeight() const;
F32 getAscenderHeight() const;
F32 getDescenderHeight() const;
// For a lowercase "g":
//
// ------------------------------
// ^ ^
// | |
// xxx x |Ascender
// x x v |
// --------- xxxx-------------- Baseline
// ^ x |
// | Descender x |
// v xxxx |LineHeight
// ----------------------- |
// v
// ------------------------------
enum
{
FIRST_CHAR = 32,
NUM_CHARS = 127 - 32,
LAST_CHAR_BASIC = 127,
// Need full 8-bit ascii range for spanish
NUM_CHARS_FULL = 255 - 32,
LAST_CHAR_FULL = 255
};
F32 getXAdvance(llwchar wc) const;
F32 getXAdvance(const LLFontGlyphInfo* glyph) const;
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters
LLFontGlyphInfo* getGlyphInfo(llwchar wch, EFontGlyphType glyph_type) const;
void reset(F32 vert_dpi, F32 horz_dpi);
void destroyGL();
const std::string& getName() const;
void dumpFontBitmaps() const;
const LLFontBitmapCache* getFontBitmapCache() const;
void setStyle(U8 style);
U8 getStyle() const;
private:
void resetBitmapCache();
void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
bool setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const;
bool hasGlyph(llwchar wch) const; // Has a glyph for this character
LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const;
void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
std::string mName;
U8 mStyle;
F32 mPointSize;
F32 mAscender;
F32 mDescender;
F32 mLineHeight;
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;
fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
// *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique)
typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
mutable LLFontBitmapCache* mFontBitmapCachep;
mutable S32 mRenderGlyphCount;
// <FS:ND> Save X-kerning data, so far only for all glyphs with index small than 256 (to not waste too much memory)
// right now it is 256 slots with 256 glyphs each, maybe consider splitting it into smaller slices to use less memory if we
// we want to cache 0xFFFF glyphs
F32 **mKerningCache;
// </FS:ND<
};
#endif // LL_FONTFREETYPE_H
+205
View File
@@ -0,0 +1,205 @@
/**
* @file llfontfreetypesvg.cpp
* @brief Freetype font library SVG glyph rendering
*
* $LicenseInfo:firstyear=2002&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 "llfontfreetypesvg.h"
#if LL_WINDOWS
#pragma warning (push)
#pragma warning (disable : 4702)
#endif
#define NANOSVG_IMPLEMENTATION
#include <nanosvg/nanosvg.h>
#define NANOSVGRAST_IMPLEMENTATION
#include <nanosvg/nanosvgrast.h>
#if LL_WINDOWS
#pragma warning (pop)
#endif
struct LLSvgRenderData
{
FT_UInt GlyphIndex = 0;
FT_Error Error = FT_Err_Ok; // FreeType currently (@2.12.1) ignores the error value returned by the preset glyph slot callback so we return it at render time
// (See https://github.com/freetype/freetype/blob/5faa1df8b93ebecf0f8fd5fe8fda7b9082eddced/src/base/ftobjs.c#L1170)
NSVGimage* pNSvgImage = nullptr;
float Scale = 0.f;
};
// static
FT_Error LLFontFreeTypeSvgRenderer::OnInit(FT_Pointer* state)
{
// The SVG driver hook state is shared across all callback invocations; since our state is lightweight
// we store it in the glyph instead.
*state = nullptr;
return FT_Err_Ok;
}
// static
void LLFontFreeTypeSvgRenderer::OnFree(FT_Pointer* state)
{
}
// static
void LLFontFreeTypeSvgRenderer::OnDataFinalizer(void* objectp)
{
FT_GlyphSlot glyph_slot = static_cast<FT_GlyphSlot>(objectp);
LLSvgRenderData* pData = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
glyph_slot->generic.data = nullptr;
glyph_slot->generic.finalizer = nullptr;
delete(pData);
}
//static
FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer*)
{
FT_SVG_Document document = static_cast<FT_SVG_Document>(glyph_slot->other);
llassert(!glyph_slot->generic.data || !cache || glyph_slot->glyph_index == ((LLSvgRenderData*)glyph_slot->generic.data)->GlyphIndex);
if (!glyph_slot->generic.data)
{
glyph_slot->generic.data = new LLSvgRenderData();
glyph_slot->generic.finalizer = LLFontFreeTypeSvgRenderer::OnDataFinalizer;
}
LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
if (!cache)
{
datap->GlyphIndex = glyph_slot->glyph_index;
datap->Error = FT_Err_Ok;
}
// NOTE: nsvgParse modifies the input string so we need a temporary copy
llassert(!datap->pNSvgImage || cache);
if (!datap->pNSvgImage)
{
char* document_buffer = new char[document->svg_document_length + 1];
memcpy(document_buffer, document->svg_document, document->svg_document_length);
document_buffer[document->svg_document_length] = '\0';
datap->pNSvgImage = nsvgParse(document_buffer, "px", 0.);
delete[] document_buffer;
}
if (!datap->pNSvgImage)
{
datap->Error = FT_Err_Invalid_SVG_Document;
return FT_Err_Invalid_SVG_Document;
}
// We don't (currently) support transformations so test for an identity rotation matrix + zero translation
if (document->transform.xx != 1 << 16 || document->transform.yx != 0 ||
document->transform.xy != 0 || document->transform.yy != 1 << 16 ||
document->delta.x > 0 || document->delta.y > 0)
{
datap->Error = FT_Err_Unimplemented_Feature;
return FT_Err_Unimplemented_Feature;
}
float svg_width = datap->pNSvgImage->width;
float svg_height = datap->pNSvgImage->height;
if (svg_width == 0.f || svg_height == 0.f)
{
svg_width = document->units_per_EM;
svg_height = document->units_per_EM;
}
float svg_x_scale = (float)document->metrics.x_ppem / floorf(svg_width);
float svg_y_scale = (float)document->metrics.y_ppem / floorf(svg_height);
float svg_scale = llmin(svg_x_scale, svg_y_scale);
datap->Scale = svg_scale;
glyph_slot->bitmap.width = (unsigned int)(floorf(svg_width) * svg_scale);
glyph_slot->bitmap.rows = (unsigned int)(floorf(svg_height) * svg_scale);
glyph_slot->bitmap_left = (document->metrics.x_ppem - glyph_slot->bitmap.width) / 2;
glyph_slot->bitmap_top = (FT_Int)(glyph_slot->face->size->metrics.ascender / 64.f);
glyph_slot->bitmap.pitch = glyph_slot->bitmap.width * 4;
glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
/* Copied as-is from fcft (MIT license) */
// Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box.
float horiBearingX = 0.f;
float horiBearingY = -(float)glyph_slot->bitmap_top;
// XXX parentheses correct?
float vertBearingX = glyph_slot->metrics.horiBearingX / 64.0f - glyph_slot->metrics.horiAdvance / 64.0f / 2;
float vertBearingY = (glyph_slot->metrics.vertAdvance / 64.0f - glyph_slot->metrics.height / 64.0f) / 2;
// Do conversion in two steps to avoid 'bad function cast' warning
glyph_slot->metrics.width = glyph_slot->bitmap.width * 64;
glyph_slot->metrics.height = glyph_slot->bitmap.rows * 64;
glyph_slot->metrics.horiBearingX = (FT_Pos)(horiBearingX * 64);
glyph_slot->metrics.horiBearingY = (FT_Pos)(horiBearingY * 64);
glyph_slot->metrics.vertBearingX = (FT_Pos)(vertBearingX * 64);
glyph_slot->metrics.vertBearingY = (FT_Pos)(vertBearingY * 64);
if (glyph_slot->metrics.vertAdvance == 0)
{
glyph_slot->metrics.vertAdvance = (FT_Pos)(glyph_slot->bitmap.rows * 1.2f * 64);
}
return FT_Err_Ok;
}
// static
FT_Error LLFontFreeTypeSvgRenderer::OnRender(FT_GlyphSlot glyph_slot, FT_Pointer*)
{
LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
llassert(FT_Err_Ok == datap->Error);
if (FT_Err_Ok != datap->Error)
{
return datap->Error;
}
// Render to glyph bitmap
NSVGrasterizer* nsvgRasterizer = nsvgCreateRasterizer();
nsvgRasterize(nsvgRasterizer, datap->pNSvgImage, 0, 0, datap->Scale, glyph_slot->bitmap.buffer, glyph_slot->bitmap.width, glyph_slot->bitmap.rows, glyph_slot->bitmap.pitch);
nsvgDeleteRasterizer(nsvgRasterizer);
nsvgDelete(datap->pNSvgImage);
datap->pNSvgImage = nullptr;
// Convert from RGBA to BGRA
U32* pixel_buffer = (U32*)glyph_slot->bitmap.buffer; U8* byte_buffer = glyph_slot->bitmap.buffer;
for (size_t y = 0, h = glyph_slot->bitmap.rows; y < h; y++)
{
for (size_t x = 0, w = glyph_slot->bitmap.pitch / 4; x < w; x++)
{
size_t pixel_idx = y * w + x;
size_t byte_idx = pixel_idx * 4;
U8 alpha = byte_buffer[byte_idx + 3];
// Store as ARGB (*TODO - do we still have to care about endianness?)
pixel_buffer[y * w + x] = alpha << 24 | (byte_buffer[byte_idx] * alpha / 0xFF) << 16 | (byte_buffer[byte_idx + 1] * alpha / 0xFF) << 8 | (byte_buffer[byte_idx + 2] * alpha / 0xFF);
}
}
glyph_slot->format = FT_GLYPH_FORMAT_BITMAP;
glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
return FT_Err_Ok;
}
+54
View File
@@ -0,0 +1,54 @@
/**
* @file llfontfreetypesvg.h
* @brief Freetype font library SVG glyph rendering
*
* $LicenseInfo:firstyear=2002&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$
*/
#pragma once
#include <ft2build.h>
#include FT_TYPES_H
#include FT_MODULE_H
#include FT_OTSVG_H
// See https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html
class LLFontFreeTypeSvgRenderer
{
public:
// Called when the very first OT-SVG glyph is rendered (across the entire lifetime of our FT_Library object)
static FT_Error OnInit(FT_Pointer* state);
// Called when the ot-svg module is being freed (but only called if the init hook was called previously)
static void OnFree(FT_Pointer* state);
// Called to preset the glyph slot, twice per glyph:
// - when FT_Load_Glyph needs to preset the glyph slot (with cache == false)
// - right before the svg module calls the render callback hook. (with cache == true)
static FT_Error OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer* state);
// Called to render an OT-SVG glyph (right after the preset hook OnPresetGlypthSlot was called with cache set to true)
static FT_Error OnRender(FT_GlyphSlot glyph_slot, FT_Pointer* state);
// Called to deallocate our per glyph slot data
static void OnDataFinalizer(void* objectp);
};
File diff suppressed because it is too large Load Diff
+261
View File
@@ -0,0 +1,261 @@
/**
* @file llfontgl.h
* @author Doug Soo
* @brief Wrapper around FreeType
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLFONTGL_H
#define LL_LLFONTGL_H
#include "llcoord.h"
#include "llfontregistry.h"
#include "llimagegl.h"
#include "llpointer.h"
#include "llrect.h"
#include "v2math.h"
class LLColor4;
// Key used to request a font.
class LLFontDescriptor;
class LLFontFreetype;
// Structure used to store previously requested fonts.
class LLFontRegistry;
class LLFontGL
{
public:
enum HAlign
{
// Horizontal location of x,y coord to render.
LEFT = 0, // Left align
RIGHT = 1, // Right align
HCENTER = 2, // Center
};
enum VAlign
{
// Vertical location of x,y coord to render.
TOP = 3, // Top align
VCENTER = 4, // Center
BASELINE = 5, // Baseline
BOTTOM = 6 // Bottom
};
enum StyleFlags
{
// text style to render. May be combined (these are bit flags)
NORMAL = 0x00,
BOLD = 0x01,
ITALIC = 0x02,
UNDERLINE = 0x04
};
enum ShadowType
{
NO_SHADOW,
DROP_SHADOW,
DROP_SHADOW_SOFT
};
LLFontGL();
~LLFontGL();
void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font.
void destroyGL();
bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);
S32 getNumFaces(const std::string& filename);
S32 getCacheGeneration() const;
S32 render(const LLWString &text, S32 begin_offset,
const LLRect& rect,
const LLColor4 &color,
HAlign halign = LEFT, VAlign valign = BASELINE,
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x=NULL,
bool use_ellipses = false,
bool use_color = true) const;
S32 render(const LLWString &text, S32 begin_offset,
const LLRectf& rect,
const LLColor4 &color,
HAlign halign = LEFT, VAlign valign = BASELINE,
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x=NULL,
bool use_ellipses = false,
bool use_color = true) const;
S32 render(const LLWString &text, S32 begin_offset,
F32 x, F32 y,
const LLColor4 &color,
HAlign halign = LEFT, VAlign valign = BASELINE,
U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x=NULL,
bool use_ellipses = false,
bool use_color = true) const;
S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
// renderUTF8 does a conversion, so is slower!
S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x = NULL, bool use_ellipses = false, bool use_color = true) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
// font metrics - override for LLFontFreetype that returns units of virtual pixels
F32 getAscenderHeight() const;
F32 getDescenderHeight() const;
S32 getLineHeight() const;
S32 getWidth(const std::string& utf8text) const;
S32 getWidth(const llwchar* wchars) const;
S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars) const;
S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars) const;
F32 getWidthF32(const std::string& utf8text) const;
F32 getWidthF32(const llwchar* wchars) const;
F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars) const;
F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, bool no_padding = false) const;
// The following are called often, frequently with large buffers, so do not use a string interface
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
typedef enum e_word_wrap_style
{
ONLY_WORD_BOUNDARIES,
WORD_BOUNDARY_IF_POSSIBLE,
ANYWHERE
} EWordWrapStyle ;
S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, EWordWrapStyle end_on_word_boundary = ANYWHERE) const;
// Returns the index of the first complete characters from text that can be drawn in max_pixels
// given that the character at start_pos should be the last character (or as close to last as possible).
S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;
// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, bool round = true) const;
const LLFontDescriptor& getFontDesc() const;
void generateASCIIglyphs();
static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::string& fonts_file, F32 size_mod = 0, bool create_gl_textures = true);
void dumpTextures();
static void dumpFonts();
static void dumpFontTextures();
// Load sans-serif, sans-serif-small, etc.
// Slow, requires multiple seconds to load fonts.
static bool loadDefaultFonts();
static void loadCommonFonts();
static void destroyDefaultFonts();
static void destroyAllGL();
// Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC"
static U8 getStyleFromString(const std::string &style);
static std::string getStringFromStyle(U8 style);
static std::string nameFromFont(const LLFontGL* fontp);
static std::string sizeFromFont(const LLFontGL* fontp);
static std::string nameFromHAlign(LLFontGL::HAlign align);
static LLFontGL::HAlign hAlignFromName(const std::string& name);
static std::string nameFromVAlign(LLFontGL::VAlign align);
static LLFontGL::VAlign vAlignFromName(const std::string& name);
static void setFontDisplay(bool flag) { sDisplayFont = flag; }
// <FS:Beq> Add B&W emoji font support
//static LLFontGL* getFontEmojiSmall();
//static LLFontGL* getFontEmojiMedium();
//static LLFontGL* getFontEmojiLarge();
//static LLFontGL* getFontEmojiHuge();
static LLFontGL* getFontEmojiSmall(bool useBW = false);
static LLFontGL* getFontEmojiMedium(bool useBW = false);
static LLFontGL* getFontEmojiLarge(bool useBW = false);
static LLFontGL* getFontEmojiHuge(bool useBW = false);
// </FS:Beq> Add B&W emoji font support
static LLFontGL* getFontMonospace();
static LLFontGL* getFontSansSerifSmall();
static LLFontGL* getFontSansSerifSmallBold();
static LLFontGL* getFontSansSerifSmallItalic();
static LLFontGL* getFontSansSerif();
static LLFontGL* getFontSansSerifBig();
static LLFontGL* getFontSansSerifHuge();
static LLFontGL* getFontSansSerifBold();
// <FS:CR> Advanced script editor
static LLFontGL* getFontScripting();
static LLFontGL* getFontOCRA();
static LLFontGL* getFontCascadia();
// </FS:CR>
static LLFontGL* getFont(const LLFontDescriptor& desc);
// Use with legacy names like "SANSSERIF_SMALL" or "OCRA"
static LLFontGL* getFontByName(const std::string& name);
static LLFontGL* getFontDefault(); // default fallback font
static std::string getFontPathLocal();
static std::string getFontPathSystem();
static LLCoordGL sCurOrigin;
static F32 sCurDepth;
static std::vector<std::pair<LLCoordGL, F32> > sOriginStack;
static LLColor4 sShadowColor;
static F32 sVertDPI;
static F32 sHorizDPI;
static F32 sScaleX;
static F32 sScaleY;
static S32 sResolutionGeneration;
static bool sDisplayFont ;
static std::string sAppDir; // For loading fonts
private:
friend class LLFontRegistry;
friend class LLTextBillboard;
friend class LLHUDText;
LLFontGL(const LLFontGL &source);
LLFontGL &operator=(const LLFontGL &source);
LLFontDescriptor mFontDescriptor;
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;
// Registry holds all instantiated fonts.
static LLFontRegistry* sFontRegistry;
};
#endif
+830
View File
@@ -0,0 +1,830 @@
/**
* @file llfontregistry.cpp
* @author Brad Payne
* @brief Storage for fonts.
*
* $LicenseInfo:firstyear=2008&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 "llgl.h"
#include "llfontfreetype.h"
#include "llfontgl.h"
#include "llfontregistry.h"
#include <boost/tokenizer.hpp>
#include "llcontrol.h"
#include "lldir.h"
#include "llwindow.h"
#include "llxmlnode.h"
extern LLControlGroup gSavedSettings;
using std::string;
using std::map;
bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc);
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);
const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/";
const std::string MACOSX_FONT_SUPPLEMENTAL = "Supplemental/";
// <FS:Beq> font functors with UI control access
static bool isEmojiUseBW(llwchar wch)
{
static LLCachedControl<bool> emoji_use_bw(gSavedSettings, "FSUseEmojiBW", false);
if(emoji_use_bw)
{
return (LLStringOps::isEmoji(wch));
}
return false;
}
static bool isEmojiUseColor(llwchar wch)
{
static LLCachedControl<bool> emoji_use_bw(gSavedSettings, "FSUseEmojiBW", false);
if(!emoji_use_bw)
{
return (LLStringOps::isEmoji(wch));
}
return false;
}
// </FS:Beq>
LLFontDescriptor::char_functor_map_t LLFontDescriptor::mCharFunctors({
{ "is_emoji", LLStringOps::isEmoji }
, { "is_emoji_use_color", isEmojiUseColor }
, { "is_emoji_use_bw", isEmojiUseBW }
});
LLFontDescriptor::LLFontDescriptor():
mStyle(0)
{
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
const std::string& size,
const U8 style,
const font_file_info_vec_t& font_files):
mName(name),
mSize(size),
mStyle(style),
mFontFiles(font_files)
{
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
const std::string& size,
const U8 style,
const font_file_info_vec_t& font_list,
const font_file_info_vec_t& font_collection_files) :
LLFontDescriptor(name, size, style, font_list)
{
mFontCollectionFiles = font_collection_files;
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
const std::string& size,
const U8 style):
mName(name),
mSize(size),
mStyle(style)
{
}
bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const
{
if (mName < b.mName)
return true;
else if (mName > b.mName)
return false;
if (mStyle < b.mStyle)
return true;
else if (mStyle > b.mStyle)
return false;
if (mSize < b.mSize)
return true;
else
return false;
}
static const std::string s_template_string("TEMPLATE");
bool LLFontDescriptor::isTemplate() const
{
return getSize() == s_template_string;
}
// Look for substring match and remove substring if matched.
bool removeSubString(std::string& str, const std::string& substr)
{
size_t pos = str.find(substr);
if (pos != string::npos)
{
str.erase(pos, substr.size());
return true;
}
return false;
}
// Check for substring match without modifying the source string.
bool findSubString(std::string& str, const std::string& substr)
{
size_t pos = str.find(substr);
if (pos != string::npos)
{
return true;
}
return false;
}
// Normal form is
// - raw name
// - bold, italic style info reflected in both style and font name.
// - other style info removed.
// - size info moved to mSize, defaults to Medium
// For example,
// - "SansSerifHuge" would normalize to { "SansSerif", "Huge", 0 }
// - "SansSerifBold" would normalize to { "SansSerifBold", "Medium", BOLD }
LLFontDescriptor LLFontDescriptor::normalize() const
{
std::string new_name(mName);
std::string new_size(mSize);
U8 new_style(mStyle);
// Only care about style to extent it can be picked up by font.
new_style &= (LLFontGL::BOLD | LLFontGL::ITALIC);
// All these transformations are to support old-style font specifications.
if (removeSubString(new_name,"Small"))
new_size = "Small";
if (removeSubString(new_name,"Big"))
new_size = "Large";
if (removeSubString(new_name,"Medium"))
new_size = "Medium";
if (removeSubString(new_name,"Large"))
new_size = "Large";
if (removeSubString(new_name,"Huge"))
new_size = "Huge";
// HACK - Monospace is the only one we don't remove, so
// name "Monospace" doesn't get taken down to ""
// For other fonts, there's no ambiguity between font name and size specifier.
if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Monospace"))
new_size = "Monospace";
// <FS:Ansariel> Advanced script editor
if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Scripting"))
new_size = "Scripting";
if (new_size != s_template_string && new_size.empty() && findSubString(new_name, "Cascadia"))
new_size = "Cascadia";
// </FS:Ansariel>
if (new_size.empty())
new_size = "Medium";
if (removeSubString(new_name,"Bold"))
new_style |= LLFontGL::BOLD;
if (removeSubString(new_name,"Italic"))
new_style |= LLFontGL::ITALIC;
return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles());
}
void LLFontDescriptor::addFontFile(const std::string& file_name, const std::string& char_functor)
{
char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
mFontFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
}
void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, const std::string& char_functor)
{
char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
mFontCollectionFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
}
LLFontRegistry::LLFontRegistry(bool create_gl_textures, F32 size_mod)
: mCreateGLTextures(create_gl_textures), mFontSizeMod(size_mod)
{
// This is potentially a slow directory traversal, so we want to
// cache the result.
mUltimateFallbackList = LLWindow::getDynamicFallbackFontList();
}
LLFontRegistry::~LLFontRegistry()
{
clear();
}
bool LLFontRegistry::parseFontInfo(const std::string& xml_filename)
{
bool success = false; // Succeed if we find and read at least one XUI file
// <FS:Kadah> User selectable fonts
// <FS:Kadah> xml_filename is now passed as a full path to a single XUI
LLXMLNodePtr root;
bool parsed_file = LLXMLNode::parseFile(xml_filename, root, NULL);
if (!parsed_file)
{
return false;
}
if ( root.isNull() || ! root->hasName( "fonts" ) )
{
LL_WARNS() << "Bad font info file: " << xml_filename << LL_ENDL;
return false;
}
std::string root_name;
root->getAttributeString("name",root_name);
if (root->hasName("fonts"))
{
// Expect a collection of children consisting of "font" or "font_size" entries
bool init_succ = init_from_xml(this, root);
success = success || init_succ;
}
// <FS:Kadah> Dont load from skins now
#if 0
const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename);
if (xml_paths.empty())
{
// We didn't even find one single XUI file
return false;
}
for (string_vec_t::const_iterator path_it = xml_paths.begin();
path_it != xml_paths.end();
++path_it)
{
LLXMLNodePtr root;
bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL);
if (!parsed_file)
continue;
if ( root.isNull() || ! root->hasName( "fonts" ) )
{
LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL;
continue;
}
std::string root_name;
root->getAttributeString("name",root_name);
if (root->hasName("fonts"))
{
// Expect a collection of children consisting of "font" or "font_size" entries
bool init_succ = init_from_xml(this, root);
success = success || init_succ;
}
}
#endif
// </FS:Kadah>
//if (success)
// dump();
return success;
}
std::string currentOsName()
{
#if LL_WINDOWS
return "Windows";
#elif LL_DARWIN
return "Mac";
#elif LL_LINUX
return "Linux";
#else
return "";
#endif
}
bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
{
if (node->hasName("font"))
{
std::string attr_name;
if (node->getAttributeString("name",attr_name))
{
desc.setName(attr_name);
}
std::string attr_style;
if (node->getAttributeString("font_style",attr_style))
{
desc.setStyle(LLFontGL::getStyleFromString(attr_style));
}
desc.setSize(s_template_string);
}
LLXMLNodePtr child;
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
std::string child_name;
child->getAttributeString("name",child_name);
if (child->hasName("file"))
{
std::string font_file_name = child->getTextContents();
std::string char_functor;
if (child->hasAttribute("functor"))
{
child->getAttributeString("functor", char_functor);
}
if (child->hasAttribute("load_collection"))
{
bool col = false;
child->getAttributeBOOL("load_collection", col);
if (col)
{
desc.addFontCollectionFile(font_file_name, char_functor);
}
}
desc.addFontFile(font_file_name, char_functor);
}
else if (child->hasName("os"))
{
if (child_name == currentOsName())
{
font_desc_init_from_xml(child, desc);
}
}
}
return true;
}
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node)
{
LLXMLNodePtr child;
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
std::string child_name;
child->getAttributeString("name",child_name);
if (child->hasName("font"))
{
LLFontDescriptor desc;
bool font_succ = font_desc_init_from_xml(child, desc);
LLFontDescriptor norm_desc = desc.normalize();
if (font_succ)
{
// if this is the first time we've seen this font name,
// create a new template map entry for it.
const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc);
if (match_desc == NULL)
{
// Create a new entry (with no corresponding font).
registry->mFontMap[norm_desc] = NULL;
}
// otherwise, find the existing entry and combine data.
else
{
// Prepend files from desc.
// A little roundabout because the map key is const,
// so we have to fetch it, make a new map key, and
// replace the old entry.
font_file_info_vec_t font_files = match_desc->getFontFiles();
font_files.insert(font_files.begin(),
desc.getFontFiles().begin(),
desc.getFontFiles().end());
font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
font_collection_files.insert(font_collection_files.begin(),
desc.getFontCollectionFiles().begin(),
desc.getFontCollectionFiles().end());
LLFontDescriptor new_desc = *match_desc;
new_desc.setFontFiles(font_files);
new_desc.setFontCollectionFiles(font_collection_files);
registry->mFontMap.erase(*match_desc);
registry->mFontMap[new_desc] = NULL;
}
}
}
else if (child->hasName("font_size"))
{
std::string size_name;
F32 size_value;
if (child->getAttributeString("name",size_name) &&
child->getAttributeF32("size",size_value))
{
//registry->mFontSizes[size_name] = size_value;
// +/- defualt font sizes -KC
registry->mFontSizes[size_name] = size_value + registry->mFontSizeMod;
}
}
}
return true;
}
bool LLFontRegistry::nameToSize(const std::string& size_name, F32& size)
{
font_size_map_t::iterator it = mFontSizes.find(size_name);
if (it != mFontSizes.end())
{
size = it->second;
return true;
}
return false;
}
LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
{
// Name should hold a font name recognized as a setting; the value
// of the setting should be a list of font files.
// Size should be a recognized string value
// Style should be a set of flags including any implied by the font name.
// First decipher the requested size.
LLFontDescriptor norm_desc = desc.normalize();
F32 point_size;
bool found_size = nameToSize(norm_desc.getSize(),point_size);
if (!found_size)
{
LL_WARNS() << "createFont unrecognized size " << norm_desc.getSize() << LL_ENDL;
return NULL;
}
LL_INFOS() << "createFont " << norm_desc.getName() << " size " << norm_desc.getSize() << " style " << ((S32) norm_desc.getStyle()) << LL_ENDL;
F32 fallback_scale = 1.0;
// Find corresponding font template (based on same descriptor with no size specified)
LLFontDescriptor template_desc(norm_desc);
template_desc.setSize(s_template_string);
const LLFontDescriptor *match_desc = getClosestFontTemplate(template_desc);
if (!match_desc)
{
LL_WARNS() << "createFont failed, no template found for "
<< norm_desc.getName() << " style [" << ((S32)norm_desc.getStyle()) << "]" << LL_ENDL;
return NULL;
}
// See whether this best-match font has already been instantiated in the requested size.
LLFontDescriptor nearest_exact_desc = *match_desc;
nearest_exact_desc.setSize(norm_desc.getSize());
font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc);
// If we fail to find a font in the fonts directory, it->second might be NULL.
// We shouldn't construcnt a font with a NULL mFontFreetype.
// This may not be the best solution, but it at least prevents a crash.
if (it != mFontMap.end() && it->second != NULL)
{
LL_INFOS() << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << LL_ENDL;
// copying underlying Freetype font, and storing in LLFontGL with requested font descriptor
LLFontGL *font = new LLFontGL;
font->mFontDescriptor = desc;
font->mFontFreetype = it->second->mFontFreetype;
mFontMap[desc] = font;
return font;
}
// Build list of font names to look for.
// Files specified for this font come first, followed by those from the default descriptor.
font_file_info_vec_t font_files = match_desc->getFontFiles();
font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
LLFontDescriptor default_desc("default",s_template_string,0);
const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc);
if (match_default_desc)
{
font_files.insert(font_files.end(),
match_default_desc->getFontFiles().begin(),
match_default_desc->getFontFiles().end());
font_collection_files.insert(font_collection_files.end(),
match_default_desc->getFontCollectionFiles().begin(),
match_default_desc->getFontCollectionFiles().end());
}
// Add ultimate fallback list - generated dynamically on linux,
// null elsewhere.
std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files),
[](const std::string& file_name) { return LLFontFileInfo(file_name); });
// Load fonts based on names.
if (font_files.empty())
{
LL_WARNS() << "createFont failed, no file names specified" << LL_ENDL;
return NULL;
}
LLFontGL *result = NULL;
// The first font will get pulled will be the "head" font, set to non-fallback.
// Rest will consitute the fallback list.
bool is_first_found = true;
string_vec_t font_search_paths;
font_search_paths.push_back(LLFontGL::getFontPathLocal());
font_search_paths.push_back(LLFontGL::getFontPathSystem());
// <FS:Kadah> User fonts: Also load from user_settings/fonts
font_search_paths.push_back(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "fonts", ""));
// <FS:Ansariel> Search executable path as well - in case we run from within VS (seems to work without as well, but just to be safe)
font_search_paths.push_back(gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "fonts", ""));
#if LL_DARWIN
font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY);
font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL);
font_search_paths.push_back(LLFontGL::getFontPathSystem() + MACOSX_FONT_SUPPLEMENTAL);
#endif
// The fontname string may contain multiple font file names separated by semicolons.
// Break it apart and try loading each one, in order.
for(font_file_info_vec_t::iterator font_file_it = font_files.begin();
font_file_it != font_files.end();
++font_file_it)
{
LLFontGL *fontp = NULL;
bool is_ft_collection = (std::find_if(font_collection_files.begin(), font_collection_files.end(),
[&font_file_it](const LLFontFileInfo& ffi) { return font_file_it->FileName == ffi.FileName; }) != font_collection_files.end());
// *HACK: Fallback fonts don't render, so we can use that to suppress
// creation of OpenGL textures for test apps. JC
bool is_fallback = !is_first_found || !mCreateGLTextures;
F32 extra_scale = (is_fallback) ? fallback_scale : 1.0f;
F32 point_size_scale = extra_scale * point_size;
bool is_font_loaded = false;
for(string_vec_t::iterator font_search_path_it = font_search_paths.begin();
font_search_path_it != font_search_paths.end();
++font_search_path_it)
{
const std::string font_path = *font_search_path_it + font_file_it->FileName;
fontp = new LLFontGL;
S32 num_faces = is_ft_collection ? fontp->getNumFaces(font_path) : 1;
for (S32 i = 0; i < num_faces; i++)
{
if (fontp == NULL)
{
fontp = new LLFontGL;
}
if (fontp->loadFace(font_path, point_size_scale,
LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i))
{
is_font_loaded = true;
if (is_first_found)
{
result = fontp;
is_first_found = false;
}
else
{
result->mFontFreetype->addFallbackFont(fontp->mFontFreetype, font_file_it->CharFunctor);
delete fontp;
fontp = NULL;
}
}
else
{
delete fontp;
fontp = NULL;
}
}
if (is_font_loaded) break;
}
if(!is_font_loaded)
{
LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << font_file_it->FileName << LL_ENDL;
delete fontp;
fontp = NULL;
}
}
if (result)
{
result->mFontDescriptor = desc;
}
else
{
LL_WARNS() << "createFont failed in some way" << LL_ENDL;
}
mFontMap[desc] = result;
return result;
}
void LLFontRegistry::reset()
{
for (font_reg_map_t::iterator it = mFontMap.begin();
it != mFontMap.end();
++it)
{
// Reset the corresponding font but preserve the entry.
if (it->second)
it->second->reset();
}
}
void LLFontRegistry::clear()
{
for (font_reg_map_t::iterator it = mFontMap.begin();
it != mFontMap.end();
++it)
{
LLFontGL *fontp = it->second;
delete fontp;
}
mFontMap.clear();
}
void LLFontRegistry::destroyGL()
{
for (font_reg_map_t::iterator it = mFontMap.begin();
it != mFontMap.end();
++it)
{
// Reset the corresponding font but preserve the entry.
if (it->second)
it->second->destroyGL();
}
}
LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc)
{
font_reg_map_t::iterator it = mFontMap.find(desc);
if (it != mFontMap.end())
return it->second;
else
{
LLFontGL *fontp = createFont(desc);
if (!fontp)
{
LL_WARNS() << "getFont failed, name " << desc.getName()
<<" style=[" << ((S32) desc.getStyle()) << "]"
<< " size=[" << desc.getSize() << "]" << LL_ENDL;
}
else
{
//generate glyphs for ASCII chars to avoid stalls later
fontp->generateASCIIglyphs();
}
return fontp;
}
}
const LLFontDescriptor *LLFontRegistry::getMatchingFontDesc(const LLFontDescriptor& desc)
{
LLFontDescriptor norm_desc = desc.normalize();
font_reg_map_t::iterator it = mFontMap.find(norm_desc);
if (it != mFontMap.end())
return &(it->first);
else
return NULL;
}
static U32 bitCount(U8 c)
{
U32 count = 0;
if (c & 1)
count++;
if (c & 2)
count++;
if (c & 4)
count++;
if (c & 8)
count++;
if (c & 16)
count++;
if (c & 32)
count++;
if (c & 64)
count++;
if (c & 128)
count++;
return count;
}
// Find nearest match for the requested descriptor.
const LLFontDescriptor *LLFontRegistry::getClosestFontTemplate(const LLFontDescriptor& desc)
{
const LLFontDescriptor *exact_match_desc = getMatchingFontDesc(desc);
if (exact_match_desc)
{
return exact_match_desc;
}
LLFontDescriptor norm_desc = desc.normalize();
const LLFontDescriptor *best_match_desc = NULL;
for (font_reg_map_t::iterator it = mFontMap.begin();
it != mFontMap.end();
++it)
{
const LLFontDescriptor* curr_desc = &(it->first);
// Ignore if not a template.
if (!curr_desc->isTemplate())
continue;
// Ignore if font name is wrong.
if (curr_desc->getName() != norm_desc.getName())
continue;
// Reject font if it matches any bits we don't want
if (curr_desc->getStyle() & ~norm_desc.getStyle())
{
continue;
}
// Take if it's the first plausible candidate we've found.
if (!best_match_desc)
{
best_match_desc = curr_desc;
continue;
}
// Take if it matches more bits than anything before.
U8 best_style_match_bits =
norm_desc.getStyle() & best_match_desc->getStyle();
U8 curr_style_match_bits =
norm_desc.getStyle() & curr_desc->getStyle();
if (bitCount(curr_style_match_bits) > bitCount(best_style_match_bits))
{
best_match_desc = curr_desc;
continue;
}
// Tie-breaker: take if it matches bold.
if (curr_style_match_bits & LLFontGL::BOLD) // Bold is requested and this descriptor matches it.
{
best_match_desc = curr_desc;
continue;
}
}
// Nothing matched.
return best_match_desc;
}
void LLFontRegistry::dump()
{
LL_INFOS() << "LLFontRegistry dump: " << LL_ENDL;
for (font_size_map_t::iterator size_it = mFontSizes.begin();
size_it != mFontSizes.end();
++size_it)
{
LL_INFOS() << "Size: " << size_it->first << " => " << size_it->second << LL_ENDL;
}
for (font_reg_map_t::iterator font_it = mFontMap.begin();
font_it != mFontMap.end();
++font_it)
{
const LLFontDescriptor& desc = font_it->first;
LL_INFOS() << "Font: name=" << desc.getName()
<< " style=[" << ((S32)desc.getStyle()) << "]"
<< " size=[" << desc.getSize() << "]"
<< " fileNames="
<< LL_ENDL;
for (font_file_info_vec_t::const_iterator file_it=desc.getFontFiles().begin();
file_it != desc.getFontFiles().end();
++file_it)
{
LL_INFOS() << " file: " << file_it->FileName << LL_ENDL;
}
}
}
void LLFontRegistry::dumpTextures()
{
for (const auto& fontEntry : mFontMap)
{
if (fontEntry.second)
{
fontEntry.second->dumpTextures();
}
}
}
const string_vec_t& LLFontRegistry::getUltimateFallbackList() const
{
return mUltimateFallbackList;
}
+144
View File
@@ -0,0 +1,144 @@
/**
* @file llfontregistry.h
* @author Brad Payne
* @brief Storage for fonts.
*
* $LicenseInfo:firstyear=2008&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_LLFONTREGISTRY_H
#define LL_LLFONTREGISTRY_H
#include "llpointer.h"
class LLFontGL;
typedef std::vector<std::string> string_vec_t;
struct LLFontFileInfo
{
LLFontFileInfo(const std::string& file_name, const std::function<bool(llwchar)>& char_functor = nullptr)
: FileName(file_name)
, CharFunctor(char_functor)
{
}
LLFontFileInfo(const LLFontFileInfo& ffi)
: FileName(ffi.FileName)
, CharFunctor(ffi.CharFunctor)
{
}
std::string FileName;
std::function<bool(llwchar)> CharFunctor;
};
typedef std::vector<LLFontFileInfo> font_file_info_vec_t;
class LLFontDescriptor
{
public:
LLFontDescriptor();
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style);
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list);
LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list, const font_file_info_vec_t& font_collection_list);
LLFontDescriptor normalize() const;
bool operator<(const LLFontDescriptor& b) const;
bool isTemplate() const;
const std::string& getName() const { return mName; }
void setName(const std::string& name) { mName = name; }
const std::string& getSize() const { return mSize; }
void setSize(const std::string& size) { mSize = size; }
void addFontFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
const font_file_info_vec_t & getFontFiles() const { return mFontFiles; }
void setFontFiles(const font_file_info_vec_t& font_files) { mFontFiles = font_files; }
void addFontCollectionFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
const font_file_info_vec_t& getFontCollectionFiles() const { return mFontCollectionFiles; }
void setFontCollectionFiles(const font_file_info_vec_t& font_collection_files) { mFontCollectionFiles = font_collection_files; }
const U8 getStyle() const { return mStyle; }
void setStyle(U8 style) { mStyle = style; }
private:
std::string mName;
std::string mSize;
font_file_info_vec_t mFontFiles;
font_file_info_vec_t mFontCollectionFiles;
U8 mStyle;
typedef std::map<std::string, std::function<bool(llwchar)>> char_functor_map_t;
static char_functor_map_t mCharFunctors;
};
class LLFontRegistry
{
public:
friend bool init_from_xml(LLFontRegistry*, LLPointer<class LLXMLNode>);
// create_gl_textures - set to false for test apps with no OpenGL window,
// such as llui_libtest
LLFontRegistry(bool create_gl_textures, F32 size_mod);
~LLFontRegistry();
// Load standard font info from XML file(s).
bool parseFontInfo(const std::string& xml_filename);
// Clear cached glyphs for all fonts.
void reset();
// Destroy all fonts.
void clear();
// GL cleanup
void destroyGL();
LLFontGL *getFont(const LLFontDescriptor& desc);
const LLFontDescriptor *getMatchingFontDesc(const LLFontDescriptor& desc);
const LLFontDescriptor *getClosestFontTemplate(const LLFontDescriptor& desc);
bool nameToSize(const std::string& size_name, F32& size);
void dump();
void dumpTextures();
const string_vec_t& getUltimateFallbackList() const;
private:
LLFontRegistry(const LLFontRegistry& other); // no-copy
LLFontGL *createFont(const LLFontDescriptor& desc);
typedef std::map<LLFontDescriptor,LLFontGL*> font_reg_map_t;
typedef std::map<std::string,F32> font_size_map_t;
// Given a descriptor, look up specific font instantiation.
font_reg_map_t mFontMap;
// Given a size name, look up the point size.
font_size_map_t mFontSizes;
string_vec_t mUltimateFallbackList;
bool mCreateGLTextures;
// +/- defualt font sizes -KC
F32 mFontSizeMod;
};
#endif // LL_LLFONTREGISTRY_H
+239
View File
@@ -0,0 +1,239 @@
/**
* @file llfontvertexbuffer.cpp
* @brief Buffer storage for font rendering.
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2024, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llfontvertexbuffer.h"
#include "llvertexbuffer.h"
bool LLFontVertexBuffer::sEnableBufferCollection = true;
LLFontVertexBuffer::LLFontVertexBuffer()
{
}
LLFontVertexBuffer::~LLFontVertexBuffer()
{
reset();
}
void LLFontVertexBuffer::reset()
{
// Todo: some form of debug only frequecy check&assert to see if this is happening too often.
// Regenerating this list is expensive
mBufferList.clear();
}
S32 LLFontVertexBuffer::render(
const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
LLRect rect,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style,
LLFontGL::ShadowType shadow,
S32 max_chars, S32 max_pixels,
F32* right_x,
bool use_ellipses,
bool use_color)
{
LLRectf rect_float((F32)rect.mLeft, (F32)rect.mTop, (F32)rect.mRight, (F32)rect.mBottom);
return render(fontp, text, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses, use_color);
}
S32 LLFontVertexBuffer::render(
const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
LLRectf rect,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style,
LLFontGL::ShadowType shadow,
S32 max_chars,
F32* right_x,
bool use_ellipses,
bool use_color)
{
F32 x = rect.mLeft;
F32 y = 0.f;
switch (valign)
{
case LLFontGL::TOP:
y = rect.mTop;
break;
case LLFontGL::VCENTER:
y = rect.getCenterY();
break;
case LLFontGL::BASELINE:
case LLFontGL::BOTTOM:
y = rect.mBottom;
break;
default:
y = rect.mBottom;
break;
}
return render(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, (S32)rect.getWidth(), right_x, use_ellipses, use_color);
}
S32 LLFontVertexBuffer::render(
const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style,
LLFontGL::ShadowType shadow,
S32 max_chars , S32 max_pixels,
F32* right_x,
bool use_ellipses,
bool use_color )
{
if (!LLFontGL::sDisplayFont) //do not display texts
{
return static_cast<S32>(text.length());
}
if (!sEnableBufferCollection)
{
// For debug purposes and performance testing
return fontp->render(text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
if (mBufferList.empty())
{
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
else if (mLastX != x
|| mLastY != y
|| mLastFont != fontp
|| mLastColor != color // alphas change often
|| mLastHalign != halign
|| mLastValign != valign
|| mLastOffset != begin_offset
|| mLastMaxChars != max_chars
|| mLastMaxPixels != max_pixels
|| mLastStyle != style
|| mLastShadow != shadow // ex: buttons change shadow state
|| mLastScaleX != LLFontGL::sScaleX
|| mLastScaleY != LLFontGL::sScaleY
|| mLastVertDPI != LLFontGL::sVertDPI
|| mLastHorizDPI != LLFontGL::sHorizDPI
|| mLastOrigin != LLFontGL::sCurOrigin
|| mLastResGeneration != LLFontGL::sResolutionGeneration
|| mLastFontCacheGen != fontp->getCacheGeneration())
{
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
else
{
renderBuffers();
if (right_x)
{
*right_x = mLastRightX;
}
}
return mChars;
}
void LLFontVertexBuffer::genBuffers(
const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style, LLFontGL::ShadowType shadow,
S32 max_chars, S32 max_pixels,
F32* right_x,
bool use_ellipses,
bool use_color)
{
// todo: add a debug build assert if this triggers too often for to long?
mBufferList.clear();
// Save before rendreing, it can change mid-render,
// so will need to rerender previous characters
mLastFontCacheGen = fontp->getCacheGeneration();
gGL.beginList(&mBufferList);
mChars = fontp->render(text, begin_offset, x, y, color, halign, valign,
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
gGL.endList();
mLastFont = fontp;
mLastOffset = begin_offset;
mLastMaxChars = max_chars;
mLastMaxPixels = max_pixels;
mLastX = x;
mLastY = y;
mLastColor = color;
mLastHalign = halign;
mLastValign = valign;
mLastStyle = style;
mLastShadow = shadow;
mLastScaleX = LLFontGL::sScaleX;
mLastScaleY = LLFontGL::sScaleY;
mLastVertDPI = LLFontGL::sVertDPI;
mLastHorizDPI = LLFontGL::sHorizDPI;
mLastOrigin = LLFontGL::sCurOrigin;
mLastResGeneration = LLFontGL::sResolutionGeneration;
if (right_x)
{
mLastRightX = *right_x;
}
}
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();
}
gGL.popUIMatrix();
}
+130
View File
@@ -0,0 +1,130 @@
/**
* @file llfontgl.h
* @author Andrii Kleshchev
* @brief Buffer storage for font rendering.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLFONTVERTEXBUFFER_H
#define LL_LLFONTVERTEXBUFFER_H
#include "llfontgl.h"
class LLVertexBufferData;
class LLFontVertexBuffer
{
public:
LLFontVertexBuffer();
~LLFontVertexBuffer();
void reset();
S32 render(const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
LLRect rect,
const LLColor4& color,
LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE,
U8 style = LLFontGL::NORMAL,
LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW,
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x = NULL,
bool use_ellipses = false,
bool use_color = true);
S32 render(const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
LLRectf rect,
const LLColor4& color,
LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE,
U8 style = LLFontGL::NORMAL,
LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW,
S32 max_chars = S32_MAX,
F32* right_x = NULL,
bool use_ellipses = false,
bool use_color = true);
S32 render(const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE,
U8 style = LLFontGL::NORMAL,
LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW,
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
F32* right_x = NULL,
bool use_ellipses = false,
bool use_color = true);
static void enableBufferCollection(bool enable) { sEnableBufferCollection = enable; }
private:
void genBuffers(const LLFontGL* fontp,
const LLWString& text,
S32 begin_offset,
F32 x, F32 y,
const LLColor4& color,
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
U8 style,
LLFontGL::ShadowType shadow,
S32 max_chars, S32 max_pixels,
F32* right_x,
bool use_ellipses,
bool use_color);
void renderBuffers();
std::list<LLVertexBufferData> mBufferList;
S32 mChars = 0;
const LLFontGL *mLastFont = nullptr;
S32 mLastOffset = 0;
S32 mLastMaxChars = 0;
S32 mLastMaxPixels = 0;
F32 mLastX = 0.f;
F32 mLastY = 0.f;
LLColor4 mLastColor;
LLFontGL::HAlign mLastHalign = LLFontGL::LEFT;
LLFontGL::VAlign mLastValign = LLFontGL::BASELINE;
U8 mLastStyle = LLFontGL::NORMAL;
LLFontGL::ShadowType mLastShadow = LLFontGL::NO_SHADOW;
F32 mLastRightX = 0.f;
// LLFontGL's statics
F32 mLastScaleX = 1.f;
F32 mLastScaleY = 1.f;
F32 mLastVertDPI = 0.f;
F32 mLastHorizDPI = 0.f;
S32 mLastResGeneration = 0;
LLCoordGL mLastOrigin;
// Adding new characters to bitmap cache can alter value from getBitmapWidth();
// which alters whole string. So rerender when new characters were added to cache.
S32 mLastFontCacheGen = 0;
static bool sEnableBufferCollection;
};
#endif
File diff suppressed because it is too large Load Diff
+488
View File
@@ -0,0 +1,488 @@
/**
* @file llgl.h
* @brief LLGL definition
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLGL_H
#define LL_LLGL_H
// This file contains various stuff for handling gl extensions and other gl related stuff.
#include <string>
#include <boost/unordered_map.hpp>
#include <list>
#include "llerror.h"
#include "v4color.h"
#include "llstring.h"
#include "stdtypes.h"
#include "v4math.h"
#include "llplane.h"
#include "llgltypes.h"
#include "llinstancetracker.h"
#include "llglheaders.h"
#include "glm/mat4x4.hpp"
extern bool gDebugGL;
extern bool gDebugSession;
extern bool gDebugGLSession;
extern llofstream gFailLog;
#define LL_GL_ERRS LL_ERRS("RenderState")
void ll_init_fail_log(std::string filename);
void ll_fail(std::string msg);
void ll_close_fail_log();
class LLSD;
// Manage GL extensions...
class LLGLManager
{
public:
LLGLManager();
bool initGL();
void shutdownGL();
#if LL_WINDOWS
void initWGL(); // Initializes stupid WGL extensions
#endif
std::string getRawGLString(); // For sending to simulator
bool mInited;
bool mIsDisabled;
// OpenGL limits
S32 mMaxSamples;
S32 mNumTextureImageUnits;
S32 mMaxSampleMaskWords;
S32 mMaxColorTextureSamples;
S32 mMaxDepthTextureSamples;
S32 mMaxIntegerSamples;
S32 mGLMaxVertexRange;
S32 mGLMaxIndexRange;
S32 mGLMaxTextureSize;
F32 mMaxAnisotropy = 0.f;
S32 mMaxUniformBlockSize = 0;
S32 mMaxVaryingVectors = 0;
// GL 4.x capabilities
bool mHasCubeMapArray = false;
bool mHasDebugOutput = false;
bool mHasTransformFeedback = false;
bool mHasAnisotropic = false;
// Vendor-specific extensions
bool mHasAMDAssociations = false;
bool mHasNVXGpuMemoryInfo = false;
bool mHasATIMemInfo = false;
bool mIsAMD;
bool mIsNVIDIA;
bool mIsIntel;
bool mIsApple = false;
// 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;
S32 mDriverVersionMajor;
S32 mDriverVersionMinor;
S32 mDriverVersionRelease;
F32 mGLVersion; // e.g = 1.4
S32 mGLSLVersionMajor;
S32 mGLSLVersionMinor;
std::string mDriverVersionVendorString;
std::string mGLVersionString;
U32 mVRAM; // VRAM in MB
S32 mVRAMDetected; // <FS:Beq/> The amount detected/reported by the OS/Drivers. If different to mVRAM there is an override in place.
std::string getGLInfoString();
void printGLInfoString();
void getGLInfo(LLSD& info);
void asLLSD(LLSD& info);
// In ALL CAPS
std::string mGLVendor;
std::string mGLVendorShort;
// In ALL CAPS
std::string mGLRenderer;
private:
void initExtensions();
void initGLStates();
};
extern LLGLManager gGLManager;
class LLQuaternion;
class LLMatrix4;
void rotate_quat(LLQuaternion& rotation);
void flush_glerror(); // Flush GL errors when we know we're handling them correctly.
void log_glerror();
void assert_glerror();
void clear_glerror();
# define stop_glerror() assert_glerror()
# define llglassertok() assert_glerror()
// stop_glerror is still needed on OS X but has performance implications
// use macro below to conditionally add stop_glerror to non-release builds
// on OS X
#if LL_DARWIN && !LL_RELEASE_FOR_DOWNLOAD
#define STOP_GLERROR stop_glerror()
#else
#define STOP_GLERROR
#endif
#define llglassertok_always() assert_glerror()
////////////////////////
//
// Note: U32's are GLEnum's...
//
// This is a class for GL state management
/*
GL STATE MANAGEMENT DESCRIPTION
LLGLState and its two subclasses, LLGLEnable and LLGLDisable, manage the current
enable/disable states of the GL to prevent redundant setting of state within a
render path or the accidental corruption of what state the next path expects.
Essentially, wherever you would call glEnable set a state and then
subsequently reset it by calling glDisable (or vice versa), make an instance of
LLGLEnable with the state you want to set, and assume it will be restored to its
original state when that instance of LLGLEnable is destroyed. It is good practice
to exploit stack frame controls for optimal setting/unsetting and readability of
code. In llglstates.h, there are a collection of helper classes that define groups
of enables/disables that can cause multiple states to be set with the creation of
one instance.
Sample usage:
//disable lighting for rendering hud objects
//INCORRECT USAGE
LLGLEnable blend(GL_BLEND);
renderHUD();
LLGLDisable blend(GL_BLEND);
//CORRECT USAGE
{
LLGLEnable blend(GL_BLEND);
renderHUD();
}
If a state is to be set on a conditional, the following mechanism
is useful:
{
LLGLEnable blend(blend_hud ? GL_GL_BLEND: 0);
renderHUD();
}
A LLGLState initialized with a parameter of 0 does nothing.
LLGLState works by maintaining a map of the current GL states, and ignoring redundant
enables/disables. If a redundant call is attempted, it becomes a noop, otherwise,
it is set in the constructor and reset in the destructor.
For debugging GL state corruption, running with debug enabled will trigger asserts
if the existing GL state does not match the expected GL state.
*/
#include "boost/function.hpp"
class LLGLState
{
public:
static void initClass();
static void restoreGL();
static void resetTextureStates();
static void dumpStates();
// make sure GL blend function, GL states, and GL color mask match
// what we expect
// writeAlpha - whether or not writing to alpha channel is expected
static void checkStates(GLboolean writeAlpha = GL_TRUE);
protected:
static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
public:
enum { CURRENT_STATE = -2, DISABLED_STATE = 0, ENABLED_STATE = 1 };
LLGLState(LLGLenum state, S32 enabled = CURRENT_STATE);
~LLGLState();
void setEnabled(S32 enabled);
void enable() { setEnabled(ENABLED_STATE); }
void disable() { setEnabled(DISABLED_STATE); }
protected:
LLGLenum mState;
bool mWasEnabled;
bool mIsEnabled;
};
// New LLGLState class wrappers that don't depend on actual GL flags.
class LLGLEnableBlending : public LLGLState
{
public:
LLGLEnableBlending(bool enable);
};
class LLGLEnableAlphaReject : public LLGLState
{
public:
LLGLEnableAlphaReject(bool enable);
};
// Enable with functor
class LLGLEnableFunc : LLGLState
{
public:
LLGLEnableFunc(LLGLenum state, bool enable, boost::function<void()> func)
: LLGLState(state, enable)
{
if (enable)
{
func();
}
}
};
/// TODO: Being deprecated.
class LLGLEnable : public LLGLState
{
public:
LLGLEnable(LLGLenum state) : LLGLState(state, ENABLED_STATE) {}
};
/// TODO: Being deprecated.
class LLGLDisable : public LLGLState
{
public:
LLGLDisable(LLGLenum state) : LLGLState(state, DISABLED_STATE) {}
};
/*
Store and modify projection matrix to create an oblique
projection that clips to the specified plane. Oblique
projections alter values in the depth buffer, so this
class should not be used mid-renderpass.
Restores projection matrix on destruction.
GL_MODELVIEW_MATRIX is active whenever program execution
leaves this class.
Does not stack.
Caches inverse of projection matrix used in gGLObliqueProjectionInverse
*/
class LLGLUserClipPlane
{
public:
LLGLUserClipPlane(const LLPlane& plane, const glm::mat4& modelview, const glm::mat4& projection, bool apply = true);
~LLGLUserClipPlane();
void setPlane(F32 a, F32 b, F32 c, F32 d);
void disable();
private:
bool mApply;
glm::mat4 mProjection;
glm::mat4 mModelview;
};
/*
Modify and load projection matrix to push depth values to far clip plane.
Restores projection matrix on destruction.
Saves/restores matrix mode around projection manipulation.
Does not stack.
*/
class LLGLSquashToFarClip
{
public:
LLGLSquashToFarClip();
LLGLSquashToFarClip(const glm::mat4& projection, U32 layer = 0);
void setProjectionMatrix(glm::mat4 projection, U32 layer);
~LLGLSquashToFarClip();
};
/*
Interface for objects that need periodic GL updates applied to them.
Used to synchronize GL updates with GL thread.
*/
class LLGLUpdate
{
public:
static std::list<LLGLUpdate*> sGLQ;
bool mInQ;
LLGLUpdate()
: mInQ(false)
{
}
virtual ~LLGLUpdate()
{
if (mInQ)
{
std::list<LLGLUpdate*>::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this);
if (iter != sGLQ.end())
{
sGLQ.erase(iter);
}
}
}
virtual void updateGL() = 0;
};
const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms
class LLGLFence
{
public:
virtual ~LLGLFence()
{
}
virtual void placeFence() = 0;
virtual bool isCompleted() = 0;
virtual void wait() = 0;
};
class LLGLSyncFence : public LLGLFence
{
public:
GLsync mSync;
LLGLSyncFence();
virtual ~LLGLSyncFence();
void placeFence();
bool isCompleted();
void wait();
};
extern LLMatrix4 gGLObliqueProjectionInverse;
#include "llglstates.h"
void init_glstates();
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string );
extern bool gClothRipple;
extern bool gHeadlessClient;
extern bool gNonInteractive;
extern bool gGLActive;
// Deal with changing glext.h definitions for newer SDK versions, specifically
// with MAC OSX 10.5 -> 10.6
#ifndef GL_DEPTH_ATTACHMENT
#define GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
#endif
#ifndef GL_STENCIL_ATTACHMENT
#define GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT
#endif
#ifndef GL_FRAMEBUFFER
#define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
#define GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_EXT
#define GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER_EXT
#define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
#define GL_FRAMEBUFFER_UNSUPPORTED GL_FRAMEBUFFER_UNSUPPORTED_EXT
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
#define glGenFramebuffers glGenFramebuffersEXT
#define glBindFramebuffer glBindFramebufferEXT
#define glCheckFramebufferStatus glCheckFramebufferStatusEXT
#define glBlitFramebuffer glBlitFramebufferEXT
#define glDeleteFramebuffers glDeleteFramebuffersEXT
#define glFramebufferRenderbuffer glFramebufferRenderbufferEXT
#define glFramebufferTexture2D glFramebufferTexture2DEXT
#endif
#ifndef GL_RENDERBUFFER
#define GL_RENDERBUFFER GL_RENDERBUFFER_EXT
#define glGenRenderbuffers glGenRenderbuffersEXT
#define glBindRenderbuffer glBindRenderbufferEXT
#define glRenderbufferStorage glRenderbufferStorageEXT
#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
#define glDeleteRenderbuffers glDeleteRenderbuffersEXT
#endif
#ifndef GL_COLOR_ATTACHMENT
#define GL_COLOR_ATTACHMENT GL_COLOR_ATTACHMENT_EXT
#endif
#ifndef GL_COLOR_ATTACHMENT0
#define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
#endif
#ifndef GL_COLOR_ATTACHMENT1
#define GL_COLOR_ATTACHMENT1 GL_COLOR_ATTACHMENT1_EXT
#endif
#ifndef GL_COLOR_ATTACHMENT2
#define GL_COLOR_ATTACHMENT2 GL_COLOR_ATTACHMENT2_EXT
#endif
#ifndef GL_COLOR_ATTACHMENT3
#define GL_COLOR_ATTACHMENT3 GL_COLOR_ATTACHMENT3_EXT
#endif
#ifndef GL_DEPTH24_STENCIL8
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT
#endif
#endif // LL_LLGL_H
+38
View File
@@ -0,0 +1,38 @@
/**
* @file llglcommonfunc.cpp
* @brief Implementation of the LLGLCommonFunc.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llglheaders.h"
#include "llglcommonfunc.h"
namespace LLGLCommonFunc
{
void selected_stencil_test()
{
// deprecated
//glStencilFunc(GL_ALWAYS, 2, 0xffff);
//glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
}
}
+30
View File
@@ -0,0 +1,30 @@
/**
* @file llglcommonfunc.h
* @brief File include common opengl code snippets
*
* $LicenseInfo:firstyear=2003&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$
*/
namespace LLGLCommonFunc
{
void selected_stencil_test();
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+390
View File
@@ -0,0 +1,390 @@
/**
* @file llglslshader.h
* @brief GLSL shader wrappers
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLGLSLSHADER_H
#define LL_LLGLSLSHADER_H
#include "llgl.h"
#include "llrender.h"
#include "llstaticstringtable.h"
#include <boost/json.hpp>
#include <unordered_map>
class LLShaderFeatures
{
public:
S32 mIndexedTextureChannels = 0;
bool calculatesLighting = false;
bool calculatesAtmospherics = false;
bool hasLighting = false; // implies no transport (it's possible to have neither though)
bool isAlphaLighting = false; // indicates lighting shaders need not be linked in (lighting performed directly in alpha shader to match deferred lighting functions)
bool isSpecular = false;
bool hasTransport = false; // implies no lighting (it's possible to have neither though)
bool hasSkinning = false;
bool hasObjectSkinning = false;
bool mGLTF = false;
bool hasAtmospherics = false;
bool hasGamma = false;
bool hasShadows = false;
bool hasAmbientOcclusion = false;
bool hasSrgb = false;
bool isDeferred = false;
bool hasFullGBuffer = false;
bool hasScreenSpaceReflections = false;
bool hasAlphaMask = false;
bool hasReflectionProbes = false;
bool attachNothing = false;
bool hasHeroProbes = false;
bool isPBRTerrain = false;
bool hasTonemap = false;
};
// ============= Structure for caching shader uniforms ===============
class LLGLSLShader;
class LLShaderUniforms
{
public:
template<typename T>
struct UniformSetting
{
S32 mUniform{ 0 };
T mValue{};
};
typedef UniformSetting<S32> IntSetting;
typedef UniformSetting<F32> FloatSetting;
typedef UniformSetting<LLVector4> VectorSetting;
typedef UniformSetting<LLVector3> Vector3Setting;
void clear()
{
mIntegers.resize(0);
mFloats.resize(0);
mVectors.resize(0);
mVector3s.resize(0);
}
void uniform1i(S32 index, S32 value)
{
mIntegers.push_back({ index, value });
}
void uniform1f(S32 index, F32 value)
{
mFloats.push_back({ index, value });
}
void uniform4fv(S32 index, const LLVector4& value)
{
mVectors.push_back({ index, value });
}
void uniform4fv(S32 index, const F32* value)
{
mVectors.push_back({ index, LLVector4(value) });
}
void uniform3fv(S32 index, const LLVector3& value)
{
mVector3s.push_back({ index, value });
}
void uniform3fv(S32 index, const F32* value)
{
mVector3s.push_back({ index, LLVector3(value) });
}
void apply(LLGLSLShader* shader);
std::vector<IntSetting> mIntegers;
std::vector<FloatSetting> mFloats;
std::vector<VectorSetting> mVectors;
std::vector<Vector3Setting> mVector3s;
};
class LLGLSLShader
{
public:
// NOTE: Keep gShaderConsts and LLGLSLShader::ShaderConsts_e in sync!
enum eShaderConsts
{
SHADER_CONST_CLOUD_MOON_DEPTH
, SHADER_CONST_STAR_DEPTH
, NUM_SHADER_CONSTS
};
// enum primarily used to control application sky settings uniforms
typedef enum
{
SG_DEFAULT = 0, // not sky or water specific
SG_SKY, //
SG_WATER,
SG_ANY,
SG_COUNT
} eGroup;
enum UniformBlock : GLuint
{
UB_REFLECTION_PROBES, // "ReflectionProbes"
UB_GLTF_JOINTS, // "GLTFJoints"
UB_GLTF_NODES, // "GLTFNodes"
UB_GLTF_MATERIALS, // "GLTFMaterials"
NUM_UNIFORM_BLOCKS
};
static std::set<LLGLSLShader*> sInstances;
static bool sProfileEnabled;
LLGLSLShader();
~LLGLSLShader();
static GLuint sCurBoundShader;
static LLGLSLShader* sCurBoundShaderPtr;
static S32 sIndexedTextureChannels;
static U32 sMaxGLTFMaterials;
static U32 sMaxGLTFNodes;
static void initProfile();
static void finishProfile(boost::json::value& stats=sDefaultStats);
static void startProfile();
static void stopProfile();
void unload();
void clearStats();
void dumpStats(boost::json::object& stats);
// place query objects for profiling if profiling is enabled
// if for_runtime is true, will place timer query only whether or not profiling is enabled
void placeProfileQuery(bool for_runtime = false);
// Readback query objects if profiling is enabled
// If for_runtime is true, will readback timer query iff query is available
// Will return false if a query is pending (try again later)
// If force_read is true, will force an immediate readback (severe performance penalty)
bool readProfileQuery(bool for_runtime = false, bool force_read = false);
bool createShader();
bool attachFragmentObject(std::string object);
bool attachVertexObject(std::string object);
void attachObject(GLuint object);
void attachObjects(GLuint* objects = NULL, S32 count = 0);
bool mapAttributes();
bool mapUniforms();
void mapUniform(GLint index);
void uniform1i(U32 index, GLint i);
void uniform1f(U32 index, GLfloat v);
void fastUniform1f(U32 index, GLfloat v);
void uniform2f(U32 index, GLfloat x, GLfloat y);
void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void uniform1iv(U32 index, U32 count, const GLint* i);
void uniform4iv(U32 index, U32 count, const GLint* i);
void uniform1fv(U32 index, U32 count, const GLfloat* v);
void uniform2fv(U32 index, U32 count, const GLfloat* v);
void uniform3fv(U32 index, U32 count, const GLfloat* v);
void uniform4fv(U32 index, U32 count, const GLfloat* v);
void uniform4uiv(U32 index, U32 count, const GLuint* v);
void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
void uniform1i(const LLStaticHashedString& uniform, GLint i);
void uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
void uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
void uniform4f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
void uniform4uiv(const LLStaticHashedString& uniform, U32 count, const GLuint* v);
void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v);
void setMinimumAlpha(F32 minimum);
void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void vertexAttrib4fv(U32 index, GLfloat* v);
//GLint getUniformLocation(const std::string& uniform);
GLint getUniformLocation(const LLStaticHashedString& uniform);
GLint getUniformLocation(U32 index);
GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size);
void clearPermutations();
void addPermutation(std::string name, std::string value);
void addPermutations(const std::map<std::string, std::string>& defines)
{
mDefines.insert(defines.begin(), defines.end());
}
void removePermutation(std::string name);
void addConstant(const LLGLSLShader::eShaderConsts shader_const);
//enable/disable texture channel for specified uniform
//if given texture uniform is active in the shader,
//the corresponding channel will be active upon return
//returns channel texture is enabled in from [0-MAX)
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
// get the texture channel of the given uniform, or -1 if uniform is not used as a texture
S32 getTextureChannel(S32 uniform) const;
// bindTexture returns the texture unit we've bound the texture to.
// 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);
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);
S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
bool link(bool suppress_errors = false);
void bind();
//helper to conditionally bind mRiggedVariant instead of this
void bind(bool rigged);
bool isComplete() const { return mProgramObject != 0; }
LLUUID hash();
// Unbinds any previously bound shader by explicitly binding no shader.
static void unbind();
U32 mMatHash[LLRender::NUM_MATRIX_MODES];
U32 mLightHash;
GLuint mProgramObject;
#if LL_RELEASE_WITH_DEBUG_INFO
struct attr_name
{
GLint loc;
const char* name;
void operator = (GLint _loc) { loc = _loc; }
operator GLint () { return loc; }
};
std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel
#else
std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
#endif
U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
typedef std::unordered_map<GLint, LLVector4> uniform_value_map_t;
uniform_value_map_t mValue; //lookup map of uniform location to last known value
std::vector<GLint> mTexture;
S32 mTotalUniformSize;
S32 mActiveTextureChannels;
S32 mShaderLevel;
S32 mShaderGroup; // see LLGLSLShader::eGroup
bool mUniformsDirty;
LLShaderFeatures mFeatures;
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
std::string mName;
typedef std::map<std::string, std::string> defines_map_t; //NOTE: this must be an ordered map to maintain hash consistency
defines_map_t mDefines;
static defines_map_t sGlobalDefines;
LLUUID mShaderHash;
bool mUsingBinaryProgram = false;
//statistics for profiling shader performance
bool mProfilePending = false;
U32 mTimerQuery;
U32 mSamplesQuery;
U32 mPrimitivesQuery;
U64 mTimeElapsed;
static U64 sTotalTimeElapsed;
U32 mTrianglesDrawn;
static U32 sTotalTrianglesDrawn;
U64 mSamplesDrawn;
static U64 sTotalSamplesDrawn;
U32 mBinds;
static U32 sTotalBinds;
// this pointer should be set to whichever shader represents this shader's rigged variant
LLGLSLShader* mRiggedVariant = nullptr;
// variants for use by GLTF renderer
// bit 0 = alpha mode blend (1) or opaque (0)
// bit 1 = rigged (1) or static (0)
// bit 2 = unlit (1) or lit (0)
// bit 3 = single (0) or multi (1) uv coordinates
struct GLTFVariant
{
constexpr static U8 ALPHA_BLEND = 1;
constexpr static U8 RIGGED = 2;
constexpr static U8 UNLIT = 4;
constexpr static U8 MULTI_UV = 8;
};
constexpr static U8 NUM_GLTF_VARIANTS = 16;
std::vector<LLGLSLShader> mGLTFVariants;
//helper to bind GLTF variant
void bind(U8 variant);
// hacky flag used for optimization in LLDrawPoolAlpha
bool mCanBindFast = false;
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
void setLabel(const char* label);
#endif
private:
void unloadInternal();
// This must be static because finishProfile() is called at least once
// within a __try block. If we default its stats parameter to a temporary
// json::value, that temporary must be destroyed when the stack is
// unwound, which __try forbids.
static boost::json::value sDefaultStats;
};
//UI shader (declared here so llui_libtest will link properly)
extern LLGLSLShader gUIProgram;
//output vec4(color.rgb,color.a*tex0[tc0].a)
extern LLGLSLShader gSolidColorProgram;
//Alpha mask shader (declared here so llappearance can access properly)
extern LLGLSLShader gAlphaMaskProgram;
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
#define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader)
#else
#define LL_SET_SHADER_LABEL(shader, label)
#endif
#endif
+196
View File
@@ -0,0 +1,196 @@
/**
* @file llglstates.h
* @brief LLGL states definitions
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
//THIS HEADER SHOULD ONLY BE INCLUDED FROM llgl.h
#ifndef LL_LLGLSTATES_H
#define LL_LLGLSTATES_H
#include "llimagegl.h"
//----------------------------------------------------------------------------
class LLGLDepthTest
{
// Enabled by default
public:
LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled = GL_TRUE, GLenum depth_func = GL_LEQUAL);
~LLGLDepthTest();
void checkState();
GLboolean mPrevDepthEnabled;
GLenum mPrevDepthFunc;
GLboolean mPrevWriteEnabled;
private:
static GLboolean sDepthEnabled; // defaults to GL_FALSE
static GLenum sDepthFunc; // defaults to GL_LESS
static GLboolean sWriteEnabled; // defaults to GL_TRUE
};
//----------------------------------------------------------------------------
class LLGLSDefault
{
protected:
LLGLDisable mBlend, mCullFace;
public:
LLGLSDefault()
:
// Disable
mBlend(GL_BLEND),
mCullFace(GL_CULL_FACE)
{ }
};
class LLGLSObjectSelect
{
protected:
LLGLDisable mBlend;
LLGLEnable mCullFace;
public:
LLGLSObjectSelect()
: mBlend(GL_BLEND),
mCullFace(GL_CULL_FACE)
{ }
};
//----------------------------------------------------------------------------
class LLGLSUIDefault
{
protected:
LLGLEnable mBlend;
LLGLDisable mCullFace;
LLGLDepthTest mDepthTest;
public:
LLGLSUIDefault()
: mBlend(GL_BLEND),
mCullFace(GL_CULL_FACE),
mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL)
{}
};
//----------------------------------------------------------------------------
class LLGLSPipeline
{
protected:
LLGLEnable mCullFace;
LLGLDepthTest mDepthTest;
public:
LLGLSPipeline()
: mCullFace(GL_CULL_FACE),
mDepthTest(GL_TRUE, GL_TRUE, GL_LEQUAL)
{ }
};
class LLGLSPipelineAlpha // : public LLGLSPipeline
{
protected:
LLGLEnable mBlend;
public:
LLGLSPipelineAlpha()
: mBlend(GL_BLEND)
{ }
};
class LLGLSPipelineSelection
{
protected:
LLGLDisable mCullFace;
public:
LLGLSPipelineSelection()
: mCullFace(GL_CULL_FACE)
{}
};
class LLGLSPipelineSkyBox
{
protected:
LLGLDisable mCullFace;
LLGLSquashToFarClip mSquashClip;
public:
LLGLSPipelineSkyBox();
~LLGLSPipelineSkyBox();
};
class LLGLSPipelineDepthTestSkyBox : public LLGLSPipelineSkyBox
{
public:
LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write);
LLGLDepthTest mDepth;
};
class LLGLSPipelineBlendSkyBox : public LLGLSPipelineDepthTestSkyBox
{
public:
LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write);
LLGLEnable mBlend;
};
class LLGLSTracker
{
protected:
LLGLEnable mCullFace, mBlend;
public:
LLGLSTracker() :
mCullFace(GL_CULL_FACE),
mBlend(GL_BLEND)
{ }
};
//----------------------------------------------------------------------------
class LLGLSSpecular
{
public:
F32 mShininess;
LLGLSSpecular(const LLColor4& color, F32 shininess)
{
mShininess = shininess;
if (mShininess > 0.0f)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color.mV);
S32 shiny = (S32)(shininess*128.f);
shiny = llclamp(shiny,0,128);
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, shiny);
}
}
~LLGLSSpecular()
{
if (mShininess > 0.f)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, LLColor4(0.f,0.f,0.f,0.f).mV);
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
}
}
};
//----------------------------------------------------------------------------
#endif
+404
View File
@@ -0,0 +1,404 @@
/**
* @file llgltexture.cpp
* @brief Opengl texture implementation
*
* $LicenseInfo:firstyear=2000&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 "llgltexture.h"
LLGLTexture::LLGLTexture(bool usemipmaps)
{
init();
mUseMipMaps = usemipmaps;
}
LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, bool usemipmaps)
{
init();
mFullWidth = width ;
mFullHeight = height ;
mUseMipMaps = usemipmaps;
mComponents = components ;
setTexelsPerImage();
}
LLGLTexture::LLGLTexture(const LLImageRaw* raw, bool usemipmaps)
{
init();
mUseMipMaps = usemipmaps ;
// Create an empty image of the specified size and width
mGLTexturep = new LLImageGL(raw, usemipmaps) ;
mFullWidth = mGLTexturep->getWidth();
mFullHeight = mGLTexturep->getHeight();
mComponents = mGLTexturep->getComponents();
setTexelsPerImage();
}
LLGLTexture::~LLGLTexture()
{
cleanup();
}
void LLGLTexture::init()
{
mBoostLevel = LLGLTexture::BOOST_NONE;
// <FS:minerjr>
// Added a previous boost level to allow for restorign boost after BOOST_SELECTED is applied
mPrevBoostLevel = LLGLTexture::BOOST_NONE;
// </FS:minerjr>
mFullWidth = 0;
mFullHeight = 0;
mTexelsPerImage = 0 ;
mUseMipMaps = false ;
mComponents = 0 ;
mTextureState = NO_DELETE ;
mDontDiscard = false;
mNeedsGLTexture = false ;
}
void LLGLTexture::cleanup()
{
if(mGLTexturep)
{
mGLTexturep->cleanup();
}
}
// virtual
void LLGLTexture::dump()
{
if(mGLTexturep)
{
mGLTexturep->dump();
}
}
void LLGLTexture::setBoostLevel(S32 level)
{
if(mBoostLevel != level)
{
mBoostLevel = level ;
if(mBoostLevel != LLGLTexture::BOOST_NONE
&& mBoostLevel != LLGLTexture::BOOST_ICON
&& mBoostLevel != LLGLTexture::BOOST_THUMBNAIL
// <FS:minerjr> [FIRE-35081] Blurry prims not changing with graphics settings
// Add the new grass, light and tree boosts
&& mBoostLevel != LLGLTexture::BOOST_GRASS
&& mBoostLevel != LLGLTexture::BOOST_LIGHT
&& mBoostLevel != LLGLTexture::BOOST_TREE
// <FS:minerjr> [FIRE-35081]
&& mBoostLevel != LLGLTexture::BOOST_TERRAIN)
{
setNoDelete() ;
}
}
}
// <FS:minerjr>
// Changes the current boost level to the previous value
void LLGLTexture::restoreBoostLevel()
{
mBoostLevel = mPrevBoostLevel;
}
// Stores the current boost level in a the previous boost.
void LLGLTexture::storeBoostLevel()
{
mPrevBoostLevel = mBoostLevel;
}
// </FS:minerjr>
void LLGLTexture::forceActive()
{
mTextureState = ACTIVE ;
}
void LLGLTexture::setActive()
{
if(mTextureState != NO_DELETE)
{
mTextureState = ACTIVE ;
}
}
//set the texture to stay in memory
void LLGLTexture::setNoDelete()
{
mTextureState = NO_DELETE ;
}
void LLGLTexture::generateGLTexture()
{
if(mGLTexturep.isNull())
{
mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ;
}
}
LLImageGL* LLGLTexture::getGLTexture() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep ;
}
bool LLGLTexture::createGLTexture()
{
if(mGLTexturep.isNull())
{
generateGLTexture() ;
}
return mGLTexturep->createGLTexture() ;
}
bool LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, bool to_create, S32 category, bool defer_copy, LLGLuint* tex_name)
{
llassert(mGLTexturep.notNull());
bool ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy, tex_name) ;
if(ret)
{
mFullWidth = mGLTexturep->getCurrentWidth() ;
mFullHeight = mGLTexturep->getCurrentHeight() ;
mComponents = mGLTexturep->getComponents() ;
setTexelsPerImage();
}
return ret ;
}
void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, bool swap_bytes)
{
llassert(mGLTexturep.notNull()) ;
mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ;
}
void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode)
{
llassert(mGLTexturep.notNull()) ;
mGLTexturep->setAddressMode(mode) ;
}
void LLGLTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
llassert(mGLTexturep.notNull()) ;
mGLTexturep->setFilteringOption(option) ;
}
//virtual
S32 LLGLTexture::getWidth(S32 discard_level) const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getWidth(discard_level) ;
}
//virtual
S32 LLGLTexture::getHeight(S32 discard_level) const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getHeight(discard_level) ;
}
S32 LLGLTexture::getMaxDiscardLevel() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getMaxDiscardLevel() ;
}
S32 LLGLTexture::getDiscardLevel() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getDiscardLevel() ;
}
S8 LLGLTexture::getComponents() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getComponents() ;
}
LLGLuint LLGLTexture::getTexName() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getTexName() ;
}
bool LLGLTexture::hasGLTexture() const
{
if(mGLTexturep.notNull())
{
return mGLTexturep->getHasGLTexture() ;
}
return false ;
}
bool LLGLTexture::getBoundRecently() const
{
if(mGLTexturep.notNull())
{
return mGLTexturep->getBoundRecently() ;
}
return false ;
}
LLTexUnit::eTextureType LLGLTexture::getTarget(void) const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getTarget() ;
}
bool LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_name) ;
}
bool LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_name) ;
}
void LLGLTexture::setGLTextureCreated (bool initialized)
{
llassert(mGLTexturep.notNull()) ;
mGLTexturep->setGLTextureCreated (initialized) ;
}
void LLGLTexture::setCategory(S32 category)
{
llassert(mGLTexturep.notNull()) ;
mGLTexturep->setCategory(category) ;
}
void LLGLTexture::setTexName(LLGLuint texName)
{
llassert(mGLTexturep.notNull());
return mGLTexturep->setTexName(texName);
}
void LLGLTexture::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
{
llassert(mGLTexturep.notNull());
return mGLTexturep->setTarget(target, bind_target);
}
LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getAddressMode() ;
}
S32Bytes LLGLTexture::getTextureMemory() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->mTextureMemory ;
}
LLGLenum LLGLTexture::getPrimaryFormat() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getPrimaryFormat() ;
}
bool LLGLTexture::getIsAlphaMask() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getIsAlphaMask() ;
}
//bool LLGLTexture::getMask(const LLVector2 &tc)
// [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay)
bool LLGLTexture::getMask(const LLVector2 &tc) const
// [/RLVa:KB]
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getMask(tc) ;
}
F32 LLGLTexture::getTimePassedSinceLastBound()
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getTimePassedSinceLastBound() ;
}
bool LLGLTexture::getMissed() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getMissed() ;
}
bool LLGLTexture::isJustBound() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->isJustBound() ;
}
void LLGLTexture::forceUpdateBindStats(void) const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->forceUpdateBindStats() ;
}
bool LLGLTexture::isGLTextureCreated() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->isGLTextureCreated() ;
}
void LLGLTexture::destroyGLTexture()
{
if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
{
mGLTexturep->destroyGLTexture() ;
mTextureState = DELETED ;
}
}
void LLGLTexture::setTexelsPerImage()
{
U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT));
U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT));
mTexelsPerImage = (U32)fullwidth * fullheight;
}
static LLUUID sStubUUID;
const LLUUID& LLGLTexture::getID() const { return sStubUUID; }
+220
View File
@@ -0,0 +1,220 @@
/**
* @file llgltexture.h
* @brief Object for managing opengl textures
*
* $LicenseInfo:firstyear=2012&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_GL_TEXTURE_H
#define LL_GL_TEXTURE_H
#include "lltexture.h"
#include "llgl.h"
class LLImageRaw;
//
//this the parent for the class LLViewerTexture
//through the following virtual functions, the class LLViewerTexture can be reached from /llrender.
//
class LLGLTexture : public LLTexture
{
public:
enum
{
MAX_IMAGE_SIZE_DEFAULT = 2048,
INVALID_DISCARD_LEVEL = 0x7fff
};
enum EBoostLevel
{
BOOST_NONE = 0,
BOOST_AVATAR ,
BOOST_AVATAR_BAKED ,
BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead.
// <FS:minerjr> [FIRE-35081] Blurry prims not changing with graphics settings
BOOST_GRASS , // Grass has a alternative calculation for virtual and face sizes.
BOOST_TREE , // Tree has a alternative calculation for virtual and face sizes.
BOOST_LIGHT , // Light textures has a alternative calculation for virtual and face sizes.
// </FS:minerjr> [FIRE-35081]
BOOST_HIGH = 10,
BOOST_SCULPTED ,
BOOST_BUMP ,
BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug
BOOST_SELECTED ,
BOOST_AVATAR_BAKED_SELF ,
BOOST_AVATAR_SELF , // needed for baking avatar
BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay.
BOOST_HUD ,
BOOST_ICON ,
BOOST_THUMBNAIL ,
BOOST_UI ,
BOOST_PREVIEW ,
BOOST_MAP ,
BOOST_MAP_VISIBLE ,
BOOST_MAX_LEVEL,
//other texture Categories
LOCAL = BOOST_MAX_LEVEL,
AVATAR_SCRATCH_TEX,
DYNAMIC_TEX,
MEDIA,
OTHER,
MAX_GL_IMAGE_CATEGORY
};
typedef enum
{
DELETED = 0, //removed from memory
ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds).
NO_DELETE = 99 //stay in memory, can not be removed.
} LLGLTextureState;
protected:
virtual ~LLGLTexture();
LOG_CLASS(LLGLTexture);
public:
LLGLTexture(bool usemipmaps = true);
LLGLTexture(const LLImageRaw* raw, bool usemipmaps) ;
LLGLTexture(const U32 width, const U32 height, const U8 components, bool usemipmaps) ;
virtual void dump(); // debug info to LL_INFOS()
virtual const LLUUID& getID() const;
void setBoostLevel(S32 level);
S32 getBoostLevel() { return mBoostLevel; }
// <FS:minerjr>
void restoreBoostLevel(); // Now restores the mBoostLevel with the mPrevBoostLevel
void storeBoostLevel(); // Stores the current mBoostLevel in mPrevBoostLevel
// </FS:minerjr>
S32 getFullWidth() const { return mFullWidth; }
S32 getFullHeight() const { return mFullHeight; }
void generateGLTexture() ;
void destroyGLTexture() ;
//---------------------------------------------------------------------------------------------
//functions to access LLImageGL
//---------------------------------------------------------------------------------------------
/*virtual*/S32 getWidth(S32 discard_level = -1) const;
/*virtual*/S32 getHeight(S32 discard_level = -1) const;
bool hasGLTexture() const ;
LLGLuint getTexName() const ;
bool createGLTexture() ;
// Create a GL Texture from an image raw
// discard_level - mip level, 0 for highest resultion mip
// imageraw - the image to copy from
// usename - explicit GL name override
// to_create - set to false to force gl texture to not be created
// category - LLGLTexture category for this LLGLTexture
// defer_copy - set to true to allocate GL texture but NOT initialize with imageraw data
// tex_name - if not null, will be set to the GL name of the texture created
bool createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, bool to_create = true, S32 category = LLGLTexture::OTHER, bool defer_copy = false, LLGLuint* tex_name = nullptr);
void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, bool swap_bytes = false);
void setAddressMode(LLTexUnit::eTextureAddressMode mode);
bool setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0);
bool setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0);
void setGLTextureCreated (bool initialized);
void setCategory(S32 category) ;
void setTexName(LLGLuint); // for forcing w/ externally created textures only
void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
S32 getMaxDiscardLevel() const;
S32 getDiscardLevel() const;
S8 getComponents() const;
bool getBoundRecently() const;
S32Bytes getTextureMemory() const ;
LLGLenum getPrimaryFormat() const;
bool getIsAlphaMask() const ;
LLTexUnit::eTextureType getTarget(void) const ;
// [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay)
bool getMask(const LLVector2 &tc) const;
// [/RLVa:KB]
// bool getMask(const LLVector2 &tc);
F32 getTimePassedSinceLastBound();
bool getMissed() const ;
bool isJustBound()const ;
void forceUpdateBindStats(void) const;
bool isGLTextureCreated() const ;
LLGLTextureState getTextureState() const { return mTextureState; }
//---------------------------------------------------------------------------------------------
//end of functions to access LLImageGL
//---------------------------------------------------------------------------------------------
//-----------------
/*virtual*/ void setActive() ;
void forceActive() ;
void setNoDelete() ;
void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; }
bool getDontDiscard() const { return mDontDiscard; }
//-----------------
private:
void cleanup();
void init();
protected:
void setTexelsPerImage();
public:
/*virtual*/ LLImageGL* getGLTexture() const ;
protected:
S32 mBoostLevel; // enum describing priority level
// <FS:minerjr>
// Added previous value to allow for restoring of BOOST_SELECTED overriding current state
S32 mPrevBoostLevel; // enum describing priority level (Previous Value for BOOST_SELECTION restore)
// </FS:minerjr>
U32 mFullWidth;
U32 mFullHeight;
bool mUseMipMaps;
S8 mComponents;
U32 mTexelsPerImage; // Texels per image.
mutable S8 mNeedsGLTexture;
//GL texture
LLPointer<LLImageGL> mGLTexturep ;
S8 mDontDiscard; // Keep full res version of this image (for UI, etc)
protected:
LLGLTextureState mTextureState ;
// <FS>ND> Expose mipmap generation so we can check it for texture memory tax
public:
bool getUseMipMaps() const { return mUseMipMaps; }
// </FS:ND>
};
#endif // LL_GL_TEXTURE_H
+39
View File
@@ -0,0 +1,39 @@
/**
* @file llgltypes.h
* @brief LLGL definition
*
* $LicenseInfo:firstyear=2006&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 LLGLTYPES_H
#define LLGLTYPES_H
#define MAX_GL_TEXTURE_UNITS 16
typedef U32 LLGLenum;
typedef U32 LLGLuint;
typedef S32 LLGLint;
typedef F32 LLGLfloat;
typedef F64 LLGLdouble;
typedef U8 LLGLboolean;
#endif
File diff suppressed because it is too large Load Diff
+371
View File
@@ -0,0 +1,371 @@
/**
* @file llimagegl.h
* @brief Object for managing images and their textures
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLIMAGEGL_H
#define LL_LLIMAGEGL_H
#include "llimage.h"
#include "llgltypes.h"
#include "llpointer.h"
#include "llrefcount.h"
#include "v2math.h"
#include "llunits.h"
#include "llthreadsafequeue.h"
#include "llrender.h"
#include "threadpool.h"
#include "workqueue.h"
#include <unordered_set>
#define LL_IMAGEGL_THREAD_CHECK 0 //set to 1 to enable thread debugging for ImageGL
class LLWindow;
#define BYTES_TO_MEGA_BYTES(x) ((x) >> 20)
#define MEGA_BYTES_TO_BYTES(x) ((x) << 20)
namespace LLImageGLMemory
{
void alloc_tex_image(U32 width, U32 height, U32 intformat, U32 count);
void free_tex_image(U32 texName);
void free_tex_images(U32 count, const U32* texNames);
void free_cur_tex_image();
}
//============================================================================
class LLImageGL : public LLRefCount
{
friend class LLTexUnit;
public:
// call once per frame
static void updateClass();
// Get an estimate of how many bytes have been allocated in vram for textures.
// Does not include mipmaps.
// NOTE: multiplying this number by two gives a good estimate for total
// video memory usage based on testing in lagland against an NVIDIA GPU.
static U64 getTextureBytesAllocated();
// These 2 functions replace glGenTextures() and glDeleteTextures()
static void generateTextures(S32 numTextures, U32 *textures);
static void deleteTextures(S32 numTextures, const U32 *textures);
// Size calculation
static S32 dataFormatBits(S32 dataformat);
static S64 dataFormatBytes(S32 dataformat, S32 width, S32 height);
static S32 dataFormatComponents(S32 dataformat);
bool updateBindStats() const ;
F32 getTimePassedSinceLastBound();
void forceUpdateBindStats(void) const;
// needs to be called every frame
static void updateStats(F32 current_time);
// cleanup GL state
static void destroyGL();
static void dirtyTexOptions();
static bool checkSize(S32 width, S32 height);
//for server side use only.
// Not currently necessary for LLImageGL, but required in some derived classes,
// so include for compatability
static bool create(LLPointer<LLImageGL>& dest, bool usemipmaps = true);
static bool create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, bool usemipmaps = true);
static bool create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, bool usemipmaps = true);
public:
LLImageGL(bool usemipmaps = true, bool allow_compression = true);
LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true, bool allow_compression = true);
LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true, bool allow_compression = true);
// For wrapping textures created via GL elsewhere with our API only. Use with caution.
LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode);
protected:
virtual ~LLImageGL();
void analyzeAlpha(const void* data_in, U32 w, U32 h);
void calcAlphaChannelOffsetAndStride();
public:
virtual void dump(); // debugging info to LL_INFOS()
bool setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
void setAllowCompression(bool allow) { mAllowCompression = allow; }
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);
bool createGLTexture() ;
bool createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, bool to_create = true,
S32 category = sMaxCategories-1, bool defer_copy = false, LLGLuint* tex_name = nullptr);
bool createGLTexture(S32 discard_level, const U8* data, bool data_hasmips = false, S32 usename = 0, bool defer_copy = false, LLGLuint* tex_name = nullptr);
void setImage(const LLImageRaw* imageraw);
bool setImage(const U8* data_in, bool data_hasmips = false, S32 usename = 0);
// *TODO: This function may not work if the textures is compressed (i.e.
// RenderCompressTextures is 0). Partial image updates do not work on
// compressed textures.
bool setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, bool force_fast_update = false, LLGLuint use_name = 0);
bool setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool force_fast_update = false, LLGLuint use_name = 0);
bool setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
// wait for gl commands to finish on current thread and push
// a lambda to main thread to swap mNewTexName and mTexName
void syncToMainThread(LLGLuint new_tex_name);
// Read back a raw image for this discard level, if it exists
bool readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
void destroyGLTexture();
void forceToInvalidateGLTexture();
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, bool swap_bytes = false);
void setComponents(S8 ncomponents) { mComponents = ncomponents; }
S32 getDiscardLevel() const { return mCurrentDiscardLevel; }
S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; }
// override the current discard level
// should only be used for local textures where you know exactly what you're doing
void setDiscardLevel(S32 level) { mCurrentDiscardLevel = level; }
S32 getCurrentWidth() const { return mWidth ;}
S32 getCurrentHeight() const { return mHeight ;}
S32 getWidth(S32 discard_level = -1) const;
S32 getHeight(S32 discard_level = -1) const;
U8 getComponents() const { return mComponents; }
S64 getBytes(S32 discard_level = -1) const;
S64 getMipBytes(S32 discard_level = -1) const;
bool getBoundRecently() const;
bool isJustBound() const;
bool getHasExplicitFormat() const { return mHasExplicitFormat; }
LLGLenum getPrimaryFormat() const { return mFormatPrimary; }
LLGLenum getFormatType() const { return mFormatType; }
bool getHasGLTexture() const { return mTexName != 0; }
LLGLuint getTexName() const { return mTexName; }
bool getIsAlphaMask() const;
bool getIsResident(bool test_now = false); // not const
void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
LLTexUnit::eTextureType getTarget(void) const { return mBindTarget; }
bool isGLTextureCreated(void) const { return mGLTextureCreated ; }
void setGLTextureCreated (bool initialized) { mGLTextureCreated = initialized; }
bool getUseMipMaps() const { return mUseMipMaps; }
void setUseMipMaps(bool usemips) { mUseMipMaps = usemips; }
void setHasMipMaps(bool hasmips) { mHasMipMaps = hasmips; }
void updatePickMask(S32 width, S32 height, const U8* data_in);
// [RLVa:KB] - Checked: RLVa-2.2 (@setoverlay)
bool getMask(const LLVector2 &tc) const;
// [/RLVa:KB]
// bool getMask(const LLVector2 &tc);
void checkTexSize(bool forced = false) const ;
// Sets the addressing mode used to sample the texture
// (such as wrapping, mirrored wrapping, and clamp)
// Note: this actually gets set the next time the texture is bound.
void setAddressMode(LLTexUnit::eTextureAddressMode mode);
LLTexUnit::eTextureAddressMode getAddressMode(void) const { return mAddressMode; }
// Sets the filtering options used to sample the texture
// (such as point sampling, bilinear interpolation, mipmapping, and anisotropic filtering)
// Note: this actually gets set the next time the texture is bound.
void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; }
LLGLenum getTexTarget()const { return mTarget; }
void init(bool usemipmaps, bool allow_compression);
virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
void setNeedsAlphaAndPickMask(bool need_mask);
#if LL_IMAGEGL_THREAD_CHECK
// thread debugging
std::thread::id mActiveThread;
void checkActiveThread();
#endif
// scale down to the desired discard level using GPU
// returns true if texture was scaled down
// desired discard will be clamped to max discard
// if desired discard is less than or equal to current discard, no scaling will occur
// only works for GL_TEXTURE_2D target
bool scaleDown(S32 desired_discard);
public:
// Various GL/Rendering options
S64Bytes mTextureMemory;
mutable F32 mLastBindTime; // last time this was bound, by discard level
private:
U32 createPickMask(S32 pWidth, S32 pHeight);
void freePickMask();
bool isCompressed();
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
LL::WorkQueue::weak_t mMainQueue;
U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
U16 mPickMaskWidth;
U16 mPickMaskHeight;
S8 mUseMipMaps;
bool mHasExplicitFormat; // If false (default), GL format is f(mComponents)
bool mAutoGenMips = false;
bool mIsMask;
bool mNeedsAlphaAndPickMask;
S8 mAlphaStride ;
S8 mAlphaOffset ;
bool mGLTextureCreated ;
LLGLuint mTexName;
U16 mWidth;
U16 mHeight;
S8 mCurrentDiscardLevel;
bool mAllowCompression;
protected:
LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps)
bool mHasMipMaps;
S32 mMipLevels;
LLGLboolean mIsResident;
S8 mComponents;
S8 mMaxDiscardLevel;
bool mTexOptionsDirty;
LLTexUnit::eTextureAddressMode mAddressMode; // Defaults to TAM_WRAP
LLTexUnit::eTextureFilterOptions mFilterOption; // Defaults to TFO_ANISOTROPIC
LLGLint mFormatInternal; // = GL internalformat
LLGLenum mFormatPrimary; // = GL format (pixel data format)
LLGLenum mFormatType;
bool mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1)
bool mExternalTexture;
// STATICS
public:
static std::unordered_set<LLImageGL*> sImageList;
static S32 sCount;
static U32 sFrameCount;
static F32 sLastFrameTime;
// Global memory statistics
static U32 sBindCount; // Tracks number of texture binds for current frame
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
static bool sGlobalUseAnisotropic;
static LLImageGL* sDefaultGLTexture ;
static bool sAutomatedTest;
static bool sCompressTextures; //use GL texture compression
#if DEBUG_MISS
bool mMissed; // Missed on last bind?
bool getMissed() const { return mMissed; };
#else
bool getMissed() const { return false; };
#endif
public:
static void initClass(LLWindow* window, S32 num_catagories, bool skip_analyze_alpha = false, bool thread_texture_loads = false, bool thread_media_updates = false);
static void allocateConversionBuffer();
static void cleanupClass() ;
private:
static S32 sMaxCategories;
static bool sSkipAnalyzeAlpha;
static U32 sScratchPBO;
static U32 sScratchPBOSize;
static U32* sManualScratch;
//the flag to allow to call readBackRaw(...).
//can be removed if we do not use that function at all.
static bool sAllowReadBackRaw ;
//
//****************************************************************************************************
//The below for texture auditing use only
//****************************************************************************************************
private:
S32 mCategory ;
public:
void setCategory(S32 category) {mCategory = category;}
S32 getCategory()const {return mCategory;}
void setTexName(GLuint texName) { mTexName = texName; }
//similar to setTexName, but will call deleteTextures on mTexName if mTexName is not 0 or texname
void syncTexName(LLGLuint texname);
//for debug use: show texture size distribution
//----------------------------------------
static S32 sCurTexSizeBar ;
static S32 sCurTexPickSize ;
static void setCurTexSizebar(S32 index, bool set_pick_size = true) ;
static void resetCurTexSizebar();
//****************************************************************************************************
//End of definitions for texture auditing use only
//****************************************************************************************************
};
class LLImageGLThread : public LLSimpleton<LLImageGLThread>, LL::ThreadPool
{
public:
// follows gSavedSettings "RenderGLMultiThreadedTextures"
static bool sEnabledTextures;
// follows gSavedSettings "RenderGLMultiThreadedMedia"
static bool sEnabledMedia;
LLImageGLThread(LLWindow* window);
// post a function to be executed on the LLImageGL background thread
template <typename CALLABLE>
bool post(CALLABLE&& func)
{
return getQueue().post(std::forward<CALLABLE>(func));
}
void run() override;
private:
LLWindow* mWindow;
void* mContext = nullptr;
LLAtomicBool mFinished;
};
#endif // LL_LLIMAGEGL_H
+454
View File
@@ -0,0 +1,454 @@
/**
* @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
glPushAttrib(GL_ALL_ATTRIB_BITS);
glPushClientAttrib(GL_ALL_ATTRIB_BITS);
/// 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
glPopClientAttrib();
glPopAttrib();
checkError();
}
void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height)
{
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture);
glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, width, height, 0);
}
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());
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
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;
char const * err_str_raw = (const char *) gluErrorString(glErr);
if(err_str_raw == NULL)
{
std::ostringstream err_builder;
err_builder << "unknown error number " << glErr;
mShaderErrorString = err_builder.str();
}
else
{
mShaderErrorString = err_str_raw;
}
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
}
+267
View File
@@ -0,0 +1,267 @@
/**
* @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
File diff suppressed because it is too large Load Diff
+574
View File
@@ -0,0 +1,574 @@
/**
* @file llrender.h
* @brief LLRender definition
*
* This class acts as a wrapper for OpenGL calls.
* The goal of this class is to minimize the number of api calls due to legacy rendering
* code, to define an interface for a multiple rendering API abstraction of the UI
* rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLGLRENDER_H
#define LL_LLGLRENDER_H
//#include "linden_common.h"
#include "v2math.h"
#include "v3math.h"
#include "v4coloru.h"
#include "v4math.h"
#include "llstrider.h"
#include "llpointer.h"
#include "llglheaders.h"
#include "llmatrix4a.h"
#include "glm/mat4x4.hpp"
#include <array>
#include <list>
class LLVertexBuffer;
class LLCubeMap;
class LLImageGL;
class LLRenderTarget;
class LLTexture;
class LLVertexBufferData;
#define LL_MATRIX_STACK_DEPTH 32
constexpr U32 LL_NUM_TEXTURE_LAYERS = 32;
constexpr U32 LL_NUM_LIGHT_UNITS = 8;
class LLTexUnit
{
friend class LLRender;
public:
static U32 sWhiteTexture;
typedef enum
{
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
TT_CUBE_MAP_ARRAY, // Array of cube maps
TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_TEXTURE_3D, // standard 3D Texture
TT_NONE, // No texture type is currently enabled
} eTextureType;
typedef enum
{
TAM_WRAP = 0, // Standard 2D Texture
TAM_MIRROR, // Non power of 2 texture
TAM_CLAMP // No texture type is currently enabled
} eTextureAddressMode;
typedef enum
{ // Note: If mipmapping or anisotropic are not enabled or supported it should fall back gracefully
TFO_POINT = 0, // Equal to: min=point, mag=point, mip=none.
TFO_BILINEAR, // Equal to: min=linear, mag=linear, mip=point.
TFO_TRILINEAR, // Equal to: min=linear, mag=linear, mip=linear.
TFO_ANISOTROPIC // Equal to: min=anisotropic, max=anisotropic, mip=linear.
} eTextureFilterOptions;
typedef enum
{
TMG_NONE = 0, // Mipmaps are not automatically generated for this texture.
TMG_AUTO, // Mipmaps are automatically generated for this texture.
TMG_MANUAL // Mipmaps are manually generated for this texture.
} eTextureMipGeneration;
typedef enum
{
TB_REPLACE = 0,
TB_ADD,
TB_MULT,
TB_MULT_X2,
TB_ALPHA_BLEND,
TB_COMBINE // Doesn't need to be set directly, setTexture___Blend() set TB_COMBINE automatically
} eTextureBlendType;
typedef enum
{
TBO_REPLACE = 0, // Use Source 1
TBO_MULT, // Multiply: ( Source1 * Source2 )
TBO_MULT_X2, // Multiply then scale by 2: ( 2.0 * ( Source1 * Source2 ) )
TBO_MULT_X4, // Multiply then scale by 4: ( 4.0 * ( Source1 * Source2 ) )
TBO_ADD, // Add: ( Source1 + Source2 )
TBO_ADD_SIGNED, // Add then subtract 0.5: ( ( Source1 + Source2 ) - 0.5 )
TBO_SUBTRACT, // Subtract Source2 from Source1: ( Source1 - Source2 )
TBO_LERP_VERT_ALPHA, // Interpolate based on Vertex Alpha (VA): ( Source1 * VA + Source2 * (1-VA) )
TBO_LERP_TEX_ALPHA, // Interpolate based on Texture Alpha (TA): ( Source1 * TA + Source2 * (1-TA) )
TBO_LERP_PREV_ALPHA, // Interpolate based on Previous Alpha (PA): ( Source1 * PA + Source2 * (1-PA) )
TBO_LERP_CONST_ALPHA // Interpolate based on Const Alpha (CA): ( Source1 * CA + Source2 * (1-CA) )
} eTextureBlendOp;
typedef enum
{
TBS_PREV_COLOR = 0, // Color from the previous texture stage
TBS_PREV_ALPHA,
TBS_ONE_MINUS_PREV_COLOR,
TBS_ONE_MINUS_PREV_ALPHA,
TBS_TEX_COLOR, // Color from the texture bound to this stage
TBS_TEX_ALPHA,
TBS_ONE_MINUS_TEX_COLOR,
TBS_ONE_MINUS_TEX_ALPHA,
TBS_VERT_COLOR, // The vertex color currently set
TBS_VERT_ALPHA,
TBS_ONE_MINUS_VERT_COLOR,
TBS_ONE_MINUS_VERT_ALPHA,
TBS_CONST_COLOR, // The constant color value currently set
TBS_CONST_ALPHA,
TBS_ONE_MINUS_CONST_COLOR,
TBS_ONE_MINUS_CONST_ALPHA
} eTextureBlendSrc;
typedef enum
{
TCS_LINEAR = 0,
TCS_SRGB
} eTextureColorSpace;
LLTexUnit(S32 index = -1);
// Refreshes renderer state of the texture unit to the cached values
// Needed when the render context has changed and invalidated the current state
void refreshState(void);
// returns the index of this texture unit
S32 getIndex(void) const { return mIndex; }
// Sets this tex unit to be the currently active one
void activate(void);
// Enables this texture unit for the given texture type
// (automatically disables any previously enabled texture type)
void enable(eTextureType type);
// Disables the current texture unit
void disable(void);
// Binds the LLImageGL to this texture unit
// (automatically enables the unit for the LLImageGL's texture type)
bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false, S32 usename = 0);
bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
// bind implementation for inner loops
// makes the following assumptions:
// - No need for gGL.flush()
// - texture is not null
// - gl_tex->getTexName() is not zero
// - This texture is not being bound redundantly
// - USE_SRGB_DECODE is disabled
// - mTexOptionsDirty is false
// -
void bindFast(LLTexture* texture);
// Binds a cubemap to this texture unit
// (automatically enables the texture unit for cubemaps)
bool bind(LLCubeMap* cubeMap);
// Binds a render target to this texture unit
// (automatically enables the texture unit for the RT's texture type)
bool bind(LLRenderTarget * renderTarget, bool bindDepth = false);
// Manually binds a texture to the texture unit
// (automatically enables the tex unit for the given texture type)
bool bindManual(eTextureType type, U32 texture, bool hasMips = false);
// Unbinds the currently bound texture of the given type
// (only if there's a texture of the given type currently bound)
void unbind(eTextureType type);
// Fast but unsafe version of unbind
void unbindFast(eTextureType type);
// Sets the addressing mode used to sample the texture
// Warning: this stays set for the bound texture forever,
// make sure you want to permanently change the address mode for the bound texture.
void setTextureAddressMode(eTextureAddressMode mode);
// Sets the filtering options used to sample the texture
// Warning: this stays set for the bound texture forever,
// make sure you want to permanently change the filtering for the bound texture.
void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option);
static U32 getInternalType(eTextureType type);
U32 getCurrTexture(void) { return mCurrTexture; }
eTextureType getCurrType(void) { return mCurrTexType; }
void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; }
protected:
friend class LLRender;
S32 mIndex;
U32 mCurrTexture;
eTextureType mCurrTexType;
S32 mCurrColorScale;
S32 mCurrAlphaScale;
bool mHasMipMaps;
void debugTextureUnit(void);
void setColorScale(S32 scale);
void setAlphaScale(S32 scale);
GLint getTextureSource(eTextureBlendSrc src);
GLint getTextureSourceType(eTextureBlendSrc src, bool isAlpha = false);
};
class LLLightState
{
public:
LLLightState(S32 index = -1);
void enable();
void disable();
void setDiffuse(const LLColor4& diffuse);
void setDiffuseB(const LLColor4& diffuse);
void setAmbient(const LLColor4& ambient);
void setSpecular(const LLColor4& specular);
void setPosition(const LLVector4& position);
void setConstantAttenuation(const F32& atten);
void setLinearAttenuation(const F32& atten);
void setQuadraticAttenuation(const F32& atten);
void setSpotExponent(const F32& exponent);
void setSpotCutoff(const F32& cutoff);
void setSpotDirection(const LLVector3& direction);
void setSunPrimary(bool v);
void setSize(F32 size);
void setFalloff(F32 falloff);
protected:
friend class LLRender;
S32 mIndex;
bool mEnabled;
LLColor4 mDiffuse;
LLColor4 mDiffuseB;
bool mSunIsPrimary;
LLColor4 mAmbient;
LLColor4 mSpecular;
LLVector4 mPosition;
LLVector3 mSpotDirection;
F32 mConstantAtten;
F32 mLinearAtten;
F32 mQuadraticAtten;
F32 mSpotExponent;
F32 mSpotCutoff;
F32 mSize = 0.f;
F32 mFalloff = 0.f;
};
class LLRender
{
friend class LLTexUnit;
public:
enum eTexIndex : U8
{
// Channels for material textures
DIFFUSE_MAP = 0,
ALTERNATE_DIFFUSE_MAP = 1,
NORMAL_MAP = 1,
SPECULAR_MAP = 2,
// Channels for PBR textures
BASECOLOR_MAP = 3,
METALLIC_ROUGHNESS_MAP = 4,
GLTF_NORMAL_MAP = 5,
EMISSIVE_MAP = 6,
// Total number of channels
NUM_TEXTURE_CHANNELS = 7,
};
enum eVolumeTexIndex : U8
{
LIGHT_TEX = 0,
SCULPT_TEX,
NUM_VOLUME_TEXTURE_CHANNELS,
};
enum eGeomModes : U8
{
TRIANGLES = 0,
TRIANGLE_STRIP,
TRIANGLE_FAN,
POINTS,
LINES,
LINE_STRIP,
LINE_LOOP,
NUM_MODES
};
enum eCompareFunc : U8
{
CF_NEVER = 0,
CF_ALWAYS,
CF_LESS,
CF_LESS_EQUAL,
CF_EQUAL,
CF_NOT_EQUAL,
CF_GREATER_EQUAL,
CF_GREATER,
CF_DEFAULT
};
enum eBlendType : U8
{
BT_ALPHA = 0,
BT_ADD,
BT_ADD_WITH_ALPHA, // Additive blend modulated by the fragment's alpha.
BT_MULT,
BT_MULT_ALPHA,
BT_MULT_X2,
BT_REPLACE
};
// WARNING: this MUST match the LL_PART_BF enum in LLPartData, so set values explicitly in case someone
// decides to add more or reorder them
enum eBlendFactor : U8
{
BF_ONE = 0,
BF_ZERO = 1,
BF_DEST_COLOR = 2,
BF_SOURCE_COLOR = 3,
BF_ONE_MINUS_DEST_COLOR = 4,
BF_ONE_MINUS_SOURCE_COLOR = 5,
BF_DEST_ALPHA = 6,
BF_SOURCE_ALPHA = 7,
BF_ONE_MINUS_DEST_ALPHA = 8,
BF_ONE_MINUS_SOURCE_ALPHA = 9,
BF_UNDEF
};
enum eMatrixMode : U8
{
MM_MODELVIEW = 0,
MM_PROJECTION,
MM_TEXTURE0,
MM_TEXTURE1,
MM_TEXTURE2,
MM_TEXTURE3,
NUM_MATRIX_MODES,
MM_TEXTURE
};
LLRender();
~LLRender();
bool init(bool needs_vertex_buffer);
void initVertexBuffer();
void resetVertexBuffer();
void shutdown();
// Refreshes renderer state to the cached values
// Needed when the render context has changed and invalidated the current state
void refreshState(void);
void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
void rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z);
void ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar);
void pushMatrix();
void popMatrix();
void loadMatrix(const GLfloat* m);
void loadIdentity();
void multMatrix(const GLfloat* m);
void matrixMode(eMatrixMode mode);
eMatrixMode getMatrixMode();
const glm::mat4& getModelviewMatrix();
const glm::mat4& getProjectionMatrix();
void syncMatrices();
void syncLightState();
void translateUI(F32 x, F32 y, F32 z);
void scaleUI(F32 x, F32 y, F32 z);
void pushUIMatrix();
void popUIMatrix();
void loadUIIdentity();
LLVector3 getUITranslation();
LLVector3 getUIScale();
void flush();
// if list is set, will store buffers in list for later use, if list isn't set, will use cache
void beginList(std::list<LLVertexBufferData> *list);
void endList();
void begin(const GLuint& mode);
void end();
U8 getMode() const { return mMode; }
void vertex2i(const GLint& x, const GLint& y);
void vertex2f(const GLfloat& x, const GLfloat& y);
void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z);
void vertex2fv(const GLfloat* v);
void vertex3fv(const GLfloat* v);
void texCoord2i(const GLint& x, const GLint& y);
void texCoord2f(const GLfloat& x, const GLfloat& y);
void texCoord2fv(const GLfloat* tc);
void color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a);
void color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a);
void color4fv(const GLfloat* c);
void color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b);
void color3fv(const GLfloat* c);
void color4ubv(const GLubyte* c);
void diffuseColor3f(F32 r, F32 g, F32 b);
void diffuseColor3fv(const F32* c);
void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);
void diffuseColor4fv(const F32* c);
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 setColorMask(bool writeColor, bool writeAlpha);
void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha);
void setSceneBlendType(eBlendType type);
// applies blend func to both color and alpha
void blendFunc(eBlendFactor sfactor, eBlendFactor dfactor);
// applies separate blend functions to color and alpha
void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor);
LLLightState* getLight(U32 index);
void setAmbientLightColor(const LLColor4& color);
void setLineWidth(F32 line_width); // <FS> Line width OGL core profile fix by Rye Mutt
LLTexUnit* getTexUnit(U32 index);
U32 getCurrentTexUnitIndex(void) const { return mCurrTextureUnitIndex; }
bool verifyTexUnitActive(U32 unitToVerify);
void debugTexUnits(void);
void clearErrors();
struct Vertex
{
GLfloat v[3];
GLubyte c[4];
GLfloat uv[2];
};
public:
static U32 sUICalls;
static U32 sUIVerts;
static bool sGLCoreProfile;
static bool sNsightDebugSupport;
static LLVector2 sUIGLScaleFactor;
static bool sClassicMode; // classic sky mode active
private:
friend class LLLightState;
LLVertexBuffer* bufferfromCache(U32 attribute_mask, U32 count);
LLVertexBuffer* genBuffer(U32 attribute_mask, S32 count);
void drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count);
void resetStriders(S32 count);
eMatrixMode mMatrixMode;
U32 mMatIdx[NUM_MATRIX_MODES];
U32 mMatHash[NUM_MATRIX_MODES];
glm::mat4 mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
U32 mCurMatHash[NUM_MATRIX_MODES];
U32 mLightHash;
LLColor4 mAmbientLightColor;
bool mDirty;
U32 mCount;
U32 mMode;
U32 mCurrTextureUnitIndex;
bool mCurrColorMask[4];
F32 mLineWidth; // <FS> Line width OGL core profile fix by Rye Mutt
// <FS:Ansariel> Don't ignore OpenGL max line width
F32 mMaxLineWidthSmooth;
F32 mMaxLineWidthAliased;
// </FS:Ansariel>
LLPointer<LLVertexBuffer> mBuffer;
LLStrider<LLVector4a> mVerticesp;
LLStrider<LLVector2> mTexcoordsp;
LLStrider<LLColor4U> mColorsp;
std::array<LLTexUnit, LL_NUM_TEXTURE_LAYERS> mTexUnits;
LLTexUnit mDummyTexUnit;
std::array<LLLightState, LL_NUM_LIGHT_UNITS> mLightState;
eBlendFactor mCurrBlendColorSFactor;
eBlendFactor mCurrBlendColorDFactor;
eBlendFactor mCurrBlendAlphaSFactor;
eBlendFactor mCurrBlendAlphaDFactor;
std::vector<LLVector3> mUIOffset;
std::vector<LLVector3> mUIScale;
};
extern F32 gGLModelView[16];
extern F32 gGLLastModelView[16];
extern F32 gGLLastProjection[16];
extern F32 gGLProjection[16];
extern S32 gGLViewport[4];
extern glm::mat4 gGLDeltaModelView;
extern glm::mat4 gGLInverseDeltaModelView;
extern thread_local LLRender gGL;
// This rotation matrix moves the default OpenGL reference frame
// (-Z at, Y up) to Cory's favorite reference frame (X at, Z up)
const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X
-1.f, 0.f, 0.f, 0.f, // -X becomes Y
0.f, 1.f, 0.f, 0.f, // Y becomes Z
0.f, 0.f, 0.f, 1.f };
glm::mat4 copy_matrix(F32* src);
glm::mat4 get_current_modelview();
glm::mat4 get_current_projection();
glm::mat4 get_last_modelview();
glm::mat4 get_last_projection();
void copy_matrix(const glm::mat4& src, F32* dst);
void set_current_modelview(const glm::mat4& mat);
void set_current_projection(const glm::mat4& mat);
void set_last_modelview(const glm::mat4& mat);
void set_last_projection(const glm::mat4& mat);
// glh compat
glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec);
#define LL_SHADER_LOADING_WARNS(...) LL_WARNS()
#endif
File diff suppressed because it is too large Load Diff
+178
View File
@@ -0,0 +1,178 @@
/**
* @file llrender2dutils.h
* @brief GL function declarations for immediate-mode gl drawing.
*
* $LicenseInfo:firstyear=2012&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$
*/
// All immediate-mode gl drawing should happen here.
#ifndef LL_RENDER2DUTILS_H
#define LL_RENDER2DUTILS_H
#include "llpointer.h" // LLPointer<>
#include "llrect.h"
#include "llsingleton.h"
#include "llglslshader.h"
class LLColor4;
class LLVector3;
class LLVector2;
class LLUIImage;
class LLUUID;
extern const LLColor4 UI_VERTEX_COLOR;
bool ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom);
void gl_state_for_2d(S32 width, S32 height);
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2);
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color );
void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, bool filled);
void gl_rect_2d_simple( S32 width, S32 height );
void gl_draw_x(const LLRect& rect, const LLColor4& color);
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, bool filled = true );
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, bool filled = true );
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, bool filled = true );
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, bool filled = true );
void gl_rect_2d(const LLRect& rect, bool filled = true );
void gl_rect_2d(const LLRect& rect, const LLColor4& color, bool filled = true );
void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f);
void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines);
void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, bool filled);
void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, bool filled, F32 start_angle, F32 end_angle);
void gl_deep_circle( F32 radius, F32 depth );
void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, bool render_center );
void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);
void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), LLRenderTarget* target = NULL);
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, bool solid_color = false, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, bool solid_color = false, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color);
void gl_rect_2d_simple_tex( S32 width, S32 height );
// segmented rectangles
/*
TL |______TOP_________| TR
/| |\
_/_|__________________|_\_
L| | MIDDLE | |R
_|_|__________________|_|_
\ | BOTTOM | /
BL\|__________________|/ BR
| |
*/
typedef enum e_rounded_edge
{
ROUNDED_RECT_LEFT = 0x1,
ROUNDED_RECT_TOP = 0x2,
ROUNDED_RECT_RIGHT = 0x4,
ROUNDED_RECT_BOTTOM = 0x8,
ROUNDED_RECT_ALL = 0xf
}ERoundedEdge;
void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);
void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);
inline void gl_rect_2d( const LLRect& rect, bool filled )
{
gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
}
inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, bool filled)
{
gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
}
class LLImageProviderInterface;
class LLRender2D : public LLSimpleton<LLRender2D>
{
LOG_CLASS(LLRender2D);
public:
LLRender2D(LLImageProviderInterface* image_provider);
~LLRender2D();
static void pushMatrix();
static void popMatrix();
static void loadIdentity();
static void translate(F32 x, F32 y, F32 z = 0.0f);
static void setLineWidth(F32 width);
LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
protected:
// since LLRender2D has no control of image provider's lifecycle
// we need a way to tell LLRender2D that provider died and
// LLRender2D needs to be updated.
static void resetProvider();
private:
LLImageProviderInterface* mImageProvider;
};
class LLImageProviderInterface
{
protected:
LLImageProviderInterface() {};
virtual ~LLImageProviderInterface();
public:
virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
virtual void cleanUp() = 0;
// to notify holders when pointer gets deleted
typedef void(*callback_t)();
void addOnRemovalCallback(callback_t func);
void deleteOnRemovalCallback(callback_t func);
private:
typedef std::list< callback_t > callback_list_t;
callback_list_t mCallbackList;
};
extern LLGLSLShader gSolidColorProgram;
extern LLGLSLShader gUIProgram;
#endif // LL_RENDER2DUTILS_H
+59
View File
@@ -0,0 +1,59 @@
/**
* @file llrendernavprim.cpp
* @brief Implementation of llrendernavprim
* @author Prep@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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 "llrendernavprim.h"
#include "llrender.h"
#include "llvertexbuffer.h"
#include "v4coloru.h"
#include "v3math.h"
//=============================================================================
LLRenderNavPrim gRenderNav;
//=============================================================================
void LLRenderNavPrim::renderLLTri( const LLVector3& a, const LLVector3& b, const LLVector3& c, const LLColor4U& color ) const
{
gGL.color4ubv(color.mV);
gGL.begin(LLRender::TRIANGLES);
{
gGL.vertex3fv( a.mV );
gGL.vertex3fv( b.mV );
gGL.vertex3fv( c.mV );
}
gGL.end();
}
//=============================================================================
void LLRenderNavPrim::renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt )
{
pVBO->setBuffer();
pVBO->drawArrays( mode, 0, vertCnt );
}
//=============================================================================
+49
View File
@@ -0,0 +1,49 @@
/**
* @file llrendernavprim.h
* @brief Header file for llrendernavprim
* @author Prep@lindenlab.com
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, 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_LLRENDERNAVPRIM_H
#define LL_LLRENDERNAVPRIM_H
#include "stdtypes.h"
class LLColor4U;
class LLVector3;
class LLVertexBuffer;
class LLRenderNavPrim
{
public:
//Draw simple tri
void renderLLTri( const LLVector3& a, const LLVector3& b, const LLVector3& c, const LLColor4U& color ) const;
//Draw the contents of vertex buffer
void renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt );
private:
};
extern LLRenderNavPrim gRenderNav;
#endif // LL_LLRENDERNAVPRIM_H
+129
View File
@@ -0,0 +1,129 @@
/**
* @file llrendersphere.cpp
* @brief implementation of the LLRenderSphere class.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// Sphere creates a set of display lists that can then be called to create
// a lit sphere at different LOD levels. You only need one instance of sphere
// per viewer - then call the appropriate list.
#include "linden_common.h"
#include "llrendersphere.h"
#include "llerror.h"
#include "llglheaders.h"
#include "llvertexbuffer.h"
#include "llglslshader.h"
LLRenderSphere gSphere;
void LLRenderSphere::render()
{
renderGGL();
gGL.flush();
}
inline LLVector3 polar_to_cart(F32 latitude, F32 longitude)
{
return LLVector3(sin(F_TWO_PI * latitude) * cos(F_TWO_PI * longitude),
sin(F_TWO_PI * latitude) * sin(F_TWO_PI * longitude),
cos(F_TWO_PI * latitude));
}
void LLRenderSphere::renderGGL()
{
LL_PROFILE_ZONE_SCOPED;
S32 const LATITUDE_SLICES = 20;
S32 const LONGITUDE_SLICES = 30;
if (mVertexBuffer.isNull())
{
mSpherePoints.resize(LATITUDE_SLICES + 1);
mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX);
mVertexBuffer->allocateBuffer((U32)(LATITUDE_SLICES + 1) * (LONGITUDE_SLICES + 1), LATITUDE_SLICES * LONGITUDE_SLICES * 6);
LLStrider<LLVector3> v;
mVertexBuffer->getVertexStrider(v);
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++)
{
mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1);
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES + 1; lon_i++)
{
F32 lat = (F32)lat_i / LATITUDE_SLICES;
F32 lon = (F32)lon_i / LONGITUDE_SLICES;
mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon);
v[lat_i * (LONGITUDE_SLICES + 1) + lon_i] = mSpherePoints[lat_i][lon_i];
}
}
LLStrider<U16> i;
mVertexBuffer->getIndexStrider(i);
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
{
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
{
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 0] = lat_i * (LONGITUDE_SLICES + 1) + lon_i;
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 1] = lat_i * (LONGITUDE_SLICES + 1) + lon_i + 1;
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 2] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i;
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 3] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i;
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 4] = lat_i * (LONGITUDE_SLICES + 1) + lon_i + 1;
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 5] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i + 1;
}
}
mVertexBuffer->unmapBuffer();
}
if (LLGLSLShader::sCurBoundShaderPtr->mAttributeMask == LLVertexBuffer::MAP_VERTEX)
{ // shader expects only vertex positions in vertex buffer, use fast path
mVertexBuffer->setBuffer();
mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, mVertexBuffer->getNumVerts(), mVertexBuffer->getNumIndices(), 0);
}
else
{ //shader wants colors in the vertex stream, use slow path
gGL.begin(LLRender::TRIANGLES);
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
{
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
{
gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV);
gGL.vertex3fv(mSpherePoints[lat_i][lon_i + 1].mV);
gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i].mV);
gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i].mV);
gGL.vertex3fv(mSpherePoints[lat_i][lon_i + 1].mV);
gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i + 1].mV);
}
}
gGL.end();
}
}
+52
View File
@@ -0,0 +1,52 @@
/**
* @file llrendersphere.h
* @brief interface for the LLRenderSphere class.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLRENDERSPHERE_H
#define LL_LLRENDERSPHERE_H
#include "llmath.h"
#include "v3math.h"
#include "v4math.h"
#include "m3math.h"
#include "m4math.h"
#include "v4color.h"
#include "llgl.h"
void lat2xyz(LLVector3 * result, F32 lat, F32 lon); // utility routine
class LLRenderSphere
{
public:
void render(); // render at highest LOD
void renderGGL(); // render using LLRender
private:
std::vector< std::vector<LLVector3> > mSpherePoints;
LLPointer<LLVertexBuffer> mVertexBuffer;
};
extern LLRenderSphere gSphere;
#endif
+605
View File
@@ -0,0 +1,605 @@
/**
* @file llrendertarget.cpp
* @brief LLRenderTarget implementation
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llrendertarget.h"
#include "llrender.h"
#include "llgl.h"
LLRenderTarget* LLRenderTarget::sBoundTarget = NULL;
U32 LLRenderTarget::sBytesAllocated = 0;
void check_framebuffer_status()
{
if (gDebugGL)
{
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
switch (status)
{
case GL_FRAMEBUFFER_COMPLETE:
break;
default:
LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL;
ll_fail("check_framebuffer_status failed");
break;
}
}
}
bool LLRenderTarget::sUseFBO = false;
U32 LLRenderTarget::sCurFBO = 0;
extern S32 gGLViewport[4];
U32 LLRenderTarget::sCurResX = 0;
U32 LLRenderTarget::sCurResY = 0;
LLRenderTarget::LLRenderTarget() :
mResX(0),
mResY(0),
mFBO(0),
mDepth(0),
mUseDepth(false),
mUsage(LLTexUnit::TT_TEXTURE)
{
}
LLRenderTarget::~LLRenderTarget()
{
release();
}
void LLRenderTarget::resize(U32 resx, U32 resy)
{
//for accounting, get the number of pixels added/subtracted
S32 pix_diff = (resx*resy)-(mResX*mResY);
mResX = resx;
mResY = resy;
llassert(mInternalFormat.size() == mTex.size());
for (U32 i = 0; i < mTex.size(); ++i)
{ //resize color attachments
gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
sBytesAllocated += pix_diff*4;
}
if (mDepth)
{
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
sBytesAllocated += pix_diff*4;
}
}
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLTexUnit::eTextureType usage, LLTexUnit::eTextureMipGeneration generateMipMaps)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(usage == LLTexUnit::TT_TEXTURE);
llassert(!isBoundInStack());
if(mResX == resx && mResY == resy && mUsage == usage && depth == mUseDepth && mGenerateMipMaps == generateMipMaps)
{
return true;
}
resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
release();
mResX = resx;
mResY = resy;
mUsage = usage;
mUseDepth = depth;
mGenerateMipMaps = generateMipMaps;
if (mGenerateMipMaps != LLTexUnit::TMG_NONE) {
// Calculate the number of mip levels based upon resolution that we should have.
mMipLevels = 1 + (U32)floor(log10((float)llmax(mResX, mResY)) / log10(2.0));
}
if (depth)
{
if (!allocateDepth())
{
LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL;
return false;
}
}
glGenFramebuffers(1, (GLuint *) &mFBO);
if (mDepth)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
}
return addColorAttachment(color_fmt);
}
void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
llassert(img != nullptr); // img must not be null
llassert(sUseFBO); // FBO support must be enabled
llassert(mDepth == 0); // depth buffers not supported with this mode
llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL)
llassert(!isBoundInStack());
if (mFBO == 0)
{
glGenFramebuffers(1, (GLuint*)&mFBO);
}
mResX = img->getWidth();
mResY = img->getHeight();
mUsage = img->getTarget();
if (use_name == 0)
{
use_name = img->getTexName();
}
mTex.push_back(use_name);
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
LLTexUnit::getInternalType(mUsage), use_name, 0);
stop_glerror();
check_framebuffer_status();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
}
void LLRenderTarget::releaseColorAttachment()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
llassert(!isBoundInStack());
llassert(mTex.size() == 1); //cannot use releaseColorAttachment with LLRenderTarget managed color targets
llassert(mFBO != 0); // mFBO must be valid
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), 0, 0);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
mTex.clear();
}
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(!isBoundInStack());
if (color_fmt == 0)
{
return true;
}
U32 offset = static_cast<U32>(mTex.size());
if( offset >= 4 )
{
LL_WARNS() << "Too many color attachments" << LL_ENDL;
llassert( offset < 4 );
return false;
}
if( offset > 0 && (mFBO == 0) )
{
llassert( mFBO != 0 );
return false;
}
U32 tex;
LLImageGL::generateTextures(1, &tex);
gGL.getTexUnit(0)->bindManual(mUsage, tex);
stop_glerror();
{
clear_glerror();
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
if (glGetError() != GL_NO_ERROR)
{
LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL;
return false;
}
}
sBytesAllocated += mResX*mResY*4;
stop_glerror();
if (offset == 0)
{ //use bilinear filtering on single texture render targets that aren't multisampled
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
stop_glerror();
}
else
{ //don't filter data attachments
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
stop_glerror();
}
if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
{
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
stop_glerror();
}
else
{
// ATI doesn't support mirrored repeat for rectangular textures.
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
}
if (mFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
LLTexUnit::getInternalType(mUsage), tex, 0);
check_framebuffer_status();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
}
mTex.push_back(tex);
mInternalFormat.push_back(color_fmt);
if (gDebugGL)
{ //bind and unbind to validate target
bindTarget();
flush();
}
return true;
}
bool LLRenderTarget::allocateDepth()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
LLImageGL::generateTextures(1, &mDepth);
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
stop_glerror();
clear_glerror();
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
sBytesAllocated += mResX*mResY*4;
if (glGetError() != GL_NO_ERROR)
{
LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL;
return false;
}
return true;
}
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
{
llassert(!isBoundInStack());
if (!mFBO || !target.mFBO)
{
LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL;
}
if (target.mDepth)
{
LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL;
}
if (target.mUseDepth)
{
LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL;
}
if (mDepth)
{
glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
check_framebuffer_status();
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
target.mUseDepth = true;
}
}
void LLRenderTarget::release()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
llassert(!isBoundInStack());
if (mDepth)
{
LLImageGL::deleteTextures(1, &mDepth);
mDepth = 0;
sBytesAllocated -= mResX*mResY*4;
}
// else if (mFBO)
if (mFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
if (mUseDepth)
{ //detach shared depth buffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
mUseDepth = false;
}
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
}
// Detach any extra color buffers (e.g. SRGB spec buffers)
//
if (mFBO && (mTex.size() > 1))
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
size_t z;
for (z = mTex.size() - 1; z >= 1; z--)
{
sBytesAllocated -= mResX*mResY*4;
glFramebufferTexture2D(GL_FRAMEBUFFER, static_cast<GLenum>(GL_COLOR_ATTACHMENT0+z), LLTexUnit::getInternalType(mUsage), 0, 0);
LLImageGL::deleteTextures(1, &mTex[z]);
}
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
}
if (mFBO)
{
if (mFBO == sCurFBO)
{
sCurFBO = 0;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
glDeleteFramebuffers(1, (GLuint *) &mFBO);
mFBO = 0;
}
if (mTex.size() > 0)
{
sBytesAllocated -= mResX*mResY*4;
LLImageGL::deleteTextures(1, &mTex[0]);
}
mTex.clear();
mInternalFormat.clear();
mResX = mResY = 0;
}
void LLRenderTarget::bindTarget()
{
LL_PROFILE_GPU_ZONE("bindTarget");
llassert(mFBO);
llassert(!isBoundInStack());
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
sCurFBO = mFBO;
//setup multiple render targets
GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3};
if (mTex.empty())
{ //no color buffer to draw to
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
else
{
glDrawBuffers(static_cast<GLsizei>(mTex.size()), drawbuffers);
glReadBuffer(GL_COLOR_ATTACHMENT0);
}
check_framebuffer_status();
glViewport(0, 0, mResX, mResY);
sCurResX = mResX;
sCurResY = mResY;
mPreviousRT = sBoundTarget;
sBoundTarget = this;
}
void LLRenderTarget::clear(U32 mask_in)
{
LL_PROFILE_GPU_ZONE("clear");
llassert(mFBO);
U32 mask = GL_COLOR_BUFFER_BIT;
if (mUseDepth)
{
mask |= GL_DEPTH_BUFFER_BIT;
}
if (mFBO)
{
check_framebuffer_status();
stop_glerror();
glClear(mask & mask_in);
stop_glerror();
}
else
{
LLGLEnable scissor(GL_SCISSOR_TEST);
glScissor(0, 0, mResX, mResY);
stop_glerror();
glClear(mask & mask_in);
}
}
U32 LLRenderTarget::getTexture(U32 attachment) const
{
if (attachment >= mTex.size())
{
LL_WARNS() << "Invalid attachment index " << attachment << " for size " << mTex.size() << LL_ENDL;
llassert(false);
return 0;
}
return mTex[attachment];
}
U32 LLRenderTarget::getNumTextures() const
{
return static_cast<U32>(mTex.size());
}
void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
{
gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index), filter_options == LLTexUnit::TFO_TRILINEAR || filter_options == LLTexUnit::TFO_ANISOTROPIC);
bool isSRGB = false;
llassert(mInternalFormat.size() > index);
switch (mInternalFormat[index])
{
case GL_SRGB:
case GL_SRGB8:
case GL_SRGB_ALPHA:
case GL_SRGB8_ALPHA8:
isSRGB = true;
break;
default:
break;
}
gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options);
}
void LLRenderTarget::flush()
{
LL_PROFILE_GPU_ZONE("rt flush");
gGL.flush();
llassert(mFBO);
llassert(sCurFBO == mFBO);
llassert(sBoundTarget == this);
if (mGenerateMipMaps == LLTexUnit::TMG_AUTO)
{
LL_PROFILE_GPU_ZONE("rt generate mipmaps");
bindTexture(0, 0, LLTexUnit::TFO_TRILINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
}
if (mPreviousRT)
{
// a bit hacky -- pop the RT stack back two frames and push
// the previous frame back on to play nice with the GL state machine
sBoundTarget = mPreviousRT->mPreviousRT;
mPreviousRT->bindTarget();
}
else
{
sBoundTarget = nullptr;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
sCurFBO = 0;
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
sCurResX = gGLViewport[2];
sCurResY = gGLViewport[3];
glReadBuffer(GL_BACK);
glDrawBuffer(GL_BACK);
}
}
bool LLRenderTarget::isComplete() const
{
return !mTex.empty() || mDepth;
}
void LLRenderTarget::getViewport(S32* viewport)
{
viewport[0] = 0;
viewport[1] = 0;
viewport[2] = mResX;
viewport[3] = mResY;
}
bool LLRenderTarget::isBoundInStack() const
{
LLRenderTarget* cur = sBoundTarget;
while (cur && cur != this)
{
cur = cur->mPreviousRT;
}
return cur == this;
}
void LLRenderTarget::swapFBORefs(LLRenderTarget& other)
{
// Must be initialized
llassert(mFBO);
llassert(other.mFBO);
// Must be unbound
// *NOTE: mPreviousRT can be non-null even if this target is unbound - presumably for debugging purposes?
llassert(sCurFBO != mFBO);
llassert(sCurFBO != other.mFBO);
llassert(!isBoundInStack());
llassert(!other.isBoundInStack());
// Must be same type
llassert(sUseFBO == other.sUseFBO);
llassert(mResX == other.mResX);
llassert(mResY == other.mResY);
llassert(mInternalFormat == other.mInternalFormat);
llassert(mTex.size() == other.mTex.size());
llassert(mDepth == other.mDepth);
llassert(mUseDepth == other.mUseDepth);
llassert(mGenerateMipMaps == other.mGenerateMipMaps);
llassert(mMipLevels == other.mMipLevels);
llassert(mUsage == other.mUsage);
std::swap(mFBO, other.mFBO);
std::swap(mTex, other.mTex);
}
+194
View File
@@ -0,0 +1,194 @@
/**
* @file llrendertarget.h
* @brief Off screen render target abstraction. Loose wrapper for GL_EXT_framebuffer_objects.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLRENDERTARGET_H
#define LL_LLRENDERTARGET_H
// LLRenderTarget is unavailible on the mapserver since it uses FBOs.
#include "llgl.h"
#include "llrender.h"
/*
Wrapper around OpenGL framebuffer objects for use in render-to-texture
SAMPLE USAGE:
LLRenderTarget target;
...
//allocate a 256x256 RGBA render target with depth buffer
target.allocate(256,256,GL_RGBA,TRUE);
//render to contents of offscreen buffer
target.bindTarget();
target.clear();
... <issue drawing commands> ...
target.flush();
...
//use target as a texture
gGL.getTexUnit(INDEX)->bind(&target);
... <issue drawing commands> ...
*/
class LLRenderTarget
{
public:
// Whether or not to use FBO implementation
static bool sUseFBO;
static U32 sBytesAllocated;
static U32 sCurFBO;
static U32 sCurResX;
static U32 sCurResY;
LLRenderTarget();
~LLRenderTarget();
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
// resX - width
// resY - height
// color_fmt - GL color format (e.g. GL_RGB)
// depth - if true, allocate a depth buffer
// usage - deprecated, should always be TT_TEXTURE
bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureMipGeneration generateMipMaps = LLTexUnit::TMG_NONE);
//resize existing attachments to use new resolution and color format
// CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
// DO NOT use for screen space buffers or for scratch space for an image that might be uploaded
// DO use for render targets that resize often and aren't likely to ruin someone's day if they break
void resize(U32 resx, U32 resy);
//point this render target at a particular LLImageGL
// Intended usage:
// LLRenderTarget target;
// target.addColorAttachment(image);
// target.bindTarget();
// < issue GL calls>
// target.flush();
// target.releaseColorAttachment();
//
// attachment -- LLImageGL to render into
// use_name -- optional texture name to target instead of attachment->getTexName()
// NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with
// addColorAttachment, allocateDepth, resize, etc.
void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0);
// detach from current color attachment
void releaseColorAttachment();
//add color buffer attachment
//limit of 4 color attachments per render target
bool addColorAttachment(U32 color_fmt);
//allocate a depth texture
bool allocateDepth();
//share depth buffer with provided render target
void shareDepthBuffer(LLRenderTarget& target);
//free any allocated resources
//safe to call redundantly
// asserts that this target is not currently bound or present in the RT stack
void release();
//bind target for rendering
//applies appropriate viewport
// If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget
// and restores previous binding on flush() (maintains a stack of Render Targets)
// Asserts that this target is not currently bound in the stack
void bindTarget();
//clear render targer, 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);
//get applied viewport
void getViewport(S32* viewport);
//get X resolution
U32 getWidth() const { return mResX; }
//get Y resolution
U32 getHeight() const { return mResY; }
LLTexUnit::eTextureType getUsage(void) const { return mUsage; }
U32 getTexture(U32 attachment = 0) const;
U32 getNumTextures() const;
U32 getDepth(void) const { return mDepth; }
void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);
//flush rendering operations
//must be called when rendering is complete
//should be used 1:1 with bindTarget
// call bindTarget once, do all your rendering, call flush once
// If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack)
// asserts that this target is currently bound
void flush();
//Returns TRUE if target is ready to be rendered into.
//That is, if the target has been allocated with at least
//one renderable attachment (i.e. color buffer, depth buffer).
bool isComplete() const;
// Returns true if this RenderTarget is bound somewhere in the stack
bool isBoundInStack() const;
static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
// *HACK
void swapFBORefs(LLRenderTarget& other);
static LLRenderTarget* sBoundTarget;
protected:
U32 mResX;
U32 mResY;
std::vector<U32> mTex;
std::vector<U32> mInternalFormat;
U32 mFBO;
LLRenderTarget* mPreviousRT = nullptr;
U32 mDepth;
bool mUseDepth;
LLTexUnit::eTextureMipGeneration mGenerateMipMaps;
U32 mMipLevels;
LLTexUnit::eTextureType mUsage;
};
#endif
File diff suppressed because it is too large Load Diff
+422
View File
@@ -0,0 +1,422 @@
/**
* @file llshadermgr.h
* @brief Shader Manager
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_SHADERMGR_H
#define LL_SHADERMGR_H
#include "llgl.h"
#include "llglslshader.h"
class LLShaderMgr
{
public:
LLShaderMgr();
virtual ~LLShaderMgr();
// Note: although you can use statically hashed strings to just bind a random uniform, it's generally preferably that you use this.
// Always document what the actual shader uniform is next to the shader uniform in this struct.
// clang-format off
typedef enum
{ // Shader uniform name, set in LLShaderMgr::initAttribsAndUniforms()
MODELVIEW_MATRIX = 0, // "modelview_matrix"
PROJECTION_MATRIX, // "projection_matrix"
INVERSE_PROJECTION_MATRIX, // "inv_proj"
MODELVIEW_PROJECTION_MATRIX, // "modelview_projection_matrix"
INVERSE_MODELVIEW_MATRIX, // "inv_modelview"
IDENTITY_MATRIX, // "identity_matrix"
NORMAL_MATRIX, // "normal_matrix"
TEXTURE_MATRIX0, // "texture_matrix0"
TEXTURE_MATRIX1, // "texture_matrix1"
TEXTURE_MATRIX2, // "texture_matrix2"
TEXTURE_MATRIX3, // "texture_matrix3"
OBJECT_PLANE_S, // "object_plane_s"
OBJECT_PLANE_T, // "object_plane_t"
TEXTURE_BASE_COLOR_TRANSFORM, // "texture_base_color_transform" (GLTF)
TEXTURE_NORMAL_TRANSFORM, // "texture_normal_transform" (GLTF)
TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_transform" (GLTF)
TEXTURE_OCCLUSION_TRANSFORM, // "texture_occlusion_transform" (GLTF)
TEXTURE_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF)
BASE_COLOR_TEXCOORD, // "base_color_texcoord" (GLTF)
EMISSIVE_TEXCOORD, // "emissive_texcoord" (GLTF)
NORMAL_TEXCOORD, // "normal_texcoord" (GLTF)
METALLIC_ROUGHNESS_TEXCOORD, // "metallic_roughness_texcoord" (GLTF)
OCCLUSION_TEXCOORD, // "occlusion_texcoord" (GLTF)
GLTF_NODE_ID, // "gltf_node_id" (GLTF)
GLTF_MATERIAL_ID, // "gltf_material_id" (GLTF)
TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF)
VIEWPORT, // "viewport"
LIGHT_POSITION, // "light_position"
LIGHT_DIRECTION, // "light_direction"
LIGHT_ATTENUATION, // "light_attenuation"
LIGHT_DEFERRED_ATTENUATION, // "light_deferred_attenuation"
LIGHT_DIFFUSE, // "light_diffuse"
LIGHT_AMBIENT, // "light_ambient"
MULTI_LIGHT_COUNT, // "light_count"
MULTI_LIGHT, // "light"
MULTI_LIGHT_COL, // "light_col"
MULTI_LIGHT_FAR_Z, // "far_z"
PROJECTOR_MATRIX, // "proj_mat"
PROJECTOR_NEAR, // "proj_near"
PROJECTOR_P, // "proj_p"
PROJECTOR_N, // "proj_n"
PROJECTOR_ORIGIN, // "proj_origin"
PROJECTOR_RANGE, // "proj_range"
PROJECTOR_AMBIANCE, // "proj_ambiance"
PROJECTOR_SHADOW_INDEX, // "proj_shadow_idx"
PROJECTOR_SHADOW_FADE, // "shadow_fade"
PROJECTOR_FOCUS, // "proj_focus"
PROJECTOR_LOD, // "proj_lod"
PROJECTOR_AMBIENT_LOD, // "proj_ambient_lod"
DIFFUSE_COLOR, // "color"
EMISSIVE_COLOR, // "emissiveColor"
METALLIC_FACTOR, // "metallicFactor"
ROUGHNESS_FACTOR, // "roughnessFactor"
MIRROR_FLAG, // "mirror_flag"
CLIP_PLANE, // "clipPlane"
CLIP_SIGN, // "clipSign"
DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap"
METALLIC_ROUGHNESS_MAP, // "metallicRoughnessMap"
NORMAL_MAP, // "normalMap"
OCCLUSION_MAP, // "occlusionMap"
EMISSIVE_MAP, // "emissiveMap"
BUMP_MAP, // "bumpMap"
BUMP_MAP2, // "bumpMap2"
ENVIRONMENT_MAP, // "environmentMap"
SCENE_MAP, // "sceneMap"
SCENE_DEPTH, // "sceneDepth"
REFLECTION_PROBES, // "reflectionProbes"
IRRADIANCE_PROBES, // "irradianceProbes"
HERO_PROBE, // "heroProbes"
CLOUD_NOISE_MAP, // "cloud_noise_texture"
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
LIGHTNORM, // "lightnorm"
SUNLIGHT_COLOR, // "sunlight_color"
AMBIENT, // "ambient_color"
SKY_HDR_SCALE, // "sky_hdr_scale"
SKY_SUNLIGHT_SCALE, // "sky_sunlight_scale"
SKY_AMBIENT_SCALE, // "sky_ambient_scale"
CLASSIC_MODE, // "classic_mode"
BLUE_HORIZON, // "blue_horizon"
BLUE_DENSITY, // "blue_density"
HAZE_HORIZON, // "haze_horizon"
HAZE_DENSITY, // "haze_density"
CLOUD_SHADOW, // "cloud_shadow"
DENSITY_MULTIPLIER, // "density_multiplier"
DISTANCE_MULTIPLIER, // "distance_multiplier"
MAX_Y, // "max_y"
GLOW, // "glow"
CLOUD_COLOR, // "cloud_color"
CLOUD_POS_DENSITY1, // "cloud_pos_density1"
CLOUD_POS_DENSITY2, // "cloud_pos_density2"
CLOUD_SCALE, // "cloud_scale"
GAMMA, // "gamma"
SCENE_LIGHT_STRENGTH, // "scene_light_strength"
LIGHT_CENTER, // "center"
LIGHT_SIZE, // "size"
LIGHT_FALLOFF, // "falloff"
BOX_CENTER, // "box_center"
BOX_SIZE, // "box_size"
GLOW_MIN_LUMINANCE, // "minLuminance"
GLOW_MAX_EXTRACT_ALPHA, // "maxExtractAlpha"
GLOW_LUM_WEIGHTS, // "lumWeights"
GLOW_WARMTH_WEIGHTS, // "warmthWeights"
GLOW_WARMTH_AMOUNT, // "warmthAmount"
GLOW_STRENGTH, // "glowStrength"
GLOW_DELTA, // "glowDelta"
GLOW_NOISE_MAP, // "glowNoiseMap"
MINIMUM_ALPHA, // "minimum_alpha"
EMISSIVE_BRIGHTNESS, // "emissive_brightness"
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"
DEFERRED_SSAO_FACTOR_INV, // "ssao_factor_inv"
DEFERRED_SSAO_EFFECT_MAT, // "ssao_effect_mat"
DEFERRED_SCREEN_RES, // "screen_res"
DEFERRED_NEAR_CLIP, // "near_clip"
DEFERRED_SHADOW_OFFSET, // "shadow_offset"
DEFERRED_SHADOW_BIAS, // "shadow_bias"
DEFERRED_SPOT_SHADOW_BIAS, // "spot_shadow_bias"
DEFERRED_SPOT_SHADOW_OFFSET, // "spot_shadow_offset"
DEFERRED_SUN_DIR, // "sun_dir"
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"
DEFERRED_SSR_RAY_STEP, // "rayStep"
DEFERRED_SSR_DIST_BIAS, // "distanceBias"
DEFERRED_SSR_REJECT_BIAS, // "depthRejectBias"
DEFERRED_SSR_GLOSSY_SAMPLES, // "glossySampleCount"
DEFERRED_SSR_NOISE_SINE, // "noiseSine"
DEFERRED_SSR_ADAPTIVE_STEP_MULT, // "adaptiveStepMultiplier"
MODELVIEW_DELTA_MATRIX, // "modelview_delta"
INVERSE_MODELVIEW_DELTA_MATRIX, // "inv_modelview_delta"
CUBE_SNAPSHOT, // "cube_snapshot"
FXAA_TC_SCALE, // "tc_scale"
FXAA_RCP_SCREEN_RES, // "rcp_screen_res"
FXAA_RCP_FRAME_OPT, // "rcp_frame_opt"
FXAA_RCP_FRAME_OPT2, // "rcp_frame_opt2"
DOF_FOCAL_DISTANCE, // "focal_distance"
DOF_BLUR_CONSTANT, // "blur_constant"
DOF_TAN_PIXEL_ANGLE, // "tan_pixel_angle"
DOF_MAGNIFICATION, // "magnification"
DOF_MAX_COF, // "max_cof"
DOF_RES_SCALE, // "res_scale"
DOF_WIDTH, // "dof_width"
DOF_HEIGHT, // "dof_height"
DEFERRED_DEPTH, // "depthMap"
DEFERRED_SHADOW0, // "shadowMap0"
DEFERRED_SHADOW1, // "shadowMap1"
DEFERRED_SHADOW2, // "shadowMap2"
DEFERRED_SHADOW3, // "shadowMap3"
DEFERRED_SHADOW4, // "shadowMap4"
DEFERRED_SHADOW5, // "shadowMap5"
DEFERRED_POSITION, // "positionMap"
DEFERRED_DIFFUSE, // "diffuseRect"
DEFERRED_SPECULAR, // "specularRect"
DEFERRED_EMISSIVE, // "emissiveRect"
EXPOSURE_MAP, // "exposureMap"
DEFERRED_BRDF_LUT, // "brdfLut"
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"
AVATAR_MATRIX, // "matrixPalette"
AVATAR_TRANSLATION, // "translationPalette"
// <FS:CR> Import Vignette from Exodus
RENDER_VIGNETTE, // "vignette"
// </FS:CR> Import Vignette from Exodus
WATER_SCREENTEX, // "screenTex"
WATER_SCREENDEPTH, // "screenDepth"
WATER_REFTEX, // "refTex"
WATER_EXCLUSIONTEX, // "exclusionTex"
WATER_EYEVEC, // "eyeVec"
WATER_TIME, // "time"
WATER_WAVE_DIR1, // "waveDir1"
WATER_WAVE_DIR2, // "waveDir2"
WATER_LIGHT_DIR, // "lightDir"
WATER_SPECULAR, // "specular"
WATER_SPECULAR_EXP, // "lightExp"
WATER_FOGCOLOR, // "waterFogColor"
WATER_FOGCOLOR_LINEAR, // "waterFogColorLinear"
WATER_FOGDENSITY, // "waterFogDensity"
WATER_FOGKS, // "waterFogKS"
WATER_REFSCALE, // "refScale"
WATER_WATERHEIGHT, // "waterHeight"
WATER_WATERPLANE, // "waterPlane"
WATER_NORM_SCALE, // "normScale"
WATER_FRESNEL_SCALE, // "fresnelScale"
WATER_FRESNEL_OFFSET, // "fresnelOffset"
WATER_BLUR_MULTIPLIER, // "blurMultiplier"
WATER_SUN_ANGLE, // "sunAngle"
WATER_SCALED_ANGLE, // "scaledAngle"
WATER_SUN_ANGLE2, // "sunAngle2"
WL_CAMPOSLOCAL, // "camPosLocal"
// [RLVa:KB] - @setsphere
RLV_EFFECT_MODE, // "rlvEffectMode"
RLV_EFFECT_PARAM1, // "rlvEffectParam1"
RLV_EFFECT_PARAM2, // "rlvEffectParam2"
RLV_EFFECT_PARAM3, // "rlvEffectParam3"
RLV_EFFECT_PARAM4, // "rlvEffectParam4"
RLV_EFFECT_PARAM5, // "rlvEffectParam5"
// [/RLVa:KB]
AVATAR_WIND, // "gWindDir"
AVATAR_SINWAVE, // "gSinWaveParams"
AVATAR_GRAVITY, // "gGravity"
TERRAIN_DETAIL0, // "detail_0"
TERRAIN_DETAIL1, // "detail_1"
TERRAIN_DETAIL2, // "detail_2"
TERRAIN_DETAIL3, // "detail_3"
TERRAIN_ALPHARAMP, // "alpha_ramp"
TERRAIN_PAINTMAP, // "paint_map"
TERRAIN_DETAIL0_BASE_COLOR, // "detail_0_base_color" (GLTF)
TERRAIN_DETAIL1_BASE_COLOR, // "detail_1_base_color" (GLTF)
TERRAIN_DETAIL2_BASE_COLOR, // "detail_2_base_color" (GLTF)
TERRAIN_DETAIL3_BASE_COLOR, // "detail_3_base_color" (GLTF)
TERRAIN_DETAIL0_NORMAL, // "detail_0_normal" (GLTF)
TERRAIN_DETAIL1_NORMAL, // "detail_1_normal" (GLTF)
TERRAIN_DETAIL2_NORMAL, // "detail_2_normal" (GLTF)
TERRAIN_DETAIL3_NORMAL, // "detail_3_normal" (GLTF)
TERRAIN_DETAIL0_METALLIC_ROUGHNESS, // "detail_0_metallic_roughness" (GLTF)
TERRAIN_DETAIL1_METALLIC_ROUGHNESS, // "detail_1_metallic_roughness" (GLTF)
TERRAIN_DETAIL2_METALLIC_ROUGHNESS, // "detail_2_metallic_roughness" (GLTF)
TERRAIN_DETAIL3_METALLIC_ROUGHNESS, // "detail_3_metallic_roughness" (GLTF)
TERRAIN_DETAIL0_EMISSIVE, // "detail_0_emissive" (GLTF)
TERRAIN_DETAIL1_EMISSIVE, // "detail_1_emissive" (GLTF)
TERRAIN_DETAIL2_EMISSIVE, // "detail_2_emissive" (GLTF)
TERRAIN_DETAIL3_EMISSIVE, // "detail_3_emissive" (GLTF)
TERRAIN_BASE_COLOR_FACTORS, // "baseColorFactors" (GLTF)
TERRAIN_METALLIC_FACTORS, // "metallicFactors" (GLTF)
TERRAIN_ROUGHNESS_FACTORS, // "roughnessFactors" (GLTF)
TERRAIN_EMISSIVE_COLORS, // "emissiveColors" (GLTF)
TERRAIN_MINIMUM_ALPHAS, // "minimum_alphas" (GLTF)
REGION_SCALE, // "region_scale" (GLTF)
SHINY_ORIGIN, // "origin"
DISPLAY_GAMMA, // "display_gamma"
INSCATTER_RT, // "inscatter"
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"
RAINBOW_MAP, // "rainbow_map"
HALO_MAP, // "halo_map"
MOON_BRIGHTNESS, // "moon_brightness"
CLOUD_VARIANCE, // "cloud_variance"
REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
REFLECTION_PROBE_MAX_LOD, // "max_probe_lod"
REFLECTION_PROBE_STRENGTH, // "probe_strength"
SH_INPUT_L1R, // "sh_input_r"
SH_INPUT_L1G, // "sh_input_g"
SH_INPUT_L1B, // "sh_input_b"
SUN_MOON_GLOW_FACTOR, // "sun_moon_glow_factor"
WATER_EDGE_FACTOR, // "water_edge"
SUN_UP_FACTOR, // "sun_up_factor"
MOONLIGHT_COLOR, // "moonlight_color"
DEBUG_NORMAL_DRAW_LENGTH, // "debug_normal_draw_length"
SMAA_EDGE_TEX, // "edgesTex"
SMAA_AREA_TEX, // "areaTex"
SMAA_SEARCH_TEX, // "searchTex"
SMAA_BLEND_TEX, // "blendTex"
// <FS:Beq> Uniforms for snapshot frame
SNAPSHOT_BORDER_COLOR, // "border_color"
SNAPSHOT_BORDER_THICKNESS, // "border_thickness"
SNAPSHOT_GUIDE_COLOR, // "guide_color"
SNAPSHOT_GUIDE_THICKNESS, // "guide_thickness"
SNAPSHOT_GUIDE_STYLE, // "guide_style"
SNAPSHOT_FRAME_RECT, // "frame_rect"
// </FS:Beq>
END_RESERVED_UNIFORMS
} eGLSLReservedUniforms;
// clang-format on
// singleton pattern implementation
static LLShaderMgr * instance();
virtual void initAttribsAndUniforms(void);
bool attachShaderFeatures(LLGLSLShader * shader);
void dumpObjectLog(GLuint ret, bool warns = true, const std::string& filename = "");
void dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text);
bool linkProgramObject(GLuint obj, bool suppress_errors = false);
bool validateProgramObject(GLuint obj);
GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
// Implemented in the application to actually update out of date uniforms for a particular shader
virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual
void initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version);
void clearShaderCache();
void persistShaderCacheMetadata();
bool loadCachedProgramBinary(LLGLSLShader* shader);
bool saveCachedProgramBinary(LLGLSLShader* shader);
public:
// Map of shader names to compiled
std::map<std::string, GLuint> mVertexShaderObjects;
std::map<std::string, GLuint> mFragmentShaderObjects;
//global (reserved slot) shader parameters
std::vector<std::string> mReservedAttribs;
std::vector<std::string> mReservedUniforms;
struct ProgramBinaryData
{
GLsizei mBinaryLength = 0;
GLenum mBinaryFormat = 0;
F32 mLastUsedTime = 0.0;
};
std::map<LLUUID, ProgramBinaryData> mShaderBinaryCache;
bool mShaderCacheInitialized = false;
bool mShaderCacheEnabled = false;
std::string mShaderCacheDir;
protected:
// our parameter manager singleton instance
static LLShaderMgr * sInstance;
}; //LLShaderMgr
#endif
+43
View File
@@ -0,0 +1,43 @@
/**
* @file lltexture.cpp
*
* $LicenseInfo:firstyear=2000&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 "lltexture.h"
//virtual
LLTexture::~LLTexture()
{
}
S8 LLTexture::getType() const { llassert(false); return 0; }
void LLTexture::setKnownDrawSize(S32 width, S32 height) { llassert(false); }
bool LLTexture::bindDefaultImage(const S32 stage) { llassert(false); return false; }
bool LLTexture::bindDebugImage(const S32 stage) { llassert(false); return false; }
void LLTexture::forceImmediateUpdate() { llassert(false); }
void LLTexture::setActive() { llassert(false); }
S32 LLTexture::getWidth(S32 discard_level) const { llassert(false); return 0; }
S32 LLTexture::getHeight(S32 discard_level) const { llassert(false); return 0; }
bool LLTexture::isActiveFetching() { llassert(false); return false; }
LLImageGL* LLTexture::getGLTexture() const { llassert(false); return nullptr; }
void LLTexture::updateBindStatsForTester() { }
+75
View File
@@ -0,0 +1,75 @@
/**
* @file lltexture.h
* @brief LLTexture definition
*
* This class acts as a wrapper for OpenGL calls.
* The goal of this class is to minimize the number of api calls due to legacy rendering
* code, to define an interface for a multiple rendering API abstraction of the UI
* rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_TEXTURE_H
#define LL_TEXTURE_H
#include "llrefcount.h"
#include "lltrace.h"
class LLImageGL ;
class LLTexUnit ;
class LLFontGL ;
//
//this is an abstract class as the parent for the class LLGLTexture
//
class LLTexture : public virtual LLRefCount
{
friend class LLTexUnit ;
friend class LLFontGL ;
protected:
virtual ~LLTexture();
public:
LLTexture()
{}
//
//interfaces to access LLGLTexture
//
virtual S8 getType() const;
virtual void setKnownDrawSize(S32 width, S32 height);
virtual bool bindDefaultImage(const S32 stage = 0);
virtual bool bindDebugImage(const S32 stage = 0);
virtual void forceImmediateUpdate();
virtual void setActive();
virtual S32 getWidth(S32 discard_level = -1) const;
virtual S32 getHeight(S32 discard_level = -1) const;
virtual bool isActiveFetching();
virtual LLImageGL* getGLTexture() const;
private:
virtual void updateBindStatsForTester();
};
#endif
+32
View File
@@ -0,0 +1,32 @@
/**
* @file lltexturemanagerbridge.cpp
* @brief Defined a null texture manager bridge. Applications must provide their own bridge implementaton.
*
* $LicenseInfo:firstyear=2012&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 "lltexturemanagerbridge.h"
// Define a null texture manager bridge. Applications must provide their own bridge implementaton.
LLTextureManagerBridge* gTextureManagerBridgep = NULL;
+47
View File
@@ -0,0 +1,47 @@
/**
* @file lltexturemanagerbridge.h
* @brief Bridge to an application-specific texture manager.
*
* $LicenseInfo:firstyear=2012&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_TEXTUREMANAGERBRIDGE_H
#define LL_TEXTUREMANAGERBRIDGE_H
#include "llpointer.h"
#include "llgltexture.h"
// Abstract bridge interface
class LLTextureManagerBridge
{
public:
virtual ~LLTextureManagerBridge() {}
virtual LLPointer<LLGLTexture> getLocalTexture(bool usemipmaps = true, bool generate_gl_tex = true) = 0;
virtual LLPointer<LLGLTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, bool usemipmaps, bool generate_gl_tex = true) = 0;
virtual LLGLTexture* getFetchedTexture(const LLUUID &image_id) = 0;
};
extern LLTextureManagerBridge* gTextureManagerBridgep;
#endif // LL_TEXTUREMANAGERBRIDGE_H
+172
View File
@@ -0,0 +1,172 @@
/**
* @file lluiimage.cpp
* @brief UI 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$
*/
// Utilities functions the user interface needs
//#include "llviewerprecompiledheaders.h"
#include "linden_common.h"
// Project includes
#include "lluiimage.h"
LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
: mName(name),
mImage(image),
mScaleRegion(0.f, 1.f, 1.f, 0.f),
mClipRegion(0.f, 1.f, 1.f, 0.f),
mImageLoaded(NULL),
mScaleStyle(SCALE_INNER),
mCachedW(-1),
mCachedH(-1)
{
getTextureWidth();
getTextureHeight();
}
LLUIImage::~LLUIImage()
{
delete mImageLoaded;
}
S32 LLUIImage::getWidth() const
{
// return clipped dimensions of actual image area
return ll_round((F32)mImage->getWidth(0) * mClipRegion.getWidth());
}
S32 LLUIImage::getHeight() const
{
// return clipped dimensions of actual image area
return ll_round((F32)mImage->getHeight(0) * mClipRegion.getHeight());
}
void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis,
const LLRect& rect, const LLColor4& color)
{
F32 border_scale = 1.f;
F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight();
F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth();
if (rect.getHeight() < border_height || rect.getWidth() < border_width)
{
if(border_height - rect.getHeight() > border_width - rect.getWidth())
{
border_scale = (F32)rect.getHeight() / border_height;
}
else
{
border_scale = (F32)rect.getWidth() / border_width;
}
}
LLRender2D::pushMatrix();
{
LLVector3 rect_origin = origin_agent + ((F32)rect.mLeft * x_axis) + ((F32)rect.mBottom * y_axis);
LLRender2D::translate(rect_origin.mV[VX],
rect_origin.mV[VY],
rect_origin.mV[VZ]);
gGL.getTexUnit(0)->bind(getImage());
gGL.color4fv(color.mV);
LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(),
mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(),
mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(),
mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight());
gl_segmented_rect_3d_tex(mClipRegion,
center_uv_rect,
LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(),
(rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(),
(rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(),
(border_height * border_scale * 0.5f) / (F32)rect.getHeight()),
(F32)rect.getWidth() * x_axis,
(F32)rect.getHeight() * y_axis);
} LLRender2D::popMatrix();
}
//#include "lluiimage.inl"
boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb )
{
if (!mImageLoaded)
{
mImageLoaded = new image_loaded_signal_t();
}
return mImageLoaded->connect(cb);
}
void LLUIImage::onImageLoaded()
{
if (mImageLoaded)
{
(*mImageLoaded)();
}
}
namespace LLInitParam
{
void ParamValue<LLUIImage*>::updateValueFromBlock()
{
// The keyword "none" is specifically requesting a null image
// do not default to current value. Used to overwrite template images.
if (name() == "none")
{
updateValue(NULL);
return;
}
LLUIImage* imagep = LLRender2D::getInstance()->getUIImage(name());
if (imagep)
{
updateValue(imagep);
}
}
void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)
{
if (getValue() == NULL)
{
name.set("none", make_block_authoritative);
}
else
{
name.set(getValue()->getName(), make_block_authoritative);
}
}
bool ParamCompare<LLUIImage*, false>::equals(
LLUIImage* const &a,
LLUIImage* const &b)
{
// force all LLUIImages for XML UI export to be "non-default"
if (!a && !b)
return false;
else
return (a == b);
}
}
+148
View File
@@ -0,0 +1,148 @@
/**
* @file lluiimage.h
* @brief wrapper for images used in the UI that handles smart scaling, etc.
*
* $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_LLUIIMAGE_H
#define LL_LLUIIMAGE_H
#include "v4color.h"
#include "llpointer.h"
#include "llrefcount.h"
#include "llrefcount.h"
#include "llrect.h"
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include "llinitparam.h"
#include "lltexture.h"
#include "llrender2dutils.h"
extern const LLColor4 UI_VERTEX_COLOR;
class LLUIImage : public LLRefCount
{
public:
enum EScaleStyle
{
SCALE_INNER,
SCALE_OUTER
};
typedef boost::signals2::signal<void (void)> image_loaded_signal_t;
LLUIImage(const std::string& name, LLPointer<LLTexture> image);
virtual ~LLUIImage();
LL_FORCE_INLINE void setClipRegion(const LLRectf& region)
{
mClipRegion = region;
}
LL_FORCE_INLINE void setScaleRegion(const LLRectf& region)
{
mScaleRegion = region;
}
LL_FORCE_INLINE void setScaleStyle(EScaleStyle style)
{
mScaleStyle = style;
}
LL_FORCE_INLINE LLPointer<LLTexture> getImage() { return mImage; }
LL_FORCE_INLINE const LLPointer<LLTexture>& getImage() const { return mImage; }
LL_FORCE_INLINE void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
LL_FORCE_INLINE void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
LL_FORCE_INLINE void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
LL_FORCE_INLINE void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
LL_FORCE_INLINE void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
LL_FORCE_INLINE void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
LL_FORCE_INLINE void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
LL_FORCE_INLINE void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
LL_FORCE_INLINE void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color);
LL_FORCE_INLINE const std::string& getName() const { return mName; }
virtual S32 getWidth() const;
virtual S32 getHeight() const;
// returns dimensions of underlying textures, which might not be equal to ui image portion
LL_FORCE_INLINE S32 getTextureWidth() const;
LL_FORCE_INLINE S32 getTextureHeight() const;
boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb );
void onImageLoaded();
protected:
image_loaded_signal_t* mImageLoaded;
std::string mName;
LLRectf mScaleRegion;
LLRectf mClipRegion;
LLPointer<LLTexture> mImage;
EScaleStyle mScaleStyle;
mutable S32 mCachedW;
mutable S32 mCachedH;
};
#include "lluiimage.inl"
namespace LLInitParam
{
template<>
class ParamValue<LLUIImage*>
: public CustomParamValue<LLUIImage*>
{
typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref;
typedef CustomParamValue<LLUIImage*> super_t;
public:
Optional<std::string> name;
ParamValue(LLUIImage* const& image = NULL)
: super_t(image)
{
updateBlockFromValue(false);
addSynonym(name, "name");
}
void updateValueFromBlock();
void updateBlockFromValue(bool make_block_authoritative);
};
// Need custom comparison function for our test app, which only loads
// LLUIImage* as NULL.
template<>
struct ParamCompare<LLUIImage*, false>
{
static bool equals(LLUIImage* const &a, LLUIImage* const &b);
};
}
typedef LLPointer<LLUIImage> LLUIImagePtr;
#endif
+77
View File
@@ -0,0 +1,77 @@
/**
* @file lluiimage.inl
* @brief UI inline func 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$
*/
void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
{
draw(x, y, getWidth(), getHeight(), color);
}
void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
{
gl_draw_scaled_image_with_border(
x, y,
width, height,
mImage,
color,
false,
mClipRegion,
mScaleRegion,
mScaleStyle == SCALE_INNER);
}
void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
{
gl_draw_scaled_image_with_border(
x, y,
width, height,
mImage,
color,
true,
mClipRegion,
mScaleRegion,
mScaleStyle == SCALE_INNER);
}
void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
{
LLRect border_rect;
border_rect.setOriginAndSize(x, y, width, height);
border_rect.stretch(border_width, border_width);
drawSolid(border_rect, color);
}
// returns dimensions of underlying textures, which might not be equal to ui image portion
S32 LLUIImage::getTextureWidth() const
{
mCachedW = (mCachedW == -1) ? getWidth() : mCachedW;
return mCachedW;
}
S32 LLUIImage::getTextureHeight() const
{
mCachedH = (mCachedH == -1) ? getHeight() : mCachedH;
return mCachedH;
}
File diff suppressed because it is too large Load Diff
+354
View File
@@ -0,0 +1,354 @@
/**
* @file llvertexbuffer.h
* @brief LLVertexBuffer wrapper for OpengGL vertex buffer objects
*
* $LicenseInfo:firstyear=2003&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_LLVERTEXBUFFER_H
#define LL_LLVERTEXBUFFER_H
#include "llgl.h"
#include "v2math.h"
#include "v3math.h"
#include "v4math.h"
#include "v4coloru.h"
#include "llstrider.h"
#include "llrender.h"
#include "lltrace.h"
#include <set>
#include <vector>
#include <list>
#include <glm/gtc/matrix_transform.hpp>
#define LL_MAX_VERTEX_ATTRIB_LOCATION 64
//============================================================================
// NOTES
// Threading:
// All constructors should take an 'create' paramater which should only be
// 'true' when called from the main thread. Otherwise createGLBuffer() will
// be called as soon as getVertexPointer(), etc is called (which MUST ONLY be
// called from the main (i.e OpenGL) thread)
//============================================================================
// base class
class LLPrivateMemoryPool;
class LLVertexBuffer;
class LLVertexBufferData
{
public:
LLVertexBufferData()
: mVB(nullptr)
, mMode(0)
, mCount(0)
, mTexName(0)
, mProjection(glm::identity<glm::mat4>())
, mModelView(glm::identity<glm::mat4>())
, mTexture0(glm::identity<glm::mat4>())
{}
LLVertexBufferData(LLVertexBuffer* buffer, U8 mode, U32 count, U32 tex_name, const glm::mat4& model_view, const glm::mat4& projection, const glm::mat4& texture0)
: mVB(buffer)
, mMode(mode)
, mCount(count)
, mTexName(tex_name)
, mProjection(model_view)
, mModelView(projection)
, mTexture0(texture0)
{}
void drawWithMatrix();
void draw();
LLPointer<LLVertexBuffer> mVB;
U8 mMode;
U32 mCount;
U32 mTexName;
glm::mat4 mProjection;
glm::mat4 mModelView;
glm::mat4 mTexture0;
};
typedef std::list<LLVertexBufferData> buffer_data_list_t;
class LLVertexBuffer final : public LLRefCount
{
public:
struct MappedRegion
{
U32 mStart;
U32 mEnd;
};
LLVertexBuffer(const LLVertexBuffer& rhs)
{
*this = rhs;
}
const LLVertexBuffer& operator=(const LLVertexBuffer& rhs)
{
LL_ERRS() << "Illegal operation!" << LL_ENDL;
return *this;
}
static void initClass(LLWindow* window);
static void cleanupClass();
static void setupClientArrays(U32 data_mask);
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos);
static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp);
static void unbind(); //unbind any bound vertex buffer
//get the size of a vertex with the given typemask
static U32 calcVertexSize(const U32& typemask);
//get the size of a buffer with the given typemask and vertex count
//fill offsets with the offset of each vertex component array into the buffer
// indexed by the following enum
static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices);
// flush any pending mapped buffers
static void flushBuffers();
//WARNING -- when updating these enums you MUST
// 1 - update LLVertexBuffer::sTypeSize
// 2 - update LLVertexBuffer::vb_type_name
// 3 - add a strider accessor
// 4 - modify LLVertexBuffer::setupVertexBuffer
// 6 - modify LLViewerShaderMgr::mReservedAttribs
// clang-format off
enum AttributeType { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms()
TYPE_VERTEX = 0, // "position"
TYPE_NORMAL, // "normal"
TYPE_TEXCOORD0, // "texcoord0"
TYPE_TEXCOORD1, // "texcoord1"
TYPE_TEXCOORD2, // "texcoord2"
TYPE_TEXCOORD3, // "texcoord3"
TYPE_COLOR, // "diffuse_color"
TYPE_EMISSIVE, // "emissive"
TYPE_TANGENT, // "tangent"
TYPE_WEIGHT, // "weight"
TYPE_WEIGHT4, // "weight4"
TYPE_CLOTHWEIGHT, // "clothing"
TYPE_JOINT, // "joint"
TYPE_TEXTURE_INDEX, // "texture_index"
TYPE_MAX, // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer
TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer
};
// clang-format on
enum {
MAP_VERTEX = (1<<TYPE_VERTEX),
MAP_NORMAL = (1<<TYPE_NORMAL),
MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0),
MAP_TEXCOORD1 = (1<<TYPE_TEXCOORD1),
MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2),
MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3),
MAP_COLOR = (1<<TYPE_COLOR),
MAP_EMISSIVE = (1<<TYPE_EMISSIVE),
MAP_TANGENT = (1<<TYPE_TANGENT),
MAP_WEIGHT = (1<<TYPE_WEIGHT),
MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
MAP_JOINT = (1<<TYPE_JOINT),
MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX),
};
protected:
friend class LLRender;
~LLVertexBuffer(); // use unref()
void setupVertexBuffer();
void genBuffer(U32 size);
void genIndices(U32 size);
bool createGLBuffer(U32 size);
bool createGLIndices(U32 size);
void destroyGLBuffer();
void destroyGLIndices();
bool updateNumVerts(U32 nverts);
bool updateNumIndices(U32 nindices);
public:
LLVertexBuffer(U32 typemask);
// allocate buffer
bool allocateBuffer(U32 nverts, U32 nindices);
// map for data access (see also getFooStrider below)
U8* mapVertexBuffer(AttributeType type, U32 index, S32 count = -1);
U8* mapIndexBuffer(U32 index, S32 count = -1);
// synonym for flushBuffers
void unmapBuffer();
// set for rendering
// assumes (and will assert on) the following:
// - this buffer has no pending unmapBuffer call
// - a shader is currently bound
// - This buffer has sufficient attributes within it to satisfy the needs of the currently bound shader
void setBuffer();
// Only call each getVertexPointer, etc, once before calling unmapBuffer()
// call unmapBuffer() after calls to getXXXStrider() before any calls to setBuffer()
// example:
// vb->getVertexBuffer(verts);
// vb->getNormalStrider(norms);
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
bool getVertexStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
bool getVertexStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
bool getIndexStrider(LLStrider<U16>& strider, U32 index=0, S32 count = -1);
bool getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
bool getNormalStrider(LLStrider<LLVector4a>& strider, U32 index = 0, S32 count = -1);
bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
bool getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
bool getWeightStrider(LLStrider<F32>& strider, U32 index=0, S32 count = -1);
// <FS:Ansariel> Vectorized Weight4Strider and ClothWeightStrider by Drake Arconis
//bool getWeight4Strider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
//bool getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
bool getWeight4Strider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
bool getClothWeightStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
// </FS:Ansariel>
void setPositionData(const LLVector4a* data);
void setNormalData(const LLVector4a* data);
void setTangentData(const LLVector4a* data);
void setWeight4Data(const LLVector4a* data);
void setJointData(const U64* data);
void setTexCoord0Data(const LLVector2* data);
void setTexCoord1Data(const LLVector2* data);
void setColorData(const LLColor4U* data);
void setIndexData(const U16* data);
void setIndexData(const U32* data);
void setPositionData(const LLVector4a* data, U32 offset, U32 count);
void setNormalData(const LLVector4a* data, U32 offset, U32 count);
void setTangentData(const LLVector4a* data, U32 offset, U32 count);
void setWeight4Data(const LLVector4a* data, U32 offset, U32 count);
void setJointData(const U64* data, U32 offset, U32 count);
void setTexCoord0Data(const LLVector2* data, U32 offset, U32 count);
void setTexCoord1Data(const LLVector2* data, U32 offset, U32 count);
void setColorData(const LLColor4U* data, U32 offset, U32 count);
void setIndexData(const U16* data, U32 offset, U32 count);
void setIndexData(const U32* data, U32 offset, U32 count);
U32 getNumVerts() const { return mNumVerts; }
U32 getNumIndices() const { return mNumIndices; }
U32 getTypeMask() const { return mTypeMask; }
bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); }
U32 getSize() const { return mSize; }
U32 getIndicesSize() const { return mIndicesSize; }
U8* getMappedData() const { return mMappedData; }
U8* getMappedIndices() const { return mMappedIndexData; }
U32 getOffset(AttributeType type) const { return mOffsets[type]; }
// these functions assume (and assert on) the current VBO being bound
// Detailed error checking can be enabled by setting gDebugGL to true
void draw(U32 mode, U32 count, U32 indices_offset) const;
void drawArrays(U32 mode, U32 offset, U32 count) const;
void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
// draw without syncing matrices. If you're positive there have been no matrix
// since the last call to syncMatrices, this is much faster than drawRange
void drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
//for debugging, validate data in given range is valid
bool validateRange(U32 start, U32 end, U32 count, U32 offset) const;
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
void setLabel(const char* label);
#endif
void clone(LLVertexBuffer& target) const;
protected:
U32 mGLBuffer = 0; // GL VBO handle
U32 mGLIndices = 0; // GL IBO handle
U32 mNumVerts = 0; // Number of vertices allocated
U32 mNumIndices = 0; // Number of indices allocated
U32 mIndicesType = GL_UNSIGNED_SHORT; // type of indices in index buffer
U32 mIndicesStride = 2; // size of each index in bytes
U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute
U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped)
U8* mMappedIndexData = nullptr; // pointer to currently mapped indices (NULL if unmapped)
U32 mTypeMask = 0; // bitmask of present vertex attributes
U32 mSize = 0; // size in bytes of mMappedData
U32 mIndicesSize = 0; // size in bytes of mMappedIndexData
std::vector<MappedRegion> mMappedVertexRegions; // list of mMappedData byte ranges that must be sent to GL
std::vector<MappedRegion> mMappedIndexRegions; // list of mMappedIndexData byte ranges that must be sent to GL
private:
// DEPRECATED
// These function signatures are deprecated, but for some reason
// there are classes in an external package that depend on LLVertexBuffer
// TODO: move these classes into viewer repository
friend class LLNavShapeVBOManager;
friend class LLNavMeshVBOManager;
void flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst);
LLVertexBuffer(U32 typemask, U32 usage)
: LLVertexBuffer(typemask)
{}
bool allocateBuffer(S32 nverts, S32 nindices, bool create) { return allocateBuffer(nverts, nindices); }
// actually unmap buffer
void _unmapBuffer();
// add to set of mapped buffers
void _mapBuffer();
bool mMapped = false;
public:
static U64 getBytesAllocated();
static const U32 sTypeSize[TYPE_MAX];
static const U32 sGLMode[LLRender::NUM_MODES];
static U32 sGLRenderBuffer;
static U32 sGLRenderIndices;
static U32 sLastMask;
static U32 sVertexCount;
};
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
#define LL_LABEL_VERTEX_BUFFER(buf, name) buf->setLabel(name)
#else
#define LL_LABEL_VERTEX_BUFFER(buf, name)
#endif
#endif // LL_LLVERTEXBUFFER_H