Fix prevent issues
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / atlas-manager / atlas-manager-impl.cpp
index 56c3269..832e5d9 100644 (file)
@@ -50,13 +50,11 @@ namespace
   attribute mediump vec2    aPosition;
   attribute mediump vec2    aTexCoord;
   uniform   mediump mat4    uMvpMatrix;
-  uniform   mediump vec3    uSize;
   varying   mediump vec2    vTexCoord;
 
   void main()
   {
     mediump vec4 position = vec4( aPosition, 0.0, 1.0 );
-    position.xyz *= uSize;
     gl_Position = uMvpMatrix * position;
     vTexCoord = aTexCoord;
   }
@@ -87,8 +85,7 @@ namespace
 }
 
 AtlasManager::AtlasManager()
-: mAddFailPolicy( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES ),
-  mFilledPixel( FILLED_PIXEL )
+: mAddFailPolicy( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES )
 {
   mNewAtlasSize.mWidth = DEFAULT_ATLAS_WIDTH;
   mNewAtlasSize.mHeight = DEFAULT_ATLAS_HEIGHT;
@@ -106,30 +103,6 @@ AtlasManagerPtr AtlasManager::New()
 
 AtlasManager::~AtlasManager()
 {
-  for ( SizeType i = 0; i < mAtlasList.size(); ++i )
-  {
-    mAtlasList[ i ].mAtlas.UploadedSignal().Disconnect( this, &AtlasManager::OnUpload );
-    delete[] mAtlasList[ i ].mStripBuffer;
-  }
-
-  // Are there any upload signals pending? Free up those buffer images now.
-  for ( SizeType i = 0; i < mUploadedImages.Size(); ++i )
-  {
-    delete[] mUploadedImages[ i ];
-  }
-}
-
-void AtlasManager::OnUpload( Image image )
-{
-  if ( mUploadedImages.Size() )
-  {
-    delete[] mUploadedImages[ 0 ];
-    mUploadedImages.Erase( mUploadedImages.Begin() );
-  }
-  else
-  {
-    DALI_LOG_ERROR("Atlas Image Upload List should not be empty\n");
-  }
 }
 
 Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasManager::AtlasSize& size, Pixel::Format pixelformat )
@@ -140,41 +113,51 @@ Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasMa
   SizeType blockHeight = size.mBlockHeight;
 
   // Check to see if the atlas is large enough to hold a single block even ?
-  if ( blockWidth > width || blockHeight > height )
+  if ( blockWidth + DOUBLE_PIXEL_PADDING + 1u > width || blockHeight + DOUBLE_PIXEL_PADDING + 1u > height )
   {
     DALI_LOG_ERROR("Atlas %i x %i too small. Dimensions need to be at least %ix%i\n",
-                    width, height, blockWidth, blockHeight );
+                    width, height, blockWidth + DOUBLE_PIXEL_PADDING + 1u, blockHeight + DOUBLE_PIXEL_PADDING + 1u );
     return 0;
   }
 
   Dali::Atlas atlas = Dali::Atlas::New( width, height, pixelformat );
   atlas.Clear( Vector4::ZERO );
-  mUploadedImages.PushBack( NULL );
   AtlasDescriptor atlasDescriptor;
   atlasDescriptor.mAtlas = atlas;
   atlasDescriptor.mSize = size;
   atlasDescriptor.mPixelFormat = pixelformat;
-  atlasDescriptor.mTotalBlocks = ( width / blockWidth ) * ( height / blockHeight );
-  atlasDescriptor.mAvailableBlocks = atlasDescriptor.mTotalBlocks - 1u;
-  atlas.UploadedSignal().Connect( this, &AtlasManager::OnUpload );
-
-  // What size do we need for this atlas' strip buffer ( assume 32bit pixel format )?
-  SizeType neededStripSize =( blockWidth > blockHeight - DOUBLE_PIXEL_PADDING ? blockWidth : blockHeight - DOUBLE_PIXEL_PADDING ) << 2;
-  atlasDescriptor.mStripBuffer = new PixelBuffer[ neededStripSize ];
-  memset( atlasDescriptor.mStripBuffer, 0, neededStripSize );
-
-  atlasDescriptor.mHorizontalStrip = BufferImage::New( atlasDescriptor.mStripBuffer,
-                                                       blockWidth,
-                                                       SINGLE_PIXEL_PADDING,
-                                                       pixelformat );
-
-  atlasDescriptor.mVerticalStrip = BufferImage::New( atlasDescriptor.mStripBuffer,
-                                                     SINGLE_PIXEL_PADDING,
-                                                     blockHeight - DOUBLE_PIXEL_PADDING,
-                                                     pixelformat );
-  mUploadedImages.PushBack( NULL );
-  atlasDescriptor.mFilledPixelImage = BufferImage::New( reinterpret_cast< PixelBuffer* >( &mFilledPixel ), 1, 1, pixelformat );
-  atlas.Upload( atlasDescriptor.mFilledPixelImage, 0, 0 );
+  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 );
 
   Sampler sampler = Sampler::New( atlas, "sTexture" );
   sampler.SetProperty( Sampler::Property::AFFECTS_TRANSPARENCY, true );
