Added Atlas::Upload(url) support 03/36203/14
authorXiangyin Ma <x1.ma@samsung.com>
Tue, 3 Mar 2015 11:18:42 +0000 (11:18 +0000)
committerXiangyin Ma <x1.ma@samsung.com>
Tue, 10 Mar 2015 17:48:30 +0000 (10:48 -0700)
Change-Id: I8cf65c95838dae55c10de77c54b5ef33b86f318a

15 files changed:
automated-tests/src/dali/utc-Dali-Atlas.cpp
dali/internal/event/images/atlas-impl.cpp
dali/internal/event/images/atlas-impl.h
dali/internal/event/images/context-recovery-interface.h [new file with mode: 0644]
dali/internal/event/images/image-factory.cpp
dali/internal/event/images/image-factory.h
dali/internal/event/resources/resource-client.cpp
dali/internal/event/resources/resource-client.h
dali/internal/render/common/texture-cache-dispatcher.h
dali/internal/render/gl-resources/texture-cache.cpp
dali/internal/render/gl-resources/texture-cache.h
dali/internal/update/resources/resource-manager.cpp
dali/internal/update/resources/resource-manager.h
dali/public-api/images/atlas.cpp
dali/public-api/images/atlas.h

index 5bfeb63..09368c9 100644 (file)
 
 using namespace Dali;
 
+namespace
+{
+static const char* gTestImageFilename = "icon_wrt.png";
+
+void PrepareResourceImage( TestApplication& application, unsigned int imageHeight, unsigned int imageWidth, Pixel::Format pixelFormat )
+{
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  platform.SetClosestImageSize(Vector2( 16, 16));
+
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
+  Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight );
+  unsigned int bytesPerPixel = GetBytesPerPixel(  pixelFormat );
+  unsigned int initialColor = 0xFF;
+  memset( pixbuffer, initialColor, imageHeight*imageWidth*bytesPerPixel);
+
+  Integration::ResourcePointer resourcePtr(bitmap);
+  platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+}
+
+}
+
 void utc_dali_atlas_startup(void)
 {
   test_return_value = TET_UNDEF;
@@ -51,6 +72,7 @@ int UtcDaliAtlasNew01(void)
   END_TEST;
 }
 
+
 // 1.2
 int UtcDaliAtlasUpload01(void)
 {
@@ -62,9 +84,11 @@ int UtcDaliAtlasUpload01(void)
   // Using correct pixel format
   PixelBuffer* buffer = new PixelBuffer[16 * 16];
   BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-
   DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
 
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) );
+
   END_TEST;
 }
 
@@ -79,9 +103,11 @@ int UtcDaliAtlasUpload02(void)
   // Using INCORRECT pixel format
   PixelBuffer* buffer = new PixelBuffer[16 * 16];
   BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::A8 );
-
   DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
 
+  PrepareResourceImage( application, 16, 16, Pixel::A8 );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+
   END_TEST;
 }
 
@@ -96,9 +122,11 @@ int UtcDaliAtlasUpload03(void)
   // Using image too big for atlas
   PixelBuffer* buffer = new PixelBuffer[16 * 16];
   BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-
   DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
 
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+
   END_TEST;
 }
 
@@ -119,6 +147,12 @@ int UtcDaliAtlasUpload04(void)
   DALI_TEST_CHECK( atlas.Upload( image,  0, 16 ) );
   DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) );
 
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename,  0,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename,  0, 16 ) );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 16 ) );
+
   END_TEST;
 }
 
@@ -141,6 +175,15 @@ int UtcDaliAtlasUpload05(void)
   DALI_TEST_CHECK( !atlas.Upload( image,  0, 99 ) );
   DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) );
 
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename,  0, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename,  0, 99 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 99 ) );
+
   END_TEST;
 }
 
index 573c600..9243841 100644 (file)
 // INTERNAL INCLUDES
 #include <dali/public-api/object/type-registry.h>
 #include <dali/internal/event/common/thread-local-storage.h>
-#include <dali/internal/event/images/buffer-image-impl.h>
+
+#include <dali/internal/event/images/image-factory.h>
 #include <dali/internal/event/resources/resource-client.h>
 #include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/platform-abstraction.h>
 
 namespace Dali
 {
@@ -36,23 +38,31 @@ namespace
 TypeRegistration mType( typeid( Dali::Atlas ), typeid( Dali::Image ), NULL );
 }
 
