X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fatlas-manager%2Fatlas-manager-impl.cpp;h=a3b9e863977f8e2850fc4a1431a2ca2e2447bc4c;hp=266e8b9568714f78fe8327f42bd1d43befad6db2;hb=e17b07e400e696c5427f5ddbafb5274cd22f9bb7;hpb=22067c2397a2fe37a04c5722c5c23346795f6191 diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp index 266e8b9..a3b9e86 100644 --- a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp +++ b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp @@ -20,6 +20,8 @@ // EXTERNAL INCLUDE #include #include +#include +#include #include 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_RGBA = MAKE_SHADER( + uniform sampler2D sTexture; + varying mediump vec2 vTexCoord; + + void main() + { + gl_FragColor = texture2D( sTexture, vTexCoord ); + } + ); + } AtlasManager::AtlasManager() @@ -51,6 +94,8 @@ 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() @@ -61,10 +106,30 @@ 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 ) @@ -87,15 +152,11 @@ 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 ) + 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 ); @@ -108,8 +169,16 @@ Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasMa 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(); } @@ -169,7 +238,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 +334,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 +419,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 +469,55 @@ 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 ); - } - 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 ( ( 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 - faces[ i ] = j; + out.mIndices.PushBack( j ); foundVertex = true; break; } @@ -472,103 +526,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 ); - } - 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, @@ -604,6 +625,10 @@ 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 ) @@ -616,6 +641,10 @@ 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, @@ -624,6 +653,10 @@ void AtlasManager::UploadImage( const BufferImage& image, { DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n"); } + else + { + mUploadedImages.PushBack( NULL ); + } } // Blit bottom strip @@ -635,6 +668,10 @@ void AtlasManager::UploadImage( const BufferImage& image, { DALI_LOG_ERROR("Uploading bottom strip to Atlas Failed!.\n"); } + else + { + mUploadedImages.PushBack( NULL ); + } } // Blit right strip @@ -646,12 +683,16 @@ void AtlasManager::UploadImage( const BufferImage& image, { 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 @@ -830,6 +871,26 @@ 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; +} + +Sampler AtlasManager::GetSampler( AtlasId atlas ) const +{ + if ( atlas && atlas <= mAtlasList.size() ) + { + return mAtlasList[ atlas -1u ].mSampler; + } + Sampler null; + return null; +} + } // namespace Internal } // namespace Toolkit