From 30915d55652783138e1020eee210eba0e207efd2 Mon Sep 17 00:00:00 2001
From: Paul Wisbey
Date: Mon, 19 Jan 2015 10:32:12 +0000
Subject: [PATCH] Minimal Atlas API
Change-Id: If43e6762a0b402fd522cda80a04e44cb2a8cf09b
---
automated-tests/src/dali/CMakeLists.txt | 1 +
automated-tests/src/dali/utc-Dali-Atlas.cpp | 146 +++++++++++++++++++
dali/internal/event/images/atlas-impl.cpp | 158 +++++++++++++++++++++
dali/internal/event/images/atlas-impl.h | 153 ++++++++++++++++++++
dali/internal/event/resources/resource-client.cpp | 10 ++
dali/internal/event/resources/resource-client.h | 9 ++
dali/internal/file.list | 1 +
.../render/common/texture-cache-dispatcher.h | 10 ++
.../render/gl-resources/bitmap-texture.cpp | 46 +++++-
dali/internal/render/gl-resources/bitmap-texture.h | 15 ++
.../internal/render/gl-resources/texture-cache.cpp | 57 +++++++-
dali/internal/render/gl-resources/texture-cache.h | 23 +++
dali/internal/render/gl-resources/texture.h | 8 ++
.../internal/update/resources/resource-manager.cpp | 8 ++
dali/internal/update/resources/resource-manager.h | 25 ++++
dali/public-api/dali-core.h | 1 +
dali/public-api/file.list | 2 +
dali/public-api/images/atlas.cpp | 74 ++++++++++
dali/public-api/images/atlas.h | 118 +++++++++++++++
19 files changed, 863 insertions(+), 2 deletions(-)
create mode 100644 automated-tests/src/dali/utc-Dali-Atlas.cpp
create mode 100644 dali/internal/event/images/atlas-impl.cpp
create mode 100644 dali/internal/event/images/atlas-impl.h
create mode 100644 dali/public-api/images/atlas.cpp
create mode 100644 dali/public-api/images/atlas.h
diff --git a/automated-tests/src/dali/CMakeLists.txt b/automated-tests/src/dali/CMakeLists.txt
index b023c1d..5388963 100644
--- a/automated-tests/src/dali/CMakeLists.txt
+++ b/automated-tests/src/dali/CMakeLists.txt
@@ -13,6 +13,7 @@ SET(TC_SOURCES
utc-Dali-AnimatableMesh.cpp
utc-Dali-Animation.cpp
utc-Dali-Any.cpp
+ utc-Dali-Atlas.cpp
utc-Dali-BaseHandle.cpp
utc-Dali-BitmapImage.cpp
utc-Dali-CameraActor.cpp
diff --git a/automated-tests/src/dali/utc-Dali-Atlas.cpp b/automated-tests/src/dali/utc-Dali-Atlas.cpp
new file mode 100644
index 0000000..e10032f
--- /dev/null
+++ b/automated-tests/src/dali/utc-Dali-Atlas.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014 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.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace Dali;
+
+void utc_dali_atlas_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_atlas_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+// 1.1
+int UtcDaliAtlasNew01(void)
+{
+ TestApplication application;
+
+ // invoke default handle constructor
+ Atlas atlas;
+
+ DALI_TEST_CHECK( !atlas );
+
+ // initialise handle
+ atlas = Atlas::New( 16, 16 );
+
+ DALI_TEST_CHECK( atlas );
+ END_TEST;
+}
+
+// 1.2
+int UtcDaliAtlasUpload01(void)
+{
+ TestApplication application;
+
+ Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas );
+
+ // Using correct pixel format
+ PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+ DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
+
+ END_TEST;
+}
+
+// 1.3
+int UtcDaliAtlasUpload02(void)
+{
+ TestApplication application;
+
+ Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas );
+
+ // Using INCORRECT pixel format
+ PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::A8 );
+
+ DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+
+ END_TEST;
+}
+
+// 1.4
+int UtcDaliAtlasUpload03(void)
+{
+ TestApplication application;
+
+ Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas );
+
+ // Using image too big for atlas
+ PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+ DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+
+ END_TEST;
+}
+
+// 1.5
+int UtcDaliAtlasUpload04(void)
+{
+ TestApplication application;
+
+ Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas );
+
+ // Using valid offsets
+ PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+ DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
+ DALI_TEST_CHECK( atlas.Upload( image, 16, 0 ) );
+ DALI_TEST_CHECK( atlas.Upload( image, 0, 16 ) );
+ DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) );
+
+ END_TEST;
+}
+
+// 1.6
+int UtcDaliAtlasUpload05(void)
+{
+ TestApplication application;
+
+ Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+ DALI_TEST_CHECK( atlas );
+
+ // Using invalid offsets
+ PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ BitmapImage image = BitmapImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+ DALI_TEST_CHECK( !atlas.Upload( image, 0, 17 ) );
+ DALI_TEST_CHECK( !atlas.Upload( image, 17, 0 ) );
+ DALI_TEST_CHECK( !atlas.Upload( image, 17, 17 ) );
+ DALI_TEST_CHECK( !atlas.Upload( image, 99, 0 ) );
+ DALI_TEST_CHECK( !atlas.Upload( image, 0, 99 ) );
+ DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) );
+
+ END_TEST;
+}
+
diff --git a/dali/internal/event/images/atlas-impl.cpp b/dali/internal/event/images/atlas-impl.cpp
new file mode 100644
index 0000000..7ad423f
--- /dev/null
+++ b/dali/internal/event/images/atlas-impl.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include
+
+// INTERNAL INCLUDES
+#include
+#include
+#include
+#include
+#include
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid( Dali::Atlas ), typeid( Dali::Image ), NULL );
+}
+
+Atlas* Atlas::New( std::size_t width,
+ std::size_t height,
+ Pixel::Format pixelFormat )
+{
+ return new Atlas( width, height, pixelFormat );
+}
+
+bool Atlas::Upload( const BitmapImage& bitmapImage,
+ std::size_t xOffset,
+ std::size_t yOffset )
+{
+ bool uploadSuccess( false );
+
+ if( IsWithin(bitmapImage, xOffset, yOffset) )
+ {
+ ResourceId destId = GetResourceId();
+ ResourceId srcId = bitmapImage.GetResourceId();
+
+ if( destId && srcId )
+ {
+ mResourceClient.UploadBitmap( destId, srcId, xOffset, yOffset );
+ uploadSuccess = true;
+ }
+ }
+
+ return uploadSuccess;
+}
+
+Atlas::~Atlas()
+{
+ ReleaseAtlas();
+}
+
+Atlas::Atlas( std::size_t width,
+ std::size_t height,
+ Pixel::Format pixelFormat )
+: mResourceClient( ThreadLocalStorage::Get().GetResourceClient() ),
+ mPixelFormat( pixelFormat )
+{
+ mWidth = width;
+ mHeight = height;
+
+ if( Dali::Image::Immediate == mLoadPolicy )
+ {
+ AllocateAtlas();
+ }
+}
+
+void Atlas::Connect()
+{
+ ++mConnectionCount;
+
+ if( Dali::Image::OnDemand == mLoadPolicy &&
+ mConnectionCount == 1 )
+ {
+ AllocateAtlas();
+ }
+}
+
+void Atlas::Disconnect()
+{
+ if( mConnectionCount )
+ {
+ --mConnectionCount;
+
+ if ( Dali::Image::Unused == mReleasePolicy &&
+ mConnectionCount == 0 )
+ {
+ ReleaseAtlas();
+ }
+ }
+}
+
+bool Atlas::IsWithin( const BitmapImage& bitmapImage,
+ std::size_t xOffset,
+ std::size_t yOffset )
+{
+ bool within(false);
+
+ if( mPixelFormat != bitmapImage.GetPixelFormat() )
+ {
+ DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", bitmapImage.GetPixelFormat(), mPixelFormat );
+ }
+ else
+ {
+ const unsigned int width = bitmapImage.GetWidth();
+ const unsigned int height = bitmapImage.GetHeight();
+
+ if( xOffset < mWidth &&
+ yOffset < mHeight &&
+ xOffset+width <= mWidth &&
+ yOffset+height <= mHeight )
+ {
+ within = true;
+ }
+ else
+ {
+ DALI_LOG_ERROR( "%dx%d image does not fit at offset %d,%d\n", width, height, xOffset, yOffset );
+ }
+ }
+
+ return within;
+}
+
+void Atlas::AllocateAtlas()
+{
+ if( !mTicket )
+ {
+ mTicket = mResourceClient.AllocateTexture( mWidth, mHeight, mPixelFormat );
+ }
+}
+
+void Atlas::ReleaseAtlas()
+{
+ mTicket.Reset();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/atlas-impl.h b/dali/internal/event/images/atlas-impl.h
new file mode 100644
index 0000000..6dddead
--- /dev/null
+++ b/dali/internal/event/images/atlas-impl.h
@@ -0,0 +1,153 @@
+#ifndef __DALI_INTERNAL_ATLAS_H__
+#define __DALI_INTERNAL_ATLAS_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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include
+#include
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ResourceClient;
+
+/**
+ * @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.
+ */
+class Atlas : public Image
+{
+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).
+ * @return A pointer to a new Atlas.
+ */
+ static Atlas* New( std::size_t width,
+ std::size_t height,
+ Pixel::Format pixelFormat = Pixel::RGBA8888 );
+
+ /**
+ * @brief Upload a bitmap to the atlas.
+ *
+ * @pre The bitmap pixel format must match the Atlas format.
+ * @param [in] bitmap The bitmap 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.
+ */
+ bool Upload( const BitmapImage& bitmap,
+ std::size_t xOffset,
+ std::size_t yOffset );
+
+protected:
+
+ /**
+ * @brief Protected constructor.
+ *
+ * @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).
+ */
+ Atlas( std::size_t width,
+ std::size_t height,
+ Pixel::Format pixelFormat );
+
+ /**
+ * A reference counted object may only be deleted by calling Unreference()
+ */
+ virtual ~Atlas();
+
+ /**
+ * @copydoc Dali::Internal::Image::Connect
+ */
+ virtual void Connect();
+
+ /**
+ * @copydoc Dali::Internal::Image::Disconnect
+ */
+ virtual void Disconnect();
+
+private:
+
+ /**
+ * Helper for Upload methods
+ * @return True if the bitmap fits within the atlas at the specified offset
+ */
+ bool IsWithin( const BitmapImage& bitmapImage,
+ std::size_t xOffset,
+ std::size_t yOffset );
+
+ /**
+ * Helper to create the Atlas resource
+ */
+ void AllocateAtlas();
+
+ /**
+ * Helper to release the Atlas resource
+ */
+ void ReleaseAtlas();
+
+private:
+
+ ResourceClient& mResourceClient;
+
+ Pixel::Format mPixelFormat;
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::Atlas& GetImplementation(Dali::Atlas& image)
+{
+ DALI_ASSERT_ALWAYS( image && "Atlas handle is empty" );
+
+ BaseObject& handle = image.GetBaseObject();
+
+ return static_cast(handle);
+}
+
+inline const Internal::Atlas& GetImplementation(const Dali::Atlas& image)
+{
+ DALI_ASSERT_ALWAYS( image && "Atlas handle is empty" );
+
+ const BaseObject& handle = image.GetBaseObject();
+
+ return static_cast(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ATLAS_H__
diff --git a/dali/internal/event/resources/resource-client.cpp b/dali/internal/event/resources/resource-client.cpp
index b8dd6cf..d82be43 100644
--- a/dali/internal/event/resources/resource-client.cpp
+++ b/dali/internal/event/resources/resource-client.cpp
@@ -437,6 +437,16 @@ void ResourceClient::UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updat
RequestUpdateBitmapAreaMessage( mUpdateManager.GetEventToUpdate(), mResourceManager, ticket->GetId(), updateArea );
}
+void ResourceClient::UploadBitmap( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+ RequestUploadBitmapMessage( mUpdateManager.GetEventToUpdate(),
+ mResourceManager,
+ destId,
+ srcId,
+ xOffset,
+ yOffset );
+}
+
void ResourceClient::UpdateMesh( ResourceTicketPtr ticket, const Dali::MeshData& meshData )
{
DALI_ASSERT_DEBUG( ticket );
diff --git a/dali/internal/event/resources/resource-client.h b/dali/internal/event/resources/resource-client.h
index 923e73f..1b5ec87 100644
--- a/dali/internal/event/resources/resource-client.h
+++ b/dali/internal/event/resources/resource-client.h
@@ -249,6 +249,15 @@ public:
void UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updateArea );
/**
+ * Upload a bitmap to a 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
+ */
+ void UploadBitmap( ResourceId destId, ResourceId srcId, 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
diff --git a/dali/internal/file.list b/dali/internal/file.list
index 904d7b6..fd31a2b 100644
--- a/dali/internal/file.list
+++ b/dali/internal/file.list
@@ -68,6 +68,7 @@ internal_src_files = \
$(internal_src_dir)/event/events/tap-gesture-detector-impl.cpp \
$(internal_src_dir)/event/events/tap-gesture-processor.cpp \
$(internal_src_dir)/event/events/touch-event-processor.cpp \
+ $(internal_src_dir)/event/images/atlas-impl.cpp \
$(internal_src_dir)/event/images/bitmap-external.cpp \
$(internal_src_dir)/event/images/bitmap-packed-pixel.cpp \
$(internal_src_dir)/event/images/bitmap-compressed.cpp \
diff --git a/dali/internal/render/common/texture-cache-dispatcher.h b/dali/internal/render/common/texture-cache-dispatcher.h
index 26d337a..1ea5f80 100644
--- a/dali/internal/render/common/texture-cache-dispatcher.h
+++ b/dali/internal/render/common/texture-cache-dispatcher.h
@@ -128,6 +128,16 @@ public:
virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap ) = 0;
/**
+ * 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;
+
+ /**
* Dispatch a message to update the texture area
* May be called from the Update thread
* @param[in] id Resource Id of the texture
diff --git a/dali/internal/render/gl-resources/bitmap-texture.cpp b/dali/internal/render/gl-resources/bitmap-texture.cpp
index e6967ce..c001da8 100644
--- a/dali/internal/render/gl-resources/bitmap-texture.cpp
+++ b/dali/internal/render/gl-resources/bitmap-texture.cpp
@@ -203,7 +203,6 @@ void BitmapTexture::AreaUpdated( const RectArea& updateArea, const unsigned char
}
}
-
void BitmapTexture::AssignBitmap( bool generateTexture, const unsigned char* pixels )
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
@@ -286,6 +285,51 @@ void BitmapTexture::Update( Integration::Bitmap* bitmap )
}
}
+void BitmapTexture::Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset )
+{
+ if( NULL != srcBitmap )
+ {
+ GLenum pixelFormat = GL_RGBA;
+ GLenum pixelDataType = GL_UNSIGNED_BYTE;
+ Integration::ConvertToGlFormat( mPixelFormat, pixelDataType, pixelFormat );
+
+ if( !mId )
+ {
+ mContext.GenTextures( 1, &mId );
+
+ mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+ mContext.Bind2dTexture( mId );
+ mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+ mContext.TexImage2D( GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, NULL );
+ mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ }
+ else
+ {
+ mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+ mContext.Bind2dTexture( mId );
+ mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ }
+
+ const unsigned char* pixels = srcBitmap->GetBuffer();
+ unsigned int srcWidth = srcBitmap->GetImageWidth();
+ const unsigned int pixelDepth = Pixel::GetBytesPerPixel( mPixelFormat );
+
+ unsigned int yBottom = yOffset + srcBitmap->GetImageHeight();
+
+ for( unsigned int y = yOffset; y < yBottom; y++ )
+ {
+ mContext.TexSubImage2D( GL_TEXTURE_2D, 0,
+ xOffset, y,
+ srcWidth, 1,
+ pixelFormat, pixelDataType, pixels );
+
+ pixels += srcWidth * pixelDepth;
+ }
+ }
+}
+
void BitmapTexture::UpdateArea( const RectArea& updateArea )
{
DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "BitmapTexture::UpdateArea()\n");
diff --git a/dali/internal/render/gl-resources/bitmap-texture.h b/dali/internal/render/gl-resources/bitmap-texture.h
index 46073c8..7cbdfbc 100644
--- a/dali/internal/render/gl-resources/bitmap-texture.h
+++ b/dali/internal/render/gl-resources/bitmap-texture.h
@@ -90,7 +90,14 @@ public: // Message interface
*/
void ClearAreas( const BitmapClearArray& areaArray, std::size_t blockSize, uint32_t color );
+ /**
+ * Retrieve the bitmap
+ * @return The bitmap or NULL if already discarded
+ */
+ Integration::Bitmap* GetBitmap() { return mBitmap.Get(); }
+
public:
+
/**
* @copydoc Texture::Init
*/
@@ -124,6 +131,14 @@ public:
virtual void Update( Integration::Bitmap* bitmap );
/**
+ * Update part of the texture with a different bitmap
+ * @param[in] srcBitmap The bitmap to copy from
+ * @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 Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* Bitmap area has been modified - update the texture appropriately.
* @pre The bitmap hasn't been discarded (should be external type)
* @param[in] area The updated area
diff --git a/dali/internal/render/gl-resources/texture-cache.cpp b/dali/internal/render/gl-resources/texture-cache.cpp
index db4f027..bfa9185 100644
--- a/dali/internal/render/gl-resources/texture-cache.cpp
+++ b/dali/internal/render/gl-resources/texture-cache.cpp
@@ -137,6 +137,30 @@ void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
}
}
+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;
+
+ 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);
+ }
+ }
+ }
+}
+
void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
{
DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
@@ -264,7 +288,6 @@ void TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target,
}
}
-
Texture* TextureCache::GetTexture(ResourceId id)
{
Texture* texture = NULL;
@@ -297,6 +320,23 @@ Texture* TextureCache::GetTexture(ResourceId id)
return texture;
}
+BitmapTexture* TextureCache::GetBitmapTexture(ResourceId id)
+{
+ BitmapTexture* texture = NULL;
+ TextureIter iter = mTextures.find( id );
+
+ if( iter != mTextures.end() )
+ {
+ TexturePointer texturePtr = iter->second;
+ if( texturePtr )
+ {
+ texture = dynamic_cast< BitmapTexture* >( texturePtr.Get() );
+ }
+ }
+
+ return texture;
+}
+
FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
{
FrameBufferTexture* offscreen = NULL;
@@ -492,6 +532,21 @@ void TextureCache::DispatchUpdateTexture( ResourceId id, Bitmap* bitmap )
}
}
+void TextureCache::DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+ // NULL, means being shutdown, so ignore msgs
+ if( mSceneGraphBuffers != NULL )
+ {
+ typedef MessageValue4< TextureCache, ResourceId, ResourceId, 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, destId, srcId, xOffset, yOffset );
+ }
+}
+
void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
{
// NULL, means being shutdown, so ignore msgs
diff --git a/dali/internal/render/gl-resources/texture-cache.h b/dali/internal/render/gl-resources/texture-cache.h
index 656d103..1bbc7f9 100644
--- a/dali/internal/render/gl-resources/texture-cache.h
+++ b/dali/internal/render/gl-resources/texture-cache.h
@@ -52,6 +52,7 @@ namespace Internal
{
class Context;
class Texture;
+class BitmapTexture;
class FrameBufferTexture;
class TextureObserver;
@@ -136,6 +137,16 @@ public:
*/
void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap );
+ /**
+ * 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
+ */
+ void UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
/**
* Add an array of bitmaps to an existing texture used as an Atlas
* @param[in] id Resource id of the texture
@@ -191,6 +202,13 @@ public:
Texture* GetTexture( ResourceId id );
/**
+ * Get the bitmaptexture associated with the resource ID
+ * @param[in] id Resource Id of the texture
+ * @return The texture or NULL
+ */
+ BitmapTexture* GetBitmapTexture(ResourceId id);
+
+ /**
* Get the framebuffer texture associated with the resource ID
* Used for writing to the framebuffer
* @param[in] id Resource Id of the framebuffer
@@ -267,6 +285,11 @@ protected: // Implements TextureCacheDispatcher
virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap );
/**
+ * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+ */
+ virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* @copydoc TextureCacheDispatcher::DispatchUpdateTextureArea()
*/
virtual void DispatchUpdateTextureArea( ResourceId id, const RectArea& area );
diff --git a/dali/internal/render/gl-resources/texture.h b/dali/internal/render/gl-resources/texture.h
index 5c0b182..0479f01 100644
--- a/dali/internal/render/gl-resources/texture.h
+++ b/dali/internal/render/gl-resources/texture.h
@@ -80,6 +80,14 @@ public:
virtual void UpdateArea( const RectArea& area );
/**
+ * Update part of the texture with a different bitmap
+ * @param[in] srcBitmap The bitmap to copy from
+ * @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 Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset ) {}
+
+ /**
* @return Return true if the texture should be updated on GL texture creation.
*/
virtual bool UpdateOnCreate();
diff --git a/dali/internal/update/resources/resource-manager.cpp b/dali/internal/update/resources/resource-manager.cpp
index 0464aa0..82b7e53 100644
--- a/dali/internal/update/resources/resource-manager.cpp
+++ b/dali/internal/update/resources/resource-manager.cpp
@@ -428,6 +428,14 @@ void ResourceManager::HandleUpdateBitmapAreaRequest( ResourceId textureId, const
}
}
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+ if( destId && srcId )
+ {
+ mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, srcId, xOffset, yOffset );
+ }
+}
+
void ResourceManager::HandleUpdateMeshRequest( BufferIndex updateBufferIndex, ResourceId id, MeshData* meshData )
{
DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
diff --git a/dali/internal/update/resources/resource-manager.h b/dali/internal/update/resources/resource-manager.h
index 2a2a947..43bab93 100644
--- a/dali/internal/update/resources/resource-manager.h
+++ b/dali/internal/update/resources/resource-manager.h
@@ -273,6 +273,15 @@ public: // Used by ResourceClient
void HandleUpdateBitmapAreaRequest( ResourceId textureId, const Dali::RectArea& area );
/**
+ * 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
+ */
+ void HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+ /**
* Upload mesh buffer changes.
* @param[in] updateBufferIndex The current update buffer index.
* @param[in] id The ID of a Mesh resource.
@@ -630,6 +639,22 @@ inline void RequestUpdateBitmapAreaMessage( EventToUpdate& eventToUpdate,
new (slot) LocalType( &manager, &ResourceManager::HandleUpdateBitmapAreaRequest, id, area );
}
+inline void RequestUploadBitmapMessage( EventToUpdate& eventToUpdate,
+ ResourceManager& manager,
+ ResourceId destId,
+ ResourceId srcId,
+ std::size_t xOffset,
+ std::size_t yOffset )
+{
+ typedef MessageValue4< ResourceManager, ResourceId, ResourceId, 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, srcId, xOffset, yOffset );
+}
+
inline void RequestUpdateMeshMessage( EventToUpdate& eventToUpdate,
ResourceManager& manager,
ResourceId id,
diff --git a/dali/public-api/dali-core.h b/dali/public-api/dali-core.h
index 2408982..a4d8ec2 100644
--- a/dali/public-api/dali-core.h
+++ b/dali/public-api/dali-core.h
@@ -90,6 +90,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/dali/public-api/file.list b/dali/public-api/file.list
index 5629dcc..b6f4c16 100644
--- a/dali/public-api/file.list
+++ b/dali/public-api/file.list
@@ -57,6 +57,7 @@ public_api_src_files = \
$(public_api_src_dir)/geometry/mesh-factory.cpp \
$(public_api_src_dir)/geometry/mesh.cpp \
$(public_api_src_dir)/geometry/spline.cpp \
+ $(public_api_src_dir)/images/atlas.cpp \
$(public_api_src_dir)/images/distance-field.cpp \
$(public_api_src_dir)/images/image.cpp \
$(public_api_src_dir)/images/image-attributes.cpp \
@@ -208,6 +209,7 @@ public_api_core_geometry_header_files = \
$(public_api_src_dir)/geometry/spline.h
public_api_core_images_header_files = \
+ $(public_api_src_dir)/images/atlas.h \
$(public_api_src_dir)/images/bitmap-image.h \
$(public_api_src_dir)/images/distance-field.h \
$(public_api_src_dir)/images/encoded-buffer-image.h \
diff --git a/dali/public-api/images/atlas.cpp b/dali/public-api/images/atlas.cpp
new file mode 100644
index 0000000..b41c00c
--- /dev/null
+++ b/dali/public-api/images/atlas.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include
+
+// INTERNAL INCLUDES
+#include
+#include
+
+namespace Dali
+{
+
+Atlas Atlas::New( std::size_t width,
+ std::size_t height,
+ Pixel::Format pixelFormat )
+{
+ 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 ) );
+}
+
+Atlas::Atlas()
+{
+}
+
+bool Atlas::Upload( const BitmapImage& bitmap,
+ std::size_t xOffset,
+ std::size_t yOffset )
+{
+ return GetImplementation(*this).Upload( GetImplementation(bitmap), xOffset, yOffset );
+}
+
+Atlas Atlas::DownCast( BaseHandle handle )
+{
+ return Atlas( dynamic_cast(handle.GetObjectPtr()) );
+}
+
+Atlas::~Atlas()
+{
+}
+
+Atlas::Atlas( const Atlas& handle )
+: Image( handle )
+{
+}
+
+Atlas& Atlas::operator=( const Atlas& rhs )
+{
+ BaseHandle::operator=(rhs);
+ return *this;
+}
+
+Atlas::Atlas( Internal::Atlas* internal )
+: Image( internal )
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/atlas.h b/dali/public-api/images/atlas.h
new file mode 100644
index 0000000..9719635
--- /dev/null
+++ b/dali/public-api/images/atlas.h
@@ -0,0 +1,118 @@
+#ifndef __DALI_ATLAS_H__
+#define __DALI_ATLAS_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.
+ *
+ */
+
+#include
+#include
+#include
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Atlas;
+}
+
+/**
+ * @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.
+ */
+class DALI_IMPORT_API Atlas : public Image
+{
+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).
+ * @return A handle to a new Atlas.
+ */
+ static Atlas New( std::size_t width,
+ std::size_t height,
+ Pixel::Format pixelFormat = Pixel::RGBA8888 );
+
+ /**
+ * @brief Create an empty handle.
+ *
+ * Calling member functions of an empty handle is not allowed.
+ */
+ Atlas();
+
+ /**
+ * @brief Upload a bitmap to the atlas.
+ *
+ * @pre The bitmap pixel format must match the Atlas format.
+ * @param [in] bitmap The bitmap 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.
+ */
+ bool Upload( const BitmapImage& bitmap,
+ std::size_t xOffset,
+ std::size_t yOffset );
+
+ /**
+ * @brief Downcast an Object handle to Atlas.
+ *
+ * If handle points to a Atlas the downcast produces valid
+ * handle. If not the returned handle is left uninitialized.
+ *
+ * @param[in] handle to An object
+ * @return handle to a Atlas or an empty handle
+ */
+ static Atlas DownCast( BaseHandle handle );
+
+ /**
+ * @brief Destructor
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ */
+ ~Atlas();
+
+ /**
+ * @brief This copy constructor is required for (smart) pointer semantics.
+ *
+ * @param [in] handle A reference to the copied handle
+ */
+ Atlas( const Atlas& handle );
+
+ /**
+ * @brief This assignment operator is required for (smart) pointer semantics.
+ *
+ * @param [in] rhs A reference to the copied handle
+ * @return A reference to this
+ */
+ Atlas& operator=( const Atlas& rhs);
+
+public: // Not intended for application developers
+
+ explicit DALI_INTERNAL Atlas( Internal::Atlas* );
+};
+
+} // namespace Dali
+
+#endif // __DALI_ATLAS_H__
--
2.7.4