-Atlas* Atlas::New( std::size_t width,
-                   std::size_t height,
-                   Pixel::Format pixelFormat )
+Atlas* Atlas::New( SizeType width,
+                   SizeType height,
+                   Pixel::Format pixelFormat,
+                   bool recoverContext)
 {
-  return new Atlas( width, height, pixelFormat );
+  return new Atlas( width, height, pixelFormat, recoverContext );
 }
 
-bool Atlas::Upload( const BufferImage& bufferImage,
-                    std::size_t xOffset,
-                    std::size_t yOffset )
+void Atlas::Clear(const Vector4& color)
 {
-  bool uploadSuccess( false );
+  ClearCache();
+  ClearBackground( color );
+}
 
-  AllocateAtlas();
+bool Atlas::Upload( BufferImage& bufferImage,
+                    SizeType xOffset,
+                    SizeType yOffset )
+{
+  bool uploadSuccess( false );
 
-  if( IsWithin(bufferImage, xOffset, yOffset) )
+  if( Compatible(bufferImage.GetPixelFormat(),
+                 xOffset + bufferImage.GetWidth(),
+                 yOffset + bufferImage.GetHeight() ) )
   {
+    AllocateAtlas();
     ResourceId destId = GetResourceId();
     ResourceId srcId = bufferImage.GetResourceId();
 
@@ -66,16 +76,72 @@ bool Atlas::Upload( const BufferImage& bufferImage,
   return uploadSuccess;
 }
 
+bool Atlas::Upload( const std::string& url,
+                    SizeType xOffset,
+                    SizeType yOffset)
+{
+  bool uploadSuccess( false );
+
+  ResourceId destId = GetResourceId();
+
+  if( destId )
+  {
+    Integration::BitmapPtr bitmap = LoadBitmap( url );
+
+    if( bitmap && Compatible(bitmap->GetPixelFormat(), xOffset + bitmap->GetImageWidth(), yOffset + bitmap->GetImageHeight()) )
+    {
+      AllocateAtlas();
+      mResourceClient.UploadBitmap( destId, bitmap, xOffset, yOffset  );
+
+      if( mRecoverContext )
+      {
+        mTiles.PushBack( new Tile(xOffset, yOffset, url) );
+      }
+      uploadSuccess = true;
+    }
+  }
+
+  return uploadSuccess;
+}
+
+void Atlas::RecoverFromContextLoss()
+{
+  ResourceId destId = GetResourceId();
+  if( destId )
+  {
+    if( mClear )
+    {
+      ClearBackground( mClearColor );
+    }
+
+    if( mRecoverContext )
+    {
+      // Restore the atlas by re-uploading the url resources
+      Vector< Tile* >::ConstIterator end = mTiles.End();
+      for( Vector<Tile*>::Iterator iter = mTiles.Begin(); iter != end; iter++ )
+      {
+        Integration::BitmapPtr bitmap = LoadBitmap( (*iter)->url );
+        mResourceClient.UploadBitmap( destId, bitmap, (*iter)->xOffset, (*iter)->yOffset  );
+      }
+    }
+  }
+}
+
 Atlas::~Atlas()
 {
   ReleaseAtlas();
 }
 
-Atlas::Atlas( std::size_t width,
-              std::size_t height,
-              Pixel::Format pixelFormat )
+Atlas::Atlas( SizeType width,
+              SizeType height,
+              Pixel::Format pixelFormat,
+              bool recoverContext )
 : mResourceClient( ThreadLocalStorage::Get().GetResourceClient() ),
-  mPixelFormat( pixelFormat )
+  mImageFactory( ThreadLocalStorage::Get().GetImageFactory() ),
+  mClearColor( Vector4::ZERO ),
+  mPixelFormat( pixelFormat ),
+  mClear( false ),
+  mRecoverContext( recoverContext )
 {
   mWidth  = width;
   mHeight = height;
@@ -105,35 +171,29 @@ void Atlas::Disconnect()
   }
 }
 
-bool Atlas::IsWithin( const BufferImage& bufferImage,
-                      std::size_t xOffset,
-                      std::size_t yOffset )
+bool Atlas::Compatible( Pixel::Format pixelFormat,
+                        SizeType x,
+                        SizeType y )
 {
-  bool within(false);
+  bool Compatible(false);
 
-  if( mPixelFormat != bufferImage.GetPixelFormat() )
+  if( mPixelFormat != pixelFormat )
   {
-    DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", bufferImage.GetPixelFormat(), mPixelFormat );
+    DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", pixelFormat, mPixelFormat );
   }
   else
   {
-    const unsigned int width  = bufferImage.GetWidth();
-    const unsigned int height = bufferImage.GetHeight();
-
-    if( xOffset < mWidth  &&
-        yOffset < mHeight &&
-        xOffset+width  <= mWidth &&
-        yOffset+height <= mHeight )
+    if( x <= mWidth  && y <= mHeight )
     {
-      within = true;
+      Compatible = true;
     }
     else
     {
-      DALI_LOG_ERROR( "%dx%d image does not fit at offset %d,%d\n", width, height, xOffset, yOffset );
+      DALI_LOG_ERROR( "image does not fit within the atlas \n" );
     }
   }
 
-  return within;
+  return Compatible;
 }
 
 void Atlas::AllocateAtlas()
@@ -141,12 +201,86 @@ void Atlas::AllocateAtlas()
   if( !mTicket )
   {
     mTicket = mResourceClient.AllocateTexture( mWidth, mHeight, mPixelFormat );
+    mImageFactory.RegisterForContextRecovery( this );
   }
 }
 
 void Atlas::ReleaseAtlas()
 {
   mTicket.Reset();
+  ClearCache();
+  mImageFactory.UnregisterFromContextRecovery( this );
+}
+
+void Atlas::ClearBackground(const Vector4& color )
+{
+  AllocateAtlas();
+  ResourceId destId = GetResourceId();
+  if( destId )
+  {
+    const unsigned int numPixels = mWidth * mHeight;
+    unsigned int bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
+    BufferImagePtr imageData = BufferImage::New( mWidth, mHeight, mPixelFormat );
+    PixelBuffer* pixbuf = imageData->GetBuffer();
+
+    // converting color value from float 0.f~1.f to byte 0~255
+    unsigned char r =  static_cast<unsigned char>( 255.f * Clamp( color.r, 0.f, 1.f ) );
+    unsigned char g =  static_cast<unsigned char>( 255.f * Clamp( color.g, 0.f, 1.f ) );
+    unsigned char b =  static_cast<unsigned char>( 255.f * Clamp( color.b, 0.f, 1.f ) );
+    unsigned char a =  static_cast<unsigned char>( 255.f * Clamp( color.a, 0.f, 1.f ) );
+    if( mPixelFormat == Pixel::RGBA8888 )
+    {
+      // For little-endian byte order, the RGBA channels needs to be reversed for bit shifting.
+      uint32_t clearColor = ( (uint32_t) a<<24 | (uint32_t)b << 16 | (uint32_t)g << 8 | (uint32_t)r );
+      uint32_t* buf = (uint32_t *) pixbuf;
+      for( unsigned int i = 0; i < numPixels; ++i )
+      {
+        buf[i] = clearColor;
+      }
+    }
+    else if( mPixelFormat == Pixel::RGB888 )
+    {
+      for( unsigned int i = 0; i < numPixels; ++i )
+      {
+        pixbuf[i*bytesPerPixel] = r;
+        pixbuf[i*bytesPerPixel+1] = g;
+        pixbuf[i*bytesPerPixel+2] = b;
+      }
+    }
+    else if( mPixelFormat == Pixel::A8 )
+    {
+      memset( pixbuf, a, numPixels );
+    }
+
+    RectArea area;
+    imageData->Update(area);
+
+    mClearColor = color;
+    mClear = true;
+    mResourceClient.UploadBitmap( destId, imageData->GetResourceId(), 0, 0 );
+  }
+}
+
+void Atlas::ClearCache()
+{
+  Vector< Tile* >::ConstIterator end = mTiles.End();
+  for( Vector<Tile*>::Iterator iter = mTiles.Begin(); iter != end; iter++ )
+  {
+    delete *iter;
+  }
+  mTiles.Clear();
+}
+
+Integration::BitmapPtr Atlas::LoadBitmap( const std::string& url )
+{
+  ImageAttributes loadedAttrs;
+  Integration::BitmapResourceType resourceType( loadedAttrs );
+  Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
+
+  Integration::ResourcePointer resource = platformAbstraction.LoadResourceSynchronously(resourceType, url);
+  Integration::BitmapPtr bitmap = static_cast<Integration::Bitmap*>( resource.Get());
+
+  return bitmap;
 }
 
 } // namespace Internal
