Commit 85260dd7 authored by hybrid's avatar hybrid

Add texture cache with proper reference handling. This avoids deletion of...

Add texture cache with proper reference handling. This avoids deletion of textures while still being active on the GPU. Test case and fix by m(att)giuca

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4151 dfc29bdd-3216-0410-991c-e03cc46cb475
parent cf9e1223
...@@ -624,9 +624,9 @@ COpenGLDriver::~COpenGLDriver() ...@@ -624,9 +624,9 @@ COpenGLDriver::~COpenGLDriver()
deleteMaterialRenders(); deleteMaterialRenders();
CurrentTexture.clear();
// I get a blue screen on my laptop, when I do not delete the // I get a blue screen on my laptop, when I do not delete the
// textures manually before releasing the dc. Oh how I love this. // textures manually before releasing the dc. Oh how I love this.
deleteAllTextures(); deleteAllTextures();
removeAllOcclusionQueries(); removeAllOcclusionQueries();
removeAllHardwareBuffers(); removeAllHardwareBuffers();
...@@ -673,8 +673,7 @@ bool COpenGLDriver::genericDriverInit() ...@@ -673,8 +673,7 @@ bool COpenGLDriver::genericDriverInit()
} }
u32 i; u32 i;
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i) CurrentTexture.clear();
CurrentTexture[i]=0;
// load extensions // load extensions
initExtensions(Params.Stencilbuffer); initExtensions(Params.Stencilbuffer);
if (queryFeature(EVDF_ARB_GLSL)) if (queryFeature(EVDF_ARB_GLSL))
...@@ -2433,7 +2432,7 @@ bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture) ...@@ -2433,7 +2432,7 @@ bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture)
if (MultiTextureExtension) if (MultiTextureExtension)
extGlActiveTexture(GL_TEXTURE0_ARB + stage); extGlActiveTexture(GL_TEXTURE0_ARB + stage);
CurrentTexture[stage]=texture; CurrentTexture.set(stage,texture);
if (!texture) if (!texture)
{ {
...@@ -2445,7 +2444,7 @@ bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture) ...@@ -2445,7 +2444,7 @@ bool COpenGLDriver::setActiveTexture(u32 stage, const video::ITexture* texture)
if (texture->getDriverType() != EDT_OPENGL) if (texture->getDriverType() != EDT_OPENGL)
{ {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
CurrentTexture[stage]=0; CurrentTexture.set(stage, 0);
os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
return false; return false;
} }
...@@ -3818,6 +3817,17 @@ void COpenGLDriver::draw3DLine(const core::vector3df& start, ...@@ -3818,6 +3817,17 @@ void COpenGLDriver::draw3DLine(const core::vector3df& start,
} }
//! Removes a texture from the texture cache and deletes it, freeing lot of memory.
void COpenGLDriver::removeTexture(ITexture* texture)
{
if (!texture)
return;
CNullDriver::removeTexture(texture);
// Remove this texture from CurrentTexture as well
CurrentTexture.remove(texture);
}
//! Only used by the internal engine. Used to notify the driver that //! Only used by the internal engine. Used to notify the driver that
//! the window was resized. //! the window was resized.
......
...@@ -387,6 +387,9 @@ namespace video ...@@ -387,6 +387,9 @@ namespace video
ITexture* createDepthTexture(ITexture* texture, bool shared=true); ITexture* createDepthTexture(ITexture* texture, bool shared=true);
void removeDepthTexture(ITexture* texture); void removeDepthTexture(ITexture* texture);
//! Removes a texture from the texture cache and deletes it, freeing lot of memory.
void removeTexture(ITexture* texture);
//! Convert E_PRIMITIVE_TYPE to OpenGL equivalent //! Convert E_PRIMITIVE_TYPE to OpenGL equivalent
GLenum primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const; GLenum primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const;
...@@ -467,7 +470,70 @@ namespace video ...@@ -467,7 +470,70 @@ namespace video
SMaterial Material, LastMaterial; SMaterial Material, LastMaterial;
COpenGLTexture* RenderTargetTexture; COpenGLTexture* RenderTargetTexture;
core::array<video::IRenderTarget> MRTargets; core::array<video::IRenderTarget> MRTargets;
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES]; class STextureStageCache
{
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
public:
STextureStageCache()
{
for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
{
CurrentTexture[i] = 0;
}
}
~STextureStageCache()
{
clear();
}
void set(u32 stage, const ITexture* tex)
{
if (stage<MATERIAL_MAX_TEXTURES)
{
const ITexture* oldTexture=CurrentTexture[stage];
if (tex)
tex->grab();
CurrentTexture[stage]=tex;
if (oldTexture)
oldTexture->drop();
}
}
const ITexture* operator[](int stage) const
{
if (stage<MATERIAL_MAX_TEXTURES)
return CurrentTexture[stage];
else
return 0;
}
void remove(const ITexture* tex)
{
for (s32 i = MATERIAL_MAX_TEXTURES-1; i>= 0; --i)
{
if (CurrentTexture[i] == tex)
{
tex->drop();
CurrentTexture[i] = 0;
}
}
}
void clear()
{
// Drop all the CurrentTexture handles
for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
{
if (CurrentTexture[i])
{
CurrentTexture[i]->drop();
CurrentTexture[i] = 0;
}
}
}
};
STextureStageCache CurrentTexture;
core::array<ITexture*> DepthTextures; core::array<ITexture*> DepthTextures;
struct SUserClipPlane struct SUserClipPlane
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment