Minimal Atlas API 81/33981/4
authorPaul Wisbey <p.wisbey@samsung.com>
Mon, 19 Jan 2015 10:32:12 +0000 (10:32 +0000)
committerPaul Wisbey <p.wisbey@samsung.com>
Mon, 19 Jan 2015 17:54:15 +0000 (09:54 -0800)
Change-Id: If43e6762a0b402fd522cda80a04e44cb2a8cf09b

19 files changed:
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/utc-Dali-Atlas.cpp [new file with mode: 0644]
dali/internal/event/images/atlas-impl.cpp [new file with mode: 0644]
dali/internal/event/images/atlas-impl.h [new file with mode: 0644]
dali/internal/event/resources/resource-client.cpp
dali/internal/event/resources/resource-client.h
dali/internal/file.list
dali/internal/render/common/texture-cache-dispatcher.h
dali/internal/render/gl-resources/bitmap-texture.cpp
dali/internal/render/gl-resources/bitmap-texture.h
dali/internal/render/gl-resources/texture-cache.cpp
dali/internal/render/gl-resources/texture-cache.h
dali/internal/render/gl-resources/texture.h
dali/internal/update/resources/resource-manager.cpp
dali/internal/update/resources/resource-manager.h
dali/public-api/dali-core.h
dali/public-api/file.list
dali/public-api/images/atlas.cpp [new file with mode: 0644]
dali/public-api/images/atlas.h [new file with mode: 0644]