index 056c8cc..4bb2ce2 100644 (file)
  */
 
 // INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/images/atlas.h>
+#include <dali/internal/event/images/context-recovery-interface.h>
 #include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/event/images/buffer-image-impl.h>
 
 namespace Dali
 {
@@ -30,14 +33,12 @@ namespace Internal
 
 class ResourceClient;
 
+typedef Dali::Atlas::SizeType SizeType;
+
 /**
- * @brief An Atlas is a large image containing multiple smaller images.
- *
- * Bitmap images must be uploaded at a specified position, to populate the Atlas.
- * The client is reponsible for generating the appropriate geometry (UV coordinates),
- * needed to draw images within the Atlas.
+ * Internal class for Dali::Atlas
  */
-class Atlas : public Image
+class Atlas : public Image, public ContextRecoveryInterface
 {
 public:
 
@@ -46,27 +47,40 @@ public:
    *
    * @pre width & height are greater than zero.
    * The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
-   * @param [in] width       The atlas width in pixels.
-   * @param [in] height      The atlas height in pixels.
-   * @param [in] pixelFormat The pixel format (rgba 32 bit by default).
+   * @param [in] width          The atlas width in pixels.
+   * @param [in] height         The atlas height in pixels.
+   * @param [in] pixelFormat    The pixel format.
+   * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context
    * @return A pointer to a new Atlas.
    */
-  static Atlas* New( std::size_t width,
-                     std::size_t height,
-                     Pixel::Format pixelFormat = Pixel::RGBA8888 );
+  static Atlas* New( SizeType width,
+                     SizeType height,
+                     Pixel::Format pixelFormat,
+                     bool recoverContext);
 
   /**
-   * @brief Upload a buffer image to the atlas.
-   *
-   * @pre The bitmap pixel format must match the Atlas format.
-   * @param [in] bufferImage The buffer image to upload.
-   * @param [in] xOffset Specifies an offset in the x direction within the atlas.
-   * @param [in] yOffset Specifies an offset in the y direction within the atlas.
-   * @return True if the bitmap fits within the atlas at the specified offset.
+   * @copydoc Dali::Atlas::Clear
+   */
+  void Clear( const Vector4& color  );
+
+  /**
+   * @copydoc Dali::Atlas::Upload( const BufferImage&, unsigned int, unsigned int )
    */
-  bool Upload( const BufferImage& bufferImage,
-               std::size_t xOffset,
-               std::size_t yOffset );
+  bool Upload( BufferImage& bufferImage,
+               SizeType xOffset,
+               SizeType yOffset );
+
+  /**
+   * @copydoc Dali::Atlas::Upload( const std::string&, unsigned int, unsigned int )
+   */
+  bool Upload( const std::string& url,
+               SizeType xOffset,
+               SizeType yOffset );
+
+  /**
+   * @copydoc ContextRecoveryInterface::RecoverFromContextLoss
+   */
+  virtual void RecoverFromContextLoss();
 
 protected:
 
@@ -75,13 +89,15 @@ protected:
    *
    * @pre width & height are greater than zero.
    * The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
-   * @param [in] width       The atlas width in pixels.
-   * @param [in] height      The atlas height in pixels.
-   * @param [in] pixelFormat The pixel format (rgba 32 bit by default).
+   * @param [in] width          The atlas width in pixels.
+   * @param [in] height         The atlas height in pixels.
+   * @param [in] pixelFormat    The pixel format.
+   * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context
    */
-  Atlas( std::size_t width,
-         std::size_t height,
-         Pixel::Format pixelFormat );
+  Atlas( SizeType width,
+         SizeType height,
+         Pixel::Format pixelFormat,
+         bool recoverContext);
 
   /**
    * A reference counted object may only be deleted by calling Unreference()
@@ -102,12 +118,11 @@ private:
 
   /**
    * Helper for Upload methods
-   * @return True if the bitmap fits within the atlas at the specified offset
+   * @return True if the bitmap has the same pixel format and its size fits within the atlas at the specified offset
    */
-  bool IsWithin( const BufferImage& bufferImage,
-                 std::size_t xOffset,
-                 std::size_t yOffset );
-
+  bool Compatible( Pixel::Format pixelFormat,
+                   SizeType x,
+                   SizeType y );
   /**
    * Helper to create the Atlas resource
    */
@@ -118,11 +133,52 @@ private:
    */
   void ReleaseAtlas();
 
+  /**
+   * Upload a bitmap with the given color to clear the background.
+   */
+  void ClearBackground( const Vector4& color  );
+
+  /**
+   * Clear all the current tiles and resources of the atlas
+   */
+  void ClearCache();
+
+  /**
+   * Load the bitmap data from the url
+   */
+  Integration::BitmapPtr LoadBitmap( const std::string& url );
+
 private:
 
-  ResourceClient& mResourceClient;
+  /**
+   * Record of the url resource in the Atlas.
+   */
+  struct Tile
+  {
+    Tile( SizeType xOffset, SizeType yOffset, const std::string& url )
+    : xOffset( xOffset ), yOffset( yOffset ), url(url)
+    {}
+
+    ~Tile(){};
+
+    SizeType xOffset;   ///< Offset in the x direction within the atlas
+    SizeType yOffset;   ///< Offset in the y direction within the atlas
+    std::string url;    ///< The URL of the resource image file to use
+
+  private:
+    Tile(const Tile& rhs); ///< not defined
+    Tile& operator=(const Tile& rhs); ///< not defined
+  };
+
+private:
 
-  Pixel::Format mPixelFormat;
+  ResourceClient&          mResourceClient;
+  ImageFactory&            mImageFactory;
+  Vector4                  mClearColor;       ///< The background clear color
+  Vector<Tile*>            mTiles;            ///< The url resources, which would recover automatically when regaining context
+  Pixel::Format            mPixelFormat;      ///< The pixel format (rgba 32 bit by default)
+  bool                     mClear:1;          ///< Clear the backgound or not
+  bool                     mRecoverContext:1; ///< Re-upload the url resources or not when regaining context
 };
 
 } // namespace Internal
