mId( mSceneHolderCounter++ ),
mSurface( nullptr ),
mAdaptor( nullptr ),
+ mIsBeingDeleted( false ),
mAdaptorStarted( false ),
mVisible( true )
{
// EXTERNAL INCLUDES
#include <memory>
#include <vector>
+#include <atomic>
#include <dali/public-api/object/base-object.h>
#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/integration-api/scene.h>
*/
void Resume();
+ /**
+ * @brief Checks whether this scene holder is being deleted in the event thread.
+ *
+ * @return true if this scene holder is being deleted in the event thread, or false if not.
+ */
+ bool IsBeingDeleted() const { return mIsBeingDeleted; }
+
/**
* @copydoc Dali::Integration::SceneHolder::FeedTouchPoint
*/
Dali::Integration::TouchEventCombiner mCombiner; ///< Combines multi-touch events.
+ std::atomic<bool> mIsBeingDeleted; ///< This is set only from the event thread and read only from the render thread
+
bool mAdaptorStarted:1; ///< Whether the adaptor has started or not
bool mVisible:1; ///< Whether the scene is visible or not
};
return mConfigurationManager->IsMultipleWindowSupported();
}
+bool Adaptor::IsRenderingWindows() const
+{
+ return ( mThreadController && mThreadController->IsRenderingWindows() );
+}
+
void Adaptor::RequestUpdateOnce()
{
if( mThreadController )
*/
bool IsMultipleWindowSupported() const;
+ /**
+ * @brief Checks whether the windows are being rendered in the render thread.
+ *
+ * @return true if the windows are being rendered in the render thread, or false if not.
+ */
+ bool IsRenderingWindows() const;
+
public: //AdaptorInternalServices
/**
// EXTERNAL INCLUDES
#include <errno.h>
#include <dali/integration-api/platform-abstraction.h>
+#include <unistd.h>
// INTERNAL INCLUDES
#include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
mSurfaceResized( FALSE ),
mForceClear( FALSE ),
mUploadWithoutRendering( FALSE ),
- mFirstFrameAfterResume( FALSE )
+ mFirstFrameAfterResume( FALSE ),
+ mIsRenderingWindows( false )
{
LOG_EVENT_TRACE;
AddPerformanceMarker( PerformanceInterface::RENDER_START );
+ mIsRenderingWindows = true;
+
// Upload shared resources
mCore.PreRender( renderStatus, mForceClear, mUploadWithoutRendering );
WindowContainer windows;
mAdaptorInterfaces.GetWindowContainerInterface( windows );
- for ( auto&& iter = windows.begin(); iter != windows.end(); ++iter )
+ for( auto&& window : windows )
{
- if (*iter)
+ if ( window && !window->IsBeingDeleted() )
{
- Dali::Integration::Scene scene = (*iter)->GetScene();
+ Dali::Integration::Scene scene = window->GetScene();
+ Dali::RenderSurfaceInterface* windowSurface = window->GetSurface();
- (*iter)->GetSurface()->InitializeGraphics();
+ if ( scene && windowSurface )
+ {
+ windowSurface->InitializeGraphics();
- // Render off-screen frame buffers first if any
- mCore.RenderScene( scene, true );
+ // Render off-screen frame buffers first if any
+ mCore.RenderScene( scene, true );
- // Switch to the EGL context of the surface
- (*iter)->GetSurface()->PreRender( surfaceResized ); // Switch GL context
+ // Switch to the EGL context of the surface
+ windowSurface->PreRender( surfaceResized ); // Switch GL context
- // Render the surface
- mCore.RenderScene( scene, false );
+ // Render the surface
+ mCore.RenderScene( scene, false );
- (*iter)->GetSurface()->PostRender( false, false, surfaceResized ); // Swap Buffer
+ windowSurface->PostRender( false, false, surfaceResized ); // Swap Buffer
+ }
}
}
}
mCore.PostRender( mUploadWithoutRendering );
+ mIsRenderingWindows = false;
AddPerformanceMarker( PerformanceInterface::RENDER_END );
// EXTERNAL INCLUDES
#include <pthread.h>
#include <semaphore.h>
+#include <atomic>
#include <stdint.h>
#include <dali/devel-api/threading/conditional-wait.h>
#include <dali/integration-api/core.h>
*/
virtual void AddSurface( Dali::RenderSurfaceInterface* surface );
+ /**
+ * @copydoc ThreadControllerInterface::IsRenderingWindows()
+ */
+ bool IsRenderingWindows() const override { return mIsRenderingWindows; }
+
private:
// Undefined copy constructor.
volatile unsigned int mUploadWithoutRendering; ///< Will be set to upload the resource only (with no rendering)
volatile unsigned int mFirstFrameAfterResume; ///< Will be set to check the first frame after resume (for log)
+
+ std::atomic<bool> mIsRenderingWindows; ///< This is set only from the render thread and read only from the event thread
};
} // namespace Adaptor
*/
virtual void AddSurface( Dali::RenderSurfaceInterface* surface ) = 0;
+ /**
+ * @copydoc Dali::Adaptor::IsRenderingWindows()
+ */
+ virtual bool IsRenderingWindows() const = 0;
+
protected:
/**
mThreadControllerInterface->AddSurface( newSurface );
}
+bool ThreadController::IsRenderingWindows() const
+{
+ return mThreadControllerInterface->IsRenderingWindows();
+}
+
} // namespace Adaptor
} // namespace Internal
*/
void AddSurface( Dali::RenderSurfaceInterface* surface );
+ /**
+ * @copydoc Dali::Adaptor::IsRenderingWindows()
+ */
+ bool IsRenderingWindows() const;
+
private:
// Undefined copy constructor.
#include <dali/internal/window-system/common/window-impl.h>
// EXTERNAL HEADERS
+#include <thread>
#include <dali/integration-api/core.h>
#include <dali/public-api/actors/actor.h>
#include <dali/public-api/actors/layer.h>
Window::~Window()
{
+ mIsBeingDeleted = true;
+
+ while ( mAdaptor && mAdaptor->IsRenderingWindows() )
+ {
+ std::this_thread::yield(); // to allow other threads to run
+ }
+
if ( mEventHandler )
{
mEventHandler->RemoveObserver( *this );