diff options
Diffstat (limited to 'indra/llrender')
28 files changed, 1633 insertions, 515 deletions
| diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 07a0d8c402..47e7ad915b 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -31,6 +31,7 @@ include_directories(SYSTEM      )  set(llrender_SOURCE_FILES +    llatmosphere.cpp      llcubemap.cpp      llfontbitmapcache.cpp      llfontfreetype.cpp @@ -57,6 +58,7 @@ set(llrender_SOURCE_FILES  set(llrender_HEADER_FILES      CMakeLists.txt +    llatmosphere.h      llcubemap.h      llfontgl.h      llfontfreetype.h @@ -78,6 +80,7 @@ set(llrender_HEADER_FILES      llshadermgr.h      lltexture.h      lluiimage.h +    lluiimage.inl      llvertexbuffer.h      llglcommonfunc.h      ) diff --git a/indra/llrender/llatmosphere.cpp b/indra/llrender/llatmosphere.cpp new file mode 100644 index 0000000000..ffc17c89f8 --- /dev/null +++ b/indra/llrender/llatmosphere.cpp @@ -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.0, 1.0, -1.0 / kRayleighScaleHeight, 0.0, 0.0); +    DensityLayer mie_density(0.0, 1.0, -1.0 / kMieScaleHeight, 0.0, 0.0); + +    m_rayleighProfile.push_back(rayleigh_density); +    m_mieProfile.push_back(mie_density); + +    // Density profile increasing linearly from 0 to 1 between 10 and 25km, and +    // decreasing linearly from 1 to 0 between 25 and 40km. This is an approximate +    // profile from http://www.kln.ac.lk/science/Chemistry/Teaching_Resources/ +    // Documents/Introduction%20to%20atmospheric%20chemistry.pdf (page 10). +    m_absorptionProfile.push_back(DensityLayer(25000.0, 0.0, 0.0, 1.0 / 15000.0, -2.0 / 3.0)); +    m_absorptionProfile.push_back(DensityLayer(0.0, 0.0, 0.0, -1.0 / 15000.0, 8.0 / 3.0)); +} + +AtmosphericModelSettings::AtmosphericModelSettings( +    DensityProfile& rayleighProfile, +    DensityProfile& mieProfile, +    DensityProfile& absorptionProfile) +: m_skyBottomRadius(6360.0f) +, m_skyTopRadius(6420.0f) +, m_rayleighProfile(rayleighProfile) +, m_mieProfile(mieProfile) +, m_absorptionProfile(absorptionProfile) +, m_sunArcRadians(0.00045f) +, m_mieAnisotropy(0.8f) +{ +} + +AtmosphericModelSettings::AtmosphericModelSettings( +    F32             skyBottomRadius, +    F32             skyTopRadius, +    DensityProfile& rayleighProfile, +    DensityProfile& mieProfile, +    DensityProfile& absorptionProfile, +    F32             sunArcRadians, +    F32             mieAniso) +: m_skyBottomRadius(skyBottomRadius) +, m_skyTopRadius(skyTopRadius) +, m_rayleighProfile(rayleighProfile) +, m_mieProfile(mieProfile) +, m_absorptionProfile(absorptionProfile) +, m_sunArcRadians(sunArcRadians) +, m_mieAnisotropy(mieAniso) +{ +} + +bool AtmosphericModelSettings::operator==(const AtmosphericModelSettings& rhs) const +{ +    if (m_skyBottomRadius != rhs.m_skyBottomRadius) +    { +        return false; +    } + +    if (m_skyTopRadius != rhs.m_skyTopRadius) +    { +        return false; +    } + +    if (m_sunArcRadians != rhs.m_sunArcRadians) +    { +        return false; +    } + +    if (m_mieAnisotropy != rhs.m_mieAnisotropy) +    { +        return false; +    } + +    if (m_rayleighProfile != rhs.m_rayleighProfile) +    { +        return false; +    } + +    if (m_mieProfile != rhs.m_mieProfile) +    { +        return false; +    } + +    if (m_absorptionProfile != rhs.m_absorptionProfile) +    { +        return false; +    } + +    return true; +} + +void LLAtmosphere::initClass() +{ +    if (!gAtmosphere) +    {  +        gAtmosphere = new LLAtmosphere;  +    } +} + +void LLAtmosphere::cleanupClass() +{ +    if(gAtmosphere) +    { +        delete gAtmosphere; +    } +    gAtmosphere = NULL; +} + +LLAtmosphere::LLAtmosphere() +{ +    for (int l = kLambdaMin; l <= kLambdaMax; l += 10) +    { +        double lambda = static_cast<double>(l) * 1e-3;  // micro-meters +        double mie    = kMieAngstromBeta / kMieScaleHeight * pow(lambda, -kMieAngstromAlpha); +        m_wavelengths.push_back(l); +        m_solar_irradiance.push_back(kSolarIrradiance[(l - kLambdaMin) / 10]); +        m_rayleigh_scattering.push_back(kRayleigh * pow(lambda, -4)); +        m_mie_scattering.push_back(mie * kMieSingleScatteringAlbedo); +        m_mie_extinction.push_back(mie); +        m_absorption_extinction.push_back(kMaxOzoneNumberDensity * kOzoneCrossSection[(l - kLambdaMin) / 10]); +        m_ground_albedo.push_back(kGroundAlbedo); +    } + +    AtmosphericModelSettings defaults; +    configureAtmosphericModel(defaults); +} + +LLAtmosphere::~LLAtmosphere() +{ +    // Cease referencing textures from atmosphere::model from our LLGLTextures wrappers for same. +    if (m_transmittance) +    { +        m_transmittance->setTexName(0); +    } + +    if (m_scattering) +    { +        m_scattering->setTexName(0); +    } + +    if (m_mie_scatter_texture) +    { +        m_mie_scatter_texture->setTexName(0); +    } +} + +bool LLAtmosphere::configureAtmosphericModel(AtmosphericModelSettings& settings) +{ +    // TBD +    return true; +} + +LLGLTexture* LLAtmosphere::getTransmittance() +{ +    if (!m_transmittance) +    { +        m_transmittance  = new LLGLTexture; +        m_transmittance->generateGLTexture(); +        m_transmittance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP); +        m_transmittance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR); +        m_transmittance->setExplicitFormat(GL_RGB32F_ARB, 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_ARB, 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_ARB, 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_ARB, GL_RGB, GL_FLOAT); +        m_illuminance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE); +    } +    return m_illuminance; +} diff --git a/indra/llrender/llatmosphere.h b/indra/llrender/llatmosphere.h new file mode 100644 index 0000000000..572365d864 --- /dev/null +++ b/indra/llrender/llatmosphere.h @@ -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 diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index af4e3fdda0..5947bca670 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -43,20 +43,13 @@  const F32 epsilon = 1e-7f;  const U16 RESOLUTION = 64; -#if LL_DARWIN -// mipmap generation on cubemap textures seems to be broken on the Mac for at least some cards. -// Since the cubemap is small (64x64 per face) and doesn't have any fine detail, turning off mipmaps is a usable workaround. -const BOOL use_cube_mipmaps = FALSE; -#else -const BOOL use_cube_mipmaps = FALSE;  //current build works best without cube mipmaps -#endif -  bool LLCubeMap::sUseCubeMaps = true; -LLCubeMap::LLCubeMap() +LLCubeMap::LLCubeMap(bool init_as_srgb)  	: mTextureStage(0),  	  mTextureCoordStage(0), -	  mMatrixStage(0) +	  mMatrixStage(0), +	  mIssRGB(init_as_srgb)  {  	mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;  	mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; @@ -82,12 +75,17 @@ void LLCubeMap::initGL()  			U32 texname = 0;  			LLImageGL::generateTextures(1, &texname); - +			  			for (int i = 0; i < 6; i++)  			{ -				mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE)); +				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(64, 64, 4); +				mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4);  				mImages[i]->createGLTexture(0, mRawImages[i], texname);  				gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);  @@ -154,7 +152,7 @@ void LLCubeMap::initGLData()  {  	for (int i = 0; i < 6; i++)  	{ -		mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64); +		mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION);  	}  } @@ -484,7 +482,7 @@ void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)  						td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);  				}  			} -		mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64); +		mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION);  	}  } diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h index ee2c41e026..95b6d12099 100644 --- a/indra/llrender/llcubemap.h +++ b/indra/llrender/llcubemap.h @@ -36,8 +36,9 @@ class LLVector3;  // Environment map hack!  class LLCubeMap : public LLRefCount  { +	bool mIssRGB;  public: -	LLCubeMap(); +	LLCubeMap(bool init_as_srgb);  	void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);  	void initGL();  	void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages); diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index c0f0cec80b..c01c15391d 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -36,6 +36,7 @@  #include "llsys.h"  #include "llgl.h" +#include "llglstates.h"  #include "llrender.h"  #include "llerror.h" @@ -998,6 +999,12 @@ void LLGLManager::initExtensions()  	mHassRGBFramebuffer = ExtensionExists("GL_EXT_framebuffer_sRGB", gGLHExts.mSysExts);  #endif +#ifdef GL_EXT_texture_sRGB_decode +    mHasTexturesRGBDecode = ExtensionExists("GL_EXT_texture_sRGB_decode", gGLHExts.mSysExts); +#else +    mHasTexturesRGBDecode = ExtensionExists("GL_ARB_texture_sRGB_decode", gGLHExts.mSysExts); +#endif +  	mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;  	mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); @@ -2044,7 +2051,8 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :  	if (mState)  	{  		mWasEnabled = sStateMap[state]; -		llassert(mWasEnabled == glIsEnabled(state)); +        // we can't actually assert on this as queued changes to state are not reflected by glIsEnabled +		//llassert(mWasEnabled == glIsEnabled(state));  		setEnabled(enabled);  		stop_glerror();  	} @@ -2267,6 +2275,17 @@ LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& mode  	}  } +void LLGLUserClipPlane::disable() +{ +    if (mApply) +	{ +		gGL.matrixMode(LLRender::MM_PROJECTION); +		gGL.popMatrix(); +		gGL.matrixMode(LLRender::MM_MODELVIEW); +	} +    mApply = false; +} +  void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)  {  	glh::matrix4f& P = mProjection; @@ -2295,12 +2314,7 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)  LLGLUserClipPlane::~LLGLUserClipPlane()  { -	if (mApply) -	{ -		gGL.matrixMode(LLRender::MM_PROJECTION); -		gGL.popMatrix(); -		gGL.matrixMode(LLRender::MM_MODELVIEW); -	} +	disable();  }  LLGLNamePool::LLGLNamePool() @@ -2478,27 +2492,45 @@ void LLGLDepthTest::checkState()  	}  } -LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P, U32 layer) +LLGLSquashToFarClip::LLGLSquashToFarClip() +{ +    glh::matrix4f proj = get_current_projection(); +    setProjectionMatrix(proj, 0); +} + +LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f& P, U32 layer) +{ +    setProjectionMatrix(P, layer); +} + + +void LLGLSquashToFarClip::setProjectionMatrix(glh::matrix4f& projection, U32 layer)  {  	F32 depth = 0.99999f - 0.0001f * layer;  	for (U32 i = 0; i < 4; i++)  	{ -		P.element(2, i) = P.element(3, i) * depth; +		projection.element(2, i) = projection.element(3, i) * depth;  	} +    LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode(); +  	gGL.matrixMode(LLRender::MM_PROJECTION);  	gGL.pushMatrix(); -	gGL.loadMatrix(P.m); -	gGL.matrixMode(LLRender::MM_MODELVIEW); +	gGL.loadMatrix(projection.m); + +	gGL.matrixMode(last_matrix_mode);  }  LLGLSquashToFarClip::~LLGLSquashToFarClip()  { +    LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode(); +  	gGL.matrixMode(LLRender::MM_PROJECTION);  	gGL.popMatrix(); -	gGL.matrixMode(LLRender::MM_MODELVIEW); + +	gGL.matrixMode(last_matrix_mode);  } @@ -2561,6 +2593,43 @@ void LLGLSyncFence::wait()  #endif  } +LLGLSPipelineSkyBox::LLGLSPipelineSkyBox() +: mAlphaTest(GL_ALPHA_TEST) +, mCullFace(GL_CULL_FACE) +, mSquashClip() +{  +    if (!LLGLSLShader::sNoFixedFunction) +    { +        glDisable(GL_LIGHTING); +        glDisable(GL_FOG); +        glDisable(GL_CLIP_PLANE0); +    } +} + +LLGLSPipelineSkyBox::~LLGLSPipelineSkyBox() +{ +    if (!LLGLSLShader::sNoFixedFunction) +    { +        glEnable(GL_LIGHTING); +        glEnable(GL_FOG); +        glEnable(GL_CLIP_PLANE0); +    } +} + +LLGLSPipelineDepthTestSkyBox::LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write) +: LLGLSPipelineSkyBox() +, mDepth(depth_test ? GL_TRUE : GL_FALSE, depth_write ? GL_TRUE : GL_FALSE, GL_LEQUAL) +{ + +} + +LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write) +: LLGLSPipelineDepthTestSkyBox(depth_test, depth_write)     +, mBlend(GL_BLEND) +{  +    gGL.setSceneBlendType(LLRender::BT_ALPHA); +} +  #if LL_WINDOWS  // Expose desired use of high-performance graphics processor to Optimus driver  extern "C"  diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 4c4302d05b..a7faea7d33 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -118,6 +118,7 @@ public:  	BOOL mHasDebugOutput;  	BOOL mHassRGBTexture;  	BOOL mHassRGBFramebuffer; +    BOOL mHasTexturesRGBDecode;  	// Vendor-specific extensions  	BOOL mIsATI; @@ -348,6 +349,7 @@ public:  	~LLGLUserClipPlane();  	void setPlane(F32 a, F32 b, F32 c, F32 d); +    void disable();  private:  	bool mApply; @@ -360,14 +362,17 @@ private:    Modify and load projection matrix to push depth values to far clip plane.    Restores projection matrix on destruction. -  GL_MODELVIEW_MATRIX is active whenever program execution -  leaves this class. +  Saves/restores matrix mode around projection manipulation.    Does not stack.  */  class LLGLSquashToFarClip  {  public: -	LLGLSquashToFarClip(glh::matrix4f projection, U32 layer = 0); +    LLGLSquashToFarClip(); +	LLGLSquashToFarClip(glh::matrix4f& projection, U32 layer = 0); + +    void setProjectionMatrix(glh::matrix4f& projection, U32 layer); +  	~LLGLSquashToFarClip();  }; diff --git a/indra/llrender/llglcommonfunc.h b/indra/llrender/llglcommonfunc.h index f1f8ff7bc4..e6d3755755 100644 --- a/indra/llrender/llglcommonfunc.h +++ b/indra/llrender/llglcommonfunc.h @@ -1,5 +1,5 @@  /** -* @file llphoenixfunc.h +* @file llglcommonfunc.h  * @brief File include common opengl code snippets  *  * $LicenseInfo:firstyear=2003&license=viewerlgpl$ diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 141ed51260..384e5bf99f 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -37,12 +37,6 @@  #include "OpenGL/OpenGL.h"  #endif -#ifdef LL_RELEASE_FOR_DOWNLOAD -#define UNIFORM_ERRS LL_WARNS_ONCE("Shader") -#else -#define UNIFORM_ERRS LL_ERRS("Shader") -#endif -  // Lots of STL stuff in here, using namespace std to keep things more readable  using std::vector;  using std::pair; @@ -84,6 +78,12 @@ LLShaderFeatures::LLShaderFeatures()      , hasObjectSkinning(false)      , hasAtmospherics(false)      , hasGamma(false) +    , hasSrgb(false) +    , encodesNormal(false) +    , isDeferred(false) +    , hasIndirect(false) +    , hasShadows(false) +    , hasAmbientOcclusion(false)      , mIndexedTextureChannels(0)      , disableTextureIndex(false)      , hasAlphaMask(false) @@ -344,13 +344,13 @@ void LLGLSLShader::unloadInternal()      {          GLhandleARB obj[1024];          GLsizei count; +        glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj); -        glGetAttachedObjectsARB(mProgramObject, sizeof(obj)/sizeof(obj[0]), &count, obj);          for (GLsizei i = 0; i < count; i++)          {              glDetachObjectARB(mProgramObject, obj[i]); -                glDeleteObjectARB(obj[i]); -            } +            glDeleteObjectARB(obj[i]); +        }          glDeleteObjectARB(mProgramObject); @@ -448,12 +448,12 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,      }      if( !success )      { -        LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL; +        LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL;          // Try again using a lower shader level;          if (mShaderLevel > 0)          { -            LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL; +            LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;              mShaderLevel--;              return createShader(attributes,uniforms);          } @@ -485,18 +485,33 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,      return success;  } -BOOL LLGLSLShader::attachObject(std::string object) +BOOL LLGLSLShader::attachVertexObject(std::string object_path) { +    if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0) +    { +        stop_glerror(); +        glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]); +        stop_glerror(); +        return TRUE; +    } +    else +    { +        LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL; +        return FALSE; +    } +} + +BOOL LLGLSLShader::attachFragmentObject(std::string object_path)  { -    if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0) +    if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0)      {          stop_glerror(); -        glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]); +        glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);          stop_glerror();          return TRUE;      }      else      { -        LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL; +        LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL;          return FALSE;      }  } @@ -511,7 +526,7 @@ void LLGLSLShader::attachObject(GLhandleARB object)      }      else      { -        LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL; +        LL_SHADER_LOADING_WARNS() << "Attempting to attach non existing shader object. " << LL_ENDL;      }  } @@ -690,6 +705,11 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *      }  } +void LLGLSLShader::clearPermutations() +{ +    mDefines.clear(); +} +  void LLGLSLShader::addPermutation(std::string name, std::string value)  {      mDefines[name] = value; @@ -759,18 +779,19 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)  	S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap");  	S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap");  	S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap"); +    S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");  	S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");  	std::set<S32> skip_index; -	if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap)) +	if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap))  	{  		GLenum type;  		GLsizei length;  		GLint size = -1;  		char name[1024]; -		diffuseMap = specularMap = bumpMap = environmentMap = -1; +		diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1;  		for (S32 i = 0; i < activeCount; i++)  		{ @@ -790,12 +811,6 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)  				continue;  			} -			if (-1 == specularMap && std::string(name) == "specularMap") -			{ -				specularMap = i; -				continue; -			} -  			if (-1 == bumpMap && std::string(name) == "bumpMap")  			{  				bumpMap = i; @@ -807,6 +822,12 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)  				environmentMap = i;  				continue;  			} + +            if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap") +			{ +				altDiffuseMap = i; +				continue; +			}  		}  		bool specularDiff = specularMap < diffuseMap && -1 != specularMap; @@ -858,7 +879,7 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)  {      BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors); -    if (!suppress_errors) +    if (!success && !suppress_errors)      {          LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName);      } @@ -916,19 +937,19 @@ void LLGLSLShader::bindNoShader(void)      }  } -S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode) +S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)  {      S32 channel = 0;      channel = getUniformLocation(uniform); -    return bindTexture(channel, texture, mode); +    return bindTexture(channel, texture, mode, colorspace);  } -S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode) +S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)  {      if (uniform < 0 || uniform >= (S32)mTexture.size())      { -        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; +        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;          return -1;      } @@ -937,6 +958,7 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu      if (uniform > -1)      {          gGL.getTexUnit(uniform)->bind(texture, mode); +        gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);      }      return uniform; @@ -954,7 +976,7 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)  {      if (uniform < 0 || uniform >= (S32)mTexture.size())      { -        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; +        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;          return -1;      } @@ -968,11 +990,11 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)      return uniform;  } -S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) +S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)  {      if (uniform < 0 || uniform >= (S32)mTexture.size())      { -        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; +        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;          return -1;      }      S32 index = mTexture[uniform]; @@ -980,21 +1002,22 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)      {          gGL.getTexUnit(index)->activate();          gGL.getTexUnit(index)->enable(mode); +        gGL.getTexUnit(index)->setTextureColorSpace(space);      }      return index;  } -S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) +S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)  {      if (uniform < 0 || uniform >= (S32)mTexture.size())      { -        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL; +        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;          return -1;      }      S32 index = mTexture[uniform];      if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE)      { -        if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) +        if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode && gGL.getTexUnit(index)->getCurrColorSpace() != space)          {              if (gDebugSession)              { @@ -1017,7 +1040,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1039,7 +1062,7 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1061,7 +1084,7 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1084,7 +1107,7 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1107,7 +1130,7 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1130,7 +1153,7 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1153,7 +1176,7 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1176,7 +1199,7 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1199,7 +1222,7 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1222,7 +1245,7 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1245,7 +1268,7 @@ void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, c      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1262,7 +1285,7 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } @@ -1279,7 +1302,7 @@ void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose,  	{	  		if (mUniform.size() <= index)  		{ -			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +			LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;  			return;  		} @@ -1296,7 +1319,7 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c      {             if (mUniform.size() <= index)          { -            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL; +            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;              return;          } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index b56b914013..7cf6d3c941 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -48,6 +48,12 @@ public:  	bool hasObjectSkinning;  	bool hasAtmospherics;  	bool hasGamma; +    bool hasShadows; +    bool hasAmbientOcclusion; +	bool hasSrgb; +    bool encodesNormal; +    bool isDeferred; +    bool hasIndirect;  	S32 mIndexedTextureChannels;  	bool disableTextureIndex;  	bool hasAlphaMask; @@ -96,7 +102,8 @@ public:  						std::vector<LLStaticHashedString> * uniforms,  						U32 varying_count = 0,  						const char** varyings = NULL); -	BOOL attachObject(std::string object); +    BOOL attachFragmentObject(std::string object); +    BOOL attachVertexObject(std::string object);  	void attachObject(GLhandleARB object);  	void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);  	BOOL mapAttributes(const std::vector<LLStaticHashedString> * attributes); @@ -139,6 +146,7 @@ public:  	GLint getAttribLocation(U32 attrib);  	GLint mapUniformTextureChannel(GLint location, GLenum type); +    void clearPermutations();  	void addPermutation(std::string name, std::string value);  	void removePermutation(std::string name); @@ -146,13 +154,13 @@ public:  	//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); +	S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); +    S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);  	// 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, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); +	S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);  	S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);  	S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE); diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index 0e2c3bcb44..a4924eba14 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -208,11 +208,27 @@ public:  class LLGLSPipelineSkyBox  {   protected: -	LLGLDisable mAlphaTest, mCullFace, mFog; +	LLGLDisable mAlphaTest; +    LLGLDisable mCullFace; +    LLGLSquashToFarClip mSquashClip;  public: -	LLGLSPipelineSkyBox() -		: mAlphaTest(GL_ALPHA_TEST), mCullFace(GL_CULL_FACE), mFog(GL_FOG) -	{ } +	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 diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index 3a6eebebba..ad501687ed 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -288,6 +288,18 @@ void  LLGLTexture::setCategory(S32 category)  	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()) ; @@ -389,9 +401,11 @@ void LLGLTexture::destroyGLTexture()  void LLGLTexture::setTexelsPerImage()  { -	S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); -	S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); -	mTexelsPerImage = (F32)fullwidth * fullheight; +	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; } diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 70610d9626..071912c2c2 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -1,5 +1,5 @@  /**  - * @file llglviewertexture.h + * @file llgltexture.h   * @brief Object for managing opengl textures   *   * $LicenseInfo:firstyear=2012&license=viewerlgpl$ @@ -104,7 +104,7 @@ public:  	virtual void dump();	// debug info to LL_INFOS() -	virtual const LLUUID& getID() const = 0; +	virtual const LLUUID& getID() const;  	void setBoostLevel(S32 level);  	S32  getBoostLevel() { return mBoostLevel; } @@ -133,6 +133,8 @@ public:  	BOOL       setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height);  	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; @@ -179,11 +181,11 @@ protected:  protected:  	S32 mBoostLevel;				// enum describing priority level -	S32 mFullWidth; -	S32 mFullHeight; +	U32 mFullWidth; +	U32 mFullHeight;  	BOOL mUseMipMaps;  	S8  mComponents; -	F32 mTexelsPerImage;			// Texels per image. +	U32 mTexelsPerImage;			// Texels per image.  	mutable S8  mNeedsGLTexture;  	//GL texture diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 40217b2e80..ff74380217 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -184,34 +184,47 @@ void LLImageGL::cleanupClass()  //static  S32 LLImageGL::dataFormatBits(S32 dataformat)  { -	switch (dataformat) -	{ -	  case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	return 4; -	  case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	return 8; -	  case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	return 8; -	  case GL_LUMINANCE:						return 8; -	  case GL_ALPHA:							return 8; -	  case GL_COLOR_INDEX:						return 8; -	  case GL_LUMINANCE_ALPHA:					return 16; -	  case GL_RGB:								return 24; -	  case GL_RGB8:								return 24; -	  case GL_RGBA:								return 32; -	  case GL_BGRA:								return 32;		// Used for QuickTime media textures on the Mac -	  default: -		LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; -		return 0; -	} +    switch (dataformat) +    { +    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	        return 4; +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:    return 4; +    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	        return 8; +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:    return 8; +    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	        return 8; +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:    return 8; +    case GL_LUMINANCE:						        return 8; +    case GL_ALPHA:							        return 8; +    case GL_COLOR_INDEX:						    return 8; +    case GL_LUMINANCE_ALPHA:					    return 16; +    case GL_RGB:								    return 24; +    case GL_SRGB:								    return 24; +    case GL_RGB8:								    return 24; +    case GL_RGBA:								    return 32; +    case GL_SRGB_ALPHA:						        return 32; +    case GL_BGRA:								    return 32;		// Used for QuickTime media textures on the Mac +    default: +        LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; +        return 0; +    }  }  //static  S32 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)  { -	if (dataformat >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT && -		dataformat <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) -	{ -		if (width < 4) width = 4; -		if (height < 4) height = 4; -	} +    switch (dataformat) +    { +    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: +    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: +    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: +        if (width < 4) width = 4; +        if (height < 4) height = 4; +        break; +    default: +        break; +    }  	S32 bytes ((width*height*dataFormatBits(dataformat)+7)>>3);  	S32 aligned = (bytes+3)&~3;  	return aligned; @@ -223,14 +236,19 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)  	switch (dataformat)  	{  	  case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	return 3; +	  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3;  	  case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	return 4; +	  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4;  	  case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	return 4; +	  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;  	  case GL_LUMINANCE:						return 1;  	  case GL_ALPHA:							return 1;  	  case GL_COLOR_INDEX:						return 1;  	  case GL_LUMINANCE_ALPHA:					return 2;  	  case GL_RGB:								return 3; +	  case GL_SRGB:								return 3;  	  case GL_RGBA:								return 4; +	  case GL_SRGB_ALPHA:						return 4;  	  case GL_BGRA:								return 4;		// Used for QuickTime media textures on the Mac  	  default:  		LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; @@ -355,7 +373,7 @@ BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, B  LLImageGL::LLImageGL(BOOL usemipmaps)  :	LLTrace::MemTrackable<LLImageGL>("LLImageGL"), -	mSaveData(0) +    mSaveData(0), mExternalTexture(FALSE)  {  	init(usemipmaps);  	setSize(0, 0, 0); @@ -365,7 +383,7 @@ LLImageGL::LLImageGL(BOOL usemipmaps)  LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)  :	LLTrace::MemTrackable<LLImageGL>("LLImageGL"), -	mSaveData(0) +    mSaveData(0), mExternalTexture(FALSE)  {  	llassert( components <= 4 );  	init(usemipmaps); @@ -376,7 +394,7 @@ LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)  LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)  :	LLTrace::MemTrackable<LLImageGL>("LLImageGL"), -	mSaveData(0) +    mSaveData(0), mExternalTexture(FALSE)  {  	init(usemipmaps);  	setSize(0, 0, 0); @@ -386,12 +404,36 @@ LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)  	createGLTexture(0, imageraw);   } +LLImageGL::LLImageGL( +    LLGLuint texName, +    U32 components, +    LLGLenum target, +    LLGLint  formatInternal, +    LLGLenum formatPrimary, +    LLGLenum formatType, +    LLTexUnit::eTextureAddressMode addressMode) +    : LLTrace::MemTrackable<LLImageGL>("LLImageGL"), mSaveData(0), mExternalTexture(TRUE) +{ +    init(false); +    mTexName = texName; +    mTarget = target; +    mComponents = components; +    mAddressMode = addressMode; +    mFormatType = formatType; +    mFormatInternal = formatInternal; +    mFormatPrimary = formatPrimary; +} + +  LLImageGL::~LLImageGL()  { -	LLImageGL::cleanup(); -	sImageList.erase(this); -	freePickMask(); -	sCount--; +    if (!mExternalTexture) +    { +	    LLImageGL::cleanup(); +	    sImageList.erase(this); +	    freePickMask(); +	    sCount--; +    }  }  void LLImageGL::init(BOOL usemipmaps) @@ -626,10 +668,20 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  {  	LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE);  	bool is_compressed = false; -	if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) -	{ -		is_compressed = true; -	} + +    switch (mFormatPrimary) +    { +    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: +    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: +    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: +    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: +        is_compressed = true; +        break; +    default: +        break; +    } @@ -1203,10 +1255,18 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt  			case GL_RGB8:  				intformat = GL_COMPRESSED_RGB;   				break; +            case GL_SRGB: +            case GL_SRGB8: +                intformat = GL_COMPRESSED_SRGB; +                break;  			case GL_RGBA:  			case GL_RGBA8:  				intformat = GL_COMPRESSED_RGBA;   				break; +            case GL_SRGB_ALPHA: +            case GL_SRGB8_ALPHA8: +                intformat = GL_COMPRESSED_SRGB_ALPHA; +                break;  			case GL_LUMINANCE:  			case GL_LUMINANCE8:  				intformat = GL_COMPRESSED_LUMINANCE; @@ -1310,33 +1370,51 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S  	if( !mHasExplicitFormat )  	{ -		switch (mComponents) -		{ -			case 1: -			// Use luminance alpha (for fonts) -			mFormatInternal = GL_LUMINANCE8; -			mFormatPrimary = GL_LUMINANCE; -			mFormatType = GL_UNSIGNED_BYTE; -			break; -			case 2: -			// Use luminance alpha (for fonts) -			mFormatInternal = GL_LUMINANCE8_ALPHA8; -			mFormatPrimary = GL_LUMINANCE_ALPHA; -			mFormatType = GL_UNSIGNED_BYTE; -			break; -			case 3: -			mFormatInternal = GL_RGB8; -			mFormatPrimary = GL_RGB; -			mFormatType = GL_UNSIGNED_BYTE; -			break; -			case 4: -			mFormatInternal = GL_RGBA8; -			mFormatPrimary = GL_RGBA; -			mFormatType = GL_UNSIGNED_BYTE; -			break; -			default: -			LL_ERRS() << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL; -		} +        switch (mComponents) +        { +        case 1: +            // Use luminance alpha (for fonts) +            mFormatInternal = GL_LUMINANCE8; +            mFormatPrimary = GL_LUMINANCE; +            mFormatType = GL_UNSIGNED_BYTE; +            break; +        case 2: +            // Use luminance alpha (for fonts) +            mFormatInternal = GL_LUMINANCE8_ALPHA8; +            mFormatPrimary = GL_LUMINANCE_ALPHA; +            mFormatType = GL_UNSIGNED_BYTE; +            break; +        case 3: +        #if USE_SRGB_DECODE +            if (gGLManager.mHasTexturesRGBDecode) +            { +                mFormatInternal = GL_SRGB8; +            } +            else +        #endif +            { +                mFormatInternal = GL_RGB8; +            } +            mFormatPrimary = GL_RGB; +            mFormatType = GL_UNSIGNED_BYTE; +            break; +        case 4: +        #if USE_SRGB_DECODE +            if (gGLManager.mHasTexturesRGBDecode) +            { +                mFormatInternal = GL_SRGB8_ALPHA8; +            } +            else +        #endif +            { +                mFormatInternal = GL_RGBA8; +            } +            mFormatPrimary = GL_RGBA; +            mFormatType = GL_UNSIGNED_BYTE; +            break; +        default: +            LL_ERRS() << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL; +        }  		calcAlphaChannelOffsetAndStride() ;  	} @@ -1764,28 +1842,30 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()  	}  	mAlphaStride = -1 ; -	switch (mFormatPrimary) -	{ -	case GL_LUMINANCE: -	case GL_ALPHA: -		mAlphaStride = 1; -		break; -	case GL_LUMINANCE_ALPHA: -		mAlphaStride = 2; -		break; -	case GL_RGB: -		mNeedsAlphaAndPickMask = FALSE ; -		mIsMask = FALSE; -		return ; //no alpha channel. -	case GL_RGBA: -		mAlphaStride = 4; -		break; -	case GL_BGRA_EXT: -		mAlphaStride = 4; -		break; -	default: -		break; -	} +    switch (mFormatPrimary) +    { +    case GL_LUMINANCE: +    case GL_ALPHA: +        mAlphaStride = 1; +        break; +    case GL_LUMINANCE_ALPHA: +        mAlphaStride = 2; +        break; +    case GL_RGB: +    case GL_SRGB: +        mNeedsAlphaAndPickMask = FALSE; +        mIsMask = FALSE; +        return; //no alpha channel. +    case GL_RGBA: +    case GL_SRGB_ALPHA: +        mAlphaStride = 4; +        break; +    case GL_BGRA_EXT: +        mAlphaStride = 4; +        break; +    default: +        break; +    }  	mAlphaOffset = -1 ;  	if (mFormatType == GL_UNSIGNED_BYTE) @@ -1968,12 +2048,13 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)  	freePickMask(); -	if (mFormatType != GL_UNSIGNED_BYTE || -	    mFormatPrimary != GL_RGBA) -	{ -		//cannot generate a pick mask for this texture -		return; -	} +    if (mFormatType != GL_UNSIGNED_BYTE || +        ((mFormatPrimary != GL_RGBA) +      && (mFormatPrimary != GL_SRGB_ALPHA))) +    { +        //cannot generate a pick mask for this texture +        return; +    }  #ifdef SHOW_ASSERT  	const U32 pickSize = createPickMask(width, height); diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 2be54be062..4f3d7eed0a 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -84,7 +84,10 @@ public:  	LLImageGL(BOOL usemipmaps = TRUE);  	LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);  	LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps = 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(); @@ -234,6 +237,8 @@ protected:  	LLGLenum mFormatType;  	BOOL	 mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1) +    BOOL mExternalTexture; +  	// STATICS  public:	  	static std::set<LLImageGL*> sImageList; @@ -279,6 +284,8 @@ public:  	void setCategory(S32 category) {mCategory = category;}  	S32  getCategory()const {return mCategory;} +    void setTexName(GLuint texName) { mTexName = texName; } +  	//for debug use: show texture size distribution   	//----------------------------------------  	static S32 sCurTexSizeBar ; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 5bcccb35af..c3345c5c16 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -59,7 +59,8 @@ static const GLenum sGLTextureType[] =  	GL_TEXTURE_2D,  	GL_TEXTURE_RECTANGLE_ARB,  	GL_TEXTURE_CUBE_MAP_ARB, -	GL_TEXTURE_2D_MULTISAMPLE +	GL_TEXTURE_2D_MULTISAMPLE, +    GL_TEXTURE_3D  };  static const GLint sGLAddressMode[] = @@ -104,7 +105,7 @@ LLTexUnit::LLTexUnit(S32 index)  	mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),  	mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),  	mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), -	mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), +    mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR),  	mHasMipMaps(false),  	mIndex(index)  { @@ -161,6 +162,8 @@ void LLTexUnit::refreshState(void)  		setTextureCombiner(mCurrColorOp, mCurrColorSrc1, mCurrColorSrc2, false);  		setTextureCombiner(mCurrAlphaOp, mCurrAlphaSrc1, mCurrAlphaSrc2, true);  	} + +    setTextureColorSpace(mTexColorSpace);  }  void LLTexUnit::activate(void) @@ -218,6 +221,8 @@ void LLTexUnit::disable(void)  		{  			glDisable(sGLTextureType[mCurrTexType]);  		} + +        setTextureColorSpace(TCS_LINEAR);  		mCurrTexType = TT_NONE;  	} @@ -254,7 +259,8 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)  						gl_tex->mTexOptionsDirty = false;  						setTextureAddressMode(gl_tex->mAddressMode);  						setTextureFilteringOption(gl_tex->mFilterOption); -					} +                    } +                    setTextureColorSpace(mTexColorSpace);  				}  			}  			else @@ -329,6 +335,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)  			setTextureFilteringOption(texture->mFilterOption);  			stop_glerror();  		} +        setTextureColorSpace(mTexColorSpace);  	}  	stop_glerror(); @@ -354,7 +361,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)  		{  			activate();  			enable(LLTexUnit::TT_CUBE_MAP); -			mCurrTexture = cubeMap->mImages[0]->getTexName(); +            mCurrTexture = cubeMap->mImages[0]->getTexName();  			glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);  			mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;  			cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory); @@ -363,7 +370,8 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)  				cubeMap->mImages[0]->mTexOptionsDirty = false;  				setTextureAddressMode(cubeMap->mImages[0]->mAddressMode);  				setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption); -			} +            } +            setTextureColorSpace(mTexColorSpace);  			return true;  		}  		else @@ -414,7 +422,8 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)  		enable(type);  		mCurrTexture = texture;  		glBindTexture(sGLTextureType[type], texture); -		mHasMipMaps = hasMips; +        mHasMipMaps = hasMips; +        setTextureColorSpace(mTexColorSpace);  	}  	return true;  } @@ -434,6 +443,9 @@ void LLTexUnit::unbind(eTextureType type)  	if (mCurrTexType == type)  	{  		mCurrTexture = 0; + +        // Always make sure our texture color space is reset to linear.  SRGB sampling should be opt-in in the vast majority of cases.  Also prevents color space "popping". +        mTexColorSpace = TCS_LINEAR;  		if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)  		{  			glBindTexture(sGLTextureType[type], sWhiteTexture); @@ -837,6 +849,28 @@ void LLTexUnit::debugTextureUnit(void)  	}  } +void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) { +    mTexColorSpace = space; + +#if USE_SRGB_DECODE +    if (gGLManager.mHasTexturesRGBDecode) { + +        if (space == TCS_SRGB) { +            glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); +        } +        else { +            glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); +        } + +        if (gDebugGL) { +            assert_glerror(); +        } +    } +#endif +    glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + +} +  LLLightState::LLLightState(S32 index)  : mIndex(index),    mEnabled(false), @@ -849,9 +883,12 @@ LLLightState::LLLightState(S32 index)  	if (mIndex == 0)  	{  		mDiffuse.set(1,1,1,1); +        mDiffuseB.set(0,0,0,0);  		mSpecular.set(1,1,1,1);  	} +    mSunIsPrimary = true; +  	mAmbient.set(0,0,0,1);  	mPosition.set(0,0,1,0);  	mSpotDirection.set(0,0,-1); @@ -894,6 +931,24 @@ void LLLightState::setDiffuse(const LLColor4& diffuse)  	}  } +void LLLightState::setDiffuseB(const LLColor4& diffuse) +{ +    if (mDiffuseB != diffuse) +	{ +		++gGL.mLightHash; +		mDiffuseB = diffuse; +	} +} + +void LLLightState::setSunPrimary(bool v) +{ +    if (mSunIsPrimary != v) +    { +        ++gGL.mLightHash; +		mSunIsPrimary = v; +    } +} +  void LLLightState::setAmbient(const LLColor4& ambient)  {  	if (mAmbient != ambient) @@ -1150,8 +1205,10 @@ void LLRender::syncLightState()  		LLVector4 position[8];  		LLVector3 direction[8]; -		LLVector3 attenuation[8]; +		LLVector4 attenuation[8];  		LLVector3 diffuse[8]; +        LLVector3 diffuse_b[8]; +        bool      sun_primary[8];  		for (U32 i = 0; i < 8; i++)  		{ @@ -1159,17 +1216,21 @@ void LLRender::syncLightState()  			position[i] = light->mPosition;  			direction[i] = light->mSpotDirection; -			attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[3]); +            attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[2], light->mSpecular.mV[3]);  			diffuse[i].set(light->mDiffuse.mV); +            diffuse_b[i].set(light->mDiffuseB.mV); +            sun_primary[i] = light->mSunIsPrimary;  		}  		shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, 8, position[0].mV);  		shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV); -		shader->uniform3fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV); +		shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV);  		shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV);  		shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV); -		//HACK -- duplicate sunlight color for compatibility with drivers that can't deal with multiple shader objects referencing the same uniform -		shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV); +        shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0); +        shader->uniform4fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV); +        shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV); +        shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);  	}  } @@ -1190,6 +1251,7 @@ void LLRender::syncMatrices()  	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;  	static glh::matrix4f cached_mvp; +    static glh::matrix4f cached_inv_mdv;  	static U32 cached_mvp_mdv_hash = 0xFFFFFFFF;  	static U32 cached_mvp_proj_hash = 0xFFFFFFFF; @@ -1203,12 +1265,18 @@ void LLRender::syncMatrices()  		bool mvp_done = false;  		U32 i = MM_MODELVIEW; -		if (mMatHash[i] != shader->mMatHash[i]) +		if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW])  		{ //update modelview, normal, and MVP -			glh::matrix4f& mat = mMatrix[i][mMatIdx[i]]; +			glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; -			shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m); -			shader->mMatHash[i] = mMatHash[i]; +            // if MDV has changed, update the cached inverse as well +            if (cached_mvp_mdv_hash != mMatHash[MM_MODELVIEW]) +            { +                cached_inv_mdv = mat.inverse(); +            } + +			shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m); +			shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW];  			//update normal matrix  			S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX); @@ -1216,7 +1284,7 @@ void LLRender::syncMatrices()  			{  				if (cached_normal_hash != mMatHash[i])  				{ -					cached_normal = mat.inverse().transpose(); +					cached_normal = cached_inv_mdv.transpose();  					cached_normal_hash = mMatHash[i];  				} @@ -1232,6 +1300,11 @@ void LLRender::syncMatrices()  				shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat);  			} +            if (shader->getUniformLocation(LLShaderMgr::INVERSE_MODELVIEW_MATRIX)) +            {                 +	            shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m);  +            } +  			//update MVP matrix  			mvp_done = true;  			loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX); @@ -1251,14 +1324,21 @@ void LLRender::syncMatrices()  			}  		} -  		i = MM_PROJECTION; -		if (mMatHash[i] != shader->mMatHash[i]) +		if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION])  		{ //update projection matrix, normal, and MVP -			glh::matrix4f& mat = mMatrix[i][mMatIdx[i]]; +			glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; + +            // it would be nice to have this automatically track the state of the proj matrix +            // but certain render paths (deferred lighting) require it to be mismatched *sigh* +            //if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX)) +            //{ +	        //    glh::matrix4f inv_proj = mat.inverse(); +	        //    shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m); +            //} -			shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m); -			shader->mMatHash[i] = mMatHash[i]; +			shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m); +			shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION];  			if (!mvp_done)  			{ @@ -1266,7 +1346,7 @@ void LLRender::syncMatrices()  				S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);  				if (loc > -1)  				{ -					if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION]) +					if (cached_mvp_mdv_hash != mMatHash[MM_PROJECTION] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])  					{  						U32 mdv = MM_MODELVIEW;  						cached_mvp = mat; @@ -1290,7 +1370,7 @@ void LLRender::syncMatrices()  		} -		if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting) +		if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics)  		{ //also sync light state  			syncLightState();  		} @@ -1307,7 +1387,7 @@ void LLRender::syncMatrices()  			GL_TEXTURE,  		}; -		for (U32 i = 0; i < 2; ++i) +		for (U32 i = 0; i < MM_TEXTURE0; ++i)  		{  			if (mMatHash[i] != mCurMatHash[i])  			{ @@ -1317,11 +1397,11 @@ void LLRender::syncMatrices()  			}  		} -		for (U32 i = 2; i < NUM_MATRIX_MODES; ++i) +		for (U32 i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i)  		{  			if (mMatHash[i] != mCurMatHash[i])  			{ -				gGL.getTexUnit(i-2)->activate(); +				gGL.getTexUnit(i-MM_TEXTURE0)->activate();  				glMatrixMode(mode[i]);  				glLoadMatrixf(mMatrix[i][mMatIdx[i]].m);  				mCurMatHash[i] = mMatHash[i]; @@ -1453,24 +1533,20 @@ void LLRender::multMatrix(const GLfloat* m)  	}  } -void LLRender::matrixMode(U32 mode) +void LLRender::matrixMode(eMatrixMode mode)  {  	if (mode == MM_TEXTURE)  	{ -		mode = MM_TEXTURE0 + gGL.getCurrentTexUnitIndex(); -		if (mode > MM_TEXTURE3) -		{ -			// getCurrentTexUnitIndex() can go as high as 32 (LL_NUM_TEXTURE_LAYERS) -			// Large value will result in a crash at mMatrix -			LL_WARNS_ONCE() << "Attempted to assign matrix mode out of bounds: " << mode << LL_ENDL; -			mode = MM_TEXTURE0; -		} +        U32 tex_index = gGL.getCurrentTexUnitIndex(); +        // the shaders don't actually reference anything beyond texture_matrix0/1 outside of terrain rendering +        llassert_always(tex_index <= 3); +		mode = eMatrixMode(MM_TEXTURE0 + gGL.getCurrentTexUnitIndex());  	}  	mMatrixMode = mode;  } -U32 LLRender::getMatrixMode() +LLRender::eMatrixMode LLRender::getMatrixMode()  {  	if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3)  	{ //always return MM_TEXTURE if current matrix mode points at any texture matrix @@ -2337,3 +2413,85 @@ void LLRender::debugTexUnits(void)  	LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL;  } + + +glh::matrix4f copy_matrix(F32* src) +{ +	glh::matrix4f ret; +	ret.set_value(src); +	return ret; +} + +glh::matrix4f get_current_modelview() +{ +	return copy_matrix(gGLModelView); +} + +glh::matrix4f get_current_projection() +{ +	return copy_matrix(gGLProjection); +} + +glh::matrix4f get_last_modelview() +{ +	return copy_matrix(gGLLastModelView); +} + +glh::matrix4f get_last_projection() +{ +	return copy_matrix(gGLLastProjection); +} + +void copy_matrix(const glh::matrix4f& src, F32* dst) +{ +	for (U32 i = 0; i < 16; i++) +	{ +		dst[i] = src.m[i]; +	} +} + +void set_current_modelview(const glh::matrix4f& mat) +{ +	copy_matrix(mat, gGLModelView); +} + +void set_current_projection(glh::matrix4f& mat) +{ +	copy_matrix(mat, gGLProjection); +} + +glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar) +{ +	glh::matrix4f ret( +		2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left), +		0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom), +		0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear), +		0.f, 0.f, 0.f, 1.f); + +	return ret; +} + +glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) +{ +	GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f); + +	return glh::matrix4f(f/aspect, 0, 0, 0, +						 0, f, 0, 0, +						 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar), +						 0, 0, -1.f, 0); +} + +glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up) +{ +	LLVector3 f = center-eye; +	f.normVec(); +	up.normVec(); +	LLVector3 s = f % up; +	LLVector3 u = s % f; + +	return glh::matrix4f(s[0], s[1], s[2], 0, +					  u[0], u[1], u[2], 0, +					  -f[0], -f[1], -f[2], 0, +					  0, 0, 0, 1); +	 +} diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 32bb728d8a..41f4fe4017 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -61,10 +61,11 @@ public:  	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_RECT_TEXTURE,	    // Non power of 2 texture +		TT_CUBE_MAP,		    // 6-sided cube map texture  		TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample -		TT_NONE 		// No texture type is currently enabled +        TT_TEXTURE_3D,          // standard 3D Texture +		TT_NONE, 		        // No texture type is currently enabled          	} eTextureType;  	typedef enum @@ -130,6 +131,12 @@ public:  		TBS_ONE_MINUS_CONST_ALPHA  	} eTextureBlendSrc; +    typedef enum +    { +        TCS_LINEAR = 0, +        TCS_SRGB +    } eTextureColorSpace; +  	LLTexUnit(S32 index);  	// Refreshes renderer state of the texture unit to the cached values @@ -152,7 +159,7 @@ public:  	// 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); -	bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false); +    bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);  	// Binds a cubemap to this texture unit   	// (automatically enables the texture unit for cubemaps) @@ -197,6 +204,10 @@ public:  	void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; } +    void setTextureColorSpace(eTextureColorSpace space); + +    eTextureColorSpace getCurrColorSpace() { return mTexColorSpace; } +  protected:  	const S32			mIndex;  	U32					mCurrTexture; @@ -208,6 +219,7 @@ protected:  	eTextureBlendOp		mCurrAlphaOp;  	eTextureBlendSrc	mCurrAlphaSrc1;  	eTextureBlendSrc	mCurrAlphaSrc2; +    eTextureColorSpace  mTexColorSpace;  	S32					mCurrColorScale;  	S32					mCurrAlphaScale;  	bool				mHasMipMaps; @@ -228,6 +240,7 @@ public:  	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); @@ -237,6 +250,7 @@ public:  	void setSpotExponent(const F32& exponent);  	void setSpotCutoff(const F32& cutoff);  	void setSpotDirection(const LLVector3& direction); +    void setSunPrimary(bool v);  protected:  	friend class LLRender; @@ -244,6 +258,8 @@ protected:  	S32 mIndex;  	bool mEnabled;  	LLColor4 mDiffuse; +    LLColor4 mDiffuseB; +    bool     mSunIsPrimary;  	LLColor4 mAmbient;  	LLColor4 mSpecular;  	LLVector4 mPosition; @@ -264,10 +280,11 @@ public:  	enum eTexIndex  	{ -		DIFFUSE_MAP = 0, -		NORMAL_MAP, -		SPECULAR_MAP, -		NUM_TEXTURE_CHANNELS, +		DIFFUSE_MAP           = 0, +        ALTERNATE_DIFFUSE_MAP = 1, +		NORMAL_MAP            = 1, +		SPECULAR_MAP          = 2,         +		NUM_TEXTURE_CHANNELS  = 3,  	};  	enum eVolumeTexIndex @@ -360,8 +377,8 @@ public:  	void loadMatrix(const GLfloat* m);  	void loadIdentity();  	void multMatrix(const GLfloat* m); -	void matrixMode(U32 mode);	 -	U32 getMatrixMode(); +	void matrixMode(eMatrixMode mode);	 +	eMatrixMode getMatrixMode();  	const glh::matrix4f& getModelviewMatrix();  	const glh::matrix4f& getProjectionMatrix(); @@ -450,7 +467,7 @@ public:  private:  	friend class LLLightState; -	U32 mMatrixMode; +	eMatrixMode mMatrixMode;  	U32 mMatIdx[NUM_MATRIX_MODES];  	U32 mMatHash[NUM_MATRIX_MODES];  	glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH]; @@ -495,4 +512,33 @@ extern S32 gGLViewport[4];  extern 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 }; + +glh::matrix4f copy_matrix(F32* src); +glh::matrix4f get_current_modelview(); +glh::matrix4f get_current_projection(); +glh::matrix4f get_last_modelview(); +glh::matrix4f get_last_projection(); + +void copy_matrix(const glh::matrix4f& src, F32* dst); +void set_current_modelview(const glh::matrix4f& mat); +void set_current_projection(glh::matrix4f& mat); + +glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar); +glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar); +glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up); + +#if LL_RELEASE_FOR_DOWNLOAD +    #define LL_SHADER_LOADING_WARNS(...) LL_WARNS_ONCE("ShaderLoading") +    #define LL_SHADER_UNIFORM_ERRS(...)  LL_WARNS_ONCE("Shader") +#else +    #define LL_SHADER_LOADING_WARNS(...) LL_WARNS() +    #define LL_SHADER_UNIFORM_ERRS(...)  LL_ERRS("Shader")     +#endif +  #endif diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index cd484b4fe9..9fb4f7f2b0 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -502,9 +502,26 @@ U32 LLRenderTarget::getNumTextures() const  } -void LLRenderTarget::bindTexture(U32 index, S32 channel) +void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)  {  	gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index)); + +    bool isSRGB = false; +    llassert(mInternalFormat.size() > index); +    switch (mInternalFormat[index]) +    { +        case GL_SRGB_ALPHA: +        case GL_SRGB: +        case GL_SRGB8_ALPHA8: +            isSRGB = true; +        break; + +        default: +        break; +    } + +    gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options); +    gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR);  }  void LLRenderTarget::flush(bool fetch_depth) diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 6dc84d978d..6c07ac5b1c 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -120,7 +120,7 @@ public:  	U32 getDepth(void) const { return mDepth; }  	bool hasStencil() const { return mStencil; } -	void bindTexture(U32 index, S32 channel); +	void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);  	//flush rendering operations  	//must be called when rendering is complete diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 643c368870..1383020873 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -25,22 +25,14 @@   */  #include "linden_common.h" -  #include "llshadermgr.h" - -#include "llfile.h"  #include "llrender.h" +#include "llfile.h"  #if LL_DARWIN  #include "OpenGL/OpenGL.h"  #endif -#ifdef LL_RELEASE_FOR_DOWNLOAD -#define UNIFORM_ERRS LL_WARNS_ONCE("Shader") -#else -#define UNIFORM_ERRS LL_ERRS("Shader") -#endif -  // Lots of STL stuff in here, using namespace std to keep things more readable  using std::vector;  using std::pair; @@ -87,20 +79,20 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	{  		if (features->hasWaterFog)  		{ -			if (!shader->attachObject("windlight/atmosphericsVarsWaterV.glsl")) +			if (!shader->attachVertexObject("windlight/atmosphericsVarsWaterV.glsl"))  			{  				return FALSE;  			}  		} -		else if (!shader->attachObject("windlight/atmosphericsVarsV.glsl")) +        else if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl"))  		{  			return FALSE;  		}  	} -	if (features->calculatesLighting || features->atmosphericHelpers) +	if (features->calculatesLighting || features->calculatesAtmospherics)  	{ -		if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl")) +		if (!shader->attachVertexObject("windlight/atmosphericsHelpersV.glsl"))  		{  			return FALSE;  		} @@ -110,40 +102,40 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	{  		if (features->isSpecular)  		{ -			if (!shader->attachObject("lighting/lightFuncSpecularV.glsl")) +            if (!shader->attachVertexObject("lighting/lightFuncSpecularV.glsl"))  			{  				return FALSE;  			}  			if (!features->isAlphaLighting)  			{ -				if (!shader->attachObject("lighting/sumLightsSpecularV.glsl")) +                if (!shader->attachVertexObject("lighting/sumLightsSpecularV.glsl"))  				{  					return FALSE;  				}  			} -			if (!shader->attachObject("lighting/lightSpecularV.glsl")) +            if (!shader->attachVertexObject("lighting/lightSpecularV.glsl"))  			{  				return FALSE;  			}  		}  		else   		{ -			if (!shader->attachObject("lighting/lightFuncV.glsl")) +            if (!shader->attachVertexObject("lighting/lightFuncV.glsl"))  			{  				return FALSE;  			}  			if (!features->isAlphaLighting)  			{ -				if (!shader->attachObject("lighting/sumLightsV.glsl")) +                if (!shader->attachVertexObject("lighting/sumLightsV.glsl"))  				{  					return FALSE;  				}  			} -			if (!shader->attachObject("lighting/lightV.glsl")) +            if (!shader->attachVertexObject("lighting/lightV.glsl"))  			{  				return FALSE;  			} @@ -152,8 +144,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	// NOTE order of shader object attaching is VERY IMPORTANT!!!  	if (features->calculatesAtmospherics) -	{ -		if (!shader->attachObject("windlight/atmosphericsV.glsl")) +    { +        if (!shader->attachVertexObject("windlight/atmosphericsFuncs.glsl")) { +            return FALSE; +        } + +        if (!shader->attachVertexObject("windlight/atmosphericsV.glsl"))  		{  			return FALSE;  		} @@ -161,7 +157,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	if (features->hasSkinning)  	{ -		if (!shader->attachObject("avatar/avatarSkinV.glsl")) +        if (!shader->attachVertexObject("avatar/avatarSkinV.glsl"))  		{  			return FALSE;  		} @@ -169,7 +165,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	if (features->hasObjectSkinning)  	{ -		if (!shader->attachObject("avatar/objectSkinV.glsl")) +        if (!shader->attachVertexObject("avatar/objectSkinV.glsl"))  		{  			return FALSE;  		} @@ -179,33 +175,95 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	// Attach Fragment Shader Features Next  	/////////////////////////////////////// +// NOTE order of shader object attaching is VERY IMPORTANT!!! +  	if(features->calculatesAtmospherics)  	{  		if (features->hasWaterFog)  		{ -			if (!shader->attachObject("windlight/atmosphericsVarsWaterF.glsl")) +			if (!shader->attachFragmentObject("windlight/atmosphericsVarsWaterF.glsl"))  			{  				return FALSE;  			}  		} -		else if (!shader->attachObject("windlight/atmosphericsVarsF.glsl")) +        else if (!shader->attachFragmentObject("windlight/atmosphericsVarsF.glsl")) +		{ +			return FALSE; +		} +	} + +    if (features->calculatesLighting || features->calculatesAtmospherics) +	{ +        if (!shader->attachFragmentObject("windlight/atmosphericsHelpersF.glsl")) +		{ +			return FALSE; +		} +	} + +    // we want this BEFORE shadows and AO because those facilities use pos/norm access +    if (features->isDeferred) +	{ +        if (!shader->attachFragmentObject("deferred/deferredUtil.glsl")) +		{ +			return FALSE; +		} +	} + +    if (features->hasShadows) +	{ +        if (!shader->attachFragmentObject("deferred/shadowUtil.glsl")) +		{ +			return FALSE; +		} +	} + +    if (features->hasAmbientOcclusion) +	{ +        if (!shader->attachFragmentObject("deferred/aoUtil.glsl")) +		{ +			return FALSE; +		} +	} + +    if (features->hasIndirect) +	{ +        if (!shader->attachFragmentObject("deferred/indirect.glsl"))  		{  			return FALSE;  		}  	} -	// NOTE order of shader object attaching is VERY IMPORTANT!!!  	if (features->hasGamma)  	{ -		if (!shader->attachObject("windlight/gammaF.glsl")) +        if (!shader->attachFragmentObject("windlight/gammaF.glsl"))  		{  			return FALSE;  		}  	} -	 -	if (features->hasAtmospherics) + +	if (features->hasSrgb)  	{ -		if (!shader->attachObject("windlight/atmosphericsF.glsl")) +        if (!shader->attachFragmentObject("environment/srgbF.glsl")) +		{ +			return FALSE; +		} +	} + +    if (features->encodesNormal) +	{ +        if (!shader->attachFragmentObject("environment/encodeNormF.glsl")) +		{ +			return FALSE; +		} +	} + +	if (features->hasAtmospherics) +    { +        if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) { +            return FALSE; +        } + +        if (!shader->attachFragmentObject("windlight/atmosphericsF.glsl"))  		{  			return FALSE;  		} @@ -213,7 +271,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	if (features->hasTransport)  	{ -		if (!shader->attachObject("windlight/transportF.glsl")) +        if (!shader->attachFragmentObject("windlight/transportF.glsl"))  		{  			return FALSE;  		} @@ -225,7 +283,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	// NOTE order of shader object attaching is VERY IMPORTANT!!!  	if (features->hasWaterFog)  	{ -		if (!shader->attachObject("environment/waterFogF.glsl")) +        if (!shader->attachFragmentObject("environment/waterFogF.glsl"))  		{  			return FALSE;  		} @@ -239,14 +297,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			{  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl"))  					{  						return FALSE;  					}  				}  				else  				{ -					if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightWaterNonIndexedF.glsl"))  					{  						return FALSE;  					} @@ -256,14 +314,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			{  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightWaterAlphaMaskF.glsl"))  					{  						return FALSE;  					}  				}  				else  				{ -					if (!shader->attachObject("lighting/lightWaterF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightWaterF.glsl"))  					{  						return FALSE;  					} @@ -278,14 +336,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			{  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightAlphaMaskNonIndexedF.glsl"))  					{  						return FALSE;  					}  				}  				else  				{ -					if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightNonIndexedF.glsl"))  					{  						return FALSE;  					} @@ -295,14 +353,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			{  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightAlphaMaskF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightAlphaMaskF.glsl"))  					{  						return FALSE;  					}  				}  				else  				{ -					if (!shader->attachObject("lighting/lightF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightF.glsl"))  					{  						return FALSE;  					} @@ -320,14 +378,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		{  			if (features->disableTextureIndex)  			{ -				if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))  				{  					return FALSE;  				}  			}  			else   			{ -				if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyWaterF.glsl"))  				{  					return FALSE;  				} @@ -340,12 +398,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			{  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl"))  					{  						return FALSE;  					}  				} -				else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) +                else if (!shader->attachFragmentObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))  				{  					return FALSE;  				} @@ -354,12 +412,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			{  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightFullbrightWaterAlphaMaskF.glsl"))  					{  						return FALSE;  					}  				} -				else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) +                else if (!shader->attachFragmentObject("lighting/lightFullbrightWaterF.glsl"))  				{  					return FALSE;  				} @@ -371,14 +429,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		{  			if (features->disableTextureIndex)  			{ -				if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))  				{  					return FALSE;  				}  			}  			else   			{ -				if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyF.glsl"))  				{  					return FALSE;  				} @@ -393,14 +451,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl"))  					{  						return FALSE;  					}  				}  				else  				{ -					if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightFullbrightNonIndexedF.glsl"))  					{  						return FALSE;  					} @@ -410,14 +468,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  			{  				if (features->hasAlphaMask)  				{ -					if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightFullbrightAlphaMaskF.glsl"))  					{  						return FALSE;  					}  				}  				else  				{ -					if (!shader->attachObject("lighting/lightFullbrightF.glsl")) +                    if (!shader->attachFragmentObject("lighting/lightFullbrightF.glsl"))  					{  						return FALSE;  					} @@ -435,14 +493,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		{  			if (features->disableTextureIndex)  			{ -				if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightShinyWaterNonIndexedF.glsl"))  				{  					return FALSE;  				}  			}  			else   			{ -				if (!shader->attachObject("lighting/lightShinyWaterF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightShinyWaterF.glsl"))  				{  					return FALSE;  				} @@ -454,14 +512,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		{  			if (features->disableTextureIndex)  			{ -				if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightShinyNonIndexedF.glsl"))  				{  					return FALSE;  				}  			}  			else   			{ -				if (!shader->attachObject("lighting/lightShinyF.glsl")) +                if (!shader->attachFragmentObject("lighting/lightShinyF.glsl"))  				{  					return FALSE;  				} @@ -472,14 +530,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  	if (features->mIndexedTextureChannels <= 1)  	{ -		if (!shader->attachObject("objects/nonindexedTextureV.glsl")) +		if (!shader->attachVertexObject("objects/nonindexedTextureV.glsl"))  		{  			return FALSE;  		}  	}  	else  	{ -		if (!shader->attachObject("objects/indexedTextureV.glsl")) +        if (!shader->attachVertexObject("objects/indexedTextureV.glsl"))  		{  			return FALSE;  		} @@ -509,31 +567,56 @@ static std::string get_object_log(GLhandleARB ret)  	return res;  } +//dump shader source for debugging +void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text) +{ +	char num_str[16]; // U32 = max 10 digits + +	LL_SHADER_LOADING_WARNS() << "\n"; + +	for (U32 i = 0; i < shader_code_count; i++) +	{ +		snprintf(num_str, sizeof(num_str), "%4d: ", i+1); +		std::string line_number(num_str); +		LL_CONT << line_number << shader_code_text[i]; +	} +    LL_CONT << LL_ENDL; +} +  void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string& filename)   {  	std::string log = get_object_log(ret); +    std::string fname = filename; +    if (filename.empty()) +    { +        fname = "unknown shader file"; +    } -	if (log.length() > 0 || warns) +	if (log.length() > 0)  	{ -        LL_DEBUGS("ShaderLoading") << "Shader loading "; -         -		if (!filename.empty()) -		{ -            LL_CONT << "From " << filename << ":\n"; -		} -        LL_CONT << log << LL_ENDL; +        LL_SHADER_LOADING_WARNS() << "Shader loading from " << fname << LL_ENDL; +        LL_SHADER_LOADING_WARNS() << "\n" << log << LL_ENDL;  	}   }  GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)  { + +// endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl) +#if LL_DARWIN +    if (defines) +    { +        (*defines)["OLD_SELECT"] = "1"; +    } +#endif +  	GLenum error = GL_NO_ERROR;  	if (gDebugGL)  	{  		error = glGetError();  		if (error != GL_NO_ERROR)  		{ -			LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; +			LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL;  		}  	} @@ -549,6 +632,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  	S32 try_gpu_class = shader_level;  	S32 gpu_class; +    std::string open_file_name;  	//find the most relevant file  	for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--)  	{	//search from the current gpu class down to class 1 to find the most relevant shader @@ -556,18 +640,33 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  		fname << getShaderDirPrefix();  		fname << gpu_class << "/" << filename; - 		 -		file = LLFile::fopen(fname.str(), "r");		/* Flawfinder: ignore */ +        open_file_name = fname.str(); + +        /* +        Would be awesome, if we didn't have shaders that re-use files +        with different environments to say, add skinning, etc +        can't depend on cached version to have evaluate ifdefs identically... +        if we can define a deterministic hash for the shader based on +        all the inputs, maybe we can save some time here. +        if (mShaderObjects.count(filename) > 0) +        { +            return mShaderObjects[filename]; +        } + +        */ + + 		LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL; +		file = LLFile::fopen(open_file_name, "r");		/* Flawfinder: ignore */  		if (file)  		{ -			LL_DEBUGS("ShaderLoading") << "Loading file: shaders/class" << gpu_class << "/" << filename << " (Want class " << gpu_class << ")" << LL_ENDL; +			LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL;              			break; // done  		}  	}  	if (file == NULL)  	{ -		LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << filename << LL_ENDL; +		LL_SHADER_LOADING_WARNS() << "GLSL Shader file not found: " << open_file_name << LL_ENDL;  		return 0;  	} @@ -612,7 +711,31 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  	}  	else  	{   -		if (major_version < 4) +        if (major_version >= 4) +        { +            //set version to 400 +			shader_code_text[shader_code_count++] = strdup("#version 400\n"); +        } +        else if (major_version == 3) +        { +            if (minor_version < 10) +		    { +			    shader_code_text[shader_code_count++] = strdup("#version 300\n"); +		    } +		    else if (minor_version <= 19) +		    { +			    shader_code_text[shader_code_count++] = strdup("#version 310\n"); +		    } +		    else if (minor_version <= 29) +		    { +			    shader_code_text[shader_code_count++] = strdup("#version 320\n"); +		    } +            else +            { +                shader_code_text[shader_code_count++] = strdup("#version 330\n"); +            } +        } +		else  		{  			//set version to 1.30  			shader_code_text[shader_code_count++] = strdup("#version 130\n"); @@ -620,10 +743,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  			extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");  			extra_code_text[extra_code_count++] = strdup("precision highp float;\n");  		} -		else -		{ //set version to 400 -			shader_code_text[shader_code_count++] = strdup("#version 400\n"); -		}  		extra_code_text[extra_code_count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n");  		extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); @@ -646,7 +765,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  		extra_code_text[extra_code_count++] = strdup("#define texture2D texture\n");  		extra_code_text[extra_code_count++] = strdup("#define textureCube texture\n");  		extra_code_text[extra_code_count++] = strdup("#define texture2DLod textureLod\n"); -		extra_code_text[extra_code_count++] = strdup("#define	shadow2D(a,b) vec2(texture(a,b))\n"); +		extra_code_text[extra_code_count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n");  		if (major_version > 1 || minor_version >= 40)  		{ //GLSL 1.40 replaces texture2DRect et al with texture @@ -704,7 +823,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  		}  		*/ -		extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP 1\n"); +		extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n");  		//uniform declartion  		for (S32 i = 0; i < texture_index_channels; ++i) @@ -763,11 +882,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  			LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL;  		}  	} -	else -	{ -		extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP 0\n"); -	} -  	//copy file into memory  	enum { @@ -897,38 +1011,8 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  			{  				//an error occured, print log  				LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL; -				dumpObjectLog(ret, TRUE, filename); -#if LL_WINDOWS -				std::stringstream ostr; -				//dump shader source for debugging -				for (GLuint i = 0; i < shader_code_count; i++) -				{ -					ostr << i << ": " << shader_code_text[i]; - -					if (i % 128 == 0) -					{ //dump every 128 lines - -						LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL; -						ostr = std::stringstream(); -					} - -				} - -				LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL; -#else -				std::string str; -				 -				for (GLuint i = 0; i < shader_code_count; i++) { -					str.append(shader_code_text[i]); -					 -					if (i % 128 == 0) -					{ -						LL_WARNS("ShaderLoading") << str << LL_ENDL; -						str = ""; -					} -				} -#endif - +				dumpObjectLog(ret, TRUE, open_file_name); +                dumpShaderSource(shader_code_count, shader_code_text);  				ret = 0;  			}  		} @@ -949,7 +1033,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  	if (ret)  	{  		// Add shader file to map -		mShaderObjects[filename] = ret; +        if (type == GL_VERTEX_SHADER_ARB) { +            mVertexShaderObjects[filename] = ret; +        } +        else if (type == GL_FRAGMENT_SHADER_ARB) { +            mFragmentShaderObjects[filename] = ret; +        }  		shader_level = try_gpu_class;  	}  	else @@ -957,7 +1046,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade  		if (shader_level > 1)  		{  			shader_level--; -			return loadShaderFile(filename,shader_level,type, defines, texture_index_channels); +			return loadShaderFile(filename, shader_level, type, defines, texture_index_channels);  		}  		LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;	  	} @@ -973,7 +1062,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)  	if (!suppress_errors && success == GL_FALSE)   	{  		//an error occured, print log -		LL_WARNS("ShaderLoading") << "GLSL Linker Error:" << LL_ENDL; +		LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL;  	}  #if LL_DARWIN @@ -1006,7 +1095,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)  		CGLGetParameter(ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing);  		if (!fragmentGPUProcessing || !vertexGPUProcessing)  		{ -			LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL; +			LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL;  			success = GL_FALSE;  			suppress_errors = FALSE;		  		} @@ -1017,7 +1106,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)  	LLStringUtil::toLower(log);  	if (log.find("software") != std::string::npos)  	{ -		LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL; +		LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL;  		success = GL_FALSE;  		suppress_errors = FALSE;  	} @@ -1033,7 +1122,7 @@ BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)  	glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success);  	if (success == GL_FALSE)  	{ -		LL_WARNS("ShaderLoading") << "GLSL program not valid: " << LL_ENDL; +		LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL;  		dumpObjectLog(obj);  	}  	else @@ -1067,6 +1156,7 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("projection_matrix");  	mReservedUniforms.push_back("inv_proj");  	mReservedUniforms.push_back("modelview_projection_matrix"); +    mReservedUniforms.push_back("inv_modelview");  	mReservedUniforms.push_back("normal_matrix");  	mReservedUniforms.push_back("texture_matrix0");  	mReservedUniforms.push_back("texture_matrix1"); @@ -1109,14 +1199,17 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("color");  	mReservedUniforms.push_back("diffuseMap"); +    mReservedUniforms.push_back("altDiffuseMap");  	mReservedUniforms.push_back("specularMap");  	mReservedUniforms.push_back("bumpMap"); +    mReservedUniforms.push_back("bumpMap2");  	mReservedUniforms.push_back("environmentMap"); -	mReservedUniforms.push_back("cloude_noise_texture"); +	mReservedUniforms.push_back("cloud_noise_texture"); +    mReservedUniforms.push_back("cloud_noise_texture_next");  	mReservedUniforms.push_back("fullbright");  	mReservedUniforms.push_back("lightnorm"); -	mReservedUniforms.push_back("sunlight_color_copy"); -	mReservedUniforms.push_back("ambient"); +	mReservedUniforms.push_back("sunlight_color"); +	mReservedUniforms.push_back("ambient_color");  	mReservedUniforms.push_back("blue_horizon");  	mReservedUniforms.push_back("blue_density");  	mReservedUniforms.push_back("haze_horizon"); @@ -1175,6 +1268,7 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("spot_shadow_bias");  	mReservedUniforms.push_back("spot_shadow_offset");  	mReservedUniforms.push_back("sun_dir"); +    mReservedUniforms.push_back("moon_dir");  	mReservedUniforms.push_back("shadow_res");  	mReservedUniforms.push_back("proj_shadow_res");  	mReservedUniforms.push_back("depth_cutoff"); @@ -1217,8 +1311,6 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("bloomMap");  	mReservedUniforms.push_back("projectionMap");  	mReservedUniforms.push_back("norm_mat"); - -	mReservedUniforms.push_back("global_gamma");  	mReservedUniforms.push_back("texture_gamma");  	mReservedUniforms.push_back("specular_color"); @@ -1232,8 +1324,8 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("refTex");  	mReservedUniforms.push_back("eyeVec");  	mReservedUniforms.push_back("time"); -	mReservedUniforms.push_back("d1"); -	mReservedUniforms.push_back("d2"); +	mReservedUniforms.push_back("waveDir1"); +	mReservedUniforms.push_back("waveDir2");  	mReservedUniforms.push_back("lightDir");  	mReservedUniforms.push_back("specular");  	mReservedUniforms.push_back("lightExp"); @@ -1265,6 +1357,34 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("origin");  	mReservedUniforms.push_back("display_gamma"); + +    mReservedUniforms.push_back("inscatter"); +    mReservedUniforms.push_back("sun_size"); +    mReservedUniforms.push_back("fog_color"); + +    mReservedUniforms.push_back("transmittance_texture"); +    mReservedUniforms.push_back("scattering_texture"); +    mReservedUniforms.push_back("single_mie_scattering_texture"); +    mReservedUniforms.push_back("irradiance_texture"); +    mReservedUniforms.push_back("blend_factor"); +    mReservedUniforms.push_back("no_atmo"); +    mReservedUniforms.push_back("moisture_level"); +    mReservedUniforms.push_back("droplet_radius"); +    mReservedUniforms.push_back("ice_level"); +    mReservedUniforms.push_back("rainbow_map"); +    mReservedUniforms.push_back("halo_map"); +    mReservedUniforms.push_back("moon_brightness"); +    mReservedUniforms.push_back("cloud_variance"); + +    mReservedUniforms.push_back("sh_input_r"); +    mReservedUniforms.push_back("sh_input_g"); +    mReservedUniforms.push_back("sh_input_b"); + +    mReservedUniforms.push_back("sun_moon_glow_factor"); +    mReservedUniforms.push_back("water_edge"); +    mReservedUniforms.push_back("sun_up_factor"); +    mReservedUniforms.push_back("moonlight_color"); +  	llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);  	std::set<std::string> dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 394b38f832..127b5ce5b6 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -42,6 +42,7 @@ public:  		PROJECTION_MATRIX,  		INVERSE_PROJECTION_MATRIX,  		MODELVIEW_PROJECTION_MATRIX, +        INVERSE_MODELVIEW_MATRIX,  		NORMAL_MATRIX,  		TEXTURE_MATRIX0,  		TEXTURE_MATRIX1, @@ -73,10 +74,13 @@ public:  		PROJECTOR_AMBIENT_LOD,  		DIFFUSE_COLOR,  		DIFFUSE_MAP, +        ALTERNATE_DIFFUSE_MAP,  		SPECULAR_MAP,  		BUMP_MAP, +        BUMP_MAP2,  		ENVIRONMENT_MAP,  		CLOUD_NOISE_MAP, +        CLOUD_NOISE_MAP_NEXT,  		FULLBRIGHT,  		LIGHTNORM,  		SUNLIGHT_COLOR, @@ -131,6 +135,7 @@ public:  		DEFERRED_SPOT_SHADOW_BIAS,  		DEFERRED_SPOT_SHADOW_OFFSET,  		DEFERRED_SUN_DIR, +        DEFERRED_MOON_DIR,  		DEFERRED_SHADOW_RES,  		DEFERRED_PROJ_SHADOW_RES,  		DEFERRED_DEPTH_CUTOFF, @@ -168,10 +173,7 @@ public:  		DEFERRED_BLOOM,  		DEFERRED_PROJECTION,  		DEFERRED_NORM_MATRIX, - -		GLOBAL_GAMMA, -		TEXTURE_GAMMA, -		 +		TEXTURE_GAMMA,		  		SPECULAR_COLOR,  		ENVIRONMENT_INTENSITY, @@ -215,7 +217,38 @@ public:  		TERRAIN_ALPHARAMP,  		SHINY_ORIGIN, -DISPLAY_GAMMA, +        DISPLAY_GAMMA, + +        INSCATTER_RT, +        SUN_SIZE, +        FOG_COLOR, + +        // precomputed textures +        TRANSMITTANCE_TEX, +        SCATTER_TEX, +        SINGLE_MIE_SCATTER_TEX, +        ILLUMINANCE_TEX, +        BLEND_FACTOR, + +        NO_ATMO, +        MOISTURE_LEVEL, +        DROPLET_RADIUS, +        ICE_LEVEL, +        RAINBOW_MAP, +        HALO_MAP, + +        MOON_BRIGHTNESS, + +        CLOUD_VARIANCE, + +        SH_INPUT_L1R, +        SH_INPUT_L1G, +        SH_INPUT_L1B, + +        SUN_MOON_GLOW_FACTOR, +        WATER_EDGE_FACTOR, +        SUN_UP_FACTOR, +        MOONLIGHT_COLOR,  		END_RESERVED_UNIFORMS  	} eGLSLReservedUniforms; @@ -226,6 +259,7 @@ DISPLAY_GAMMA,  	BOOL attachShaderFeatures(LLGLSLShader * shader);  	void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE, const std::string& filename = ""); +    void dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text);  	BOOL	linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);  	BOOL	validateProgramObject(GLhandleARB obj);  	GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1); @@ -238,7 +272,8 @@ DISPLAY_GAMMA,  public:  	// Map of shader names to compiled -	std::map<std::string, GLhandleARB> mShaderObjects; +    std::map<std::string, GLhandleARB> mVertexShaderObjects; +    std::map<std::string, GLhandleARB> mFragmentShaderObjects;  	//global (reserved slot) shader parameters  	std::vector<std::string> mReservedAttribs; diff --git a/indra/llrender/lltexture.cpp b/indra/llrender/lltexture.cpp index 90fbcec2be..6eef36216c 100644 --- a/indra/llrender/lltexture.cpp +++ b/indra/llrender/lltexture.cpp @@ -29,3 +29,15 @@  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() { } diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 9fca8b8cd3..41481fb8a7 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -58,21 +58,21 @@ public:  	//  	//interfaces to access LLGLTexture  	// -	virtual S8         getType() const = 0 ; -	virtual void       setKnownDrawSize(S32 width, S32 height) = 0 ; -	virtual bool       bindDefaultImage(const S32 stage = 0) = 0 ; -	virtual bool       bindDebugImage(const S32 stage = 0) = 0; -	virtual void       forceImmediateUpdate() = 0 ; -	virtual void       setActive() = 0 ; -	virtual S32	       getWidth(S32 discard_level = -1) const = 0 ; -	virtual S32	       getHeight(S32 discard_level = -1) const = 0 ; -	virtual bool       isActiveFetching() = 0; +	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();  private:  	//note: do not make this function public. -	virtual LLImageGL* getGLTexture() const = 0 ; +	virtual LLImageGL* getGLTexture() const; -	virtual void updateBindStatsForTester() = 0 ; +	virtual void updateBindStatsForTester();  };  #endif diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp index c8337feabb..424672fe8e 100644 --- a/indra/llrender/lluiimage.cpp +++ b/indra/llrender/lluiimage.cpp @@ -31,7 +31,6 @@  // Project includes  #include "lluiimage.h" -#include "llrender2dutils.h"  LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)  :	mName(name), @@ -39,67 +38,29 @@ LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)  	mScaleRegion(0.f, 1.f, 1.f, 0.f),  	mClipRegion(0.f, 1.f, 1.f, 0.f),  	mImageLoaded(NULL), -	mScaleStyle(SCALE_INNER) -{} +	mScaleStyle(SCALE_INNER), +    mCachedW(-1), +    mCachedH(-1) +{ +    getTextureWidth(); +    getTextureHeight(); +}  LLUIImage::~LLUIImage()  {  	delete mImageLoaded;  } -void LLUIImage::setClipRegion(const LLRectf& region)  +S32 LLUIImage::getWidth() const  {  -	mClipRegion = region;  +	// return clipped dimensions of actual image area +	return ll_round((F32)mImage->getWidth(0) * mClipRegion.getWidth());   } -void LLUIImage::setScaleRegion(const LLRectf& region)  +S32 LLUIImage::getHeight() const  {  -	mScaleRegion = region;  -} - -void LLUIImage::setScaleStyle(LLUIImage::EScaleStyle style) -{ -	mScaleStyle = style; -} - -//TODO: move drawing implementation inside class -void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const -{ -	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); +	// 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,  @@ -145,28 +106,7 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c  	} LLRender2D::getInstance()->popMatrix();  } - -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());  -} - -S32 LLUIImage::getTextureWidth() const -{ -	return mImage->getWidth(0); -} - -S32 LLUIImage::getTextureHeight() const -{ -	return mImage->getHeight(0); -} +//#include "lluiimage.inl"  boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb )   { @@ -186,7 +126,6 @@ void LLUIImage::onImageLoaded()  	}  } -  namespace LLInitParam  {  	void ParamValue<LLUIImage*>::updateValueFromBlock() diff --git a/indra/llrender/lluiimage.h b/indra/llrender/lluiimage.h index 6f47385eb0..e462e19004 100644 --- a/indra/llrender/lluiimage.h +++ b/indra/llrender/lluiimage.h @@ -36,6 +36,7 @@  #include <boost/signals2.hpp>  #include "llinitparam.h"  #include "lltexture.h" +#include "llrender2dutils.h"  extern const LLColor4 UI_VERTEX_COLOR; @@ -53,35 +54,46 @@ public:  	LLUIImage(const std::string& name, LLPointer<LLTexture> image);  	virtual ~LLUIImage(); -	void setClipRegion(const LLRectf& region); -	void setScaleRegion(const LLRectf& region); -	void setScaleStyle(EScaleStyle style); +	LL_FORCE_INLINE void setClipRegion(const LLRectf& region) +    {  +	    mClipRegion = region;  +    } -	LLPointer<LLTexture> getImage() { return mImage; } -	const LLPointer<LLTexture>& getImage() const { return mImage; } +	LL_FORCE_INLINE void setScaleRegion(const LLRectf& region) +    {  +	    mScaleRegion = region;  +    } -	void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const; -	void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const; -	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 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); } -	void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const; -	void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } -	void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), 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); } -	void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; -	void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } -	void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } +	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); -	const std::string& getName() const { return mName; } +	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 -	S32 getTextureWidth() const; -	S32 getTextureHeight() const; +	LL_FORCE_INLINE S32 getTextureWidth() const; +	LL_FORCE_INLINE S32 getTextureHeight() const;  	boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb ); @@ -95,8 +107,12 @@ protected:  	LLRectf					mClipRegion;  	LLPointer<LLTexture>	mImage;  	EScaleStyle				mScaleStyle; +    mutable S32             mCachedW; +    mutable S32             mCachedH;  }; +#include "lluiimage.inl" +  namespace LLInitParam  {  	template<> diff --git a/indra/llrender/lluiimage.inl b/indra/llrender/lluiimage.inl new file mode 100644 index 0000000000..f5227556f0 --- /dev/null +++ b/indra/llrender/lluiimage.inl @@ -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; +} diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1312f6afda..94a04d4ddb 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -660,6 +660,9 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto  void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const  { +    llassert(start < (U32)mNumVerts); +    llassert(end < (U32)mNumVerts); +  	if (start >= (U32) mNumVerts ||  	    end >= (U32) mNumVerts)  	{ @@ -679,6 +682,9 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of  		U16* idx = ((U16*) getIndicesPointer())+indices_offset;  		for (U32 i = 0; i < count; ++i)  		{ +            llassert(idx[i] >= start); +            llassert(idx[i] <= end); +  			if (idx[i] < start || idx[i] > end)  			{  				LL_ERRS() << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << LL_ENDL; @@ -697,6 +703,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of  			for (U32 i = start; i < end; i++)  			{  				S32 idx = (S32) (v[i][3]+0.25f); +                llassert(idx >= 0);  				if (idx < 0 || idx >= shader->mFeatures.mIndexedTextureChannels)  				{  					LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL; @@ -942,15 +949,15 @@ S32 LLVertexBuffer::determineUsage(S32 usage)  	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default  		if (ret_usage != GL_DYNAMIC_COPY_ARB)  		{ -		if (sDisableVBOMapping) -		{ //always use stream draw if VBO mapping is disabled -			ret_usage = GL_STREAM_DRAW_ARB; -		} -		else -		{ -			ret_usage = GL_DYNAMIC_DRAW_ARB; -		} -	} +		    if (sDisableVBOMapping) +		    { //always use stream draw if VBO mapping is disabled +			    ret_usage = GL_STREAM_DRAW_ARB; +		    } +		    else +		    { +			    ret_usage = GL_DYNAMIC_DRAW_ARB; +		    } +	    }  	}  	return ret_usage; @@ -1506,10 +1513,10 @@ bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)  	llassert(newnverts >= 0);  	llassert(newnindices >= 0); -	bool sucsess = true; +	bool success = true; -	sucsess &= updateNumVerts(newnverts);		 -	sucsess &= updateNumIndices(newnindices); +	success &= updateNumVerts(newnverts);		 +	success &= updateNumIndices(newnindices);  	if (useVBOs())  	{ @@ -1521,7 +1528,7 @@ bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)  		}  	} -	return sucsess; +	return success;  }  bool LLVertexBuffer::useVBOs() const @@ -2319,34 +2326,35 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  			{  				U32 unsatisfied_mask = (required_mask & ~data_mask); -				U32 i = 0; -				while (i < TYPE_MAX) -				{ +                for (U32 i = 0; i < TYPE_MAX; i++) +                {                      U32 unsatisfied_flag = unsatisfied_mask & (1 << i); -					switch (unsatisfied_flag) -					{ -						case MAP_VERTEX: LL_INFOS() << "Missing vert pos" << LL_ENDL; break; -						case MAP_NORMAL: LL_INFOS() << "Missing normals" << LL_ENDL; break; -						case MAP_TEXCOORD0: LL_INFOS() << "Missing TC 0" << LL_ENDL; break; -						case MAP_TEXCOORD1: LL_INFOS() << "Missing TC 1" << LL_ENDL; break; -						case MAP_TEXCOORD2: LL_INFOS() << "Missing TC 2" << LL_ENDL; break; -						case MAP_TEXCOORD3: LL_INFOS() << "Missing TC 3" << LL_ENDL; break; -						case MAP_COLOR: LL_INFOS() << "Missing vert color" << LL_ENDL; break; -						case MAP_EMISSIVE: LL_INFOS() << "Missing emissive" << LL_ENDL; break; -						case MAP_TANGENT: LL_INFOS() << "Missing tangent" << LL_ENDL; break; -						case MAP_WEIGHT: LL_INFOS() << "Missing weight" << LL_ENDL; break; -						case MAP_WEIGHT4: LL_INFOS() << "Missing weightx4" << LL_ENDL; break; -						case MAP_CLOTHWEIGHT: LL_INFOS() << "Missing clothweight" << LL_ENDL; break; -						case MAP_TEXTURE_INDEX: LL_INFOS() << "Missing tex index" << LL_ENDL; break; -						default: LL_INFOS() << "Missing who effin knows: " << unsatisfied_flag << LL_ENDL; -					}					 -				} - -            if (unsatisfied_mask & (1 << TYPE_INDEX)) -            { -               LL_INFOS() << "Missing indices" << LL_ENDL; -            } +                    switch (unsatisfied_flag) +                    { +                        case 0: break; +                        case MAP_VERTEX: LL_INFOS() << "Missing vert pos" << LL_ENDL; break; +                        case MAP_NORMAL: LL_INFOS() << "Missing normals" << LL_ENDL; break; +                        case MAP_TEXCOORD0: LL_INFOS() << "Missing TC 0" << LL_ENDL; break; +                        case MAP_TEXCOORD1: LL_INFOS() << "Missing TC 1" << LL_ENDL; break; +                        case MAP_TEXCOORD2: LL_INFOS() << "Missing TC 2" << LL_ENDL; break; +                        case MAP_TEXCOORD3: LL_INFOS() << "Missing TC 3" << LL_ENDL; break; +                        case MAP_COLOR: LL_INFOS() << "Missing vert color" << LL_ENDL; break; +                        case MAP_EMISSIVE: LL_INFOS() << "Missing emissive" << LL_ENDL; break; +                        case MAP_TANGENT: LL_INFOS() << "Missing tangent" << LL_ENDL; break; +                        case MAP_WEIGHT: LL_INFOS() << "Missing weight" << LL_ENDL; break; +                        case MAP_WEIGHT4: LL_INFOS() << "Missing weightx4" << LL_ENDL; break; +                        case MAP_CLOTHWEIGHT: LL_INFOS() << "Missing clothweight" << LL_ENDL; break; +                        case MAP_TEXTURE_INDEX: LL_INFOS() << "Missing tex index" << LL_ENDL; break; +                        default: LL_INFOS() << "Missing who effin knows: " << unsatisfied_flag << LL_ENDL; +                    } +                } + +                // TYPE_INDEX is beyond TYPE_MAX, so check for it individually +                if (unsatisfied_mask & (1 << TYPE_INDEX)) +                { +                   LL_INFOS() << "Missing indices" << LL_ENDL; +                }  				LL_ERRS() << "Shader consumption mismatches data provision." << LL_ENDL;  			} diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index c89d7e3958..9867bd16d6 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -179,8 +179,8 @@ public:  		TYPE_WEIGHT4,  		TYPE_CLOTHWEIGHT,  		TYPE_TEXTURE_INDEX, -		TYPE_MAX, -		TYPE_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	  	};  	enum {  		MAP_VERTEX = (1<<TYPE_VERTEX), | 