diff --git a/dali/internal/event/images/context-recovery-interface.h b/dali/internal/event/images/context-recovery-interface.h
new file mode 100644 (file)
index 0000000..4ba86bc
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
+#define __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 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.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Abstract interface for Context Recovery
+ *
+ */
+class ContextRecoveryInterface
+{
+
+public:
+
+  /**
+   * Restore the object after context loss
+   */
+  virtual void RecoverFromContextLoss() = 0;
+
+protected:
+
+  /**
+   * Constructor
+   */
+  ContextRecoveryInterface()
+  {
+  }
+  /**
+   * Destructor.
+   */
+  virtual ~ContextRecoveryInterface()
+  {
+  }
+
+private:
+
+  // Undefined copy constructor.
+  ContextRecoveryInterface( const ContextRecoveryInterface& );
+
+  // Undefined assignment operator.
+  ContextRecoveryInterface& operator=( const ContextRecoveryInterface& );
+
+};
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
index 2e97ffd..72e7752 100644 (file)
@@ -187,6 +187,47 @@ void ImageFactory::RecoverFromContextLoss()
       }
     }
   }
+
+  Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+  for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+      iter != end; iter++)
+  {
+    (*iter)->RecoverFromContextLoss();
+  }
+}
+
+
+void ImageFactory::RegisterForContextRecovery( ContextRecoveryInterface* object  )
+{
+  bool exist( false );
+  // To avoid registering the same object again
+  Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+  for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+          iter != end; iter++)
+  {
+    if( object == *(iter) )
+    {
+      exist = true;
+      break;
+    }
+  }
+  if( !exist )
+  {
+    mContextRecoveryList.PushBack( object );
+  }
+}
+void ImageFactory::UnregisterFromContextRecovery( ContextRecoveryInterface* object  )
+{
+  Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+  for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+        iter != end; iter++ )
+  {
+    if( object == *(iter) )
+    {
+      iter = mContextRecoveryList.Erase( iter );
+      break;
+    }
+  }
 }
 
 const std::string& ImageFactory::GetRequestPath( const ImageFactoryCache::RequestPtr& request ) const
