Remove TextureManager::getTexture2D

Instead use getImage and let the caller create the Texture. Sharing of textures is then handled in post by the SharedStateManager.

This is closer to what the OSG serializer does.

Streamlines the TextureManager and will make it easier to multithread.
pull/893/head
scrawl 9 years ago
parent fbd4ad9b0c
commit 6ef848b7c5

@ -2015,9 +2015,9 @@ namespace MWGui
continue;
std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0,0).texture;
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(tex_name, osg::Texture::CLAMP, osg::Texture::CLAMP);
osg::ref_ptr<osg::Image> image = mResourceSystem->getTextureManager()->getImage(tex_name);
if(tex.valid())
if(image.valid())
{
//everything looks good, send it to the cursor manager
Uint8 size_x = imgSetPointer->getSize().width;
@ -2026,7 +2026,7 @@ namespace MWGui
Uint8 hotspot_y = imgSetPointer->getHotSpot().top;
int rotation = imgSetPointer->getRotation();
mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, tex->getImage(), size_x, size_y, hotspot_x, hotspot_y);
mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, image, size_x, size_y, hotspot_x, hotspot_y);
}
}
}

@ -1059,7 +1059,10 @@ namespace MWRender
stream << i;
stream << ".dds";
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(stream.str(), osg::Texture2D::REPEAT, osg::Texture2D::REPEAT);
osg::ref_ptr<osg::Image> image = mResourceSystem->getTextureManager()->getImage(stream.str());
osg::ref_ptr<osg::Texture2D> tex (new osg::Texture2D(image));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture2D::REPEAT);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture2D::REPEAT);
mResourceSystem->getSceneManager()->applyFilterSettings(tex);
textures.push_back(tex);
}

@ -231,6 +231,13 @@ namespace MWRender
return mResourceSystem;
}
void RenderingManager::clearCache()
{
mResourceSystem->clearCache();
if (mTerrain.get())
mTerrain->clearCache();
}
osg::Group* RenderingManager::getLightRoot()
{
return mLightRoot.get();

@ -65,6 +65,8 @@ namespace MWRender
Resource::ResourceSystem* getResourceSystem();
void clearCache();
osg::Group* getLightRoot();
void setNightEyeFactor(float factor);

@ -15,6 +15,7 @@
#include <components/nifosg/controller.hpp>
#include <components/resource/texturemanager.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/fallback/fallback.hpp>
#include "vismask.hpp"
@ -39,7 +40,11 @@ namespace
{
std::ostringstream texname;
texname << "textures/water/" << tex << std::setw(2) << std::setfill('0') << i << ".dds";
textures.push_back(resourceSystem->getTextureManager()->getTexture2D(texname.str(), osg::Texture::REPEAT, osg::Texture::REPEAT));
osg::ref_ptr<osg::Texture2D> tex (new osg::Texture2D(resourceSystem->getTextureManager()->getImage(texname.str())));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
resourceSystem->getSceneManager()->applyFilterSettings(tex);
textures.push_back(tex);
}
osg::ref_ptr<NifOsg::FlipController> controller (new NifOsg::FlipController(0, 0.3f/rippleFrameCount, textures));

@ -476,9 +476,9 @@ public:
mTransform->addUpdateCallback(mUpdater);
mTransform->setNodeMask(Mask_Sun);
osg::ref_ptr<osg::Texture2D> sunTex = textureManager.getTexture2D("textures/tx_sun_05.dds",
osg::Texture::CLAMP,
osg::Texture::CLAMP);
osg::ref_ptr<osg::Texture2D> sunTex (new osg::Texture2D(textureManager.getImage("textures/tx_sun_05.dds")));
sunTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
sunTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
mGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, sunTex, osg::StateAttribute::ON);
@ -604,9 +604,9 @@ private:
void createSunFlash(Resource::TextureManager& textureManager)
{
osg::ref_ptr<osg::Texture2D> tex = textureManager.getTexture2D("textures/tx_sun_flash_grey_05.dds",
osg::Texture::CLAMP,
osg::Texture::CLAMP);
osg::ref_ptr<osg::Texture2D> tex (new osg::Texture2D(textureManager.getImage("textures/tx_sun_flash_grey_05.dds")));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
osg::ref_ptr<osg::PositionAttitudeTransform> transform (new osg::PositionAttitudeTransform);
const float scale = 2.6f;
@ -1055,8 +1055,12 @@ private:
void setTextures(const std::string& phaseTex, const std::string& circleTex)
{
mPhaseTex = mTextureManager.getTexture2D(phaseTex, osg::Texture::CLAMP, osg::Texture::CLAMP);
mCircleTex = mTextureManager.getTexture2D(circleTex, osg::Texture::CLAMP, osg::Texture::CLAMP);
mPhaseTex = new osg::Texture2D(mTextureManager.getImage(phaseTex));
mPhaseTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
mPhaseTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
mCircleTex = new osg::Texture2D(mTextureManager.getImage(circleTex));
mCircleTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
mCircleTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
reset();
}
@ -1342,8 +1346,12 @@ void SkyManager::createRain()
mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,-1));
osg::ref_ptr<osg::StateSet> stateset (mRainParticleSystem->getOrCreateStateSet());
stateset->setTextureAttributeAndModes(0, mSceneManager->getTextureManager()->getTexture2D("textures/tx_raindrop_01.dds",
osg::Texture::CLAMP, osg::Texture::CLAMP), osg::StateAttribute::ON);
osg::ref_ptr<osg::Texture2D> raindropTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage("textures/tx_raindrop_01.dds")));
raindropTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
raindropTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
stateset->setTextureAttributeAndModes(0, raindropTex, osg::StateAttribute::ON);
stateset->setNestRenderBins(false);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
@ -1549,8 +1557,11 @@ void SkyManager::setWeather(const WeatherResult& weather)
std::string texture = Misc::ResourceHelpers::correctTexturePath(mClouds, mSceneManager->getVFS());
mCloudUpdater->setTexture(mSceneManager->getTextureManager()->getTexture2D(texture,
osg::Texture::REPEAT, osg::Texture::REPEAT));
osg::ref_ptr<osg::Texture2D> cloudTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage(texture)));
cloudTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
cloudTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
mCloudUpdater->setTexture(cloudTex);
}
if (mNextClouds != weather.mNextCloudTexture)
@ -1561,8 +1572,11 @@ void SkyManager::setWeather(const WeatherResult& weather)
{
std::string texture = Misc::ResourceHelpers::correctTexturePath(mNextClouds, mSceneManager->getVFS());
mCloudUpdater2->setTexture(mSceneManager->getTextureManager()->getTexture2D(texture,
osg::Texture::REPEAT, osg::Texture::REPEAT));
osg::ref_ptr<osg::Texture2D> cloudTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage(texture)));
cloudTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
cloudTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
mCloudUpdater2->setTexture(cloudTex);
}
}

