using namespace Dali;
+namespace
+{
+static const char* gTestImageFilename = "icon_wrt.png";
+
+void PrepareResourceImage( TestApplication& application, unsigned int imageHeight, unsigned int imageWidth, Pixel::Format pixelFormat )
+{
+ TestPlatformAbstraction& platform = application.GetPlatform();
+ platform.SetClosestImageSize(Vector2( 16, 16));
+
+ Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::RETAIN );
+ Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight );
+ unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat );
+ unsigned int initialColor = 0xFF;
+ memset( pixbuffer, initialColor, imageHeight*imageWidth*bytesPerPixel);
+
+ Integration::ResourcePointer resourcePtr(bitmap);
+ platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+}
+
+}
+
void utc_dali_atlas_startup(void)
{
test_return_value = TET_UNDEF;
END_TEST;
}
+
// 1.2
int UtcDaliAtlasUpload01(void)
{
// Using correct pixel format
PixelBuffer* buffer = new PixelBuffer[16 * 16];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-
DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
+ PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) );
+
END_TEST;
}
// Using INCORRECT pixel format
PixelBuffer* buffer = new PixelBuffer[16 * 16];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::A8 );
-
DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+ PrepareResourceImage( application, 16, 16, Pixel::A8 );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+
END_TEST;
}
// Using image too big for atlas
PixelBuffer* buffer = new PixelBuffer[16 * 16];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
-
DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+ PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+
END_TEST;
}
DALI_TEST_CHECK( atlas.Upload( image, 0, 16 ) );
DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) );
+ PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) );
+ DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 0 ) );
+ DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 16 ) );
+ DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 16 ) );
+
END_TEST;
}
DALI_TEST_CHECK( !atlas.Upload( image, 0, 99 ) );
DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) );
+ PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 17 ) );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 0 ) );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 17 ) );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 0 ) );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 99 ) );
+ DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 99 ) );
+
END_TEST;
}
// INTERNAL INCLUDES
#include <dali/public-api/object/type-registry.h>
#include <dali/internal/event/common/thread-local-storage.h>
-#include <dali/internal/event/images/buffer-image-impl.h>
+
+#include <dali/internal/event/images/image-factory.h>
#include <dali/internal/event/resources/resource-client.h>
#include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/platform-abstraction.h>
namespace Dali
{
TypeRegistration mType( typeid( Dali::Atlas ), typeid( Dali::Image ), NULL );
}
-Atlas* Atlas::New( std::size_t width,
- std::size_t height,
- Pixel::Format pixelFormat )
+Atlas* Atlas::New( SizeType width,
+ SizeType height,
+ Pixel::Format pixelFormat,
+ bool recoverContext)
{
- return new Atlas( width, height, pixelFormat );
+ return new Atlas( width, height, pixelFormat, recoverContext );
}
-bool Atlas::Upload( const BufferImage& bufferImage,
- std::size_t xOffset,
- std::size_t yOffset )
+void Atlas::Clear(const Vector4& color)
{
- bool uploadSuccess( false );
+ ClearCache();
+ ClearBackground( color );
+}
- AllocateAtlas();
+bool Atlas::Upload( BufferImage& bufferImage,
+ SizeType xOffset,
+ SizeType yOffset )
+{
+ bool uploadSuccess( false );
- if( IsWithin(bufferImage, xOffset, yOffset) )
+ if( Compatible(bufferImage.GetPixelFormat(),
+ xOffset + bufferImage.GetWidth(),
+ yOffset + bufferImage.GetHeight() ) )
{
+ AllocateAtlas();
ResourceId destId = GetResourceId();
ResourceId srcId = bufferImage.GetResourceId();
return uploadSuccess;
}
+bool Atlas::Upload( const std::string& url,
+ SizeType xOffset,
+ SizeType yOffset)
+{
+ bool uploadSuccess( false );
+
+ ResourceId destId = GetResourceId();
+
+ if( destId )
+ {
+ Integration::BitmapPtr bitmap = LoadBitmap( url );
+
+ if( bitmap && Compatible(bitmap->GetPixelFormat(), xOffset + bitmap->GetImageWidth(), yOffset + bitmap->GetImageHeight()) )
+ {
+ AllocateAtlas();
+ mResourceClient.UploadBitmap( destId, bitmap, xOffset, yOffset );
+
+ if( mRecoverContext )
+ {
+ mTiles.PushBack( new Tile(xOffset, yOffset, url) );
+ }
+ uploadSuccess = true;
+ }
+ }
+
+ return uploadSuccess;
+}
+
+void Atlas::RecoverFromContextLoss()
+{
+ ResourceId destId = GetResourceId();
+ if( destId )
+ {
+ if( mClear )
+ {
+ ClearBackground( mClearColor );
+ }
+
+ if( mRecoverContext )
+ {
+ // Restore the atlas by re-uploading the url resources
+ Vector< Tile* >::ConstIterator end = mTiles.End();
+ for( Vector<Tile*>::Iterator iter = mTiles.Begin(); iter != end; iter++ )
+ {
+ Integration::BitmapPtr bitmap = LoadBitmap( (*iter)->url );
+ mResourceClient.UploadBitmap( destId, bitmap, (*iter)->xOffset, (*iter)->yOffset );
+ }
+ }
+ }
+}
+
Atlas::~Atlas()
{
ReleaseAtlas();
}
-Atlas::Atlas( std::size_t width,
- std::size_t height,
- Pixel::Format pixelFormat )
+Atlas::Atlas( SizeType width,
+ SizeType height,
+ Pixel::Format pixelFormat,
+ bool recoverContext )
: mResourceClient( ThreadLocalStorage::Get().GetResourceClient() ),
- mPixelFormat( pixelFormat )
+ mImageFactory( ThreadLocalStorage::Get().GetImageFactory() ),
+ mClearColor( Vector4::ZERO ),
+ mPixelFormat( pixelFormat ),
+ mClear( false ),
+ mRecoverContext( recoverContext )
{
mWidth = width;
mHeight = height;
}
}
-bool Atlas::IsWithin( const BufferImage& bufferImage,
- std::size_t xOffset,
- std::size_t yOffset )
+bool Atlas::Compatible( Pixel::Format pixelFormat,
+ SizeType x,
+ SizeType y )
{
- bool within(false);
+ bool Compatible(false);
- if( mPixelFormat != bufferImage.GetPixelFormat() )
+ if( mPixelFormat != pixelFormat )
{
- DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", bufferImage.GetPixelFormat(), mPixelFormat );
+ DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", pixelFormat, mPixelFormat );
}
else
{
- const unsigned int width = bufferImage.GetWidth();
- const unsigned int height = bufferImage.GetHeight();
-
- if( xOffset < mWidth &&
- yOffset < mHeight &&
- xOffset+width <= mWidth &&
- yOffset+height <= mHeight )
+ if( x <= mWidth && y <= mHeight )
{
- within = true;
+ Compatible = true;
}
else
{
- DALI_LOG_ERROR( "%dx%d image does not fit at offset %d,%d\n", width, height, xOffset, yOffset );
+ DALI_LOG_ERROR( "image does not fit within the atlas \n" );
}
}
- return within;
+ return Compatible;
}
void Atlas::AllocateAtlas()
if( !mTicket )
{
mTicket = mResourceClient.AllocateTexture( mWidth, mHeight, mPixelFormat );
+ mImageFactory.RegisterForContextRecovery( this );
}
}
void Atlas::ReleaseAtlas()
{
mTicket.Reset();
+ ClearCache();
+ mImageFactory.UnregisterFromContextRecovery( this );
+}
+
+void Atlas::ClearBackground(const Vector4& color )
+{
+ AllocateAtlas();
+ ResourceId destId = GetResourceId();
+ if( destId )
+ {
+ const unsigned int numPixels = mWidth * mHeight;
+ unsigned int bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
+ BufferImagePtr imageData = BufferImage::New( mWidth, mHeight, mPixelFormat );
+ PixelBuffer* pixbuf = imageData->GetBuffer();
+
+ // converting color value from float 0.f~1.f to byte 0~255
+ unsigned char r = static_cast<unsigned char>( 255.f * Clamp( color.r, 0.f, 1.f ) );
+ unsigned char g = static_cast<unsigned char>( 255.f * Clamp( color.g, 0.f, 1.f ) );
+ unsigned char b = static_cast<unsigned char>( 255.f * Clamp( color.b, 0.f, 1.f ) );
+ unsigned char a = static_cast<unsigned char>( 255.f * Clamp( color.a, 0.f, 1.f ) );
+ if( mPixelFormat == Pixel::RGBA8888 )
+ {
+ // For little-endian byte order, the RGBA channels needs to be reversed for bit shifting.
+ uint32_t clearColor = ( (uint32_t) a<<24 | (uint32_t)b << 16 | (uint32_t)g << 8 | (uint32_t)r );
+ uint32_t* buf = (uint32_t *) pixbuf;
+ for( unsigned int i = 0; i < numPixels; ++i )
+ {
+ buf[i] = clearColor;
+ }
+ }
+ else if( mPixelFormat == Pixel::RGB888 )
+ {
+ for( unsigned int i = 0; i < numPixels; ++i )
+ {
+ pixbuf[i*bytesPerPixel] = r;
+ pixbuf[i*bytesPerPixel+1] = g;
+ pixbuf[i*bytesPerPixel+2] = b;
+ }
+ }
+ else if( mPixelFormat == Pixel::A8 )
+ {
+ memset( pixbuf, a, numPixels );
+ }
+
+ RectArea area;
+ imageData->Update(area);
+
+ mClearColor = color;
+ mClear = true;
+ mResourceClient.UploadBitmap( destId, imageData->GetResourceId(), 0, 0 );
+ }
+}
+
+void Atlas::ClearCache()
+{
+ Vector< Tile* >::ConstIterator end = mTiles.End();
+ for( Vector<Tile*>::Iterator iter = mTiles.Begin(); iter != end; iter++ )
+ {
+ delete *iter;
+ }
+ mTiles.Clear();
+}
+
+Integration::BitmapPtr Atlas::LoadBitmap( const std::string& url )
+{
+ ImageAttributes loadedAttrs;
+ Integration::BitmapResourceType resourceType( loadedAttrs );
+ Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
+
+ Integration::ResourcePointer resource = platformAbstraction.LoadResourceSynchronously(resourceType, url);
+ Integration::BitmapPtr bitmap = static_cast<Integration::Bitmap*>( resource.Get());
+
+ return bitmap;
}
} // namespace Internal
*/
// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/images/atlas.h>
+#include <dali/internal/event/images/context-recovery-interface.h>
#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/event/images/buffer-image-impl.h>
namespace Dali
{
class ResourceClient;
+typedef Dali::Atlas::SizeType SizeType;
+
/**
- * @brief An Atlas is a large image containing multiple smaller images.
- *
- * Bitmap images must be uploaded at a specified position, to populate the Atlas.
- * The client is reponsible for generating the appropriate geometry (UV coordinates),
- * needed to draw images within the Atlas.
+ * Internal class for Dali::Atlas
*/
-class Atlas : public Image
+class Atlas : public Image, public ContextRecoveryInterface
{
public:
*
* @pre width & height are greater than zero.
* The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
- * @param [in] width The atlas width in pixels.
- * @param [in] height The atlas height in pixels.
- * @param [in] pixelFormat The pixel format (rgba 32 bit by default).
+ * @param [in] width The atlas width in pixels.
+ * @param [in] height The atlas height in pixels.
+ * @param [in] pixelFormat The pixel format.
+ * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context
* @return A pointer to a new Atlas.
*/
- static Atlas* New( std::size_t width,
- std::size_t height,
- Pixel::Format pixelFormat = Pixel::RGBA8888 );
+ static Atlas* New( SizeType width,
+ SizeType height,
+ Pixel::Format pixelFormat,
+ bool recoverContext);
/**
- * @brief Upload a buffer image to the atlas.
- *
- * @pre The bitmap pixel format must match the Atlas format.
- * @param [in] bufferImage The buffer image to upload.
- * @param [in] xOffset Specifies an offset in the x direction within the atlas.
- * @param [in] yOffset Specifies an offset in the y direction within the atlas.
- * @return True if the bitmap fits within the atlas at the specified offset.
+ * @copydoc Dali::Atlas::Clear
+ */
+ void Clear( const Vector4& color );
+
+ /**
+ * @copydoc Dali::Atlas::Upload( const BufferImage&, unsigned int, unsigned int )
*/
- bool Upload( const BufferImage& bufferImage,
- std::size_t xOffset,
- std::size_t yOffset );
+ bool Upload( BufferImage& bufferImage,
+ SizeType xOffset,
+ SizeType yOffset );
+
+ /**
+ * @copydoc Dali::Atlas::Upload( const std::string&, unsigned int, unsigned int )
+ */
+ bool Upload( const std::string& url,
+ SizeType xOffset,
+ SizeType yOffset );
+
+ /**
+ * @copydoc ContextRecoveryInterface::RecoverFromContextLoss
+ */
+ virtual void RecoverFromContextLoss();
protected:
*
* @pre width & height are greater than zero.
* The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
- * @param [in] width The atlas width in pixels.
- * @param [in] height The atlas height in pixels.
- * @param [in] pixelFormat The pixel format (rgba 32 bit by default).
+ * @param [in] width The atlas width in pixels.
+ * @param [in] height The atlas height in pixels.
+ * @param [in] pixelFormat The pixel format.
+ * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context
*/
- Atlas( std::size_t width,
- std::size_t height,
- Pixel::Format pixelFormat );
+ Atlas( SizeType width,
+ SizeType height,
+ Pixel::Format pixelFormat,
+ bool recoverContext);
/**
* A reference counted object may only be deleted by calling Unreference()
/**
* Helper for Upload methods
- * @return True if the bitmap fits within the atlas at the specified offset
+ * @return True if the bitmap has the same pixel format and its size fits within the atlas at the specified offset
*/
- bool IsWithin( const BufferImage& bufferImage,
- std::size_t xOffset,
- std::size_t yOffset );
-
+ bool Compatible( Pixel::Format pixelFormat,
+ SizeType x,
+ SizeType y );
/**
* Helper to create the Atlas resource
*/
*/
void ReleaseAtlas();
+ /**
+ * Upload a bitmap with the given color to clear the background.
+ */
+ void ClearBackground( const Vector4& color );
+
+ /**
+ * Clear all the current tiles and resources of the atlas
+ */
+ void ClearCache();
+
+ /**
+ * Load the bitmap data from the url
+ */
+ Integration::BitmapPtr LoadBitmap( const std::string& url );
+
private:
- ResourceClient& mResourceClient;
+ /**
+ * Record of the url resource in the Atlas.
+ */
+ struct Tile
+ {
+ Tile( SizeType xOffset, SizeType yOffset, const std::string& url )
+ : xOffset( xOffset ), yOffset( yOffset ), url(url)
+ {}
+
+ ~Tile(){};
+
+ SizeType xOffset; ///< Offset in the x direction within the atlas
+ SizeType yOffset; ///< Offset in the y direction within the atlas
+ std::string url; ///< The URL of the resource image file to use
+
+ private:
+ Tile(const Tile& rhs); ///< not defined
+ Tile& operator=(const Tile& rhs); ///< not defined
+ };
+
+private:
- Pixel::Format mPixelFormat;
+ ResourceClient& mResourceClient;
+ ImageFactory& mImageFactory;
+ Vector4 mClearColor; ///< The background clear color
+ Vector<Tile*> mTiles; ///< The url resources, which would recover automatically when regaining context
+ Pixel::Format mPixelFormat; ///< The pixel format (rgba 32 bit by default)
+ bool mClear:1; ///< Clear the backgound or not
+ bool mRecoverContext:1; ///< Re-upload the url resources or not when regaining context
};
} // namespace Internal
--- /dev/null
+#ifndef __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
+#define __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Abstract interface for Context Recovery
+ *
+ */
+class ContextRecoveryInterface
+{
+
+public:
+
+ /**
+ * Restore the object after context loss
+ */
+ virtual void RecoverFromContextLoss() = 0;
+
+protected:
+
+ /**
+ * Constructor
+ */
+ ContextRecoveryInterface()
+ {
+ }
+ /**
+ * Destructor.
+ */
+ virtual ~ContextRecoveryInterface()
+ {
+ }
+
+private:
+
+ // Undefined copy constructor.
+ ContextRecoveryInterface( const ContextRecoveryInterface& );
+
+ // Undefined assignment operator.
+ ContextRecoveryInterface& operator=( const ContextRecoveryInterface& );
+
+};
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
}
}
}
+
+ Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+ for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+ iter != end; iter++)
+ {
+ (*iter)->RecoverFromContextLoss();
+ }
+}
+
+
+void ImageFactory::RegisterForContextRecovery( ContextRecoveryInterface* object )
+{
+ bool exist( false );
+ // To avoid registering the same object again
+ Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+ for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+ iter != end; iter++)
+ {
+ if( object == *(iter) )
+ {
+ exist = true;
+ break;
+ }
+ }
+ if( !exist )
+ {
+ mContextRecoveryList.PushBack( object );
+ }
+}
+void ImageFactory::UnregisterFromContextRecovery( ContextRecoveryInterface* object )
+{
+ Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+ for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+ iter != end; iter++ )
+ {
+ if( object == *(iter) )
+ {
+ iter = mContextRecoveryList.Erase( iter );
+ break;
+ }
+ }
}
const std::string& ImageFactory::GetRequestPath( const ImageFactoryCache::RequestPtr& request ) const
*/
// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
#include <dali/internal/event/resources/resource-type-path-id-map.h>
#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/event/images/context-recovery-interface.h>
#include <dali/internal/event/images/image-factory-cache.h>
namespace Dali
void RecoverFromContextLoss();
/**
+ * Register an object into the context recovery list of the image factory.
+ * Thus its RecoverFromContextLoss() function would be called when the Stage regaining context.
+ * @param[in] object The object whose RecoverFromContextLoss() function needs to be called to regain the context.
+ */
+ void RegisterForContextRecovery( ContextRecoveryInterface* object );
+
+ /**
+ * Unregister an object from the context recovery list of the image factory
+ * @param[in] object The object whose RecoverFromContextLoss() function needs to be called to regain the context.
+ */
+ void UnregisterFromContextRecovery( ContextRecoveryInterface* object );
+
+ /**
* Get resource path used in request.
* @param [in] request of the image
* @return resource path
std::size_t GetHashForCachedRequest( const ImageFactoryCache::Request& request );
private:
- ResourceClient& mResourceClient;
- ImageFactoryCache::RequestPathHashMap mUrlCache; ///< A multimap of url hashes and request IDs
- ImageFactoryCache::RequestIdMap mRequestCache; ///< A map of request IDs and request information.
- ResourceTicketContainer mTicketsToRelease; ///< List of ticket handles
- float mMaxScale; ///< Defines maximum size difference between compatible resources
- ImageFactoryCache::RequestId mReqIdCurrent; ///< Internal counter for Request IDs
+ ResourceClient& mResourceClient;
+ ImageFactoryCache::RequestPathHashMap mUrlCache; ///< A multimap of url hashes and request IDs
+ ImageFactoryCache::RequestIdMap mRequestCache; ///< A map of request IDs and request information.
+ ResourceTicketContainer mTicketsToRelease; ///< List of ticket handles
+ Vector<ContextRecoveryInterface*> mContextRecoveryList; ///< List of the objects who needs context recovery
+ float mMaxScale; ///< Defines maximum size difference between compatible resources
+ ImageFactoryCache::RequestId mReqIdCurrent; ///< Internal counter for Request IDs
};
} // namespace Internal
yOffset );
}
+
+void ResourceClient::UploadBitmap( ResourceId destId,Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset)
+{
+ RequestUploadBitmapMessage( mUpdateManager.GetEventToUpdate(),
+ mResourceManager,
+ destId,
+ bitmap,
+ xOffset,
+ yOffset );
+}
+
void ResourceClient::UpdateMesh( ResourceTicketPtr ticket, const Dali::MeshData& meshData )
{
DALI_ASSERT_DEBUG( ticket );
void UploadBitmap( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
/**
+ * Upload a bitmap to a texture
+ * @param[in] destId The destination texture ID
+ * @param[in] bitmap The pointer pointing to the bitmap to upload
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ void UploadBitmap( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset);
+
+ /**
* Update the mesh used by ticket
* @note Should use same mechanism as update manager
* @param[in] ticket The ticket holding the mesh data
virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap ) = 0;
/**
- * Update the part of a texture with a newly loaded bitmap
+ * Dispatch a message to update the part of a texture with the bitmap data.
+ * May be called from Update thread
+ * @param[in] destId The ID of the texture to update
+ * @param[in] bitmap The pointer pointing to the source bitmap data.
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ virtual void DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset ) = 0;
+
+ /**
+ * Dispatch a message to update the part of a texture with a newly loaded bitmap
* May be called from Update thread
* @param[in] destId The ID of the texture to update
* @param[in] srcId The resource ID of the source bitmap
* @param [in] xOffset Specifies an offset in the x direction within the texture
* @param [in] yOffset Specifies an offset in the y direction within the texture
*/
- virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId,std::size_t xOffset, std::size_t yOffset ) = 0;
+ virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset ) = 0;
/**
* Dispatch a message to update the texture area
}
}
+void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
+{
+ DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
+
+ TextureIter textureIter = mTextures.find(id);
+ if( textureIter != mTextures.end() )
+ {
+ TexturePointer texturePtr = textureIter->second;
+ if( texturePtr )
+ {
+ texturePtr->Update( bitmap.Get(), xOffset, yOffset );
+
+ ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+ mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+ }
+ }
+}
+
void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
{
DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(destId=%i srcId=%i )\n", destId, srcId );
BitmapTexture* srcTexture = TextureCache::GetBitmapTexture( srcId );
- Integration::Bitmap* srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
+ Integration::BitmapPtr srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
if( srcBitmap )
{
- TextureIter textureIter = mTextures.find( destId );
- if( textureIter != mTextures.end() )
- {
- TexturePointer texturePtr = textureIter->second;
- if( texturePtr )
- {
- texturePtr->Update( srcBitmap, xOffset, yOffset );
-
- ResourcePostProcessRequest ppRequest( srcId, ResourcePostProcessRequest::UPLOADED );
- mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
- }
- }
+ UpdateTexture( destId, srcBitmap, xOffset, yOffset );
}
}
}
}
+void TextureCache::DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap , std::size_t xOffset, std::size_t yOffset)
+{
+ // NULL, means being shutdown, so ignore msgs
+ if( mSceneGraphBuffers != NULL )
+ {
+ typedef MessageValue4< TextureCache, ResourceId, Integration::BitmapPtr, std::size_t, std::size_t > DerivedType;
+
+ // Reserve some memory inside the render queue
+ unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap, xOffset, yOffset );
+ }
+}
+
void TextureCache::DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
{
// NULL, means being shutdown, so ignore msgs
void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap );
/**
+ * Update the texture with a newly loaded bitmap
+ * @param[in] id Resource Id of the bitmap
+ * @param[in] bitmap The bitmap
+ * @param[in] xOffset Specifies an offset in the x direction within the texture
+ * @param[in] yOffset Specifies an offset in the y direction within the texture
+ */
+ void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* Update the part of a texture with a newly loaded bitmap
* May be called from Update thread
* @param[in] destId The ID of the texture to update
* @param[in] srcId The resource ID of the source bitmap
- * @param [in] xOffset Specifies an offset in the x direction within the texture
- * @param [in] yOffset Specifies an offset in the y direction within the texture
+ * @param[in] xOffset Specifies an offset in the x direction within the texture
+ * @param[in] yOffset Specifies an offset in the y direction within the texture
*/
void UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
/**
* @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
*/
+ virtual void DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset ) ;
+
+ /**
+ * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+ */
virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
/**
}
}
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
+{
+ if( destId && bitmap )
+ {
+ mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, bitmap, xOffset, yOffset );
+ }
+}
+
void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
{
if( destId && srcId )
/**
* Upload a bitmap to a position within a specified texture
* @param[in] destId The destination texture ID
+ * @param[in] bitmap The pointer pointing to the bitmap data to upload
+ * @param [in] xOffset Specifies an offset in the x direction within the texture
+ * @param [in] yOffset Specifies an offset in the y direction within the texture
+ */
+ void HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset );
+
+ /**
+ * Upload a bitmap to a position within a specified texture
+ * @param[in] destId The destination texture ID
* @param[in] srcId The resource ID of the bitmap to upload
* @param [in] xOffset Specifies an offset in the x direction within the texture
* @param [in] yOffset Specifies an offset in the y direction within the texture
********************************* Private Methods *****************************
********************************************************************************/
private:
+
/**
* @param[in] id Resource id to clear
* @param[in] typePath Glyphs to be loaded, and cleared beforehand
inline void RequestUploadBitmapMessage( EventToUpdate& eventToUpdate,
ResourceManager& manager,
ResourceId destId,
+ Integration::BitmapPtr bitmap,
+ std::size_t xOffset,
+ std::size_t yOffset )
+{
+ typedef MessageValue4< ResourceManager, ResourceId, Integration::BitmapPtr , std::size_t, std::size_t > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ), false );
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, bitmap, xOffset, yOffset );
+}
+
+inline void RequestUploadBitmapMessage( EventToUpdate& eventToUpdate,
+ ResourceManager& manager,
+ ResourceId destId,
ResourceId srcId,
std::size_t xOffset,
std::size_t yOffset )
namespace Dali
{
-Atlas Atlas::New( std::size_t width,
- std::size_t height,
- Pixel::Format pixelFormat )
+Atlas Atlas::New( SizeType width,
+ SizeType height,
+ Pixel::Format pixelFormat,
+ bool recoverContext )
{
DALI_ASSERT_ALWAYS( 0u != width && "Invalid Atlas width requested" );
DALI_ASSERT_ALWAYS( 0u != height && "Invalid Atlas height requested" );
- return Atlas( Internal::Atlas::New( width, height, pixelFormat ) );
+ return Atlas( Internal::Atlas::New( width, height, pixelFormat, recoverContext ) );
}
Atlas::Atlas()
{
}
-bool Atlas::Upload( const BufferImage& bufferImage,
- std::size_t xOffset,
- std::size_t yOffset )
+void Atlas::Clear( const Vector4& color )
+{
+ GetImplementation( *this ).Clear( color );
+}
+
+bool Atlas::Upload( BufferImage bufferImage,
+ SizeType xOffset,
+ SizeType yOffset )
{
return GetImplementation(*this).Upload( GetImplementation(bufferImage), xOffset, yOffset );
}
+bool Atlas::Upload( const std::string& url,
+ SizeType xOffset,
+ SizeType yOffset )
+{
+ return GetImplementation(*this).Upload( url, xOffset, yOffset );
+}
+
Atlas Atlas::DownCast( BaseHandle handle )
{
return Atlas( dynamic_cast<Dali::Internal::Atlas*>(handle.GetObjectPtr()) );
*
*/
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/images/image.h>
#include <dali/public-api/images/buffer-image.h>
/**
* @brief An Atlas is a large image containing multiple smaller images.
*
- * Bitmap images must be uploaded at a specified position, to populate the Atlas.
- * The client is reponsible for generating the appropriate geometry (UV coordinates),
- * needed to draw images within the Atlas.
+ * Buffer image and resource image( by providing the url ) are supported for uploading.
+ * Images must be uploaded at a specified position, to populate the Atlas.
+ * The client is responsible for generating the appropriate geometry (UV coordinates) needed to draw images within the Atlas.
+ *
+ * For context recovery after loss:
+ * By default, the atlas will re-upload the resource images automatically,
+ * while the buffer images are left to the client to upload again by connecting to the Stage::ContextRegainedSignal().
+ * If resource and buffer images are mixed and they overlap inside the atlas, the recovered contents may be incorrect.
+ * In these case, switch off the context recovery by calling SetContextRecovery( false ),
+ * and upload both buffer images and resource image to the atlas in order to restore the atlas.
*/
class DALI_IMPORT_API Atlas : public Image
{
public:
+ typedef uint32_t SizeType;
+
+public:
+
/**
* @brief Create a new Atlas.
*
* @pre width & height are greater than zero.
* The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
- * @param [in] width The atlas width in pixels.
- * @param [in] height The atlas height in pixels.
- * @param [in] pixelFormat The pixel format (rgba 32 bit by default).
+ * @param [in] width The atlas width in pixels.
+ * @param [in] height The atlas height in pixels.
+ * @param [in] pixelFormat The pixel format (rgba 32 bit by default).
+ * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context( true by default )
* @return A handle to a new Atlas.
*/
- static Atlas New( std::size_t width,
- std::size_t height,
- Pixel::Format pixelFormat = Pixel::RGBA8888 );
+ static Atlas New( SizeType width,
+ SizeType height,
+ Pixel::Format pixelFormat = Pixel::RGBA8888,
+ bool recoverContext = true );
/**
* @brief Create an empty handle.
Atlas();
/**
- * @brief Upload a bitmap to the atlas.
+ * @brief Clear the Atlas with the given color
+ *
+ * @note The Atlas does not clear itself automatically during construction.
+ * Application should call this clear function to avoid getting garbage pixels in the atlas.
+ * By calling Clear, all the current uploaded image information will be lost.
+ * @param [in] color The color used to clear the Atlas.
+ */
+ void Clear( const Vector4& color );
+
+ /**
+ * @brief Upload a buffer image to the atlas.
*
- * @pre The bitmap pixel format must match the Atlas format.
+ * @pre The pixel format of this buffer image must match the Atlas format.
* @param [in] bufferImage The buffer image to upload.
* @param [in] xOffset Specifies an offset in the x direction within the atlas.
* @param [in] yOffset Specifies an offset in the y direction within the atlas.
- * @return True if the bitmap fits within the atlas at the specified offset.
+ * @return True if the image has compatible pixel format and fits within the atlas at the specified offset.
*/
- bool Upload( const BufferImage& bufferImage,
- std::size_t xOffset,
- std::size_t yOffset );
+ bool Upload( BufferImage bufferImage,
+ SizeType xOffset,
+ SizeType yOffset );
/**
+ * @brief Upload a resource image to atlas
+ *
+ * @param [in] url The URL of the resource image file to use
+ * @param [in] xOffset Specifies an offset in the x direction within the atlas.
+ * @param [in] yOffset Specifies an offset in the y direction within the atlas.
+ * @return True if the image has compatible pixel format and fits within the atlas at the specified offset.
+ */
+ bool Upload( const std::string& url,
+ SizeType xOffset,
+ SizeType yOffset );
+ /**
* @brief Downcast an Object handle to Atlas.
*
* If handle points to a Atlas the downcast produces valid