index fe8ed7b..1dd4db1 100644 (file)
  */
 
 // INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
 #include <dali/internal/event/resources/resource-type-path-id-map.h>
 #include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/event/images/context-recovery-interface.h>
 #include <dali/internal/event/images/image-factory-cache.h>
 
 namespace Dali
@@ -99,6 +101,19 @@ public:
   void RecoverFromContextLoss();
 
   /**
+   * Register an object into the context recovery list of  the image factory.
+   * Thus its RecoverFromContextLoss() function would be called when the Stage regaining context.
+   * @param[in] object The object whose RecoverFromContextLoss() function needs to be called to regain the context.
+   */
+  void RegisterForContextRecovery( ContextRecoveryInterface* object  );
+
+  /**
+   * Unregister an object from the context recovery list of the image factory
+   * @param[in] object The object whose RecoverFromContextLoss() function needs to be called to regain the context.
+   */
+  void UnregisterFromContextRecovery( ContextRecoveryInterface* object  );
+
+  /**
    * Get resource path used in request.
    * @param [in] request of the image
    * @return     resource path
@@ -215,12 +230,13 @@ private:
   std::size_t GetHashForCachedRequest( const ImageFactoryCache::Request& request );
 
 private:
-  ResourceClient&                        mResourceClient;
-  ImageFactoryCache::RequestPathHashMap  mUrlCache;         ///< A multimap of url hashes and request IDs
-  ImageFactoryCache::RequestIdMap        mRequestCache;     ///< A map of request IDs and request information.
-  ResourceTicketContainer                mTicketsToRelease; ///< List of ticket handles
-  float                                  mMaxScale;         ///< Defines maximum size difference between compatible resources
-  ImageFactoryCache::RequestId           mReqIdCurrent;     ///< Internal counter for Request IDs
+  ResourceClient&                          mResourceClient;
+  ImageFactoryCache::RequestPathHashMap    mUrlCache;         ///< A multimap of url hashes and request IDs
+  ImageFactoryCache::RequestIdMap          mRequestCache;     ///< A map of request IDs and request information.
+  ResourceTicketContainer                  mTicketsToRelease; ///< List of ticket handles
+  Vector<ContextRecoveryInterface*>        mContextRecoveryList; ///< List of the objects who needs context recovery
+  float                                    mMaxScale;         ///< Defines maximum size difference between compatible resources
+  ImageFactoryCache::RequestId             mReqIdCurrent;     ///< Internal counter for Request IDs
 };
 
 } // namespace Internal
index 8ba4d3a..e846bfe 100644 (file)
@@ -444,6 +444,17 @@ void ResourceClient::UploadBitmap( ResourceId destId, ResourceId srcId, std::siz
                               yOffset );
 }
 
+
+void ResourceClient::UploadBitmap( ResourceId destId,Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset)
+{
+  RequestUploadBitmapMessage( mUpdateManager.GetEventToUpdate(),
+                              mResourceManager,
+                              destId,
+                              bitmap,
+                              xOffset,
+                              yOffset );
+}
+
 void ResourceClient::UpdateMesh( ResourceTicketPtr ticket, const Dali::MeshData& meshData )
 {
   DALI_ASSERT_DEBUG( ticket );
index 0c88d06..9c0edc3 100644 (file)
@@ -258,6 +258,15 @@ public:
   void UploadBitmap( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
 
   /**
+   * Upload a bitmap to a texture
+   * @param[in] destId The destination texture ID
+   * @param[in] bitmap The pointer pointing to the bitmap to upload
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UploadBitmap( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset);
+
+  /**
    * Update the mesh used by ticket
    * @note Should use same mechanism as update manager
    * @param[in] ticket The ticket holding the mesh data
index 38c8fb2..1078ce5 100644 (file)
@@ -128,14 +128,24 @@ public:
   virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap ) = 0;
 
   /**
-   * Update the part of a texture with a newly loaded bitmap
+   * Dispatch a message to update the part of a texture with the bitmap data.
+   * May be called from Update thread
+   * @param[in] destId The ID of the texture to update
+   * @param[in] bitmap The pointer pointing to the source bitmap data.
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset ) = 0;
+
+  /**
+   * Dispatch a message to update the part of a texture with a newly loaded bitmap
    * May be called from Update thread
    * @param[in] destId The ID of the texture to update
    * @param[in] srcId The resource ID of the source bitmap
    * @param [in] xOffset Specifies an offset in the x direction within the texture
    * @param [in] yOffset Specifies an offset in the y direction within the texture
    */
