diff Framework/Viewport/SdlViewport.cpp @ 1216:5147277850cf broker

better abstraction for IViewport
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 05 Dec 2019 16:36:40 +0100
parents 86a8266b8888
children c04d0aa40f73
line wrap: on
line diff
--- a/Framework/Viewport/SdlViewport.cpp	Wed Dec 04 20:12:15 2019 +0100
+++ b/Framework/Viewport/SdlViewport.cpp	Thu Dec 05 16:36:40 2019 +0100
@@ -24,7 +24,33 @@
 
 namespace OrthancStone
 {
-  SdlViewport::SdlViewport()
+  ICompositor& SdlViewport::SdlLock::GetCompositor()
+  {
+    if (that_.compositor_.get() == NULL)
+    {
+      // The derived class should have called "AcquireCompositor()"
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+    }
+    else
+    {
+      return *that_.compositor_;
+    }
+  }
+
+
+  void SdlViewport::AcquireCompositor(ICompositor* compositor /* takes ownership */)
+  {
+    if (compositor == NULL)
+    {
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+    }
+
+    compositor_.reset(compositor);
+  }
+
+
+  SdlViewport::SdlViewport() :
+    controller_(new ViewportController)
   {
     refreshEvent_ = SDL_RegisterEvents(1);
     
@@ -50,29 +76,52 @@
                                        bool allowDpiScaling) :
     context_(title, width, height, allowDpiScaling)
   {
-    compositor_.reset(new OpenGLCompositor(context_));
+    AcquireCompositor(new OpenGLCompositor(context_));  // (*)
+  }
+
+
+  SdlOpenGLViewport::~SdlOpenGLViewport()
+  {
+    // Make sure that the "OpenGLCompositor" is destroyed BEFORE the
+    // "OpenGLContext" it references (*)
+    ClearCompositor();
+  }
+
+
+  void SdlOpenGLViewport::Paint()
+  {
+    SdlLock lock(*this);
+    lock.GetCompositor().Refresh(lock.GetController().GetScene());
   }
 
-  void SdlOpenGLViewport::Invalidate()
+
+  void SdlOpenGLViewport::UpdateSize(unsigned int width, 
+                                     unsigned int height)
   {
-    SendRefreshEvent();
+    // nothing to do in OpenGL, the OpenGLCompositor::UpdateSize will be called automatically
+    SdlLock lock(*this);
+    lock.Invalidate();
   }
 
-  void SdlOpenGLViewport::Paint(const Scene2D& scene)
+
+  void SdlOpenGLViewport::ToggleMaximize()
   {
-    boost::mutex::scoped_lock lock(mutex_);
-    compositor_->Refresh(scene);
+    // No need to call "Invalidate()" here, as "UpdateSize()" will
+    // be invoked after event "SDL_WINDOWEVENT_SIZE_CHANGED"
+    SdlLock lock(*this);
+    context_.ToggleMaximize();
   }
 
 
+
   SdlCairoViewport::SdlCairoViewport(const char* title,
                                      unsigned int width,
                                      unsigned int height,
                                      bool allowDpiScaling) :
     window_(title, width, height, false /* enable OpenGL */, allowDpiScaling),
-    compositor_(width, height),
     sdlSurface_(NULL)
   {
+    AcquireCompositor(new CairoCompositor(width, height));
   }
 
   SdlCairoViewport::~SdlCairoViewport()
@@ -83,50 +132,56 @@
     }
   }
   
-  void SdlCairoViewport::Paint(const Scene2D& scene)
+  void SdlCairoViewport::Paint()
   {
-    boost::mutex::scoped_lock lock(mutex_);
+    SdlLock lock(*this);
 
-    compositor_.Refresh(scene);
-    CreateSdlSurfaceFromCompositor();
+    lock.GetCompositor().Refresh(lock.GetController().GetScene());
+    CreateSdlSurfaceFromCompositor(dynamic_cast<CairoCompositor&>(lock.GetCompositor()));
     
     if (sdlSurface_ != NULL)
     {
       window_.Render(sdlSurface_);
-    }    
+    }
   }
 
-  void SdlCairoViewport::Invalidate()
-  {
-    SendRefreshEvent();
-  }
 
   void SdlCairoViewport::UpdateSize(unsigned int width,
                                     unsigned int height)
   {
-    {
-      boost::mutex::scoped_lock lock(mutex_);
-      compositor_.UpdateSize(width, height);
-    }
-
-    Invalidate();
+    SdlLock lock(*this);
+    dynamic_cast<CairoCompositor&>(lock.GetCompositor()).UpdateSize(width, height);
+    lock.Invalidate();
   }
   
-  void SdlCairoViewport::CreateSdlSurfaceFromCompositor()  // Assumes that the mutex is locked
+
+  void SdlCairoViewport::ToggleMaximize()
+  {
+    // No need to call "Invalidate()" here, as "UpdateSize()" will
+    // be invoked after event "SDL_WINDOWEVENT_SIZE_CHANGED"
+    SdlLock lock(*this);
+    window_.ToggleMaximize();
+  }
+
+  
+  // Assumes that the mutex is locked
+  void SdlCairoViewport::CreateSdlSurfaceFromCompositor(CairoCompositor& compositor)
   {
     static const uint32_t rmask = 0x00ff0000;
     static const uint32_t gmask = 0x0000ff00;
     static const uint32_t bmask = 0x000000ff;
 
-    const unsigned int width = compositor_.GetCanvas().GetWidth();
-    const unsigned int height = compositor_.GetCanvas().GetHeight();
+    const unsigned int width = compositor.GetCanvas().GetWidth();
+    const unsigned int height = compositor.GetCanvas().GetHeight();
+
+    printf("%dx%d\n", width, height);
     
     if (sdlSurface_ != NULL)
     {
-      if (sdlSurface_->pixels == compositor_.GetCanvas().GetBuffer() &&
+      if (sdlSurface_->pixels == compositor.GetCanvas().GetBuffer() &&
           sdlSurface_->w == static_cast<int>(width) &&
           sdlSurface_->h == static_cast<int>(height) &&
-          sdlSurface_->pitch == static_cast<int>(compositor_.GetCanvas().GetPitch()))
+          sdlSurface_->pitch == static_cast<int>(compositor.GetCanvas().GetPitch()))
       {
         // The image from the compositor has not changed, no need to update the surface
         return;
@@ -137,8 +192,8 @@
       }
     }
 
-    sdlSurface_ = SDL_CreateRGBSurfaceFrom((void*)(compositor_.GetCanvas().GetBuffer()), width, height, 32,
-                                           compositor_.GetCanvas().GetPitch(), rmask, gmask, bmask, 0);
+    sdlSurface_ = SDL_CreateRGBSurfaceFrom((void*)(compositor.GetCanvas().GetBuffer()), width, height, 32,
+                                           compositor.GetCanvas().GetPitch(), rmask, gmask, bmask, 0);
     if (!sdlSurface_)
     {
       LOG(ERROR) << "Cannot create a SDL surface from a Cairo surface";