Merge branch 'devel/master' into tizen
authorSeungho, Baek <sbsh.baek@samsung.com>
Mon, 15 Jul 2019 05:58:47 +0000 (14:58 +0900)
committerSeungho, Baek <sbsh.baek@samsung.com>
Mon, 15 Jul 2019 05:58:47 +0000 (14:58 +0900)
24 files changed:
dali/devel-api/adaptor-framework/file-stream.cpp [new file with mode: 0644]
dali/devel-api/adaptor-framework/file-stream.h [new file with mode: 0644]
dali/devel-api/file.list
dali/integration-api/scene-holder-impl.cpp
dali/internal/adaptor-framework/common/file-stream-impl.h [new file with mode: 0644]
dali/internal/adaptor-framework/file.list
dali/internal/adaptor-framework/generic/file-stream-impl-generic.cpp [new file with mode: 0644]
dali/internal/adaptor/common/adaptor-impl.cpp
dali/internal/adaptor/common/adaptor-impl.h
dali/internal/adaptor/common/combined-update-render-controller.cpp
dali/internal/adaptor/common/combined-update-render-controller.h
dali/internal/adaptor/common/thread-controller-interface.h
dali/internal/system/common/color-controller-impl.cpp
dali/internal/system/common/file-reader.h
dali/internal/system/common/file-writer.h
dali/internal/system/common/thread-controller.cpp
dali/internal/system/common/thread-controller.h
dali/internal/text/text-abstraction/cairo-renderer.cpp
dali/internal/window-system/common/window-impl.cpp
dali/internal/window-system/common/window-render-surface.cpp
dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp
dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp
dali/public-api/dali-adaptor-version.cpp
packaging/dali-adaptor.spec

diff --git a/dali/devel-api/adaptor-framework/file-stream.cpp b/dali/devel-api/adaptor-framework/file-stream.cpp
new file mode 100644 (file)
index 0000000..f6528e4
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/adaptor-framework/file-stream.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/internal/adaptor-framework/common/file-stream-impl.h>
+
+namespace Dali
+{
+
+FileStream::FileStream(const std::string& filename, uint8_t mode)
+{
+  mImpl.reset( new Impl( filename, mode ) );
+}
+
+FileStream::FileStream(uint8_t* buffer, size_t dataSize, uint8_t mode)
+{
+  mImpl.reset( new Impl( buffer, dataSize, mode ) );
+}
+
+FileStream::FileStream(Dali::Vector<uint8_t>& buffer, size_t dataSize, uint8_t mode)
+{
+  mImpl.reset( new Impl( buffer, dataSize, mode ) );
+}
+
+FileStream::~FileStream() = default;
+
+FileStream& FileStream::operator=(FileStream&&) = default;
+
+std::iostream& FileStream::GetStream()
+{
+  return mImpl->GetStream();
+}
+
+FILE* FileStream::GetFile()
+{
+  return mImpl->GetFile();
+}
+
+} // Dali
diff --git a/dali/devel-api/adaptor-framework/file-stream.h b/dali/devel-api/adaptor-framework/file-stream.h
new file mode 100644 (file)
index 0000000..8fa9999
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef DALI_FILE_STREAM_H
+#define DALI_FILE_STREAM_H
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <stdio.h>
+#include <stdint.h>
+
+#include <iostream>
+#include <string>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/dali-adaptor-common.h>
+
+namespace Dali
+{
+
+class DALI_ADAPTOR_API FileStream
+{
+public:
+
+  /**
+   * @brief File type formats
+   * The default format is binary
+   */
+  enum FileMode  ///< FileType format
+  {
+    BINARY = 0x1,      ///< File stream will be opened as a binary
+    TEXT   = 0x2,      ///< File stream will be opened as text
+    READ   = 0x4,      ///< File stream will be opened for reading
+    WRITE  = 0x8,      ///< File stream will be opende for writing
+  };
+
+  /**
+   * Constructor
+   * @param[in] filename Filename of the file to open the stream for
+   * @param[in] mode How we want to open the stream. Binary or Text, Read or Write. Binary & Read default
+   */
+  FileStream(const std::string& filename, uint8_t mode = BINARY | READ);
+
+  /**
+   * Constructor
+   * @param[in] buffer Buffer to open the stream for.
+   *                   The buffer is not owned by FileStream and must be valid for entire lifetime of FileStream
+   * @param[in] dataSize The maximum size of the data in the buffer.
+   * @param[in] mode How we want to open the stream. Binary or Text, Read or Write. Binary & Read default
+   */
+  FileStream(uint8_t* buffer, size_t dataSize, uint8_t mode = BINARY | READ);
+
+  /**
+   * Constructor
+   * @param[in] buffer Buffer to open the stream for.
+   *                   The buffer is not owned by FileStream and must be valid for entire lifetime of FileStream
+   * @param[in] dataSize The maximum size of the data in the buffer.
+   * @param[in] mode How we want to open the stream. Binary or Text, Read or Write. Binary & Read default
+   */
+  FileStream(Dali::Vector<uint8_t>& buffer, size_t dataSize, uint8_t mode = BINARY | READ);
+
+  /**
+   * Default move constructor
+   */
+  FileStream(FileStream&&) = default;
+
+  /**
+   * Non copyable
+   */
+  FileStream(const FileStream&) = delete;
+
+  /**
+   * Non assignable
+   */
+  FileStream& operator=(const FileStream&) = delete;
+
+  /**
+   * Move assignable
+   */
+  FileStream& operator=(FileStream&&);
+
+  /**
+   * Destructor
+   */
+  ~FileStream();
+
+  /**
+   * @brief Returns the stream
+   * @return std::iostream.
+   */
+  std::iostream& GetStream();
+
+  /**
+   * @brief Returns the file stream
+   * @return FILE.
+   */
+  FILE* GetFile();
+
+private:
+
+  struct Impl;
+  std::unique_ptr<Impl> mImpl;
+};
+
+} // Dali
+
+#endif // DALI_FILE_STREAM_H
index e0495d7..19a2bbd 100755 (executable)
@@ -10,6 +10,7 @@ devel_api_src_files = \
   $(adaptor_devel_api_dir)/adaptor-framework/event-thread-callback.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/feedback-player.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/file-loader.cpp \
