Merged with Tizen Branch ( builds )
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / atlas-manager / atlas-manager-impl.cpp
index 853c0ae..4a55e59 100644 (file)
@@ -20,6 +20,8 @@
 // EXTERNAL INCLUDE
 #include <iostream>
 #include <string.h>
+#include <dali/public-api/shader-effects/sampler.h>
+#include <dali/public-api/shader-effects/shader.h>
 #include <dali/integration-api/debug.h>
 
 namespace Dali
@@ -41,6 +43,47 @@ namespace
   const uint32_t DOUBLE_PIXEL_PADDING( SINGLE_PIXEL_PADDING << 1 );
   const uint32_t FILLED_PIXEL( -1 );
   Toolkit::AtlasManager::AtlasSize EMPTY_SIZE;
+
+  #define MAKE_SHADER(A)#A
+
+  const char* VERTEX_SHADER = MAKE_SHADER(
+  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;
+  }
+  );
+
+  const char* FRAGMENT_SHADER_L8 = MAKE_SHADER(
+  uniform lowp    vec4      uColor;
+  uniform         sampler2D sTexture;
+  varying mediump vec2      vTexCoord;
+
+  void main()
+  {
+    mediump vec4 color = texture2D( sTexture, vTexCoord );
+    gl_FragColor = vec4( uColor.rgb, uColor.a * color.r );
+  }
+  );
+
+  const char* FRAGMENT_SHADER_BGRA = MAKE_SHADER(
+  uniform         sampler2D sTexture;
+  varying mediump vec2      vTexCoord;
+
+  void main()
+  {
+    gl_FragColor = texture2D( sTexture, vTexCoord );
+  }
+  );
+
 }
 
 AtlasManager::AtlasManager()
@@ -87,11 +130,6 @@ Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasMa
   atlasDescriptor.mAtlas = atlas;
   atlasDescriptor.mSize = size;
   atlasDescriptor.mPixelFormat = pixelformat;
-  std::stringstream materialLabel;
-  materialLabel << "Atlas Material - ";
-  materialLabel << mAtlasList.size();
-  atlasDescriptor.mMaterial = Material::New( materialLabel.str() );
-  atlasDescriptor.mMaterial.SetDiffuseTexture( atlas );
   atlasDescriptor.mNextFreeBlock = 1u; // indicate next free block will be the first ( +1 )
 
   // What size do we need for this atlas' strip buffer ( assume 32bit pixel format )?
@@ -110,6 +148,22 @@ Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasMa
                                                      pixelformat );
   atlasDescriptor.mFilledPixelImage = BufferImage::New( reinterpret_cast< PixelBuffer* >( &mFilledPixel ), 1, 1, pixelformat );
   atlas.Upload( atlasDescriptor.mFilledPixelImage, 0, 0 );
+
+  Sampler sampler = Sampler::New( atlas, "sTexture" );
+  sampler.SetFilterMode( Sampler::NEAREST, Sampler::NEAREST );
+  sampler.SetProperty( Sampler::Property::AFFECTS_TRANSPARENCY, true );
+  Shader shader;
+  if ( pixelformat == Pixel::BGRA8888 )
+  {
+    shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_BGRA );
+  }
+  else
+  {
+    shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_L8 );
+  }
+  atlasDescriptor.mMaterial = Material::New( shader );
+  atlasDescriptor.mMaterial.AddSampler( sampler );
+  atlasDescriptor.mMaterial.SetBlendMode( BlendingMode::ON );
   mAtlasList.push_back( atlasDescriptor );
   return mAtlasList.size();
 }
@@ -169,7 +223,7 @@ void AtlasManager::Add( const BufferImage& image,
     if ( Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy || !foundAtlas-- )
     {
       // Haven't found an atlas for this image!!!!!!
-          return;
+      return;
     }
   }
 
