diff --git a/src/common/ml_scene_renderer.cpp b/src/common/ml_scene_renderer.cpp index 84b82431f..64c23e320 100644 --- a/src/common/ml_scene_renderer.cpp +++ b/src/common/ml_scene_renderer.cpp @@ -29,11 +29,11 @@ bool MLThreadSafeGLMeshAttributesFeeder::renderedWithBO() const return GLMeshAttributesFeeder::isPossibleToUseBORendering(); } -void MLThreadSafeGLMeshAttributesFeeder::meshAttributesUpdated( int mask ) -{ - QWriteLocker locker(&_lock); - GLMeshAttributesFeeder::meshAttributesUpdated(mask); -} +//void MLThreadSafeGLMeshAttributesFeeder::meshAttributesUpdated( int mask ) +//{ +// QWriteLocker locker(&_lock); +// GLMeshAttributesFeeder::meshAttributesUpdated(mask); +//} vcg::GLFeederInfo::ReqAtts MLThreadSafeGLMeshAttributesFeeder::setupRequestedAttributes(const vcg::GLFeederInfo::ReqAtts& rq,bool& allocated ) { @@ -180,12 +180,24 @@ void MLThreadSafeGLMeshAttributesFeeder::deAllocateBO() GLMeshAttributesFeeder::buffersDeAllocationRequested(); } +void MLThreadSafeGLMeshAttributesFeeder::deAllocateBO(const vcg::GLFeederInfo::ReqAtts& req) +{ + QWriteLocker locker(&_lock); + GLMeshAttributesFeeder::buffersDeAllocationRequested(req); +} + void MLThreadSafeGLMeshAttributesFeeder::deAllocateTextures() { QWriteLocker locker(&_lock); _textids.clear(); } +void MLThreadSafeGLMeshAttributesFeeder::invalidateRequestedAttributes( vcg::GLFeederInfo::ReqAtts& rq ) +{ + QWriteLocker locker(&_lock); + GLMeshAttributesFeeder::invalidateRequestedAttributes(rq); +} + MLThreadSafeGLMeshAttributesFeeder::MLThreadSafeTextureNamesContainer::MLThreadSafeTextureNamesContainer() :_tmid(),_lock(QReadWriteLock::Recursive) { @@ -598,6 +610,32 @@ vcg::GLFeederInfo::PRIMITIVE_MODALITY MLSceneRenderModeAdapter::renderModeToPrim return vcg::GLFeederInfo::PR_NONE; } +vcg::GLFeederInfo::ReqAtts MLSceneRenderModeAdapter::convertUpdateMaskToMinimalReqAtts( int updatemask,const MeshModel& m,const RenderMode& rm ) +{ + vcg::GLFeederInfo::ReqAtts res; + if (updatemask & MeshModel::MM_NONE) + return res; + MLSceneRenderModeAdapter::renderModeToReqAtts(rm,res); + + if ((updatemask & MeshModel::MM_UNKNOWN) || (updatemask & MeshModel::MM_ALL) || (updatemask & MeshModel::MM_VERTNUMBER) || (updatemask & MeshModel::MM_FACENUMBER) || (updatemask & MeshModel::MM_VERTFACETOPO) || (updatemask & MeshModel::MM_FACEFACETOPO)) + { + vcg::GLFeederInfo::ReqAtts::computeARequestedAttributesSetCompatibleWithMesh(res,m.cm); + return res; + } + + res[vcg::GLFeederInfo::ATT_VERTPOSITION] = (updatemask & MeshModel::MM_VERTCOORD); + res[vcg::GLFeederInfo::ATT_VERTNORMAL] = (updatemask & MeshModel::MM_VERTNORMAL); + res[vcg::GLFeederInfo::ATT_FACENORMAL] = (updatemask & MeshModel::MM_FACENORMAL); + res[vcg::GLFeederInfo::ATT_VERTCOLOR] = (updatemask & MeshModel::MM_VERTCOLOR); + res[vcg::GLFeederInfo::ATT_FACECOLOR] = (updatemask & MeshModel::MM_FACECOLOR); + res[vcg::GLFeederInfo::ATT_MESHCOLOR] = (updatemask & MeshModel::MM_COLOR); + res[vcg::GLFeederInfo::ATT_VERTTEXTURE] = (updatemask & MeshModel::MM_VERTTEXCOORD); + res[vcg::GLFeederInfo::ATT_WEDGETEXTURE] = (updatemask & MeshModel::MM_WEDGTEXCOORD); + + vcg::GLFeederInfo::ReqAtts::computeARequestedAttributesSetCompatibleWithMesh(res,m.cm); + return res; +} + //bool MLSceneRenderModeAdapter::setupRequestedAttributesAccordingToRenderMode( unsigned int meshid,GLArea& area ) //{ // bool res = false; diff --git a/src/common/ml_scene_renderer.h b/src/common/ml_scene_renderer.h index 2bc21efda..312f0d7a0 100644 --- a/src/common/ml_scene_renderer.h +++ b/src/common/ml_scene_renderer.h @@ -64,14 +64,20 @@ public: GLuint bufferObjectHandle() const; - void meshAttributesUpdated(int mask); + //void meshAttributesUpdated(int mask); vcg::GLFeederInfo::ReqAtts setupRequestedAttributes(const vcg::GLFeederInfo::ReqAtts& rq,bool& allocated); vcg::GLFeederInfo::ReqAtts removeRequestedAttributes(const vcg::GLFeederInfo::ReqAtts& rq); + void invalidateRequestedAttributes(vcg::GLFeederInfo::ReqAtts& rq); + + //Deallocate all the BO void deAllocateBO(); + //Deallocate just the BO requested by the req parameter + void deAllocateBO(const vcg::GLFeederInfo::ReqAtts& req); + void deAllocateTextures(); void drawWire(vcg::GLFeederInfo::ReqAtts& rq); @@ -84,6 +90,8 @@ public: void drawBBox(vcg::GLFeederInfo::ReqAtts& rq); + + inline CMeshO& mesh() {return _mesh;} inline MLThreadSafeTextureNamesContainer& textureIDContainer() {return _textids;} @@ -145,6 +153,7 @@ struct MLSceneRenderModeAdapter static void renderModeToReqAtts(const RenderMode& rm,vcg::GLFeederInfo::ReqAtts& rq); /*static bool setupRequestedAttributesAccordingToRenderMode(unsigned int meshid,GLArea& area);*/ static void renderMesh(QGLContext& area,MLThreadSafeGLMeshAttributesFeeder& feed,const RenderMode& rm,int pointsz,bool pointsmooth,bool pointatt); + static vcg::GLFeederInfo::ReqAtts convertUpdateMaskToMinimalReqAtts(int updatemask,const MeshModel& m,const RenderMode& rm); private: static vcg::GLFeederInfo::PRIMITIVE_MODALITY renderModeToPrimitiveModality(const RenderMode& rm); static void renderModeColorToReqAtts(const RenderMode& rm,vcg::GLFeederInfo::ReqAtts& rq); diff --git a/src/general.pri b/src/general.pri index b1070f49d..a8cdd2689 100644 --- a/src/general.pri +++ b/src/general.pri @@ -10,7 +10,7 @@ GLEWDIR = ../external/glew-1.7.0 CONFIG += c++11 -QMAKE_CXXFLAGS += -Wno-inconsistent-missing-override +macx:QMAKE_CXXFLAGS += -Wno-inconsistent-missing-override MACLIBDIR = ../../external/lib/macx64 diff --git a/src/meshlab/mainwindow.h b/src/meshlab/mainwindow.h index 7e3172c66..c2d7aa6e6 100644 --- a/src/meshlab/mainwindow.h +++ b/src/meshlab/mainwindow.h @@ -257,7 +257,9 @@ private: void initDocumentMeshRenderState(MeshLabXMLFilterContainer* mfc); void initDocumentRasterRenderState(MeshLabXMLFilterContainer* mfc); - void deallocateReqAttsConsideringAllOtherGLArea(GLArea* ar,const int meshid,const RenderMode& currentrendmode,const RenderMode& newrendermode); + + void updatePerMeshRenderingDataAccordingToUpdateMaskConsideringAllGLArea(int meshid,int updatemask); + void deallocateNotMoreNecessaryPerMeshAndPerGLAreaRenderingDataConsideringAllOtherGLArea(const int meshid,GLArea* gla,const RenderMode& currentrendmode,const RenderMode& newrendermode); QNetworkAccessManager *httpReq; QBuffer myLocalBuf; @@ -521,8 +523,17 @@ private: QAction *onscreenHelpAct; QAction *checkUpdatesAct; //////////////////////////////////////////////////// + struct MeshModelTmpData + { + int _mask; + size_t _nvert; + size_t _nface; - QSet existingmeshesbeforefilterexecution; + MeshModelTmpData(int mask,size_t nvert,size_t nface) + :_mask(mask),_nvert(nvert),_nface(nface) + {} + }; + QMap existingmeshesbeforefilterexecution; static QString getDecoratedFileName(const QString& name); void updateRenderToolBar( RenderModeAction* act ); diff --git a/src/meshlab/mainwindow_Init.cpp b/src/meshlab/mainwindow_Init.cpp index 9730fb086..6761d7367 100644 --- a/src/meshlab/mainwindow_Init.cpp +++ b/src/meshlab/mainwindow_Init.cpp @@ -51,7 +51,7 @@ QProgressBar *MainWindow::qb; MainWindow::MainWindow() -:mwsettings(),xmlfiltertimer(),wama(),gpumeminfo(NULL) +:mwsettings(),xmlfiltertimer(),wama(),gpumeminfo(NULL),existingmeshesbeforefilterexecution() { //xmlfiltertimer will be called repeatedly, so like Qt documentation suggests, the first time start function should be called. //Subsequently restart function will be invoked. diff --git a/src/meshlab/mainwindow_RunTime.cpp b/src/meshlab/mainwindow_RunTime.cpp index 8c8ff05ad..5eafc8b44 100644 --- a/src/meshlab/mainwindow_RunTime.cpp +++ b/src/meshlab/mainwindow_RunTime.cpp @@ -1199,9 +1199,9 @@ void MainWindow::executeFilter(QAction *action, RichParameterSet ¶ms, bool i iFilter->glContext->create(filterWidget->context()); try { - QSet existingmeshesbeforefilterexecutionlocal; + existingmeshesbeforefilterexecution.clear(); for(MeshModel* mm = meshDoc()->nextMesh();mm != NULL;mm=meshDoc()->nextMesh(mm)) - existingmeshesbeforefilterexecutionlocal.insert(mm->id()); + existingmeshesbeforefilterexecution.insert(mm->id(),MeshModelTmpData(mm->dataMask(),(size_t) mm->cm.VN(),(size_t) mm->cm.FN())); ret=iFilter->applyFilter(action, *(meshDoc()), MergedEnvironment, QCallBack); meshDoc()->setBusy(false); @@ -1265,7 +1265,7 @@ void MainWindow::executeFilter(QAction *action, RichParameterSet ¶ms, bool i } int fclasses = iFilter->getClass(action); - + MLSceneGLSharedDataContext* sharedcont = GLA()->getSceneGLSharedContext(); for(MeshModel* mm = meshDoc()->nextMesh();mm != NULL;mm = meshDoc()->nextMesh(mm)) { int postCondMask = iFilter->postCondition(action); @@ -1283,16 +1283,23 @@ void MainWindow::executeFilter(QAction *action, RichParameterSet ¶ms, bool i if ((mm->hasDataMask(MeshModel::MM_VERTQUALITY)) && (fclasses & MeshFilterInterface::Quality )) postCondMask = postCondMask | MeshModel::MM_VERTQUALITY; - RenderMode rm = GLA()->rendermodemap[mm->id()]; - vcg::GLW::NormalMode nmmode = vcg::GlTrimesh::convertDrawModeToNormalMode(rm.drawMode); + QMap::Iterator existit = existingmeshesbeforefilterexecution.find(mm->id()); + if (existit != existingmeshesbeforefilterexecution.end()) + { + RenderMode rm = GLA()->rendermodemap[mm->id()]; + int updatemask = MeshModel::MM_NONE; + if ((mm->cm.VN() != existit->_nvert) || (mm->cm.FN() != existit->_nface) || (postCondMask == MeshModel::MM_UNKNOWN) || (postCondMask == MeshModel::MM_ALL) || (postCondMask == MeshModel::MM_VERTNUMBER) || (postCondMask == MeshModel::MM_FACENUMBER) || (postCondMask == MeshModel::MM_VERTFACETOPO) || (postCondMask == MeshModel::MM_FACEFACETOPO)) + updatemask = MeshModel::MM_ALL; + else + //masks differences bitwise operator (^) -> remove the attributes that didn't apparently change + the ones that for sure changed according to the postCondition function + //this operation has been introduced in order to minimize problems with filters that didn't declared properly the postCondition mask + updatemask = (existit->_mask ^ mm->dataMask()) | postCondMask; - - //WARNING!!!!!!!!!!!!!!!! TOBEDELETED - //init the buffer object structures for the newly created mesh. It covers both the MeshCreating filters and the filters creating a new layer (i.e. poisson) - // if (!existingmeshesbeforefilterexecutionlocal.contains(mm->id())) - // mm->bor.update(mm->cm,MeshModel::MM_ALL,rm.drawMode,nmmode,rm.colorMode,rm.textureMode); - // else - // mm->bor.update(mm->cm,postCondMask,rm.drawMode,nmmode,rm.colorMode,rm.textureMode); + updatePerMeshRenderingDataAccordingToUpdateMaskConsideringAllGLArea(mm->id(),updatemask); + } + else + updatePerMeshRenderingDataAccordingToUpdateMaskConsideringAllGLArea(mm->id(),(int) MeshModel::MM_ALL); + existingmeshesbeforefilterexecution.clear(); } } catch (std::bad_alloc& bdall) @@ -1506,7 +1513,7 @@ void MainWindow::executeFilter(MeshLabXMLFilterContainer* mfc,const QMapxmlhistory << funcall; existingmeshesbeforefilterexecution.clear(); for(MeshModel* mm = meshDoc()->nextMesh();mm != NULL;mm=meshDoc()->nextMesh(mm)) - existingmeshesbeforefilterexecution.insert(mm->id()); + existingmeshesbeforefilterexecution.insert(mm->id(),MeshModelTmpData(mm->dataMask(),(size_t) mm->cm.VN(),(size_t) mm->cm.FN())); if (filtercpp) { enableDocumentSensibleActionsContainer(false); @@ -1596,6 +1603,23 @@ void MainWindow::postFilterExecution() rm = ci.value(); nm = vcg::GlTrimesh::convertDrawModeToNormalMode(rm.drawMode); } + + QMap::Iterator existit = existingmeshesbeforefilterexecution.find(mm->id()); + if (existit != existingmeshesbeforefilterexecution.end()) + { + RenderMode rm = GLA()->rendermodemap[mm->id()]; + int updatemask = MeshModel::MM_NONE; + if ((mm->cm.VN() != existit->_nvert) || (mm->cm.FN() != existit->_nface) || (postCondMask == MeshModel::MM_UNKNOWN) || (postCondMask == MeshModel::MM_ALL) || (postCondMask == MeshModel::MM_VERTNUMBER) || (postCondMask == MeshModel::MM_FACENUMBER) || (postCondMask == MeshModel::MM_VERTFACETOPO) || (postCondMask == MeshModel::MM_FACEFACETOPO)) + updatemask = MeshModel::MM_ALL; + else + //masks differences bitwise operator (^) -> remove the attributes that didn't apparently change + the ones that for sure changed according to the postCondition function + //this operation has been introduced in order to minimize problems with filters that didn't declared properly the postCondition mask + updatemask = (existit->_mask ^ mm->dataMask()) | postCondMask; + + updatePerMeshRenderingDataAccordingToUpdateMaskConsideringAllGLArea(mm->id(),updatemask); + } + else + updatePerMeshRenderingDataAccordingToUpdateMaskConsideringAllGLArea(mm->id(),(int) MeshModel::MM_ALL); //WARNING!!!!!!!!!!!!!!!! TOBEDELETED //init the buffer object structures for the newly created mesh. It covers both the MeshCreating filters and the filters creating a new layer (i.e. poisson) // if (!existingmeshesbeforefilterexecution.contains(mm->id())) @@ -3046,8 +3070,8 @@ void MainWindow::updateRenderMode( ) MeshModel* mmod = meshDoc()->getMesh(it.key()); if (mmod == NULL) throw MeshLabException("A RenderModeAction referred to a non-existent mesh."); - - deallocateReqAttsConsideringAllOtherGLArea(GLA(),it.key(),old,rm); + + deallocateNotMoreNecessaryPerMeshAndPerGLAreaRenderingDataConsideringAllOtherGLArea(it.key(),GLA(),old,rm); GLA()->setupRequestedAttributesPerMesh(it.key()); } } @@ -3069,39 +3093,12 @@ void MainWindow::updateRenderMode( ) if (mmod == NULL) throw MeshLabException("A RenderModeAction referred to a non-existent mesh."); - deallocateReqAttsConsideringAllOtherGLArea(GLA(),it.key(),old,rm); + deallocateNotMoreNecessaryPerMeshAndPerGLAreaRenderingDataConsideringAllOtherGLArea(it.key(),GLA(),old,rm); GLA()->setupRequestedAttributesPerMesh(it.key()); } GLA()->update(); } -void MainWindow::deallocateReqAttsConsideringAllOtherGLArea(GLArea* ar,const int meshid,const RenderMode& currentrendmode,const RenderMode& newrendermode) -{ - MultiViewer_Container* mvc = currentViewContainer(); - if ((mvc == NULL) || (ar == NULL)) - return; - - int currentid = ar->getId(); - vcg::GLFeederInfo::ReqAtts oldatts; - MLSceneRenderModeAdapter::renderModeToReqAtts(currentrendmode,oldatts); - vcg::GLFeederInfo::ReqAtts newatts; - MLSceneRenderModeAdapter::renderModeToReqAtts(newrendermode,newatts); - oldatts = vcg::GLFeederInfo::ReqAtts::setComplement(oldatts,newatts); - for(int ii = 0; ii < mvc->viewerCounter();++ii) - { - GLArea* otherarea = mvc->getViewer(ii); - if ((ii != currentid) && (otherarea != NULL)) - { - vcg::GLFeederInfo::ReqAtts othermeshview; - MLSceneRenderModeAdapter::renderModeToReqAtts(mvc->getViewer(ii)->rendermodemap[meshid],othermeshview); - oldatts = vcg::GLFeederInfo::ReqAtts::setComplement(oldatts,othermeshview); - } - } - MLThreadSafeGLMeshAttributesFeeder* feed = mvc->sharedDataContext()->meshAttributesFeeder(meshid); - if (feed != NULL) - feed->invalidateRequestedAttributes(oldatts); -} - void MainWindow::connectRenderModeActionList(QList& actlist) { for (int ii = 0; ii < actlist.size();++ii) @@ -3133,3 +3130,60 @@ void MainWindow::setBestTextureModePerMesh(RenderModeAction* textact,const int m rm.setTextureMode(texmode); } } + +void MainWindow::updatePerMeshRenderingDataAccordingToUpdateMaskConsideringAllGLArea(int meshid,int updatemask) +{ + MultiViewer_Container* mvc = currentViewContainer(); + if ((meshDoc() == NULL) || (mvc == NULL)) + return; + vcg::GLFeederInfo::ReqAtts res; + MeshModel* mm = meshDoc()->getMesh(meshid); + if (mm == NULL) + return; + for(int ii = 0; ii < mvc->viewerCounter();++ii) + { + + GLArea* glar = mvc->getViewer(ii); + if (glar != NULL) + { + QMap::const_iterator it =glar->rendermodemap.find(meshid); + if (it != NULL) + { + vcg::GLFeederInfo::ReqAtts reqattperglarea; + reqattperglarea = MLSceneRenderModeAdapter::convertUpdateMaskToMinimalReqAtts(updatemask,*mm,it.value()); + res = vcg::GLFeederInfo::ReqAtts::setUnion(res,reqattperglarea); + } + } + } + MLThreadSafeGLMeshAttributesFeeder* feed = mvc->sharedDataContext()->meshAttributesFeeder(meshid); + bool allocated; + feed->invalidateRequestedAttributes(res); + feed->setupRequestedAttributes(res,allocated); +} + +void MainWindow::deallocateNotMoreNecessaryPerMeshAndPerGLAreaRenderingDataConsideringAllOtherGLArea(const int meshid,GLArea* gla,const RenderMode& currentrendmode,const RenderMode& newrendermode) +{ + MultiViewer_Container* mvc = currentViewContainer(); + if ((meshDoc() == NULL) || (mvc == NULL)) + return; + if (gla == NULL) + return; + vcg::GLFeederInfo::ReqAtts oldatts; + MLSceneRenderModeAdapter::renderModeToReqAtts(currentrendmode,oldatts); + vcg::GLFeederInfo::ReqAtts newatts; + MLSceneRenderModeAdapter::renderModeToReqAtts(newrendermode,newatts); + oldatts = vcg::GLFeederInfo::ReqAtts::setComplement(oldatts,newatts); + for(int ii = 0; ii < mvc->viewerCounter();++ii) + { + GLArea* otherarea = mvc->getViewer(ii); + if ((otherarea != NULL) && (otherarea->getId() != gla->getId())) + { + vcg::GLFeederInfo::ReqAtts othermeshview; + MLSceneRenderModeAdapter::renderModeToReqAtts(otherarea->rendermodemap[meshid],othermeshview); + oldatts = vcg::GLFeederInfo::ReqAtts::setComplement(oldatts,othermeshview); + } + } + MLThreadSafeGLMeshAttributesFeeder* feed = mvc->sharedDataContext()->meshAttributesFeeder(meshid); + if (feed != NULL) + feed->deAllocateBO(oldatts); +} \ No newline at end of file