index b023c1d..5388963 100644 (file)
@@ -13,6 +13,7 @@ SET(TC_SOURCES
         utc-Dali-AnimatableMesh.cpp
         utc-Dali-Animation.cpp
         utc-Dali-Any.cpp
+        utc-Dali-Atlas.cpp
         utc-Dali-BaseHandle.cpp
         utc-Dali-BitmapImage.cpp
         utc-Dali-CameraActor.cpp
diff --git a/automated-tests/src/dali/utc-Dali-Atlas.cpp b/automated-tests/src/dali/utc-Dali-Atlas.cpp
new file mode 100644 (file)
index 0000000..e10032f
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <test-native-image.h>
+
+using namespace Dali;
+
+void utc_dali_atlas_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_atlas_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+// 1.1
+int UtcDaliAtlasNew01(void)
+{
+  TestApplication application;
+
+  // invoke default handle constructor
+  Atlas atlas;
+
+  DALI_TEST_CHECK( !atlas );
+
+  // initialise handle
+  atlas = Atlas::New( 16, 16 );
+
+  DALI_TEST_CHECK( atlas );
+  END_TEST;
+}
+
+// 1.2
+int UtcDaliAtlasUpload01(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using correct pixel format
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
+
+  END_TEST;
+}
+
+// 1.3
+int UtcDaliAtlasUpload02(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using INCORRECT pixel format
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::A8 );
+
+  DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+
+  END_TEST;
+}
+
+// 1.4
+int UtcDaliAtlasUpload03(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using image too big for atlas
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+
+  END_TEST;
+}
+
+// 1.5
+int UtcDaliAtlasUpload04(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using valid offsets
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( atlas.Upload( image,  0,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( image, 16,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( image,  0, 16 ) );
+  DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) );
+
+  END_TEST;
+}
+
+// 1.6
+int UtcDaliAtlasUpload05(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using invalid offsets
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( !atlas.Upload( image,  0, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 17,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 17, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 99,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image,  0, 99 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) );
+
+  END_TEST;
+}
+
diff --git a/dali/internal/event/images/atlas-impl.cpp b/dali/internal/event/images/atlas-impl.cpp
new file mode 100644 (file)
index 0000000..7ad423f
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/atlas-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/images/bitmap-image-impl.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/integration-api/bitmap.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid( Dali::Atlas ), typeid( Dali::Image ), NULL );
+}
+
+Atlas* Atlas::New( std::size_t width,
+                   std::size_t height,
+                   Pixel::Format pixelFormat )
+{
+  return new Atlas( width, height, pixelFormat );
+}
+
+bool Atlas::Upload( const BitmapImage& bitmapImage,
+                    std::size_t xOffset,
+                    std::size_t yOffset )
+{
+  bool uploadSuccess( false );
+
+  if( IsWithin(bitmapImage, xOffset, yOffset) )
+  {
+    ResourceId destId = GetResourceId();
+    ResourceId srcId = bitmapImage.GetResourceId();
+
+    if( destId && srcId )
+    {
+      mResourceClient.UploadBitmap( destId, srcId, xOffset, yOffset );
+      uploadSuccess = true;
+    }
+  }
+
+  return uploadSuccess;
+}
+
+Atlas::~Atlas()
+{
+  ReleaseAtlas();
+}
+
+Atlas::Atlas( std::size_t width,
+              std::size_t height,
+              Pixel::Format pixelFormat )
+: mResourceClient( ThreadLocalStorage::Get().GetResourceClient() ),
+  mPixelFormat( pixelFormat )
+{
+  mWidth  = width;
+  mHeight = height;
+
+  if( Dali::Image::Immediate == mLoadPolicy )
+  {
+    AllocateAtlas();
+  }
+}
+
+void Atlas::Connect()
+{
+  ++mConnectionCount;
+
+  if( Dali::Image::OnDemand == mLoadPolicy &&
+      mConnectionCount == 1 )
+  {
+    AllocateAtlas();
+  }
+}
+
+void Atlas::Disconnect()
+{
+  if( mConnectionCount )
+  {
+    --mConnectionCount;
+
+    if ( Dali::Image::Unused == mReleasePolicy &&
+         mConnectionCount == 0 )
+    {
+      ReleaseAtlas();
+    }
+  }
+}
+
+bool Atlas::IsWithin( const BitmapImage& bitmapImage,
+                      std::size_t xOffset,
+                      std::size_t yOffset )
+{
+  bool within(false);
+
+  if( mPixelFormat != bitmapImage.GetPixelFormat() )
+  {
+    DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", bitmapImage.GetPixelFormat(), mPixelFormat );
+  }
+  else
+  {
+    const unsigned int width  = bitmapImage.GetWidth();
+    const unsigned int height = bitmapImage.GetHeight();
+
+    if( xOffset < mWidth  &&
+        yOffset < mHeight &&
+        xOffset+width  <= mWidth &&
+        yOffset+height <= mHeight )
+    {
+      within = true;
+    }
+    else
+    {
+      DALI_LOG_ERROR( "%dx%d image does not fit at offset %d,%d\n", width, height, xOffset, yOffset );
+    }
+  }
+
+  return within;
+}
+
+void Atlas::AllocateAtlas()
+{
+  if( !mTicket )
+  {
+    mTicket = mResourceClient.AllocateTexture( mWidth, mHeight, mPixelFormat );
+  }
+}
+
+void Atlas::ReleaseAtlas()
+{
+  mTicket.Reset();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/atlas-impl.h b/dali/internal/event/images/atlas-impl.h
new file mode 100644 (file)
index 0000000..6dddead
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef __DALI_INTERNAL_ATLAS_H__
+#define __DALI_INTERNAL_ATLAS_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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/atlas.h>
+#include <dali/internal/event/images/image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ResourceClient;
+
+/**
+ * @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.
+ */
+class Atlas : public Image
+{
+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).
+   * @return A pointer to a new Atlas.
+   */
+  static Atlas* New( std::size_t width,
+                     std::size_t height,
+                     Pixel::Format pixelFormat = Pixel::RGBA8888 );
+
+  /**
+   * @brief Upload a bitmap to the atlas.
+   *
+   * @pre The bitmap pixel format must match the Atlas format.
+   * @param [in] bitmap The bitmap 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.
+   */
+  bool Upload( const BitmapImage& bitmap,
+               std::size_t xOffset,
+               std::size_t yOffset );
+
+protected:
+
+  /**
+   * @brief Protected constructor.
+   *
+   * @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).
+   */
+  Atlas( std::size_t width,
+         std::size_t height,
+         Pixel::Format pixelFormat );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Atlas();
+
+  /**
+   * @copydoc Dali::Internal::Image::Connect
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Image::Disconnect
+   */
+  virtual void Disconnect();
+
+private:
+
+  /**
+   * Helper for Upload methods
+   * @return True if the bitmap fits within the atlas at the specified offset
+   */
+  bool IsWithin( const BitmapImage& bitmapImage,
+                 std::size_t xOffset,
+                 std::size_t yOffset );
+
+  /**
+   * Helper to create the Atlas resource
+   */
+  void AllocateAtlas();
+
+  /**
+   * Helper to release the Atlas resource
+   */
+  void ReleaseAtlas();
+
+private:
+
+  ResourceClient& mResourceClient;
+
+  Pixel::Format mPixelFormat;
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::Atlas& GetImplementation(Dali::Atlas& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Atlas handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::Atlas&>(handle);
+}
+
+inline const Internal::Atlas& GetImplementation(const Dali::Atlas& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Atlas handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::Atlas&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ATLAS_H__
index b8dd6cf..d82be43 100644 (file)
@@ -437,6 +437,16 @@ void ResourceClient::UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updat
   RequestUpdateBitmapAreaMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, ticket->GetId(), updateArea );
 }
 