-  virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId,std::size_t xOffset, std::size_t yOffset ) = 0;
+  virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset ) = 0;
 
   /**
    * Dispatch a message to update the texture area
index bf8e768..4fafdd1 100644 (file)
@@ -137,27 +137,34 @@ void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
   }
 }
 
+void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
+
+  TextureIter textureIter = mTextures.find(id);
+  if( textureIter != mTextures.end() )
+  {
+    TexturePointer texturePtr = textureIter->second;
+    if( texturePtr )
+    {
+      texturePtr->Update( bitmap.Get(), xOffset, yOffset );
+
+      ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+      mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+    }
+  }
+}
+
 void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
 {
   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(destId=%i srcId=%i )\n", destId, srcId );
 
   BitmapTexture* srcTexture = TextureCache::GetBitmapTexture( srcId );
-  Integration::Bitmap* srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
+  Integration::BitmapPtr srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
 
   if( srcBitmap )
   {
-    TextureIter textureIter = mTextures.find( destId );
-    if( textureIter != mTextures.end() )
-    {
-      TexturePointer texturePtr = textureIter->second;
-      if( texturePtr )
-      {
-        texturePtr->Update( srcBitmap, xOffset, yOffset );
-
-        ResourcePostProcessRequest ppRequest( srcId, ResourcePostProcessRequest::UPLOADED );
-        mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
-      }
-    }
+    UpdateTexture( destId, srcBitmap, xOffset, yOffset );
   }
 }
 
@@ -532,6 +539,21 @@ void TextureCache::DispatchUpdateTexture( ResourceId id, Bitmap* bitmap )
   }
 }
 
+void TextureCache::DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap , std::size_t xOffset, std::size_t yOffset)
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue4< TextureCache, ResourceId, Integration::BitmapPtr, std::size_t, std::size_t > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap, xOffset, yOffset );
+  }
+}
+
 void TextureCache::DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
 {
   // NULL, means being shutdown, so ignore msgs
index f7cd399..7f2960a 100644 (file)
@@ -138,12 +138,21 @@ public:
   void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap );
 
   /**
+   * Update the texture with a newly loaded bitmap
+   * @param[in] id Resource Id of the bitmap
+   * @param[in] bitmap The bitmap
+   * @param[in] xOffset Specifies an offset in the x direction within the texture
+   * @param[in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * Update the part of a texture with a newly loaded bitmap
    * May be called from Update thread
    * @param[in] destId The ID of the texture to update
    * @param[in] srcId The resource ID of the source bitmap
-   * @param [in] xOffset Specifies an offset in the x direction within the texture
-   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   * @param[in] xOffset Specifies an offset in the x direction within the texture
+   * @param[in] yOffset Specifies an offset in the y direction within the texture
    */
   void UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
 
