99
1010#include " opengl-precomp.h" // Precompiled header
1111//
12+ #include < mrpt/containers/bimap.h>
1213#include < mrpt/core/get_env.h>
1314#include < mrpt/core/lock_helper.h>
1415#include < mrpt/opengl/Texture.h>
@@ -57,8 +58,8 @@ class TextureResourceHandler
5758 return o;
5859 }
5960
60- // / Return [ textureName, textureUnit]
61- texture_name_t generateTextureID ()
61+ // / Return textureName
62+ texture_name_t generateTextureID (const uint8_t * rgbDataForAssociation )
6263 {
6364#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
6465 auto lck = mrpt::lockHelper (m_texturesMtx);
@@ -71,6 +72,8 @@ class TextureResourceHandler
7172 CHECK_OPENGL_ERROR_IN_DEBUG ();
7273 m_textureReservedFrom[textureID] = std::this_thread::get_id ();
7374
75+ if (rgbDataForAssociation) m_textureToRGBdata.insert (textureID, rgbDataForAssociation);
76+
7477 if (MRPT_OPENGL_VERBOSE)
7578 std::cout << " [mrpt generateTextureID] textureName:" << textureID << std::endl;
7679
@@ -80,6 +83,21 @@ class TextureResourceHandler
8083#endif
8184 }
8285
86+ std::optional<texture_name_t > checkIfTextureAlreadyExists (const mrpt::img::CImage& rgb)
87+ {
88+ #if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
89+ auto lck = mrpt::lockHelper (m_texturesMtx);
90+
91+ auto it = m_textureToRGBdata.getInverseMap ().find (rgb.asCvMatRef ().data );
92+ if (it != m_textureToRGBdata.getInverseMap ().end ())
93+ return it->second ;
94+ else
95+ return {};
96+ #else
97+ return {};
98+ #endif
99+ }
100+
83101 void releaseTextureID (unsigned int texName)
84102 {
85103#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
@@ -109,19 +127,36 @@ class TextureResourceHandler
109127 void processDestroyQueue ()
110128 {
111129#if MRPT_HAS_OPENGL_GLUT || MRPT_HAS_EGL
112- if (auto itLst = m_destroyQueue.find (std::this_thread::get_id ()); itLst != m_destroyQueue.end ())
130+ if (auto itLst = m_destroyQueue.find (std::this_thread::get_id ());
131+ itLst != m_destroyQueue.end () && !itLst->second .empty ())
113132 {
114133 auto & lst = itLst->second ;
134+
135+ // Delete in OpenGL:
115136 glDeleteTextures (lst.size (), lst.data ());
116137 CHECK_OPENGL_ERROR_IN_DEBUG ();
138+
139+ // delete in rgb data container too:
140+ for (const auto id : lst)
141+ {
142+ if (m_textureToRGBdata.hasKey (id)) m_textureToRGBdata.erase_by_key (id);
143+ }
144+
145+ if (MRPT_OPENGL_VERBOSE)
146+ {
147+ std::cout << " [mrpt processDestroyQueue] threadId=" << std::this_thread::get_id ()
148+ << " destroyed " << lst.size () << " \n " ;
149+ }
117150 lst.clear ();
151+ m_destroyQueue.erase (itLst);
118152 }
119- if (MRPT_OPENGL_VERBOSE)
153+ if (!m_destroyQueue. empty () && MRPT_OPENGL_VERBOSE)
120154 {
121155 std::cout << " [mrpt processDestroyQueue] threadId=" << std::this_thread::get_id ()
122- << " . At output: " ;
156+ << " . Remaining at output: " ;
123157 for (const auto & lst : m_destroyQueue)
124- std::cout << " [" << lst.first << " ]=" << lst.second .size () << " " ;
158+ std::cout << " [" << lst.first << " ]=" << lst.second .size () << " textures " ;
159+ std::cout << " \n " ;
125160 }
126161#endif
127162 }
@@ -130,14 +165,20 @@ class TextureResourceHandler
130165 std::mutex m_texturesMtx;
131166 std::map<GLuint, std::thread::id> m_textureReservedFrom;
132167 std::map<std::thread::id, std::vector<GLuint>> m_destroyQueue;
168+ mrpt::containers::bimap<GLuint, const uint8_t *> m_textureToRGBdata;
133169 GLint m_maxTextureUnits;
134170#endif
135171};
136172
173+ std::optional<texture_name_t > checkIfTextureAlreadyExists (const mrpt::img::CImage& rgb)
174+ {
175+ return TextureResourceHandler::Instance ().checkIfTextureAlreadyExists (rgb);
176+ }
177+
137178// / Returns: [texture name, texture unit]
138- texture_name_t mrpt::opengl::getNewTextureNumber ()
179+ texture_name_t mrpt::opengl::getNewTextureNumber (const uint8_t * optionalRgbDataForAssociation )
139180{
140- return TextureResourceHandler::Instance ().generateTextureID ();
181+ return TextureResourceHandler::Instance ().generateTextureID (optionalRgbDataForAssociation );
141182}
142183
143184void mrpt::opengl::releaseTextureName (const texture_name_t & t)
@@ -247,6 +288,21 @@ void Texture::internalAssignImage_2D(
247288 in_rgb->forceLoad (); // just in case they are lazy-load imgs
248289 if (in_alpha) in_alpha->forceLoad ();
249290
291+ // Check if we already have this texture loaded in GPU and avoid creating
292+ // duplicated texture ID:
293+ const auto existingTextureId = checkIfTextureAlreadyExists (*in_rgb);
294+ if (existingTextureId.has_value ())
295+ {
296+ get () = existingTextureId.value ();
297+ get ()->unit = textureUnit;
298+
299+ if (MRPT_OPENGL_VERBOSE)
300+ std::cout << " [mrpt internalAssignImage_2D] Reusing existing textureName:" << get ()->name
301+ << " \n " ;
302+
303+ return ;
304+ }
305+
250306 mrpt::img::CImage rgb;
251307
252308 switch (in_rgb->getPixelDepth ())
@@ -290,7 +346,7 @@ void Texture::internalAssignImage_2D(
290346 if (in_alpha) alpha = mrpt::img::CImage (*in_alpha, mrpt::img::SHALLOW_COPY);
291347
292348 // allocate texture names:
293- get () = getNewTextureNumber ();
349+ get () = getNewTextureNumber (in_rgb-> asCvMatRef (). data );
294350 get ()->unit = textureUnit;
295351
296352 // activate the texture unit first before binding texture
@@ -536,7 +592,7 @@ void Texture::assignCubeImages(const std::array<mrpt::img::CImage, 6>& imgs, int
536592 }
537593
538594 // allocate texture "name" (ID):
539- get () = getNewTextureNumber ();
595+ get () = getNewTextureNumber (nullptr ); /* no cached img for cube textures */
540596
541597 // activate the texture unit first before binding texture
542598 bindAsCubeTexture ();
0 commit comments