+  $(adaptor_devel_api_dir)/adaptor-framework/file-stream.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/image-loading.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/gif-loading.cpp \
   $(adaptor_devel_api_dir)/adaptor-framework/input-method-context.cpp \
@@ -51,6 +52,7 @@ devel_api_adaptor_framework_header_files = \
   $(adaptor_devel_api_dir)/adaptor-framework/feedback-plugin.h \
   $(adaptor_devel_api_dir)/adaptor-framework/feedback-player.h \
   $(adaptor_devel_api_dir)/adaptor-framework/file-loader.h \
+  $(adaptor_devel_api_dir)/adaptor-framework/file-stream.h \
   $(adaptor_devel_api_dir)/adaptor-framework/image-loader-input.h \
   $(adaptor_devel_api_dir)/adaptor-framework/image-loader-plugin.h \
   $(adaptor_devel_api_dir)/adaptor-framework/image-loading.h \
index 64d0a42..491c5b4 100644 (file)
@@ -131,6 +131,9 @@ SceneHolder::~SceneHolder()
   {
     mAdaptor->RemoveObserver( *mLifeCycleObserver.get() );
     mAdaptor->RemoveWindow( this );
+
+    mAdaptor->DeleteSurface( *mSurface.get() );
+
     mAdaptor = nullptr;
   }
 
diff --git a/dali/internal/adaptor-framework/common/file-stream-impl.h b/dali/internal/adaptor-framework/common/file-stream-impl.h
new file mode 100644 (file)
index 0000000..8b4e3ae
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef DALI_FILE_STREAM_IMPL_GENERIC_H
+#define DALI_FILE_STREAM_IMPL_GENERIC_H
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/file-stream.h>
+#include <fstream>
+#include <sstream>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+class FileStream::Impl
+{
+public:
+  Impl(const std::string& filename, uint8_t mode);
+
+  Impl(uint8_t* buffer, size_t dataSize, uint8_t mode);
+
+  Impl(Dali::Vector<uint8_t>& buffer, size_t dataSize, uint8_t mode);
+
+  ~Impl();
+
+  std::iostream& GetStream();
+
+  FILE* GetFile();
+
+private:
+  std::string mFileName;
+  uint8_t mMode;
+  uint8_t* mBuffer; // external buffer, not owned
+  size_t mDataSize;
+
+  Dali::Vector<char> mFileBuffer; // for internal usage only
+  FILE* mFile;
+  std::fstream mFileStream;
+  std::stringstream mBufferStream;
+};
+
+} // Dali
+
+#endif // DALI_FILE_STREAM_IMPL_GENERIC_H
index 443056e..c818283 100644 (file)
@@ -1,3 +1,4 @@
 # module: adaptor-framework, backend: generic
 adaptor_framework_generic_src_files=\