+void ResourceClient::UploadBitmap( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+  RequestUploadBitmapMessage( mUpdateManager.GetEventToUpdate(),
+                              mResourceManager,
+                              destId,
+                              srcId,
+                              xOffset,
+                              yOffset );
+}
+
 void ResourceClient::UpdateMesh( ResourceTicketPtr ticket, const Dali::MeshData& meshData )
 {
   DALI_ASSERT_DEBUG( ticket );
index 923e73f..1b5ec87 100644 (file)
@@ -249,6 +249,15 @@ public:
   void UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updateArea );
 
   /**
+   * Upload a bitmap to a 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
+   */
+  void UploadBitmap( ResourceId destId, ResourceId srcId, 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 904d7b6..fd31a2b 100644 (file)
@@ -68,6 +68,7 @@ internal_src_files = \
   $(internal_src_dir)/event/events/tap-gesture-detector-impl.cpp \
   $(internal_src_dir)/event/events/tap-gesture-processor.cpp \
   $(internal_src_dir)/event/events/touch-event-processor.cpp \
+  $(internal_src_dir)/event/images/atlas-impl.cpp \
   $(internal_src_dir)/event/images/bitmap-external.cpp \
   $(internal_src_dir)/event/images/bitmap-packed-pixel.cpp \
   $(internal_src_dir)/event/images/bitmap-compressed.cpp \
index 26d337a..1ea5f80 100644 (file)
@@ -128,6 +128,16 @@ public:
   virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap ) = 0;
 
   /**
+   * 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;
+
+  /**
    * Dispatch a message to update the texture area
    * May be called from the Update thread
    * @param[in] id Resource Id of the texture
index e6967ce..c001da8 100644 (file)
@@ -203,7 +203,6 @@ void BitmapTexture::AreaUpdated( const RectArea& updateArea, const unsigned char
   }
 }
 
-
 void BitmapTexture::AssignBitmap( bool generateTexture, const unsigned char* pixels )
 {
   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
@@ -286,6 +285,51 @@ void BitmapTexture::Update( Integration::Bitmap* bitmap )
   }
 }
 
+void BitmapTexture::Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset )
+{
+  if( NULL != srcBitmap )
+  {
+    GLenum pixelFormat   = GL_RGBA;
+    GLenum pixelDataType = GL_UNSIGNED_BYTE;
+    Integration::ConvertToGlFormat( mPixelFormat, pixelDataType, pixelFormat );
+
+    if( !mId )
+    {
+      mContext.GenTextures( 1, &mId );
+
+      mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+      mContext.Bind2dTexture( mId );
+      mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+      mContext.TexImage2D( GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, NULL );
+      mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+      mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+    }
+    else
+    {
+      mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+      mContext.Bind2dTexture( mId );
+      mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+    }
+
+    const unsigned char* pixels = srcBitmap->GetBuffer();
+    unsigned int srcWidth = srcBitmap->GetImageWidth();
+    const unsigned int pixelDepth = Pixel::GetBytesPerPixel( mPixelFormat );
+
+    unsigned int yBottom = yOffset + srcBitmap->GetImageHeight();
+
+    for( unsigned int y = yOffset; y < yBottom; y++ )
+    {
+      mContext.TexSubImage2D( GL_TEXTURE_2D, 0,
+                              xOffset, y,
+                              srcWidth, 1,
+                              pixelFormat, pixelDataType, pixels );
+
+      pixels += srcWidth * pixelDepth;
+    }
+  }
+}
+
 void BitmapTexture::UpdateArea( const RectArea& updateArea )
 {
   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "BitmapTexture::UpdateArea()\n");
index 46073c8..7cbdfbc 100644 (file)
@@ -90,7 +90,14 @@ public: // Message interface
    */
   void ClearAreas( const BitmapClearArray& areaArray, std::size_t blockSize, uint32_t color );
 
+  /**
+   * Retrieve the bitmap
+   * @return The bitmap or NULL if already discarded
+   */
+  Integration::Bitmap* GetBitmap() { return mBitmap.Get(); }
+
 public:
+
   /**
    * @copydoc Texture::Init
    */