@@ -265,16 +319,12 @@ void AtlasManager::CreateMesh( SizeType atlas,
                                const Vector2& position,
                                SizeType widthInBlocks,
                                SizeType heightInBlocks,
-                               Dali::MeshData& meshData,
+                               Toolkit::AtlasManager::Mesh2D& mesh,
                                AtlasSlotDescriptor& desc )
 {
-  Dali::MeshData::Vertex vertex;
-  Dali::MeshData::VertexContainer vertices;
-  Dali::MeshData::FaceIndices faces;
-  Dali::MeshData::FaceIndex faceIndex = 0;
-  meshData.SetHasNormals( false );
-  meshData.SetHasColor( true );
-  meshData.SetHasTextureCoords( true );
+
+  Toolkit::AtlasManager::Vertex2D vertex;
+  uint32_t faceIndex = 0;       // TODO change to unsigned short when property type is available
 
   SizeType blockWidth = mAtlasList[ atlas ].mSize.mBlockWidth;
   SizeType blockHeight = mAtlasList[ atlas ].mSize.mBlockHeight;
@@ -354,49 +404,45 @@ void AtlasManager::CreateMesh( SizeType atlas,
       }
 
       // Top left
-      vertex.x = topLeft.x;
-      vertex.y = topLeft.y;
-      vertex.z = 0.0f;
-      vertex.u = fBlockX;
-      vertex.v = fBlockY;
+      vertex.mPosition.x = topLeft.x;
+      vertex.mPosition.y = topLeft.y;
+      vertex.mTexCoords.x = fBlockX;
+      vertex.mTexCoords.y = fBlockY;
 
-      vertices.push_back( vertex );
+      mesh.mVertices.PushBack( vertex );
 
       // Top Right
-      vertex.x = topLeft.x + ndcVWidth;
-      vertex.y = topLeft.y;
-      vertex.z = 0.0f;
-      vertex.u = fBlockX + ndcWidth;
-      vertex.v = fBlockY;
+      vertex.mPosition.x = topLeft.x + ndcVWidth;
+      vertex.mPosition.y = topLeft.y;
+      vertex.mTexCoords.x = fBlockX + ndcWidth;
+      vertex.mTexCoords.y = fBlockY;
 
-      vertices.push_back( vertex );
+      mesh.mVertices.PushBack( vertex );
 
       // Bottom Left
-      vertex.x = topLeft.x;
-      vertex.y = topLeft.y + ndcVHeight;
-      vertex.z = 0.0f;
-      vertex.u = fBlockX;
-      vertex.v = fBlockY + ndcHeight;
+      vertex.mPosition.x = topLeft.x;
+      vertex.mPosition.y = topLeft.y + ndcVHeight;
+      vertex.mTexCoords.x = fBlockX;
+      vertex.mTexCoords.y = fBlockY + ndcHeight;
 
-      vertices.push_back( vertex );
+      mesh.mVertices.PushBack( vertex );
 
       // Bottom Right
       topLeft.x += ndcVWidth;
-      vertex.x = topLeft.x;
-      vertex.y = topLeft.y + ndcVHeight;
-      vertex.z = 0.0f;
-      vertex.u = fBlockX + ndcWidth;
-      vertex.v = fBlockY + ndcHeight;
+      vertex.mPosition.x = topLeft.x;
+      vertex.mPosition.y = topLeft.y + ndcVHeight;
+      vertex.mTexCoords.x = fBlockX + ndcWidth;
+      vertex.mTexCoords.y = fBlockY + ndcHeight;
 
-      vertices.push_back( vertex );
+      mesh.mVertices.PushBack( vertex );
 
       // Six indices in counter clockwise winding
-      faces.push_back( faceIndex + 1u );
-      faces.push_back( faceIndex );
-      faces.push_back( faceIndex + 2u );
-      faces.push_back( faceIndex + 2u );
-      faces.push_back( faceIndex + 3u );
-      faces.push_back( faceIndex + 1u );
+      mesh.mIndices.PushBack( faceIndex + 1u );
+      mesh.mIndices.PushBack( faceIndex );
+      mesh.mIndices.PushBack( faceIndex + 2u );
+      mesh.mIndices.PushBack( faceIndex + 2u );
+      mesh.mIndices.PushBack( faceIndex + 3u );
+      mesh.mIndices.PushBack( faceIndex + 1u );
       faceIndex += 4;
     }
 
@@ -408,62 +454,53 @@ void AtlasManager::CreateMesh( SizeType atlas,
   // If there's only one block then skip this next vertex optimisation
   if ( widthInBlocks * heightInBlocks > 1 )
   {
-    Dali::MeshData::VertexContainer optimizedVertices;
-    OptimizeVertices( vertices, faces, optimizedVertices );
-    meshData.SetVertices( optimizedVertices );
+    Toolkit::AtlasManager::Mesh2D optimizedMesh;
+    OptimizeMesh( mesh, optimizedMesh );
   }
-  else
-  {
-    meshData.SetVertices( vertices );
-  }
-
-  meshData.SetFaceIndices( faces );
-  meshData.SetMaterial( mAtlasList[ atlas ].mMaterial );
+  //PrintMeshData( mesh );
 }
 
