Merge "There is an issue with scale, so change to LINEAR. and fixed pixel alignment...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / rendering / atlas / atlas-manager-impl.cpp
index dacb141..ba07cef 100644 (file)
@@ -41,8 +41,12 @@ namespace
   const uint32_t DEFAULT_BLOCK_HEIGHT( 16u );
   const uint32_t SINGLE_PIXEL_PADDING( 1u );
   const uint32_t DOUBLE_PIXEL_PADDING( SINGLE_PIXEL_PADDING << 1 );
-  const uint32_t FILLED_PIXEL( -1 );
   Toolkit::AtlasManager::AtlasSize EMPTY_SIZE;
+
+  bool IsBlockSizeSufficient( uint32_t width, uint32_t height, uint32_t requiredBlockWidth, uint32_t requiredBlockHeight )
+  {
+    return ( width + DOUBLE_PIXEL_PADDING <= requiredBlockWidth ) && ( height + DOUBLE_PIXEL_PADDING <= requiredBlockHeight );
+  }
 }
 
 AtlasManager::AtlasManager()
@@ -79,8 +83,15 @@ Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasMa
     return 0;
   }
 
-  Dali::Atlas atlas = Dali::Atlas::New( width, height, pixelformat );
-  atlas.Clear( Vector4::ZERO );
+  Dali::Texture atlas = Dali::Texture::New( TextureType::TEXTURE_2D, pixelformat, width, height );
+
+  // Clear the background
+  unsigned int bufferSize(  width * height * Dali::Pixel::GetBytesPerPixel( pixelformat ) );
+  unsigned char* background = new unsigned char[bufferSize];
+  memset( background, 0, bufferSize );
+  PixelData backgroundPixels = PixelData::New( background, bufferSize, width, height, pixelformat, PixelData::DELETE_ARRAY );
+  atlas.Upload( backgroundPixels, 0u, 0u, 0u, 0u, width, height );
+
   AtlasDescriptor atlasDescriptor;
   atlasDescriptor.mAtlas = atlas;
   atlasDescriptor.mSize = size;
@@ -88,35 +99,21 @@ Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasMa
   atlasDescriptor.mTotalBlocks = ( ( width - 1u ) / blockWidth ) * ( ( height - 1u ) / blockHeight );
   atlasDescriptor.mAvailableBlocks = atlasDescriptor.mTotalBlocks;
 
-  atlasDescriptor.mHorizontalStrip = BufferImage::New( blockWidth, SINGLE_PIXEL_PADDING, pixelformat );
-  atlasDescriptor.mVerticalStrip = BufferImage::New( SINGLE_PIXEL_PADDING, blockHeight - DOUBLE_PIXEL_PADDING, pixelformat );
-
-  PixelBuffer* buffer = atlasDescriptor.mHorizontalStrip.GetBuffer();
-  if( buffer == NULL )
-  {
-    DALI_LOG_ERROR("atlasDescriptor.mHorizontalStrip.GetBuffer() returns NULL\n");
-    return 0;
-  }
-  memset( buffer, 0, atlasDescriptor.mHorizontalStrip.GetBufferSize() );
-
-  buffer = atlasDescriptor.mVerticalStrip.GetBuffer();
-  if( buffer == NULL )
-  {
-    DALI_LOG_ERROR("atlasDescriptor.mVerticalStrip.GetBuffer() returns NULL\n");
-    return 0;
-  }
-  memset( buffer, 0, atlasDescriptor.mVerticalStrip.GetBufferSize() );
-
-  BufferImage filledPixelImage = BufferImage::New( 1u, 1u, pixelformat );
-  buffer = filledPixelImage.GetBuffer();
-  if( buffer == NULL)
-  {
-    DALI_LOG_ERROR("filledPixelImage.GetBuffer() returns NULL\n");
-    return 0;
-  }
-
-  memset( buffer, 0xFF, filledPixelImage.GetBufferSize() );
-  atlas.Upload( filledPixelImage, 0, 0 );
+  bufferSize = blockWidth * SINGLE_PIXEL_PADDING * Dali::Pixel::GetBytesPerPixel(pixelformat);
+  unsigned char* bufferHorizontalStrip = new unsigned char[bufferSize];
+  memset( bufferHorizontalStrip, 0, bufferSize );
+  atlasDescriptor.mHorizontalStrip = PixelData::New( bufferHorizontalStrip, bufferSize, blockWidth, SINGLE_PIXEL_PADDING, pixelformat, PixelData::DELETE_ARRAY );
+
+  bufferSize = SINGLE_PIXEL_PADDING * (blockHeight - DOUBLE_PIXEL_PADDING) * Dali::Pixel::GetBytesPerPixel(pixelformat);
+  unsigned char* bufferVerticalStrip = new unsigned char[bufferSize];
+  memset( bufferVerticalStrip, 0, bufferSize );
+  atlasDescriptor.mVerticalStrip = PixelData::New( bufferVerticalStrip, bufferSize, SINGLE_PIXEL_PADDING, blockHeight - DOUBLE_PIXEL_PADDING, pixelformat, PixelData::DELETE_ARRAY );
+
+  bufferSize = Dali::Pixel::GetBytesPerPixel(pixelformat);
+  unsigned char* buffer = new unsigned char[bufferSize];
+  memset( buffer, 0xFF, bufferSize );
+  PixelData filledPixelImage = PixelData::New( buffer, bufferSize, 1u, 1u, pixelformat, PixelData::DELETE_ARRAY );
+  atlas.Upload( filledPixelImage, 0u, 0u, 0u, 0u, 1u, 1u );
   mAtlasList.push_back( atlasDescriptor );
   return mAtlasList.size();
 }