@@ -225,20 +208,24 @@ void AtlasManager::Add( const BufferImage& image,
   {
     if ( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES == mAddFailPolicy )
     {
-      SizeType newAtlas = CreateAtlas( mNewAtlasSize, pixelFormat );
-      if ( !newAtlas-- )
+      foundAtlas = CreateAtlas( mNewAtlasSize, pixelFormat );
+      if ( !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;
       }
-      else
-      {
-        foundAtlas = CheckAtlas( newAtlas, width, height, pixelFormat, blockArea );
-      }
+
+      foundAtlas = CheckAtlas( foundAtlas, width, height, pixelFormat, blockArea );
     }
 
     if ( !foundAtlas-- || Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy )
     {
       // Haven't found an atlas for this image!!!!!!
+      DALI_LOG_ERROR("Failed to create an atlas under current policy.\n");
       return;
     }
   }
@@ -330,7 +317,7 @@ void AtlasManager::CreateMesh( SizeType atlas,
   SizeType width = mAtlasList[ atlas ].mSize.mWidth;
   SizeType height = mAtlasList[ atlas ].mSize.mHeight;
 
-  SizeType atlasWidthInBlocks = width / blockWidth;
+  SizeType atlasWidthInBlocks = ( width - 1u ) / blockWidth;
 
   // Get the normalized size of a texel in both directions
   // TODO when texture resizing and passing texture size via uniforms is available,
@@ -339,8 +326,8 @@ void AtlasManager::CreateMesh( SizeType atlas,
   float texelX = 1.0f / static_cast< float >( width );
   float texelY = 1.0f / static_cast< float >( height );
 
-  float halfTexelX = texelX * 0.5f;
-  float halfTexelY = texelY * 0.5f;
+  float oneAndAHalfTexelX = texelX + ( texelX * 0.5f );
+  float oneAndAHalfTexelY = texelY + ( texelY * 0.5f );
 
   // Get the normalized size of a block in texels
   float texelBlockWidth = texelX * vertexBlockWidth;
@@ -393,9 +380,9 @@ void AtlasManager::CreateMesh( SizeType atlas,
       float fBlockX = texelBlockWidth * static_cast< float >( block % atlasWidthInBlocks );
       float fBlockY = texelBlockHeight * static_cast< float >( block / atlasWidthInBlocks );
 
-      // Add on texture filtering compensation
-      fBlockX += halfTexelX;
-      fBlockY += halfTexelY;
+      // Add on texture filtering compensation ( half a texel plus compensation for filled pixel in top left corner )
+      fBlockX += oneAndAHalfTexelX;
+      fBlockY += oneAndAHalfTexelY;
 
       if (  ( widthInBlocks - 1u ) == x && vertexEdgeWidth > 0.0f )
       {
@@ -500,8 +487,10 @@ void AtlasManager::OptimizeMesh( const Toolkit::AtlasManager::Mesh2D& in,
     Toolkit::AtlasManager::Vertex2D v = in.mVertices[ in.mIndices[ i ] ];
     for ( SizeType j = 0; j < out.mVertices.Size(); ++j )
     {
-      if ( v.mPosition.x == out.mVertices[ j ].mPosition.x && v.mPosition.y == out.mVertices[ j ].mPosition.y &&
-           v.mTexCoords.x == out.mVertices[ j ].mTexCoords.x && v.mTexCoords.y == out.mVertices[ j ].mTexCoords.y )
+      if ( ( fabsf( v.mPosition.x - out.mVertices[ j ].mPosition.x ) < Math::MACHINE_EPSILON_1000 ) &&
+           ( fabsf( v.mPosition.y - out.mVertices[ j ].mPosition.y ) < Math::MACHINE_EPSILON_1000 ) &&
+           ( fabsf( v.mTexCoords.x - out.mVertices[ j ].mTexCoords.x ) < Math::MACHINE_EPSILON_1000 ) &&
+           ( fabsf( v.mTexCoords.y - out.mVertices[ j ].mTexCoords.y ) < Math::MACHINE_EPSILON_1000 ) )
       {
         // Yes, so store this down as the vertex to use
         out.mIndices.PushBack( j );
@@ -524,16 +513,22 @@ void AtlasManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
                                const Toolkit::AtlasManager::Mesh2D& second,
                                bool optimize )
 {
-  uint32_t vc = first.mVertices.Size();
+  const uint32_t verticesCount = first.mVertices.Size();
+  first.mVertices.Insert( first.mVertices.End(),
+                          second.mVertices.Begin(),
+                          second.mVertices.End() );
 
-  for ( uint32_t v = 0; v < second.mVertices.Size(); ++v )
-  {
-    first.mVertices.PushBack( second.mVertices[ v ] );
-  }
+  const uint32_t indicesCount = first.mIndices.Size();
+  first.mIndices.Insert( first.mIndices.End(),
+                         second.mIndices.Begin(),
+                         second.mIndices.End() );
 
-  for ( uint32_t i = 0; i < second.mIndices.Size(); ++i )
+  for( Vector<unsigned int>::Iterator it = first.mIndices.Begin() + indicesCount,
+         endIt = first.mIndices.End();
+       it != endIt;
+       ++it )
   {
-    first.mIndices.PushBack( second.mIndices[ i ] + vc );
+    *it += verticesCount;
   }
 
   if ( optimize )
@@ -544,41 +539,6 @@ void AtlasManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
   }
 }
 
-void AtlasManager::StitchMesh( const Toolkit::AtlasManager::Mesh2D& first,
-                               const Toolkit::AtlasManager::Mesh2D& second,
-                               Toolkit::AtlasManager::Mesh2D& out,
-                               bool optimize )
-{
-  uint32_t vc = first.mVertices.Size();
-
-  for ( uint32_t v = 0; v < vc; ++v )
-  {
-    out.mVertices.PushBack( first.mVertices[ v ] );
-  }
-
-  for ( uint32_t v = 0; v < second.mVertices.Size(); ++v )
-  {
-    out.mVertices.PushBack( second.mVertices[ v ] );
-  }
-
-  for ( uint32_t i = 0; i < first.mIndices.Size(); ++i )
-  {
-    out.mIndices.PushBack( first.mIndices[ i ] );
-  }
-
-  for ( uint32_t i = 0; i < second.mIndices.Size(); ++i )
-  {
-    out.mIndices.PushBack( second.mIndices[ i ] + vc );
-  }
-
-  if ( optimize )
-  {
-    Toolkit::AtlasManager::Mesh2D optimizedMesh;
-    OptimizeMesh( out, optimizedMesh );
-    out = optimizedMesh;
-  }
-}
-
 void AtlasManager::UploadImage( const BufferImage& image,
                                 const AtlasSlotDescriptor& desc )
 {
@@ -594,13 +554,13 @@ void AtlasManager::UploadImage( const BufferImage& image,
 
   SizeType atlasBlockWidth = mAtlasList[ atlas ].mSize.mBlockWidth;
   SizeType atlasBlockHeight = mAtlasList[ atlas ].mSize.mBlockHeight;
-  SizeType atlasWidthInBlocks = mAtlasList[ atlas ].mSize.mWidth / mAtlasList[ atlas ].mSize.mBlockWidth;
+  SizeType atlasWidthInBlocks = ( mAtlasList[ atlas ].mSize.mWidth - 1u ) / mAtlasList[ atlas ].mSize.mBlockWidth;
 
   SizeType block = desc.mBlocksList[ 0 ];
   SizeType blockX = block % atlasWidthInBlocks;
   SizeType blockY = block / atlasWidthInBlocks;
-  SizeType blockOffsetX = blockX * atlasBlockWidth;
-  SizeType blockOffsetY = blockY * atlasBlockHeight;
+  SizeType blockOffsetX = ( blockX * atlasBlockWidth ) + 1u;
+  SizeType blockOffsetY = ( blockY * atlasBlockHeight) + 1u;
 
   SizeType width = image.GetWidth();
   SizeType height = image.GetHeight();
@@ -612,10 +572,6 @@ void AtlasManager::UploadImage( const BufferImage& image,
   {
     DALI_LOG_ERROR("Uploading image to Atlas Failed!.\n");
   }
-  else
-  {
-     mUploadedImages.PushBack( const_cast< BufferImage& >( image ).GetBuffer() );
-  }
 
   // Blit top strip
   if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip,
@@ -624,10 +580,6 @@ void AtlasManager::UploadImage( const BufferImage& image,
   {
     DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n");
   }
-  else
-  {
-    mUploadedImages.PushBack( NULL );
-  }
 
   // Blit left strip
   if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip,
@@ -636,10 +588,6 @@ void AtlasManager::UploadImage( const BufferImage& image,
   {
     DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n");
   }
-  else
-  {
-    mUploadedImages.PushBack( NULL );
-  }
 
   // Blit bottom strip
   if ( blockOffsetY + height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mHeight )
@@ -650,10 +598,6 @@ void AtlasManager::UploadImage( const BufferImage& image,
     {
       DALI_LOG_ERROR("Uploading bottom strip to Atlas Failed!.\n");
     }
-    else
-    {
-     mUploadedImages.PushBack( NULL );
-    }
   }
 
   // Blit right strip
@@ -665,10 +609,6 @@ void AtlasManager::UploadImage( const BufferImage& image,
     {
       DALI_LOG_ERROR("Uploading right strip to Atlas Failed!.\n");
     }
-    else
-    {
-      mUploadedImages.PushBack( NULL );
-    }
   }
 }
 
@@ -677,29 +617,36 @@ void AtlasManager::GenerateMeshData( ImageId id,
                                      Toolkit::AtlasManager::Mesh2D& meshData,
                                      bool addReference )
 {
-  // Read the atlas Id to use for this image
-  SizeType imageId = id - 1u;
-  SizeType atlas = mImageList[ imageId ].mAtlasId - 1u;
-  SizeType width = mImageList[ imageId ].mImageWidth;
-  SizeType height = mImageList[ imageId ].mImageHeight;
-
-  SizeType widthInBlocks = width / mAtlasList[ atlas ].mSize.mBlockWidth;
-  if ( width % mAtlasList[ atlas ].mSize.mBlockWidth )
-  {
-    widthInBlocks++;
-  }
-  SizeType heightInBlocks = height / mAtlasList[ atlas ].mSize.mBlockHeight;
-  if ( height % mAtlasList[ atlas ].mSize.mBlockHeight )
+  if ( id )
   {
-    heightInBlocks++;
-  }
+    // Read the atlas Id to use for this image
+    SizeType imageId = id - 1u;
+    SizeType atlas = mImageList[ imageId ].mAtlasId - 1u;
+    SizeType width = mImageList[ imageId ].mImageWidth;
+    SizeType height = mImageList[ imageId ].mImageHeight;
 
-  CreateMesh( atlas, width, height, position, widthInBlocks, heightInBlocks, meshData, mImageList[ imageId ] );
+    SizeType widthInBlocks = width / mAtlasList[ atlas ].mSize.mBlockWidth;
+    if ( width % mAtlasList[ atlas ].mSize.mBlockWidth )
+    {
+      widthInBlocks++;
+    }
+    SizeType heightInBlocks = height / mAtlasList[ atlas ].mSize.mBlockHeight;
+    if ( height % mAtlasList[ atlas ].mSize.mBlockHeight )
+    {
+      heightInBlocks++;
+    }
+
+    CreateMesh( atlas, width, height, position, widthInBlocks, heightInBlocks, meshData, mImageList[ imageId ] );
 
-  // Mesh created so increase the reference count, if we're asked to
-  if ( addReference )
+    // Mesh created so increase the reference count, if we're asked to
+    if ( addReference )
+    {
+      mImageList[ imageId ].mCount++;
+    }
+  }
+  else
   {
-    mImageList[ imageId ].mCount++;
+    DALI_LOG_ERROR("Cannot generate mesh with invalid AtlasId\n");
   }
 }
 
@@ -763,6 +710,8 @@ AtlasManager::AtlasId AtlasManager::GetAtlas( ImageId id ) const
 void AtlasManager::SetNewAtlasSize( const Toolkit::AtlasManager::AtlasSize& size )
 {
   mNewAtlasSize = size;
+
+  // Add on padding for borders around atlas entries
   mNewAtlasSize.mBlockWidth += DOUBLE_PIXEL_PADDING;
   mNewAtlasSize.mBlockHeight += DOUBLE_PIXEL_PADDING;
 }