@ -15,8 +15,10 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou
return;
std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(texture, resourceSystem->getVFS());
// Not sure if wrap settings should be pulled from the overridden texture?
osg::ref_ptr<osg::Texture2D> tex = resourceSystem->getTextureManager()->getTexture2D(correctedTexture, osg::Texture2D::CLAMP,
osg::Texture2D::CLAMP);
osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D(resourceSystem->getTextureManager()->getImage(correctedTexture));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
osg::ref_ptr<osg::StateSet> stateset;
if (node->getStateSet())
stateset = static_cast<osg::StateSet*>(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY));

@ -317,6 +317,7 @@ public:
mRefractionTexture->setInternalFormat(GL_RGB);
mRefractionTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
mRefractionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
mRefractionTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter");
attach(osg::Camera::COLOR_BUFFER, mRefractionTexture);
@ -328,6 +329,7 @@ public:
mRefractionDepthTexture->setSourceType(GL_UNSIGNED_INT);
mRefractionDepthTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
mRefractionDepthTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
mRefractionDepthTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter");
attach(osg::Camera::DEPTH_BUFFER, mRefractionDepthTexture);
}
@ -388,6 +390,7 @@ public:
mReflectionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
mReflectionTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
mReflectionTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
mReflectionTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter");
attach(osg::Camera::COLOR_BUFFER, mReflectionTexture);
@ -553,7 +556,10 @@ void Water::createSimpleWaterStateSet(osg::Node* node, float alpha)
{
std::ostringstream texname;
texname << "textures/water/" << texture << std::setw(2) << std::setfill('0') << i << ".dds";
textures.push_back(mResourceSystem->getTextureManager()->getTexture2D(texname.str(), osg::Texture::REPEAT, osg::Texture::REPEAT));
osg::ref_ptr<osg::Texture2D> tex (new osg::Texture2D(mResourceSystem->getTextureManager()->getImage(texname.str())));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
textures.push_back(tex);
}
if (!textures.size())