@@ -287,6 +296,11 @@ protected: // Implements TextureCacheDispatcher
   /**
    * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
    */
+  virtual void DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset ) ;
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+   */
   virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
 
   /**
index dca0c7b..0b4d719 100644 (file)
@@ -423,6 +423,14 @@ void ResourceManager::HandleUpdateBitmapAreaRequest( ResourceId textureId, const
   }
 }
 
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
+{
+  if( destId && bitmap )
+  {
+    mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, bitmap, xOffset, yOffset );
+  }
+}
+
 void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
 {
   if( destId && srcId )
index f7cb835..ff201de 100644 (file)
@@ -274,6 +274,15 @@ public: // Used by ResourceClient
   /**
    * Upload a bitmap to a position within a specified texture
    * @param[in] destId The destination texture ID
+   * @param[in] bitmap The pointer pointing to the bitmap data to upload
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * Upload a bitmap to a position within a specified texture
+   * @param[in] destId The destination texture ID
    * @param[in] srcId The resource ID of the bitmap to upload
    * @param [in] xOffset Specifies an offset in the x direction within the texture
    * @param [in] yOffset Specifies an offset in the y direction within the texture
@@ -400,6 +409,7 @@ public:
    ********************************* Private Methods  *****************************
    ********************************************************************************/
 private:
+
   /**
    * @param[in] id Resource id to clear
    * @param[in] typePath Glyphs to be loaded, and cleared beforehand
@@ -627,6 +637,22 @@ inline void RequestUpdateBitmapAreaMessage( EventToUpdate& eventToUpdate,
 inline void RequestUploadBitmapMessage( EventToUpdate& eventToUpdate,
                                         ResourceManager& manager,
                                         ResourceId destId,
+                                        Integration::BitmapPtr bitmap,
+                                        std::size_t xOffset,
+                                        std::size_t yOffset )
+{
+  typedef MessageValue4< ResourceManager, ResourceId, Integration::BitmapPtr , std::size_t, std::size_t > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, bitmap, xOffset, yOffset );
+}
+
+inline void RequestUploadBitmapMessage( EventToUpdate& eventToUpdate,
+                                        ResourceManager& manager,
+                                        ResourceId destId,
                                         ResourceId srcId,
                                         std::size_t xOffset,
                                         std::size_t yOffset )
index ddeb054..67558d0 100644 (file)
 namespace Dali
 {
 
-Atlas Atlas::New( std::size_t width,
-                  std::size_t height,
-                  Pixel::Format pixelFormat )
+Atlas Atlas::New( SizeType width,
+                  SizeType height,
+                  Pixel::Format pixelFormat,
+                  bool recoverContext )
 {
   DALI_ASSERT_ALWAYS( 0u != width  && "Invalid Atlas width requested" );
   DALI_ASSERT_ALWAYS( 0u != height && "Invalid Atlas height requested" );
 
-  return Atlas( Internal::Atlas::New( width, height, pixelFormat ) );
+  return Atlas( Internal::Atlas::New( width, height, pixelFormat, recoverContext ) );
 }
 
 Atlas::Atlas()
 {
 }
 
-bool Atlas::Upload( const BufferImage& bufferImage,
-                    std::size_t xOffset,
-                    std::size_t yOffset )
+void Atlas::Clear( const Vector4& color  )
+{
+  GetImplementation( *this ).Clear( color );
+}
+
+bool Atlas::Upload( BufferImage bufferImage,
+                    SizeType xOffset,
+                    SizeType yOffset )
 {
   return GetImplementation(*this).Upload( GetImplementation(bufferImage), xOffset, yOffset );
 }
 
+bool Atlas::Upload( const std::string& url,
+                    SizeType xOffset,
+                    SizeType yOffset )
+{
+  return GetImplementation(*this).Upload( url, xOffset, yOffset );
+}
+
 Atlas Atlas::DownCast( BaseHandle handle )
 {
   return Atlas( dynamic_cast<Dali::Internal::Atlas*>(handle.GetObjectPtr()) );
index 454cc6f..025b9ad 100644 (file)
  *
  */
 
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/images/image.h>
 #include <dali/public-api/images/buffer-image.h>