@@ -126,7 +123,7 @@ void AtlasManager::SetAddPolicy( Toolkit::AtlasManager::AddFailPolicy policy )
   mAddFailPolicy = policy;
 }
 
-bool AtlasManager::Add( const BufferImage& image,
+bool AtlasManager::Add( const PixelData& image,
                         Toolkit::AtlasManager::AtlasSlot& slot,
                         Toolkit::AtlasManager::AtlasId atlas )
 {
@@ -147,39 +144,46 @@ bool AtlasManager::Add( const BufferImage& image,
   }
 
   // Search current atlases to see if there is a good match
-  while( !foundAtlas && index < mAtlasList.size() )
+  while( ( 0u == foundAtlas ) && ( index < mAtlasList.size() ) )
   {
     foundAtlas = CheckAtlas( index, width, height, pixelFormat );
     ++index;
   }
 
   // If we can't find a suitable atlas then check the policy to determine action
-  if ( !foundAtlas-- )
+  if ( 0u == foundAtlas )
   {
     if ( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES == mAddFailPolicy )
     {
-      foundAtlas = CreateAtlas( mNewAtlasSize, pixelFormat );
-      if ( !foundAtlas-- )
+      if ( IsBlockSizeSufficient( width, height, mNewAtlasSize.mBlockWidth, mNewAtlasSize.mBlockHeight ) ) // Checks if image fits within the atlas blocks
       {
-        DALI_LOG_ERROR("Failed to create an atlas of %i x %i blocksize: %i x %i.\n",
-                       mNewAtlasSize.mWidth,
-                       mNewAtlasSize.mHeight,
-                       mNewAtlasSize.mBlockWidth,
-                       mNewAtlasSize.mBlockHeight );
-        return created;
+        foundAtlas = CreateAtlas( mNewAtlasSize, pixelFormat ); // Creating atlas with mNewAtlasSize, may not be the needed size!
+        if (  0u == foundAtlas )
+        {
+          DALI_LOG_ERROR("Failed to create an atlas of %i x %i blocksize: %i x %i.\n",
+                         mNewAtlasSize.mWidth,
+                         mNewAtlasSize.mHeight,
+                         mNewAtlasSize.mBlockWidth,
+                         mNewAtlasSize.mBlockHeight );
+          return false;
+        }
+        else
+        {
+          created = true;
+        }
       }
-      created = true;
-      foundAtlas = CheckAtlas( foundAtlas, width, height, pixelFormat );
     }
 
-    if ( !foundAtlas-- || Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy )
+    if ( (  0u == foundAtlas )  || Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy )
     {
-      // Haven't found an atlas for this image!!!!!!
+      // Haven't found an atlas for this image ( may have failed to add image to atlas )
       DALI_LOG_ERROR("Failed to create an atlas under current policy.\n");
-      return created;
+      return false;
     }
   }
 
+  foundAtlas--; // Atlas created successfully, decrement by 1 to get <vector> index (starts at 0 not 1)
+
   // Work out which the block we're going to use
   // Is there currently a next free block available ?
   if ( mAtlasList[ foundAtlas ].mAvailableBlocks )
@@ -196,7 +200,7 @@ bool AtlasManager::Add( const BufferImage& image,
 
   desc.mImageWidth = width;
   desc.mImageHeight = height;
-  desc.mAtlasId = foundAtlas + 1u;
+  desc.mAtlasId = foundAtlas + 1u;  // Ids start from 1 not the 0 index
   desc.mCount = 1u;
 
   // See if there's a previously freed image ID that we can assign to this new image
@@ -219,7 +223,7 @@ bool AtlasManager::Add( const BufferImage& image,
     mImageList[ imageId - 1u ] = desc;
     slot.mImageId = imageId;
   }
-  slot.mAtlasId = foundAtlas + 1u;
+  slot.mAtlasId = foundAtlas + 1u; // Ids start from 1 not the 0 index
 
   // Upload the buffer image into the atlas
   UploadImage( image, desc );
@@ -234,18 +238,19 @@ AtlasManager::SizeType AtlasManager::CheckAtlas( SizeType atlas,
   AtlasManager::SizeType result = 0u;
   if ( pixelFormat == mAtlasList[ atlas ].mPixelFormat )
   {
-    // Check to see if the image will fit in these blocks, if not we'll need to create a new atlas
-    if ( ( mAtlasList[ atlas ].mAvailableBlocks + mAtlasList[ atlas ].mFreeBlocksList.Size() )
-           && width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockWidth
-           && height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockHeight )
+    // Check to see if the image will fit in these blocks
+
+    const SizeType availableBlocks = mAtlasList[ atlas ].mAvailableBlocks + mAtlasList[ atlas ].mFreeBlocksList.Size();
+
+    if ( availableBlocks && IsBlockSizeSufficient( width, height,mAtlasList[ atlas ].mSize.mBlockWidth, mAtlasList[ atlas ].mSize.mBlockHeight ) )
     {
-      result = atlas + 1u;
+      result = atlas + 1u; // Atlas ids start from 1 not 0
     }
   }
   return result;
 }
 
-void AtlasManager::UploadImage( const BufferImage& image,
+void AtlasManager::UploadImage( const PixelData& image,
                                 const AtlasSlotDescriptor& desc )
 {
   // Get the atlas to upload the image to
@@ -271,25 +276,30 @@ void AtlasManager::UploadImage( const BufferImage& image,
   SizeType height = image.GetHeight();
 
   // Blit image 1 pixel to the right and down into the block to compensate for texture filtering
-  if ( !mAtlasList[ atlas ].mAtlas.Upload( image,
+  if ( !mAtlasList[ atlas ].mAtlas.Upload( image, 0u, 0u,
                                            blockOffsetX + SINGLE_PIXEL_PADDING,
-                                           blockOffsetY + SINGLE_PIXEL_PADDING ) )
+                                           blockOffsetY + SINGLE_PIXEL_PADDING,
+                                           width, height) )
   {
     DALI_LOG_ERROR("Uploading image to Atlas Failed!.\n");
   }
 
   // Blit top strip
-  if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip,
+  if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, 0u, 0u,
                                            blockOffsetX,
-                                           blockOffsetY ) )
+                                           blockOffsetY,
+                                           mAtlasList[ atlas ].mHorizontalStrip.GetWidth(),
+                                           mAtlasList[ atlas ].mHorizontalStrip.GetHeight()) )
   {
     DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n");
   }
 
   // Blit left strip
-  if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip,
+  if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, 0u, 0u,
                                            blockOffsetX,
-                                           blockOffsetY + SINGLE_PIXEL_PADDING ) )
+                                           blockOffsetY + SINGLE_PIXEL_PADDING,
+                                           mAtlasList[ atlas ].mVerticalStrip.GetWidth(),
+                                           mAtlasList[ atlas ].mVerticalStrip.GetHeight() ) )
   {
     DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n");
   }