-void AtlasManager::PrintMeshData( const MeshData& meshData )
+void AtlasManager::PrintMeshData( const Toolkit::AtlasManager::Mesh2D& mesh )
 {
-  std::cout << "\nMesh Data for Image: VertexCount = " << meshData.GetVertexCount();
-  std::cout << ", Triangles = " << meshData.GetFaceCount() << std::endl;
-
-  Dali::MeshData::VertexContainer vertices = meshData.GetVertices();
-  Dali::MeshData::FaceIndices faces = meshData.GetFaces();
+  uint32_t vertexCount = mesh.mVertices.Size();
+  uint32_t indexCount = mesh.mIndices.Size();
+  std::cout << "\nMesh Data for Image: VertexCount = " << vertexCount;
+  std::cout << ", Triangles = " << indexCount / 3 << std::endl;
 
-  for ( SizeType v = 0; v < vertices.size(); ++v )
+  for ( SizeType v = 0; v < vertexCount; ++v )
   {
-    std::cout << " Vertex(" << v << ") x = " << vertices[v].x << ", ";
-    std::cout << "y = " << vertices[v].y << ", " << "z = " << vertices[v].z << ", ";
-    std::cout << "u = " << vertices[v].u << ", " << "v = " << vertices[v].v << std::endl;
+    std::cout << " Vertex(" << v << ") x = " << mesh.mVertices[v].mPosition.x << ", ";
+    std::cout << "y = " << mesh.mVertices[v].mPosition.y << ", ";
+    std::cout << "u = " << mesh.mVertices[v].mTexCoords.x << ", ";
+    std::cout << "v = " << mesh.mVertices[v].mTexCoords.y << std::endl;
   }
 
   std::cout << "\n Indices: ";
-  for ( SizeType i = 0; i < faces.size(); ++i )
+  for ( SizeType i = 0; i < indexCount; ++i )
   {
-    std::cout << " " << faces[ i ];
+    std::cout << " " << mesh.mIndices[ i ];
   }
   std::cout << std::endl;
 }
 