@@ -124,6 +131,14 @@ public:
   virtual void Update( Integration::Bitmap* bitmap );
 
   /**
+   * Update part of the texture with a different bitmap
+   * @param[in] srcBitmap The bitmap to copy from
+   * @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 Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * Bitmap area has been modified - update the texture appropriately.
    * @pre The bitmap hasn't been discarded (should be external type)
    * @param[in] area The updated area
index db4f027..bfa9185 100644 (file)
@@ -137,6 +137,30 @@ void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
   }
 }
 
+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;
+
+  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);
+      }
+    }
+  }
+}
+
 void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
 {
   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
@@ -264,7 +288,6 @@ void TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target,
   }
 }
 
-
 Texture* TextureCache::GetTexture(ResourceId id)
 {
   Texture* texture = NULL;
@@ -297,6 +320,23 @@ Texture* TextureCache::GetTexture(ResourceId id)
   return texture;
 }
 
+BitmapTexture* TextureCache::GetBitmapTexture(ResourceId id)
+{
+  BitmapTexture* texture = NULL;
+  TextureIter iter = mTextures.find( id );
+
+  if( iter != mTextures.end() )
+  {
+    TexturePointer texturePtr = iter->second;
+    if( texturePtr )
+    {
+      texture = dynamic_cast< BitmapTexture* >( texturePtr.Get() );
+    }
+  }
+
+  return texture;
+}
+
 FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
 {
   FrameBufferTexture* offscreen = NULL;
@@ -492,6 +532,21 @@ void TextureCache::DispatchUpdateTexture( ResourceId id, Bitmap* bitmap )
   }
 }
 
+void TextureCache::DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue4< TextureCache, ResourceId, ResourceId, 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, destId, srcId, xOffset, yOffset );
+  }
+}
+
 void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
 {
   // NULL, means being shutdown, so ignore msgs
index 656d103..1bbc7f9 100644 (file)
@@ -52,6 +52,7 @@ namespace Internal
 {
 class Context;
 class Texture;
+class BitmapTexture;
 class FrameBufferTexture;
 class TextureObserver;
 
@@ -136,6 +137,16 @@ public:
    */
   void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap );
 
+  /**
+   * 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
+   */
+  void UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
  /**
    * Add an array of bitmaps to an existing texture used as an Atlas
    * @param[in] id Resource id of the texture
@@ -191,6 +202,13 @@ public:
   Texture* GetTexture( ResourceId id );
 
   /**
+   * Get the bitmaptexture associated with the resource ID
+   * @param[in] id Resource Id of the texture
+   * @return The texture or NULL
+   */
+  BitmapTexture* GetBitmapTexture(ResourceId id);
+
+  /**
    * Get the framebuffer texture associated with the resource ID
    * Used for writing to the framebuffer
    * @param[in] id Resource Id of the framebuffer
@@ -267,6 +285,11 @@ protected: // Implements TextureCacheDispatcher
   virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap );
 
   /**
+   * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+   */
+  virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * @copydoc TextureCacheDispatcher::DispatchUpdateTextureArea()
    */
   virtual void DispatchUpdateTextureArea( ResourceId id, const RectArea& area );
index 5c0b182..0479f01 100644 (file)
@@ -80,6 +80,14 @@ public:
   virtual void UpdateArea( const RectArea& area );
 
   /**
+   * Update part of the texture with a different bitmap
+   * @param[in] srcBitmap The bitmap to copy from
+   * @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 Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset ) {}
+
+  /**
    * @return Return true if the texture should be updated on GL texture creation.
    */
   virtual bool UpdateOnCreate();