@@ -297,9 +307,11 @@ void AtlasManager::UploadImage( const BufferImage& image,
   // Blit bottom strip
   if ( blockOffsetY + height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mHeight )
   {
-    if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip,
+    if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, 0u, 0u,
                                              blockOffsetX,
-                                             blockOffsetY + height + SINGLE_PIXEL_PADDING ) )
+                                             blockOffsetY + height + SINGLE_PIXEL_PADDING,
+                                             mAtlasList[ atlas ].mHorizontalStrip.GetWidth(),
+                                             mAtlasList[ atlas ].mHorizontalStrip.GetHeight() ) )
     {
       DALI_LOG_ERROR("Uploading bottom strip to Atlas Failed!.\n");
     }
@@ -308,9 +320,11 @@ void AtlasManager::UploadImage( const BufferImage& image,
   // Blit right strip
   if ( blockOffsetX + width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mWidth )
   {
-    if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip,
+    if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, 0u, 0u,
                                              blockOffsetX + width + SINGLE_PIXEL_PADDING,
-                                             blockOffsetY + SINGLE_PIXEL_PADDING ) )
+                                             blockOffsetY + SINGLE_PIXEL_PADDING,
+                                             mAtlasList[ atlas ].mVerticalStrip.GetWidth(),
+                                             mAtlasList[ atlas ].mVerticalStrip.GetHeight() ) )
     {
       DALI_LOG_ERROR("Uploading right strip to Atlas Failed!.\n");
     }