@ -402,7 +402,7 @@ namespace MWWorld
mCellChanged = true;
mRendering.getResourceSystem()->clearCache();
mRendering.clearCache();
}
void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos)
@ -515,7 +515,7 @@ namespace MWWorld
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
mRendering.getResourceSystem()->clearCache();
mRendering.clearCache();
}
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos)

@ -709,7 +709,9 @@ namespace NifOsg
}
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, textureManager->getVFS());
osg::ref_ptr<osg::Texture2D> texture = textureManager->getTexture2D(filename, wrapS, wrapT);
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D(textureManager->getImage(filename)));
texture->setWrap(osg::Texture::WRAP_S, wrapS);
texture->setWrap(osg::Texture::WRAP_T, wrapT);
textures.push_back(texture);
}
osg::ref_ptr<FlipController> callback(new FlipController(flipctrl, textures));
@ -1376,9 +1378,10 @@ namespace NifOsg
int wrapT = (clamp) & 0x1;
int wrapS = (clamp >> 1) & 0x1;
osg::ref_ptr<osg::Texture2D> texture2d = textureManager->getTexture2D(filename,
wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP,
wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);
// create a new texture, will later attempt to share using the SharedStateManager
osg::ref_ptr<osg::Texture2D> texture2d (new osg::Texture2D(textureManager->getImage(filename)));
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP);
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP);
int texUnit = boundTextures.size();