-void AtlasManager::OptimizeVertices( const MeshData::VertexContainer& in,
-                                     MeshData::FaceIndices& faces,
-                                     MeshData::VertexContainer& out )
+void AtlasManager::OptimizeMesh( const Toolkit::AtlasManager::Mesh2D& in,
+                                 Toolkit::AtlasManager::Mesh2D& out )
 {
   unsigned short vertexIndex = 0;
 
   // We could check to see if blocks are next to each other, but it's probably just as quick to compare verts
-  for ( SizeType i = 0; i < faces.size(); ++i )
+  for ( SizeType i = 0; i < in.mIndices.Size(); ++i )
   {
     // Fetch a vertex, has it already been assigned?
     bool foundVertex = false;
-    Dali::MeshData::Vertex v = in[ faces [ i ] ];
-    for ( SizeType j = 0; j < vertexIndex; ++j )
+    Toolkit::AtlasManager::Vertex2D v = in.mVertices[ in.mIndices[ i ] ];
+    for ( SizeType j = 0; j < out.mVertices.Size(); ++j )
     {
-      if ( v.x == out[ j ].x && v.y == out[ j ].y && v.z == out[ j ].z &&
-           v.u == out[ j ].u && v.v == out[ j ].v && v.nX == out[ j ].nX &&
-           v.nY == out[ j ].nY && v.nZ == out[ j ].nZ )
+      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 )
       {
         // Yes, so store this down as the vertex to use
-        faces[ i ] = j;
+        out.mIndices.PushBack( j );
         foundVertex = true;
         break;
       }
@@ -472,103 +509,70 @@ void AtlasManager::OptimizeVertices( const MeshData::VertexContainer& in,
     // Did we find a vertex ?
     if ( !foundVertex )
     {
-      // Add a new vertex
-      faces[ i ] = vertexIndex++;
-      out.push_back( v );
+      // No so add a new one
+      out.mVertices.PushBack( v );
+      vertexIndex++;
     }
   }
 }
 
-void AtlasManager::StitchMesh( MeshData& first,
-                               const MeshData& second,
+void AtlasManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
+                               const Toolkit::AtlasManager::Mesh2D& second,
                                bool optimize )
 {
+  uint32_t vc = first.mVertices.Size();
 
-  // Would be much quicker to be able to get a non-const reference to these containers and update in situ
-  MeshData::VertexContainer v1 = first.GetVertices();
-  MeshData::VertexContainer v2 = second.GetVertices();
-  MeshData::FaceIndices f1 = first.GetFaces();
-  MeshData::FaceIndices f2 = second.GetFaces();
-
-  uint32_t vc1 = first.GetVertexCount();
-  uint32_t vc2 = second.GetVertexCount();
-
-  for ( uint32_t v = 0; v < vc2; ++v )
+  for ( uint32_t v = 0; v < second.mVertices.Size(); ++v )
   {
-    v1.push_back( v2[ v ] );
+    first.mVertices.PushBack( second.mVertices[ v ] );
   }
 
-  for ( uint32_t f = 0; f < f2.size(); ++f )
+  for ( uint32_t i = 0; i < second.mIndices.Size(); ++i )
   {
-    f1.push_back( f2[ f ] + vc1 );
+    first.mIndices.PushBack( second.mIndices[ i ] + vc );
   }
 
   if ( optimize )
   {
-    MeshData::VertexContainer optimizedVertices;
-    OptimizeVertices( v1, f1, optimizedVertices );
-    first.SetVertices( optimizedVertices );
+    Toolkit::AtlasManager::Mesh2D optimizedMesh;
+    OptimizeMesh( first, optimizedMesh );
+    first = optimizedMesh;
   }
-  else
-  {
-    first.SetVertices( v1 );
-  }
-
-  first.SetFaceIndices( f1 );
 }
 
-void AtlasManager::StitchMesh( const MeshData& first,
-                               const MeshData& second,
-                               MeshData& out,
+void AtlasManager::StitchMesh( const Toolkit::AtlasManager::Mesh2D& first,
+                               const Toolkit::AtlasManager::Mesh2D& second,
+                               Toolkit::AtlasManager::Mesh2D& out,
                                bool optimize )
 {
-  MeshData::VertexContainer v1 = first.GetVertices();
-  MeshData::VertexContainer v2 = second.GetVertices();
-  MeshData::FaceIndices f1 = first.GetFaces();
-  MeshData::FaceIndices f2 = second.GetFaces();
-
-  uint32_t vc1 = first.GetVertexCount();
-  uint32_t vc2 = second.GetVertexCount();
-
-  MeshData::VertexContainer vertices;
+  uint32_t vc = first.mVertices.Size();
 
-  MeshData::FaceIndices faces;
-
-  MeshData::Vertex vertex;
-
-  for ( uint32_t v = 0; v < vc1; ++v )
+  for ( uint32_t v = 0; v < vc; ++v )
   {
-    vertices.push_back( v1[ v ] );
+    out.mVertices.PushBack( first.mVertices[ v ] );
   }
 
-  for ( uint32_t v = 0; v < vc2; ++v )
+  for ( uint32_t v = 0; v < second.mVertices.Size(); ++v )
   {
-    vertices.push_back( v2[ v  ] );
+    out.mVertices.PushBack( second.mVertices[ v ] );
   }
 
-  for ( uint32_t f = 0; f < f1.size(); ++f )
+  for ( uint32_t i = 0; i < first.mIndices.Size(); ++i )
   {
-    faces.push_back( f1[ f ] );
+    out.mIndices.PushBack( first.mIndices[ i ] );
   }
 
-  for ( uint32_t f = 0; f < f2.size(); ++f )
+  for ( uint32_t i = 0; i < second.mIndices.Size(); ++i )
   {
-    faces.push_back( f2[ f ] + vc1 );
+    out.mIndices.PushBack( second.mIndices[ i ] + vc );
   }
 
   if ( optimize )
   {
-    MeshData::VertexContainer optimizedVertices;
-    OptimizeVertices( vertices, faces, optimizedVertices );
-    out.SetVertices( optimizedVertices );
-  }
-  else
-  {
-    out.SetVertices( vertices );
+    Toolkit::AtlasManager::Mesh2D optimizedMesh;
+    OptimizeMesh( out, optimizedMesh );
+    out = optimizedMesh;
   }
-
-  out.SetMaterial( first.GetMaterial() );
-  out.SetFaceIndices( faces );
 }
 
 void AtlasManager::UploadImage( const BufferImage& image,
@@ -651,7 +655,7 @@ void AtlasManager::UploadImage( const BufferImage& image,
 
 void AtlasManager::GenerateMeshData( ImageId id,
                                      const Vector2& position,
-                                     MeshData& meshData )
+                                     Toolkit::AtlasManager::Mesh2D& meshData )
 {
   // Read the atlas Id to use for this image
   SizeType imageId = id - 1u;
@@ -826,6 +830,15 @@ void AtlasManager::GetMetrics( Toolkit::AtlasManager::Metrics& metrics )
   metrics.mTextureMemoryUsed = textureMemoryUsed;
 }
 
+Material AtlasManager::GetMaterial( AtlasId atlas ) const
+{
+  if ( atlas && atlas <= mAtlasList.size() )
+  {
+    return mAtlasList[ atlas -1u ].mMaterial;
+  }
+  Material null;
+  return null;
+}
 
 } // namespace Internal