index 0464aa0..82b7e53 100644 (file)
@@ -428,6 +428,14 @@ void ResourceManager::HandleUpdateBitmapAreaRequest( ResourceId textureId, const
   }
 }
 
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+  if( destId && srcId )
+  {
+    mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, srcId, xOffset, yOffset );
+  }
+}
+
 void ResourceManager::HandleUpdateMeshRequest( BufferIndex updateBufferIndex, ResourceId id, MeshData* meshData )
 {
   DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
index 2a2a947..43bab93 100644 (file)
@@ -273,6 +273,15 @@ public: // Used by ResourceClient
   void HandleUpdateBitmapAreaRequest( ResourceId textureId, const Dali::RectArea& area );
 
   /**
+   * 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
+   */
+  void HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+  /**
    * Upload mesh buffer changes.
    * @param[in] updateBufferIndex The current update buffer index.
    * @param[in] id The ID of a Mesh resource.
@@ -630,6 +639,22 @@ inline void RequestUpdateBitmapAreaMessage( EventToUpdate& eventToUpdate,
   new (slot) LocalType( &manager, &ResourceManager::HandleUpdateBitmapAreaRequest, id, area );
 }
 
+inline void RequestUploadBitmapMessage( EventToUpdate& eventToUpdate,
+                                        ResourceManager& manager,
+                                        ResourceId destId,
+                                        ResourceId srcId,
+                                        std::size_t xOffset,
+                                        std::size_t yOffset )
+{
+  typedef MessageValue4< ResourceManager, ResourceId, ResourceId, 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, srcId, xOffset, yOffset );
+}
+
 inline void RequestUpdateMeshMessage( EventToUpdate& eventToUpdate,
                                       ResourceManager& manager,
                                       ResourceId id,
index 2408982..a4d8ec2 100644 (file)
@@ -90,6 +90,7 @@
 #include <dali/public-api/geometry/mesh-factory.h>
 #include <dali/public-api/geometry/spline.h>
 
+#include <dali/public-api/images/atlas.h>
 #include <dali/public-api/images/bitmap-image.h>
 #include <dali/public-api/images/distance-field.h>
 #include <dali/public-api/images/encoded-buffer-image.h>
index 5629dcc..b6f4c16 100644 (file)
@@ -57,6 +57,7 @@ public_api_src_files = \
   $(public_api_src_dir)/geometry/mesh-factory.cpp \
   $(public_api_src_dir)/geometry/mesh.cpp \
   $(public_api_src_dir)/geometry/spline.cpp \
+  $(public_api_src_dir)/images/atlas.cpp \
   $(public_api_src_dir)/images/distance-field.cpp \
   $(public_api_src_dir)/images/image.cpp \
   $(public_api_src_dir)/images/image-attributes.cpp \
@@ -208,6 +209,7 @@ public_api_core_geometry_header_files = \
   $(public_api_src_dir)/geometry/spline.h
 
 public_api_core_images_header_files = \
+  $(public_api_src_dir)/images/atlas.h \
   $(public_api_src_dir)/images/bitmap-image.h \
   $(public_api_src_dir)/images/distance-field.h \
   $(public_api_src_dir)/images/encoded-buffer-image.h \
diff --git a/dali/public-api/images/atlas.cpp b/dali/public-api/images/atlas.cpp
new file mode 100644 (file)
index 0000000..b41c00c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/atlas.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/atlas-impl.h>
+#include <dali/internal/event/images/bitmap-image-impl.h>
+
+namespace Dali
+{
+
+Atlas Atlas::New( std::size_t width,
+                  std::size_t height,
+                  Pixel::Format pixelFormat )
+{
+  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 ) );
+}
+
+Atlas::Atlas()
+{
+}
+
+bool Atlas::Upload( const BitmapImage& bitmap,
+                    std::size_t xOffset,
+                    std::size_t yOffset )
+{
+  return GetImplementation(*this).Upload( GetImplementation(bitmap), xOffset, yOffset );
+}
+
+Atlas Atlas::DownCast( BaseHandle handle )
+{
+  return Atlas( dynamic_cast<Dali::Internal::Atlas*>(handle.GetObjectPtr()) );
+}
+
+Atlas::~Atlas()
+{
+}
+
+Atlas::Atlas( const Atlas& handle )
+: Image( handle )
+{
+}
+
+Atlas& Atlas::operator=( const Atlas& rhs )
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+Atlas::Atlas( Internal::Atlas* internal )
+: Image( internal )
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/atlas.h b/dali/public-api/images/atlas.h
new file mode 100644 (file)
index 0000000..9719635
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef __DALI_ATLAS_H__
+#define __DALI_ATLAS_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.
+ *
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/bitmap-image.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+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.
+ */
+class DALI_IMPORT_API Atlas : public Image
+{
+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).
+   * @return A handle to a new Atlas.
+   */
+  static Atlas New( std::size_t width,
+                    std::size_t height,
+                    Pixel::Format pixelFormat = Pixel::RGBA8888 );
+
+  /**
+   * @brief Create an empty handle.
+   *
+   * Calling member functions of an empty handle is not allowed.
+   */
+  Atlas();
+
+  /**
+   * @brief Upload a bitmap to the atlas.
+   *
+   * @pre The bitmap pixel format must match the Atlas format.
+   * @param [in] bitmap The bitmap 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.
+   */
+  bool Upload( const BitmapImage& bitmap,
+               std::size_t xOffset,
+               std::size_t yOffset );
+
+  /**
+   * @brief Downcast an Object handle to Atlas.
+   *
+   * If handle points to a Atlas the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @param[in] handle to An object
+   * @return handle to a Atlas or an empty handle
+   */
+  static Atlas DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~Atlas();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @param [in] handle A reference to the copied handle
+   */
+  Atlas( const Atlas& handle );
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Atlas& operator=( const Atlas& rhs);
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL Atlas( Internal::Atlas* );
+};
+
+} // namespace Dali
+
+#endif // __DALI_ATLAS_H__