// EXTERNAL INCLUDE
#include <iostream>
#include <string.h>
+#include <dali/devel-api/rendering/sampler.h>
+#include <dali/devel-api/rendering/shader.h>
#include <dali/integration-api/debug.h>
namespace Dali
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_RGBA = MAKE_SHADER(
+ uniform sampler2D sTexture;
+ varying mediump vec2 vTexCoord;
+
+ void main()
+ {
+ gl_FragColor = texture2D( sTexture, vTexCoord );
+ }
+ );
+
}
AtlasManager::AtlasManager()
mNewAtlasSize.mHeight = DEFAULT_ATLAS_HEIGHT;
mNewAtlasSize.mBlockWidth = DEFAULT_BLOCK_WIDTH;
mNewAtlasSize.mBlockHeight = DEFAULT_BLOCK_HEIGHT;
+ mShaderL8 = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_L8 );
+ mShaderRgba = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_RGBA );
}
AtlasManagerPtr AtlasManager::New()
AtlasManager::~AtlasManager()
{
- for ( uint32_t i = 0; i < mAtlasList.size(); ++i )
+ 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 )
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 )
+ atlas.UploadedSignal().Connect( this, &AtlasManager::OnUpload );
// What size do we need for this atlas' strip buffer ( assume 32bit pixel format )?
- uint32_t neededStripSize =( blockWidth > blockHeight - DOUBLE_PIXEL_PADDING ? blockWidth : blockHeight - DOUBLE_PIXEL_PADDING ) << 2;
+ SizeType neededStripSize =( blockWidth > blockHeight - DOUBLE_PIXEL_PADDING ? blockWidth : blockHeight - DOUBLE_PIXEL_PADDING ) << 2;
atlasDescriptor.mStripBuffer = new PixelBuffer[ neededStripSize ];
memset( atlasDescriptor.mStripBuffer, 0, neededStripSize );
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 );
+
+ Sampler sampler = Sampler::New( atlas, "sTexture" );
+ sampler.SetProperty( Sampler::Property::AFFECTS_TRANSPARENCY, true );
+ atlasDescriptor.mMaterial = Material::New( pixelformat == Pixel::L8 ? mShaderL8 : mShaderRgba );
+ atlasDescriptor.mMaterial.AddSampler( sampler );
+ atlasDescriptor.mSampler = sampler;
+ atlasDescriptor.mMaterial.SetBlendMode( BlendingMode::ON );
mAtlasList.push_back( atlasDescriptor );
return mAtlasList.size();
}
if ( Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy || !foundAtlas-- )
{
// Haven't found an atlas for this image!!!!!!
- return;
+ return;
}
}
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;
}
// 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;
}
// 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 );
- }
- else
- {
- meshData.SetVertices( vertices );
+ Toolkit::AtlasManager::Mesh2D optimizedMesh;
+ OptimizeMesh( mesh, optimizedMesh );
}
-
- 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;
+ 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;
- Dali::MeshData::VertexContainer vertices = meshData.GetVertices();
- Dali::MeshData::FaceIndices faces = meshData.GetFaces();
-
- 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;
}
// 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 );
- }
- else
- {
- first.SetVertices( v1 );
+ Toolkit::AtlasManager::Mesh2D optimizedMesh;
+ OptimizeMesh( first, optimizedMesh );
+ first = optimizedMesh;
}
-
- 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;
-
- MeshData::FaceIndices faces;
-
- MeshData::Vertex vertex;
+ uint32_t vc = first.mVertices.Size();
- 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 );
+ Toolkit::AtlasManager::Mesh2D optimizedMesh;
+ OptimizeMesh( out, optimizedMesh );
+ out = optimizedMesh;
}
- else
- {
- out.SetVertices( vertices );
- }
-
- out.SetMaterial( first.GetMaterial() );
- out.SetFaceIndices( faces );
}
void AtlasManager::UploadImage( const BufferImage& image,
{
DALI_LOG_ERROR("Uploading image to Atlas Failed!.\n");
}
+ else
+ {
+ mUploadedImages.PushBack( const_cast< BufferImage& >( image ).GetBuffer() );
+ }
// If this is the first block then we need to keep the first pixel free for underline texture
if ( block )
{
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,
{
DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n");
}
+ else
+ {
+ mUploadedImages.PushBack( NULL );
+ }
}
// Blit bottom strip
{
DALI_LOG_ERROR("Uploading bottom strip to Atlas Failed!.\n");
}
+ else
+ {
+ mUploadedImages.PushBack( NULL );
+ }
}
// Blit right strip
{
DALI_LOG_ERROR("Uploading right strip to Atlas Failed!.\n");
}
+ else
+ {
+ mUploadedImages.PushBack( NULL );
+ }
}
}
void AtlasManager::GenerateMeshData( ImageId id,
const Vector2& position,
- MeshData& meshData,
+ Toolkit::AtlasManager::Mesh2D& meshData,
bool addReference )
{
// Read the atlas Id to use for this image
metrics.mTextureMemoryUsed = textureMemoryUsed;
}
+Material AtlasManager::GetMaterial( AtlasId atlas ) const
+{
+ if ( atlas && atlas <= mAtlasList.size() )
+ {
+ return mAtlasList[ atlas -1u ].mMaterial;
+ }
+ Material null;
+ return null;
+}
+
+Sampler AtlasManager::GetSampler( AtlasId atlas ) const
+{
+ if ( atlas && atlas <= mAtlasList.size() )
+ {
+ return mAtlasList[ atlas -1u ].mSampler;
+ }
+ Sampler null;
+ return null;
+}
+
} // namespace Internal
} // namespace Toolkit