@ -4,8 +4,6 @@
#include <osg/GLExtensions>
#include <osg/Version>
#include <stdexcept>
#include <components/vfs/manager.hpp>
#ifdef OSG_LIBRARY_STATIC
@ -47,6 +45,7 @@ namespace Resource
TextureManager::TextureManager(const VFS::Manager *vfs)
: mVFS(vfs)
, mWarningTexture(createWarningTexture())
, mWarningImage(mWarningTexture->getImage())
, mOptions(new osgDB::Options("dds_flip dds_dxt1_detect_rgba"))
{
}
@ -56,13 +55,6 @@ namespace Resource
}
/*
osg::ref_ptr<osg::Image> TextureManager::getImage(const std::string &filename)
{
}
*/
bool checkSupported(osg::Image* image, const std::string& filename)
{
switch(image->getPixelFormat())
@ -113,7 +105,7 @@ namespace Resource
catch (std::exception& e)
{
std::cerr << "Failed to open image: " << e.what() << std::endl;
return NULL;
return mWarningImage;
}
size_t extPos = normalized.find_last_of('.');
@ -124,20 +116,20 @@ namespace Resource
if (!reader)
{
std::cerr << "Error loading " << filename << ": no readerwriter for '" << ext << "' found" << std::endl;
return NULL;
return mWarningImage;
}
osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions);
if (!result.success())
{
std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl;
return NULL;
return mWarningImage;
}
osg::Image* image = result.getImage();
if (!checkSupported(image, filename))
{
return NULL;
return mWarningImage;
}
mImages.insert(std::make_pair(normalized, image));
@ -145,63 +137,6 @@ namespace Resource
}
}
osg::ref_ptr<osg::Texture2D> TextureManager::getTexture2D(const std::string &filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT)
{
std::string normalized = filename;
mVFS->normalizeFilename(normalized);
MapKey key = std::make_pair(std::make_pair(wrapS, wrapT), normalized);
std::map<MapKey, osg::ref_ptr<osg::Texture2D> >::iterator found = mTextures.find(key);
if (found != mTextures.end())
{
return found->second;
}
else
{
Files::IStreamPtr stream;
try
{
stream = mVFS->get(normalized.c_str());
}
catch (std::exception& e)
{
std::cerr << "Failed to open texture: " << e.what() << std::endl;
return mWarningTexture;
}
size_t extPos = normalized.find_last_of('.');
std::string ext;
if (extPos != std::string::npos && extPos+1 < normalized.size())
ext = normalized.substr(extPos+1);
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext);
if (!reader)
{
std::cerr << "Error loading " << filename << ": no readerwriter for '" << ext << "' found" << std::endl;
return mWarningTexture;
}
osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions);
if (!result.success())
{
std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl;
return mWarningTexture;
}
osg::Image* image = result.getImage();
if (!checkSupported(image, filename))
{
return mWarningTexture;
}
osg::ref_ptr<osg::Texture2D> texture(new osg::Texture2D);
texture->setImage(image);
texture->setWrap(osg::Texture::WRAP_S, wrapS);
texture->setWrap(osg::Texture::WRAP_T, wrapT);
mTextures.insert(std::make_pair(key, texture));
return texture;
}
}
osg::Texture2D* TextureManager::getWarningTexture()
{
return mWarningTexture.get();

@ -26,18 +26,15 @@ namespace osgDB
namespace Resource
{
/// @brief Handles loading/caching of Images and Texture StateAttributes.
/// @brief Handles loading/caching of Images.
class TextureManager
{
public:
TextureManager(const VFS::Manager* vfs);
~TextureManager();
/// Create or retrieve a Texture2D using the specified image filename, and wrap parameters.
/// Returns the dummy texture if the given texture is not found.
osg::ref_ptr<osg::Texture2D> getTexture2D(const std::string& filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT);
/// Create or retrieve an Image
/// Returns the dummy image if the given image is not found.
osg::ref_ptr<osg::Image> getImage(const std::string& filename);
const VFS::Manager* getVFS() { return mVFS; }
@ -47,13 +44,11 @@ namespace Resource
private:
const VFS::Manager* mVFS;
typedef std::pair<std::pair<int, int>, std::string> MapKey;
// TODO: use ObjectCache
std::map<std::string, osg::ref_ptr<osg::Image> > mImages;
std::map<MapKey, osg::ref_ptr<osg::Texture2D> > mTextures;
osg::ref_ptr<osg::Texture2D> mWarningTexture;
osg::ref_ptr<osg::Image> mWarningImage;
osg::ref_ptr<osgDB::Options> mOptions;
TextureManager(const TextureManager&);

@ -4,6 +4,7 @@
#include <components/resource/resourcesystem.hpp>
#include <components/resource/texturemanager.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
@ -134,10 +135,19 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
// For compiling textures, I don't think the osgFX::Effect does it correctly
osg::ref_ptr<osg::Node> textureCompileDummy (new osg::Node);
unsigned int dummyTextureCounter = 0;
std::vector<osg::ref_ptr<osg::Texture2D> > layerTextures;
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
{
layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT));
osg::ref_ptr<osg::Texture2D> tex = mTextureCache[it->mDiffuseMap];
if (!tex)
{
tex = new osg::Texture2D(mResourceSystem->getTextureManager()->getImage(it->mDiffuseMap));
tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
mTextureCache[it->mDiffuseMap] = tex;
}
layerTextures.push_back(tex);
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, layerTextures.back());
}
@ -148,15 +158,18 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
texture->setImage(*it);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
texture->setResizeNonPowerOfTwoHint(false);
texture->getOrCreateUserDataContainer()->addDescription("dont_override_filter");
blendmapTextures.push_back(texture);
mResourceSystem->getSceneManager()->applyFilterSettings(texture);
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, blendmapTextures.back());
}
// SharedStatemanager->share(textureCompileDummy);
// Remove unrefImageDataAfterApply for better state sharing
// use texture coordinates for both texture units, the layer texture and blend texture
for (unsigned int i=0; i<2; ++i)
geometry->setTexCoordArray(i, mCache.getUVBuffer());
@ -226,4 +239,15 @@ void TerrainGrid::unloadCell(int x, int y)
mGrid.erase(it);
}
void TerrainGrid::clearCache()
{
for (TextureCache::iterator it = mTextureCache.begin(); it != mTextureCache.end();)
{
if (it->second->referenceCount() <= 1)
mTextureCache.erase(it++);
else
++it;
}
}
}

@ -27,12 +27,18 @@ namespace Terrain
virtual void loadCell(int x, int y);
virtual void unloadCell(int x, int y);
/// Clear cached textures that are no longer referenced
void clearCache();
private:
osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter);
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
unsigned int mNumSplits;
typedef std::map<std::string, osg::ref_ptr<osg::Texture2D> > TextureCache;
TextureCache mTextureCache;
typedef std::map<std::pair<int, int>, GridElement*> Grid;
Grid mGrid;

@ -39,6 +39,8 @@ namespace Terrain
Storage* storage, int nodeMask);
virtual ~World();
virtual void clearCache() {}
float getHeightAt (const osg::Vec3f& worldPos);
// This is only a hint and may be ignored by the implementation.

Loading…
Cancel
Save