-    ${adaptor_framework_dir}/generic/file-loader-impl-generic.cpp
+    ${adaptor_framework_dir}/generic/file-loader-impl-generic.cpp \
+    ${adaptor_framework_dir}/generic/file-stream-impl-generic.cpp
diff --git a/dali/internal/adaptor-framework/generic/file-stream-impl-generic.cpp b/dali/internal/adaptor-framework/generic/file-stream-impl-generic.cpp
new file mode 100644 (file)
index 0000000..7273b94
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/internal/adaptor-framework/common/file-stream-impl.h>
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <fstream>
+
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+FileStream::Impl::Impl(const std::string& filename, uint8_t mode)
+: mFileName( filename ),
+  mMode( mode ),
+  mBuffer( nullptr ),
+  mDataSize( 0 ),
+  mFile( nullptr )
+{
+  DALI_ASSERT_DEBUG( !filename.empty() && "Can't open a empty filename." );
+  DALI_ASSERT_DEBUG( mode != 0 && "No mode is undefined behaviour" );
+}
+
+FileStream::Impl::Impl(uint8_t* buffer, size_t dataSize, uint8_t mode)
+: mMode( mode ),
+  mBuffer( buffer ),
+  mDataSize( dataSize ),
+  mFile( nullptr )
+{
+  DALI_ASSERT_DEBUG( buffer != 0 && "Can't open file on null buffer." );
+  DALI_ASSERT_DEBUG( dataSize > 0 && "Pointless to open file on empty buffer." );
+  DALI_ASSERT_DEBUG( mode != 0 && "No mode is undefined behaviour." );
+}
+
+FileStream::Impl::Impl(Dali::Vector<uint8_t>& vector, size_t dataSize, uint8_t mode)
+: mMode( mode ),
+  mBuffer( nullptr ),
+  mDataSize( dataSize ),
+  mFile( nullptr )
+{
+  // Resize the buffer to ensure any null that gets written by
+  // fmemopen is written past the end of any data that is written to the buffer.
+  // (Workaround for a bug in Ubuntu that overwrites null to the last byte of the
+  // data block regardless of whether binary mode was specified. Tizen doesn't write
+  // null if binary mode is specified).
+
+  ++mDataSize;
+  vector.Resize( mDataSize );
+  mBuffer = &vector[0];
+
+  DALI_ASSERT_DEBUG( mBuffer != nullptr && "Can't open file on null buffer." );
+  DALI_ASSERT_DEBUG( dataSize > 0 && "Pointless to open file on empty buffer." );
+  DALI_ASSERT_DEBUG( mode != 0 && "No mode is undefined behaviour." );
+}
+
+FileStream::Impl::~Impl()
+{
+  if( mFile )
+  {
+    const int closeFailed = fclose( mFile );
+    if( closeFailed )
+    {
+      DALI_LOG_WARNING( "File close failed for FILE: \"%p\".\n", static_cast<void*>( mFile ) );
+    }
+
+    mFile = nullptr;
+  }
+
+  if( mFileStream.is_open() )
+  {
+    mFileStream.close();
+  }
+}
+
+std::iostream& FileStream::Impl::GetStream()
+{
+  if( mFile )
+  {
+    // return empty stream if FILE stream is open to avoid simultaneous access to the same file
+    return mFileStream;
+  }
+
+  if( mFileStream.is_open() )
+  {
+    return mFileStream;
+  }
+
+  if( mBufferStream.rdbuf()->in_avail() )
+  {
+    return mBufferStream;
+  }
+
+  std::ios_base::openmode openMode = std::ios::ate;
+  if( mMode & Dali::FileStream::BINARY )
+  {
+    openMode |= std::ios::binary;
+  }
+
+  if( mMode & Dali::FileStream::WRITE )
+  {
+    openMode |= std::ios::out;
+  }
+  else
+  {
+    openMode |= std::ios::in;
+  }
+
+  if( !mFileName.empty() )
+  {
+    mFileStream.open( mFileName, openMode );
+    if( !mFileStream.is_open() )
+    {
+      DALI_LOG_WARNING( "stream open failed for: \"%s\", in mode: \"%d\".\n", mFileName, static_cast<int>( openMode ) );
+    }
+    return mFileStream;
+  }
+  else if( mBuffer )
+  {
+    mBufferStream.rdbuf()->pubsetbuf( reinterpret_cast<char*>( mBuffer ), mDataSize );
+    if( !mBufferStream.rdbuf()->in_avail() )
+    {
+      DALI_LOG_WARNING( "File open failed for memory buffer at location: \"%p\", of size: \"%u\", in mode: \"%d\".\n",
+          static_cast<void*>( mBuffer ), static_cast<unsigned>( mDataSize ), static_cast<int>( openMode ) );
+    }
+  }
+
+  return mBufferStream;
+}
+
+FILE* FileStream::Impl::GetFile()
+{
+  if( mFileStream.is_open() || mBufferStream.rdbuf()->in_avail() )
+  {
+    // return empty FILE stream if the stream is open to avoid simultaneous access to the same file
+    return nullptr;
+  }
+
+  if( mFile )
+  {
+    return mFile;
+  }
+
+  char openMode[16] = { 0 };
+  int i = 0;
+
+  if( mMode & Dali::FileStream::WRITE )
+  {
+    openMode[i++] = 'w';
+  }
+  else
+  {
+    openMode[i++] = 'r';
+  }
+
+  if( mMode & Dali::FileStream::BINARY )
+  {
+    openMode[i++] = 'b';
+  }
+
+  openMode[i++] = 0;
+
+  if( !mFileName.empty() )
+  {
+    mFile = fopen( mFileName.c_str(), openMode );
+    if( !mFile )
+    {
+      DALI_LOG_WARNING( "file open failed for: \"%s\", in mode: \"%s\".\n", mFileName, openMode );
+    }
+  }
+  else if( mBuffer )
+  {
+    mFile = fmemopen( mBuffer, mDataSize, openMode );
+    if( !mFile )
+    {
+      DALI_LOG_WARNING( "File open failed for memory buffer at location: \"%p\", of size: \"%u\", in mode: \"%s\".\n",
+          static_cast<void*>( mBuffer ), static_cast<unsigned>( mDataSize ), openMode );
+    }
+  }
+
+  return mFile;
+}
+
+} // Dali
index d1c1a5d..a4ab857 100755 (executable)
@@ -523,6 +523,16 @@ void Adaptor::ReplaceSurface( Dali::Integration::SceneHolder window, Dali::Rende
   }
 }
 