@@ -349,10 +363,10 @@ void AtlasManager::GenerateMeshData( ImageId id,
   }
 }
 
-Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const
+Dali::Texture AtlasManager::GetAtlasContainer( AtlasId atlas ) const
 {
   DALI_ASSERT_DEBUG( atlas && atlas <= mAtlasList.size() );
-  Dali::Atlas atlasContainer;
+  Dali::Texture atlasContainer;
   if ( atlas && atlas-- <= mAtlasList.size() )
   {
     atlasContainer = mAtlasList[ atlas ].mAtlas;
@@ -436,7 +450,7 @@ AtlasManager::SizeType AtlasManager::GetAtlasCount() const
   return mAtlasList.size();
 }
 
-Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas )
+Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas ) const
 {
   DALI_ASSERT_DEBUG( atlas && atlas <= mAtlasList.size() );
   Pixel::Format pixelFormat = Pixel::RGBA8888;
@@ -476,23 +490,23 @@ void AtlasManager::GetMetrics( Toolkit::AtlasManager::Metrics& metrics )
   metrics.mTextureMemoryUsed = textureMemoryUsed;
 }
 
-Material AtlasManager::GetMaterial( AtlasId atlas ) const
+TextureSet AtlasManager::GetTextures( AtlasId atlas ) const
 {
   DALI_ASSERT_DEBUG( atlas && atlas <= mAtlasList.size() );
-  Material material;
+  TextureSet textureSet;
   if ( atlas && atlas-- <= mAtlasList.size() )
   {
-    material = mAtlasList[ atlas ].mMaterial;
+    textureSet = mAtlasList[ atlas ].mTextureSet;
   }
-  return material;
+  return textureSet;
 }
 
-void AtlasManager::SetMaterial( AtlasId atlas, Material& material )
+void AtlasManager::SetTextures( AtlasId atlas, TextureSet& textureSet )
 {
   DALI_ASSERT_DEBUG( atlas && atlas <= mAtlasList.size() );
   if ( atlas && atlas-- <= mAtlasList.size() )
   {
-    mAtlasList[ atlas ].mMaterial = material;
+    mAtlasList[ atlas ].mTextureSet = textureSet;
   }
 }