@@ -33,27 +37,40 @@ class Atlas;
 /**
  * @brief An Atlas is a large image containing multiple smaller images.
  *
- * Bitmap images must be uploaded at a specified position, to populate the Atlas.
- * The client is reponsible for generating the appropriate geometry (UV coordinates),
- * needed to draw images within the Atlas.
+ * Buffer image and resource image( by providing the url ) are supported for uploading.
+ * Images must be uploaded at a specified position, to populate the Atlas.
+ * The client is responsible for generating the appropriate geometry (UV coordinates) needed to draw images within the Atlas.
+ *
+ * For context recovery after loss:
+ * By default, the atlas will re-upload the resource images automatically,
+ * while the buffer images are left to the client to upload again by connecting to the Stage::ContextRegainedSignal().
+ * If resource and buffer images are mixed and they overlap inside the atlas, the recovered contents may be incorrect.
+ * In these case, switch off the context recovery by calling SetContextRecovery( false ),
+ * and upload both buffer images and resource image to the atlas in order to restore the atlas.
  */
 class DALI_IMPORT_API Atlas : public Image
 {
 public:
 
+  typedef uint32_t SizeType;
+
+public:
+
   /**
    * @brief Create a new Atlas.
    *
    * @pre width & height are greater than zero.
    * The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
-   * @param [in] width       The atlas width in pixels.
-   * @param [in] height      The atlas height in pixels.
-   * @param [in] pixelFormat The pixel format (rgba 32 bit by default).
+   * @param [in] width          The atlas width in pixels.
+   * @param [in] height         The atlas height in pixels.
+   * @param [in] pixelFormat    The pixel format (rgba 32 bit by default).
+   * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context( true by default )
    * @return A handle to a new Atlas.
    */
-  static Atlas New( std::size_t width,
-                    std::size_t height,
-                    Pixel::Format pixelFormat = Pixel::RGBA8888 );
+  static Atlas New( SizeType width,
+                    SizeType height,
+                    Pixel::Format pixelFormat = Pixel::RGBA8888,
+                    bool recoverContext = true );
 
   /**
    * @brief Create an empty handle.
@@ -63,19 +80,40 @@ public:
   Atlas();
 
   /**
-   * @brief Upload a bitmap to the atlas.
+   * @brief Clear the Atlas with the given color
+   *
+   * @note The Atlas does not clear itself automatically during construction.
+   * Application should call this clear function to avoid getting garbage pixels in the atlas.
+   * By calling Clear, all the current uploaded image information will be lost.
+   * @param [in] color The color used to clear the Atlas.
+   */
+  void Clear( const Vector4& color  );
+
+  /**
+   * @brief Upload a buffer image to the atlas.
    *
-   * @pre The bitmap pixel format must match the Atlas format.
+   * @pre The pixel format of this buffer image must match the Atlas format.
    * @param [in] bufferImage The buffer image to upload.
    * @param [in] xOffset Specifies an offset in the x direction within the atlas.
    * @param [in] yOffset Specifies an offset in the y direction within the atlas.
-   * @return True if the bitmap fits within the atlas at the specified offset.
+   * @return True if the image has compatible pixel format and fits within the atlas at the specified offset.
    */
-  bool Upload( const BufferImage& bufferImage,
-               std::size_t xOffset,
-               std::size_t yOffset );
+  bool Upload( BufferImage bufferImage,
+               SizeType xOffset,
+               SizeType yOffset );
 
   /**
+   * @brief Upload a resource image to atlas
+   *
+   * @param [in] url The URL of the resource image file to use
+   * @param [in] xOffset Specifies an offset in the x direction within the atlas.
+   * @param [in] yOffset Specifies an offset in the y direction within the atlas.
+   * @return True if the image has compatible pixel format and fits within the atlas at the specified offset.
+   */
+  bool Upload( const std::string& url,
+               SizeType xOffset,
+               SizeType yOffset );
+  /**
    * @brief Downcast an Object handle to Atlas.
    *
    * If handle points to a Atlas the downcast produces valid