+void Adaptor::DeleteSurface( Dali::RenderSurfaceInterface& surface )
+{
+  // Flush the event queue to give the update-render thread chance
+  // to start processing messages for new camera setup etc as soon as possible
+  ProcessCoreEvents();
+
+  // This method blocks until the render thread has finished rendering the current surface.
+  mThreadController->DeleteSurface( &surface );
+}
+
 Dali::RenderSurfaceInterface& Adaptor::GetSurface() const
 {
   return *mWindows.front()->GetSurface();
index 37a7438..a716bea 100755 (executable)
@@ -295,6 +295,12 @@ public: // AdaptorInternalServices implementation
   bool RemoveWindow( Dali::Internal::Adaptor::SceneHolder* childWindow );
 
   /**
+   * @brief Deletes the rendering surface
+   * @param[in] surface to delete
+   */
+  void DeleteSurface( Dali::RenderSurfaceInterface& surface );
+
+  /**
    * @brief Retrieve the window that the given actor is added to.
    *
    * @param[in] actor The actor
index 4486766..aae3340 100644 (file)
@@ -112,6 +112,7 @@ CombinedUpdateRenderController::CombinedUpdateRenderController( AdaptorInternalS
   mPendingRequestUpdate( FALSE ),
   mUseElapsedTimeAfterWait( FALSE ),
   mNewSurface( NULL ),
+  mDeletedSurface( nullptr ),
   mPostRendering( FALSE ),
   mSurfaceResized( FALSE ),
   mForceClear( FALSE )
@@ -294,23 +295,49 @@ void CombinedUpdateRenderController::ReplaceSurface( Dali::RenderSurfaceInterfac
 {
   LOG_EVENT_TRACE;
 
-  // Set the ThreadSyncronizationInterface on the new surface
-  newSurface->SetThreadSynchronization( *this );
+  if( mUpdateRenderThread )
+  {
+    // Set the ThreadSyncronizationInterface on the new surface
+    newSurface->SetThreadSynchronization( *this );
 
-  LOG_EVENT( "Starting to replace the surface, event-thread blocked" );
+    LOG_EVENT( "Starting to replace the surface, event-thread blocked" );
 
-  // Start replacing the surface.
-  {
-    ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
-    mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will replace the surface now
-    mNewSurface = newSurface;
-    mUpdateRenderThreadWaitCondition.Notify( lock );
+    // Start replacing the surface.
+    {
+      ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
+      mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will replace the surface now
+      mNewSurface = newSurface;
+      mUpdateRenderThreadWaitCondition.Notify( lock );
+    }
+
+    // Wait until the surface has been replaced
+    sem_wait( &mEventThreadSemaphore );
+
+    LOG_EVENT( "Surface replaced, event-thread continuing" );
   }
+}
 
-  // Wait until the surface has been replaced
-  sem_wait( &mEventThreadSemaphore );
+void CombinedUpdateRenderController::DeleteSurface( Dali::RenderSurfaceInterface* surface )
+{
+  LOG_EVENT_TRACE;
+
+  if( mUpdateRenderThread )
+  {
+    LOG_EVENT( "Starting to delete the surface, event-thread blocked" );
+
+    // Start replacing the surface.
+    {
+      ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
+      mPostRendering = FALSE; // Clear the post-rendering flag as Update/Render thread will delete the surface now
+      mDeletedSurface = surface;
+      mUpdateRenderThreadWaitCondition.Notify( lock );
+    }
+
+    // Wait until the surface has been deleted
+    sem_wait( &mEventThreadSemaphore );
 
-  LOG_EVENT( "Surface replaced, event-thread continuing" );
+    LOG_EVENT( "Surface deleted, event-thread continuing" );
+  }
 }
 
 void CombinedUpdateRenderController::ResizeSurface()
@@ -608,6 +635,21 @@ void CombinedUpdateRenderController::UpdateRenderThread()
 
     AddPerformanceMarker( PerformanceInterface::RENDER_START );
     mCore.Render( renderStatus, mForceClear );
+
+    //////////////////////////////
+    // DELETE SURFACE
+    //////////////////////////////
+
+    Integration::RenderSurface* deletedSurface = ShouldSurfaceBeDeleted();
+    if( DALI_UNLIKELY( deletedSurface ) )
+    {
+      LOG_UPDATE_RENDER_TRACE_FMT( "Deleting Surface" );
+
+      mCore.SurfaceDeleted( deletedSurface );
+
+      SurfaceDeleted();
+    }
+
     AddPerformanceMarker( PerformanceInterface::RENDER_END );
 
     mForceClear = false;
@@ -692,12 +734,14 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bo
            ( mUpdateRenderThreadCanSleep && ! updateRequired && ! mPendingRequestUpdate ) ) && // Ensure we wait if we're supposed to be sleeping AND do not require another update
          ! mDestroyUpdateRenderThread && // Ensure we don't wait if the update-render-thread is supposed to be destroyed
          ! mNewSurface &&  // Ensure we don't wait if we need to replace the surface
+         ! mDeletedSurface && // Ensure we don't wait if we need to delete the surface
          ! mSurfaceResized ) // Ensure we don't wait if we need to resize the surface
   {
     LOG_UPDATE_RENDER( "WAIT: mUpdateRenderRunCount:       %d", mUpdateRenderRunCount );
     LOG_UPDATE_RENDER( "      mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate );
     LOG_UPDATE_RENDER( "      mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread );
     LOG_UPDATE_RENDER( "      mNewSurface:                 %d", mNewSurface );
+    LOG_UPDATE_RENDER( "      mDeletedSurface:             %d", mDeletedSurface );
     LOG_UPDATE_RENDER( "      mSurfaceResized:             %d", mSurfaceResized );
 
     // Reset the time when the thread is waiting, so the sleep-until time for
@@ -717,6 +761,7 @@ bool CombinedUpdateRenderController::UpdateRenderReady( bool& useElapsedTime, bo
   LOG_COUNTER_UPDATE_RENDER( "mUpdateRenderThreadCanSleep: %d, updateRequired: %d, mPendingRequestUpdate: %d", mUpdateRenderThreadCanSleep, updateRequired, mPendingRequestUpdate );
   LOG_COUNTER_UPDATE_RENDER( "mDestroyUpdateRenderThread:  %d", mDestroyUpdateRenderThread );
   LOG_COUNTER_UPDATE_RENDER( "mNewSurface:                 %d", mNewSurface );
+  LOG_COUNTER_UPDATE_RENDER( "mDeletedSurface:             %d", mDeletedSurface );
   LOG_COUNTER_UPDATE_RENDER( "mSurfaceResized:             %d", mSurfaceResized );
 
   mUseElapsedTimeAfterWait = FALSE;
@@ -750,6 +795,22 @@ void CombinedUpdateRenderController::SurfaceReplaced()
   sem_post( &mEventThreadSemaphore );
 }
 
+Integration::RenderSurface* CombinedUpdateRenderController::ShouldSurfaceBeDeleted()
+{
+  ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
+
+  Integration::RenderSurface* deletedSurface = mDeletedSurface;
+  mDeletedSurface = NULL;
+
+  return deletedSurface;
+}
+
+void CombinedUpdateRenderController::SurfaceDeleted()
+{
+  // Just increment the semaphore
+  sem_post( &mEventThreadSemaphore );
+}
+
 bool CombinedUpdateRenderController::ShouldSurfaceBeResized()
 {
   ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
@@ -806,6 +867,7 @@ void CombinedUpdateRenderController::PostRenderWaitForCompletion()
   ConditionalWait::ScopedLock lock( mUpdateRenderThreadWaitCondition );
   while( mPostRendering &&
          ! mNewSurface &&                // We should NOT wait if we're replacing the surface
+         ! mDeletedSurface &&            // We should NOT wait if we're deleting the surface
          ! mSurfaceResized &&            // We should NOT wait if we're resizing the surface
          ! mDestroyUpdateRenderThread )
   {
index a8cb5f2..41f519c 100644 (file)
@@ -127,6 +127,11 @@ public:
   virtual void ReplaceSurface( Dali::RenderSurfaceInterface* surface );
 
   /**
+   * @copydoc ThreadControllerInterface::DeleteSurface()
+   */
+  virtual void DeleteSurface( Dali::RenderSurfaceInterface* surface );
+
+  /**
    * @copydoc ThreadControllerInterface::ResizeSurface()
    */
   virtual void ResizeSurface();
@@ -227,6 +232,21 @@ private:
   void SurfaceReplaced();
 
   /**
+   * Checks to see if the surface needs to be deleted.
+   * This will lock the mutex in mUpdateRenderThreadWaitCondition.
+   *
+   * @return Pointer to the deleted surface, nullptr otherwise
+   */
+  Integration::RenderSurface* ShouldSurfaceBeDeleted();
+
+  /**
+   * Called by the Update/Render thread after a surface has been deleted.
+   *
+   * This will lock the mutex in mEventThreadWaitCondition
+   */
+  void SurfaceDeleted();
+
+  /**
    * Checks to see if the surface needs to be resized.
    * This will lock the mutex in mUpdateRenderThreadWaitCondition.
    *
@@ -336,6 +356,7 @@ private:
   volatile unsigned int             mUseElapsedTimeAfterWait;          ///< Whether we should use the elapsed time after waiting (set by the event-thread, read by the update-render-thread).
 
   Integration::RenderSurface* volatile mNewSurface;                    ///< Will be set to the new-surface if requested (set by the event-thread, read & cleared by the update-render thread).
+  Integration::RenderSurface* volatile mDeletedSurface;                ///< Will be set to the deleted surface if requested (set by the event-thread, read & cleared by the update-render thread).
 
   volatile unsigned int             mPostRendering;                    ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
   volatile unsigned int             mSurfaceResized;                   ///< Will be set to resize the surface (set by the event-thread, read & cleared by the update-render thread).
index d805ced..751dceb 100644 (file)
@@ -86,6 +86,12 @@ public:
   virtual void ReplaceSurface( Dali::RenderSurfaceInterface* surface ) = 0;
 
   /**
+   * Deletes the surface.
+   * @param[in] surface The surface to be deleted
+   */
+  virtual void DeleteSurface( Dali::RenderSurfaceInterface* surface ) = 0;
+
+  /**
    * Resize the surface.
    */
   virtual void ResizeSurface() = 0;
index c0e8874..b8cf94d 100644 (file)
@@ -74,6 +74,16 @@ ColorController::ColorController()
 
 ColorController::~ColorController()
 {
+  if( mPlugin )
+  {
+    delete mPlugin;
+    mPlugin = NULL;
+
+    if( mLibHandle && dlclose( mLibHandle ) )
+    {
+      DALI_LOG_ERROR( "Error closing color controller plugin library: %s\n", dlerror() );
+    }
+  }
 }
 
 void ColorController::Initialize()
index 0893571..0b87fe3 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 // INTERNAL INCLUDES
-#include <dali/internal/system/common/file-closer.h>
+#include <dali/devel-api/adaptor-framework/file-stream.h>
 
 // EXTERNAL INCLUDES
 
@@ -29,26 +29,26 @@ namespace Internal
 namespace Platform
 {
 
-class FileReader : public FileCloser
+class FileReader : public FileStream
 {
 public:
   FileReader( const std::string& filename )
-  : FileCloser( filename.c_str(), "rb" )
+  : FileStream( filename, FileStream::READ | FileStream::BINARY )
   {
   }
 
   FileReader( Dali::Vector<uint8_t>& vector )
-  : FileCloser( &vector[0], vector.Size(), "rb" )
+  : FileStream( &vector[0], vector.Size(), FileStream::READ | FileStream::BINARY )
   {
   }
 
   FileReader( Dali::Vector<uint8_t>& vector, size_t dataSize )
-  : FileCloser( &vector[0], dataSize, "rb" )
+  : FileStream( &vector[0], dataSize, FileStream::READ | FileStream::BINARY )
   {
   }
 
   FileReader( uint8_t* data, size_t dataSize )
-  : FileCloser( data, dataSize, "rb" )
+  : FileStream( data, dataSize, FileStream::READ | FileStream::BINARY )
   {
   }
 };
index da62c9c..6bc0c0c 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 // INTERNAL INCLUDES
-#include <dali/internal/system/common/file-closer.h>
+#include <dali/devel-api/adaptor-framework/file-stream.h>
 
 // EXTERNAL INCLUDES
 
@@ -29,7 +29,7 @@ namespace Internal
 namespace Platform
 {
 
-class FileWriter : public FileCloser
+class FileWriter : public FileStream
 {
 public:
   /**
@@ -39,7 +39,7 @@ public:
    * @param[in] dataSize the amount of data to be written
    */
   FileWriter( Dali::Vector<uint8_t>& vector, size_t dataSize )
-  : FileCloser( vector, dataSize, "wb" )
+  : FileStream( vector, dataSize, FileStream::WRITE | FileStream::BINARY )
   {
   }
 };
index 3d70efe..ac7e49e 100644 (file)
@@ -90,6 +90,11 @@ void ThreadController::ReplaceSurface( Dali::RenderSurfaceInterface* newSurface
   mThreadControllerInterface->ReplaceSurface( newSurface );
 }
 
+void ThreadController::DeleteSurface( Dali::RenderSurfaceInterface* surface )
+{
+  mThreadControllerInterface->DeleteSurface( surface );
+}
+
 void ThreadController::ResizeSurface()
 {
   mThreadControllerInterface->ResizeSurface();
index 8e13370..4a7b81e 100644 (file)
@@ -108,6 +108,12 @@ public:
   void ReplaceSurface( Dali::RenderSurfaceInterface* surface );
 
   /**
+   * Deletes the surface.
+   * @param surface The surface to be deleted
+   */
+  void DeleteSurface( Dali::RenderSurfaceInterface* surface );
+
+  /**
    * Resize the surface.
    */
   void ResizeSurface();
index bf062ef..99d951d 100755 (executable)
@@ -234,6 +234,30 @@ Devel::PixelBuffer RenderTextCairo( const TextAbstraction::TextRenderer::Paramet
     return CreateVoidPixelBuffer( parameters );
   }
 
+  // Choose the pixel format to be used.
+  //
+  // @note Behdad wrote "Upper 8 bits maps to the fourth byte in a little-endian machine like the intels."
+  //       https://lists.cairographics.org/archives/cairo/2006-March/006563.html
+  //
+  //       Here in practice Cairo's ARGB32 is like DALi's RGBA8888.
+  //
+  const bool isDstRgba = TextAbstraction::TextRenderer::Parameters::RGBA8888 == parameters.pixelFormat;
+  const Pixel::Format pixelFormat = isDstRgba ? Pixel::Format::RGBA8888 : Pixel::Format::A8;
+  const cairo_format_t cairoFormat = isDstRgba ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A8;
+
+  const int bpp = Pixel::GetBytesPerPixel( pixelFormat );
+  if( 0u == bpp )
+  {
+    // return a pixel buffer with all pixels set to transparent.
+    return CreateVoidPixelBuffer( parameters );
+  }
+
+  // This function provides a stride value that will respect all alignment requirements of the
+  // accelerated image-rendering code within cairo.
+  const int stride = cairo_format_stride_for_width( cairoFormat,
+                                                    static_cast<int>( parameters.width ) );
+  const int strideWidth = stride / bpp;
+
   // Convert from DALi glyphs to Cairo glyphs.
   std::vector<cairo_glyph_t> cairoGlyphs;
   cairoGlyphs.resize( numberOfGlyphs );
@@ -371,23 +395,6 @@ Devel::PixelBuffer RenderTextCairo( const TextAbstraction::TextRenderer::Paramet
     glyphRuns.push_back( currentGlyphRun );
   }
 
-  // Choose the pixel format to be used.
-  //
-  // @note Behdad wrote "Upper 8 bits maps to the fourth byte in a little-endian machine like the intels."
-  //       https://lists.cairographics.org/archives/cairo/2006-March/006563.html
-  //
-  //       Here in practice Cairo's ARGB32 is like DALi's RGBA8888.
-  //
-  const bool isDstRgba = TextAbstraction::TextRenderer::Parameters::RGBA8888 == parameters.pixelFormat;
-  const Pixel::Format pixelFormat = isDstRgba ? Pixel::Format::RGBA8888 : Pixel::Format::A8;
-  const cairo_format_t cairoFormat = isDstRgba ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_A8;
-
-  // This function provides a stride value that will respect all alignment requirements of the
-  // accelerated image-rendering code within cairo.
-  const int stride = cairo_format_stride_for_width( cairoFormat,
-                                                    static_cast<int>( parameters.width ) );
-  const int strideWidth = stride / Pixel::GetBytesPerPixel( pixelFormat );
-
   // Creates the pixel buffer and retrieves the buffer pointer used to create the Cairo's surface.
   Devel::PixelBuffer pixelBuffer = Devel::PixelBuffer::New( strideWidth, parameters.height, pixelFormat );
 
index 568b79a..981ede0 100644 (file)
@@ -164,16 +164,19 @@ std::string Window::GetClassName() const
 void Window::Raise()
 {
   mWindowBase->Raise();
+  DALI_LOG_RELEASE_INFO( "Window (%p) Raise() \n", this );
 }
 
 void Window::Lower()
 {
   mWindowBase->Lower();
+  DALI_LOG_RELEASE_INFO( "Window (%p) Lower() \n", this );
 }
 
 void Window::Activate()
 {
   mWindowBase->Activate();
+  DALI_LOG_RELEASE_INFO( "Window (%p) Activate() \n", this );
 }
 
 uint32_t Window::GetLayerCount() const
index 18ae128..f9eb552 100644 (file)
@@ -83,6 +83,11 @@ WindowRenderSurface::~WindowRenderSurface()
   {
     delete mRotationTrigger;
   }
+
+  if ( mEGLSurface )
+  {
+    DestroySurface();
+  }
 }
 
 void WindowRenderSurface::Initialize( Any surface )
index dd35dcb..54004b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -76,6 +76,11 @@ NativeRenderSurfaceEcoreWl::NativeRenderSurfaceEcoreWl( Dali::PositionSize posit
 
 NativeRenderSurfaceEcoreWl::~NativeRenderSurfaceEcoreWl()
 {
+  if ( mEGLSurface )
+  {
+    DestroySurface();
+  }
+
   // release the surface if we own one
   if( mOwnSurface )
   {
index c8e049c..514b049 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -81,6 +81,8 @@ PixmapRenderSurfaceEcoreX::PixmapRenderSurfaceEcoreX( Dali::PositionSize positio
 
 PixmapRenderSurfaceEcoreX::~PixmapRenderSurfaceEcoreX()
 {
+  DestroySurface();
+
   // release the surface if we own one
   if( mOwnSurface )
   {
index db393bc..d14a81a 100644 (file)
@@ -28,7 +28,7 @@ namespace Dali
 
 const unsigned int ADAPTOR_MAJOR_VERSION = 1;
 const unsigned int ADAPTOR_MINOR_VERSION = 4;
-const unsigned int ADAPTOR_MICRO_VERSION = 27;
+const unsigned int ADAPTOR_MICRO_VERSION = 28;
 const char * const ADAPTOR_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index a782e95..036d6be 100644 (file)
@@ -17,7 +17,7 @@
 
 Name:       dali-adaptor
 Summary:    The DALi Tizen Adaptor
-Version:    1.4.27
+Version:    1.4.28
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT