diff --git a/gale/context/Context.cpp b/gale/context/Context.cpp index 9a0d62b..d6b7f9d 100644 --- a/gale/context/Context.cpp +++ b/gale/context/Context.cpp @@ -439,11 +439,13 @@ void gale::Context::clipBoardSet(enum gale::context::clipBoard::clipboardListe _ } bool gale::Context::OS_Draw(bool _displayEveryTime) { + gale::openGL::threadHasContext(); int64_t currentTime = gale::getTime(); // this is to prevent the multiple display at the a high frequency ... #if (!defined(__TARGET_OS__Android) && !defined(__TARGET_OS__Windows)) if(currentTime - m_previousDisplayTime < 1000000/120) { usleep(1000); + gale::openGL::threadHasNoMoreContext(); return false; } #endif @@ -541,6 +543,7 @@ bool gale::Context::OS_Draw(bool _displayEveryTime) { // release the curent interface : unLockContext(); } + gale::openGL::threadHasNoMoreContext(); return hasDisplayDone; } diff --git a/gale/renderer/openGL/openGL.cpp b/gale/renderer/openGL/openGL.cpp index 3d11745..ed0bc82 100644 --- a/gale/renderer/openGL/openGL.cpp +++ b/gale/renderer/openGL/openGL.cpp @@ -13,6 +13,7 @@ #include //#define DIRECT_MODE #include +#include #define CHECK_ERROR_OPENGL @@ -83,6 +84,45 @@ void gale::openGL::unLock() { mutexOpenGl().unlock(); } +static std::vector& getContextList() { + static std::vector g_val; + return g_val; +} + +bool gale::openGL::hasContext() { + bool ret = false; + mutexOpenGl().lock(); + auto it = std::find(getContextList().begin(), getContextList().end(), std11::this_thread::get_id()); + if (it != getContextList().end()) { + ret = true; + } + mutexOpenGl().unlock(); + return ret; +} + +void gale::openGL::threadHasContext() { + mutexOpenGl().lock(); + auto it = std::find(getContextList().begin(), getContextList().end(), std11::this_thread::get_id()); + if (it != getContextList().end()) { + GALE_ERROR("set openGL context associate with threadID a second time ... "); + } else { + getContextList().push_back(std11::this_thread::get_id()); + } + mutexOpenGl().unlock(); +} + +void gale::openGL::threadHasNoMoreContext() { + mutexOpenGl().lock(); + auto it = std::find(getContextList().begin(), getContextList().end(), std11::this_thread::get_id()); + if (it != getContextList().end()) { + getContextList().erase(it); + } else { + GALE_ERROR("rm openGL context associate with threadID that is not registered."); + } + + mutexOpenGl().unlock(); +} + void gale::openGL::setBasicMatrix(const mat4& _newOne) { if (l_matrixList.size()!=1) { GALE_ERROR("matrix is not corect size in the stack : " << l_matrixList.size()); diff --git a/gale/renderer/openGL/openGL.h b/gale/renderer/openGL/openGL.h index 27fc132..3d05849 100644 --- a/gale/renderer/openGL/openGL.h +++ b/gale/renderer/openGL/openGL.h @@ -24,6 +24,21 @@ namespace gale { */ void startSimulationMode(); #endif + /** + * @brief Get the current thread context status. + * @return true The thread can acces to openGL. + * @return false The Thread Can not acces to OpenGL. + */ + bool hasContext(); + /** + * @brief must be called by the thread that has openGl context to notify the system + * @note Call @ref gale::openGL::threadHasNoMoreContext when ended + */ + void threadHasContext(); + /** + * @brief At the end of the thread exection, set the thead has no more openGL cotext + */ + void threadHasNoMoreContext(); /** * @brief Lock the openGL context for one user only == > better to keep flags and other things ... */ diff --git a/gale/resource/Manager.cpp b/gale/resource/Manager.cpp index 0c13442..5ce843f 100644 --- a/gale/resource/Manager.cpp +++ b/gale/resource/Manager.cpp @@ -21,6 +21,7 @@ gale::resource::Manager::Manager() : } gale::resource::Manager::~Manager() { + std11::unique_lock lock(m_mutex); bool hasError = false; if (m_resourceListToUpdate.size()!=0) { GALE_ERROR("Must not have anymore resources to update !!!"); @@ -37,6 +38,7 @@ gale::resource::Manager::~Manager() { } void gale::resource::Manager::unInit() { + std11::unique_lock lock(m_mutex); display(); m_resourceListToUpdate.clear(); // remove all resources ... @@ -57,6 +59,7 @@ void gale::resource::Manager::unInit() { void gale::resource::Manager::display() { GALE_INFO("Resources loaded : "); // remove all resources ... + std11::unique_lock lock(m_mutex); for (auto &it : m_resourceList) { std::shared_ptr tmpRessource = it.lock(); if (tmpRessource != nullptr) { @@ -72,6 +75,7 @@ void gale::resource::Manager::display() { void gale::resource::Manager::reLoadResources() { GALE_INFO("------------- Resources re-loaded -------------"); // remove all resources ... + std11::unique_lock lock(m_mutex); if (m_resourceList.size() != 0) { for (size_t jjj=0; jjj& _object) { // chek if not added before + std11::unique_lock lock(m_mutex); for (auto &it : m_resourceListToUpdate) { if ( it != nullptr && it == _object) { @@ -106,6 +111,7 @@ void gale::resource::Manager::update(const std::shared_ptr& _obj // Specific to load or update the data in the openGl context == > system use only void gale::resource::Manager::updateContext() { + std11::unique_lock lock(m_mutex); // TODO : Check the number of call this ... GALE_INFO("update open-gl context ... "); if (m_contextHasBeenRemoved == true) { // need to update all ... @@ -142,6 +148,7 @@ void gale::resource::Manager::updateContext() { // in this case, it is really too late ... void gale::resource::Manager::contextHasBeenDestroyed() { + std11::unique_lock lock(m_mutex); for (auto &it : m_resourceList) { std::shared_ptr tmpRessource = it.lock(); if (tmpRessource != nullptr) { @@ -154,6 +161,7 @@ void gale::resource::Manager::contextHasBeenDestroyed() { // internal generic keeper ... std::shared_ptr gale::resource::Manager::localKeep(const std::string& _filename) { + std11::unique_lock lock(m_mutex); GALE_VERBOSE("KEEP (DEFAULT) : file : '" << _filename << "' in " << m_resourceList.size() << " resources"); for (auto &it : m_resourceList) { std::shared_ptr tmpRessource = it.lock(); @@ -168,6 +176,7 @@ std::shared_ptr gale::resource::Manager::localKeep(const std::st // internal generic keeper ... void gale::resource::Manager::localAdd(const std::shared_ptr& _object) { + std11::unique_lock lock(m_mutex); //Add ... find empty slot for (auto &it : m_resourceList) { std::shared_ptr tmpRessource = it.lock(); @@ -182,6 +191,7 @@ void gale::resource::Manager::localAdd(const std::shared_ptr& _o // in case of error ... void gale::resource::Manager::cleanInternalRemoved() { + std11::unique_lock lock(m_mutex); //GALE_INFO("remove object in Manager"); updateContext(); for (auto it(m_resourceList.begin()); it!=m_resourceList.end(); ++it) { diff --git a/gale/resource/Manager.h b/gale/resource/Manager.h index e124bab..c011928 100644 --- a/gale/resource/Manager.h +++ b/gale/resource/Manager.h @@ -22,6 +22,7 @@ namespace gale { std::list> m_resourceList; std::vector> m_resourceListToUpdate; bool m_contextHasBeenRemoved; + std11::mutex m_mutex; public: /** * @brief initialize the internal variable diff --git a/gale/resource/Program.cpp b/gale/resource/Program.cpp index 8de9401..a14952a 100644 --- a/gale/resource/Program.cpp +++ b/gale/resource/Program.cpp @@ -32,6 +32,7 @@ gale::resource::Program::Program() : void gale::resource::Program::init(const std::string& _filename) { gale::Resource::init(_filename); + std11::unique_lock lock(m_mutex); GALE_DEBUG("OGL : load PROGRAM '" << m_name << "'"); // load data from file "all the time ..." @@ -97,7 +98,11 @@ void gale::resource::Program::init(const std::string& _filename) { // close the file: file.fileClose(); } - updateContext(); + if (gale::openGL::hasContext() == true) { + updateContext(); + } else { + getManager().update(std::dynamic_pointer_cast(shared_from_this())); + } } gale::resource::Program::~Program() { @@ -156,6 +161,7 @@ static char l_bufferDisplayError[LOG_OGL_INTERNAL_BUFFER_LEN] = ""; bool gale::resource::Program::checkIdValidity(int32_t _idElem) { + std11::unique_lock lock(m_mutex); if ( _idElem < 0 || (size_t)_idElem > m_elementList.size()) { return false; @@ -164,6 +170,7 @@ bool gale::resource::Program::checkIdValidity(int32_t _idElem) { } int32_t gale::resource::Program::getAttribute(std::string _elementName) { + std11::unique_lock lock(m_mutex); // check if it exist previously : for(size_t iii=0; iii lock(m_mutex); m_fileData.clear(); gale::openGL::shader::remove(m_shader); m_exist = false; } void gale::resource::Shader::updateContext() { + std11::unique_lock lock(m_mutex); if (m_exist == true) { // Do nothing == > too dangerous ... } else { @@ -80,6 +83,7 @@ void gale::resource::Shader::updateContext() { } void gale::resource::Shader::removeContext() { + std11::unique_lock lock(m_mutex); if (true == m_exist) { gale::openGL::shader::remove(m_shader); m_exist = false; @@ -87,11 +91,13 @@ void gale::resource::Shader::removeContext() { } void gale::resource::Shader::removeContextToLate() { + std11::unique_lock lock(m_mutex); m_exist = false; m_shader = 0; } void gale::resource::Shader::reload() { + std11::unique_lock lock(m_mutex); etk::FSNode file(m_name); if (false == file.exist()) { GALE_CRITICAL("File does not Exist : '" << file << "' : '" << file.getFileSystemName() << "'"); @@ -112,7 +118,17 @@ void gale::resource::Shader::reload() { file.fileClose(); // now change the OGL context ... - removeContext(); - updateContext(); + + if (gale::openGL::hasContext() == true) { + GALE_DEBUG("OGL : load SHADER \"" << m_name << "\" ==> call update context (direct)"); + removeContext(); + updateContext(); + } else { + GALE_DEBUG("OGL : load SHADER \"" << m_name << "\" ==> tagged has update context needed"); + // TODO : Check this, this is a leek ==> in the GPU ... really bad ... + m_exist = false; + m_shader = 0; + getManager().update(std::dynamic_pointer_cast(shared_from_this())); + } } diff --git a/gale/resource/Texture.cpp b/gale/resource/Texture.cpp index 40c90cd..2986694 100644 --- a/gale/resource/Texture.cpp +++ b/gale/resource/Texture.cpp @@ -57,6 +57,7 @@ gale::resource::Texture::~Texture() { } void gale::resource::Texture::updateContext() { + std11::unique_lock lock(m_mutex); if (false == m_loaded) { // Request a new texture at openGl : glGenTextures(1, &m_texId); @@ -88,6 +89,7 @@ void gale::resource::Texture::updateContext() { } void gale::resource::Texture::removeContext() { + std11::unique_lock lock(m_mutex); if (true == m_loaded) { // Request remove texture ... GALE_INFO("TEXTURE: Rm [" << getId() << "] texId=" << m_texId); @@ -97,11 +99,13 @@ void gale::resource::Texture::removeContext() { } void gale::resource::Texture::removeContextToLate() { + std11::unique_lock lock(m_mutex); m_loaded = false; m_texId=0; } void gale::resource::Texture::flush() { + std11::unique_lock lock(m_mutex); // request to the manager to be call at the next update ... getManager().update(std::dynamic_pointer_cast(shared_from_this())); } @@ -110,6 +114,7 @@ void gale::resource::Texture::setTexture(const std::shared_ptr const ivec2& _size, enum gale::resource::Texture::dataType _dataType, enum gale::resource::Texture::color _dataColorSpace) { + std11::unique_lock lock(m_mutex); m_data = _data; m_size = _size; m_endPointSize = _size; diff --git a/gale/resource/VirtualBufferObject.cpp b/gale/resource/VirtualBufferObject.cpp index 4a94f8f..0132581 100644 --- a/gale/resource/VirtualBufferObject.cpp +++ b/gale/resource/VirtualBufferObject.cpp @@ -39,6 +39,7 @@ void gale::resource::VirtualBufferObject::retreiveData() { } void gale::resource::VirtualBufferObject::updateContext() { + std11::unique_lock lock(m_mutex); if (false == m_exist) { // Allocate and assign a Vertex Array Object to our handle gale::openGL::genBuffers(m_vbo); @@ -59,6 +60,7 @@ void gale::resource::VirtualBufferObject::updateContext() { } void gale::resource::VirtualBufferObject::removeContext() { + std11::unique_lock lock(m_mutex); if (true == m_exist) { gale::openGL::deleteBuffers(m_vbo); m_exist = false; @@ -66,6 +68,7 @@ void gale::resource::VirtualBufferObject::removeContext() { } void gale::resource::VirtualBufferObject::removeContextToLate() { + std11::unique_lock lock(m_mutex); m_exist = false; for (size_t iii=0; iii lock(m_mutex); removeContext(); updateContext(); } void gale::resource::VirtualBufferObject::flush() { + std11::unique_lock lock(m_mutex); // request to the manager to be call at the next update ... getManager().update(std::dynamic_pointer_cast(shared_from_this())); } void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const vec3& _data) { + std11::unique_lock lock(m_mutex); if (m_vboSizeDataOffset[_id] == -1) { m_vboSizeDataOffset[_id] = 3; } else if (m_vboSizeDataOffset[_id] != 3) { @@ -96,6 +102,7 @@ void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const vec3& } vec3 gale::resource::VirtualBufferObject::getOnBufferVec3(int32_t _id, int32_t _elementID) { + std11::unique_lock lock(m_mutex); if ((size_t)_elementID*3 > m_buffer[_id].size()) { return vec3(0,0,0); } @@ -105,13 +112,16 @@ vec3 gale::resource::VirtualBufferObject::getOnBufferVec3(int32_t _id, int32_t _ } int32_t gale::resource::VirtualBufferObject::bufferSize(int32_t _id) { + std11::unique_lock lock(m_mutex); return m_buffer[_id].size()/m_vboSizeDataOffset[_id]; } int32_t gale::resource::VirtualBufferObject::getElementSize(int32_t _id) { + std11::unique_lock lock(m_mutex); return m_vboSizeDataOffset[_id]; } void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const vec2& _data) { + std11::unique_lock lock(m_mutex); if (m_vboSizeDataOffset[_id] == -1) { m_vboSizeDataOffset[_id] = 2; } else if (m_vboSizeDataOffset[_id] != 2) { @@ -124,6 +134,7 @@ void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const vec2& } vec2 gale::resource::VirtualBufferObject::getOnBufferVec2(int32_t _id, int32_t _elementID) { + std11::unique_lock lock(m_mutex); if ((size_t)_elementID*2 > m_buffer[_id].size()) { return vec2(0,0); } @@ -133,6 +144,7 @@ vec2 gale::resource::VirtualBufferObject::getOnBufferVec2(int32_t _id, int32_t _ void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const etk::Color& _data) { + std11::unique_lock lock(m_mutex); if (m_vboSizeDataOffset[_id] == -1) { m_vboSizeDataOffset[_id] = 4; } else if (m_vboSizeDataOffset[_id] != 4) { @@ -147,6 +159,7 @@ void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const etk::C } void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const etk::Color& _data) { + std11::unique_lock lock(m_mutex); if (m_vboSizeDataOffset[_id] == -1) { m_vboSizeDataOffset[_id] = 3; } else if (m_vboSizeDataOffset[_id] != 3) { @@ -160,6 +173,7 @@ void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const etk::C } void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const etk::Color& _data) { + std11::unique_lock lock(m_mutex); if (m_vboSizeDataOffset[_id] == -1) { m_vboSizeDataOffset[_id] = 2; } else if (m_vboSizeDataOffset[_id] != 2) { @@ -172,6 +186,7 @@ void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const etk::C } void gale::resource::VirtualBufferObject::pushOnBuffer(int32_t _id, const etk::Color& _data) { + std11::unique_lock lock(m_mutex); if (m_vboSizeDataOffset[_id] == -1) { m_vboSizeDataOffset[_id] = 1; } else if (m_vboSizeDataOffset[_id] != 1) {