DALI_TEST_CHECK( atlas );
// Using correct pixel format
- PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
DALI_TEST_CHECK( atlas );
// Using image too big for atlas
- PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
DALI_TEST_CHECK( atlas );
// Using valid offsets
- PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
DALI_TEST_CHECK( atlas );
// Using invalid offsets
- PixelBuffer* buffer = new PixelBuffer[16 * 16];
+ PixelBuffer* buffer = new PixelBuffer[16 * 16 * 4];
BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
DALI_TEST_CHECK( !atlas.Upload( image, 0, 17 ) );
END_TEST;
}
-int UtcDaliInternalAllocateBitmapImage01(void)
-{
- TestApplication application;
- tet_infoline("Testing AllocateBitmapImage()");
- testTicketObserver.Reset();
-
- Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
- Internal::ImageTicketPtr imageTicket = resourceClient.AllocateBitmapImage(80, 80, 80, 80, Pixel::RGB565);
- imageTicket->AddObserver( testTicketObserver );
-
- DALI_TEST_CHECK( imageTicket );
- DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
- DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
- DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
-
- application.SendNotification(); // Flush update queue
- application.Render(0); // Process message
- application.SendNotification(); // Send message to tickets
-
- DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
- DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
- DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
- DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
-
- Integration::Bitmap* bitmap = resourceClient.GetBitmap(imageTicket);
- DALI_TEST_CHECK ( bitmap != NULL );
- DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGB565, TEST_LOCATION );
- END_TEST;
-}
-
int UtcDaliInternalAddBitmapImage01(void)
{
TestApplication application;
DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
-
- Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket);
- DALI_TEST_CHECK ( theBitmap != NULL );
- DALI_TEST_CHECK ( bitmap == theBitmap );
- DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGB565, TEST_LOCATION );
END_TEST;
}
DALI_TEST_EQUALS ( imageTicket->GetWidth(), 0, TEST_LOCATION );
DALI_TEST_EQUALS ( imageTicket->GetHeight(), 0, TEST_LOCATION );
DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
-
- Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket);
- DALI_TEST_CHECK ( theBitmap != NULL );
- DALI_TEST_CHECK ( bitmap == theBitmap );
- DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 0u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 0u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 0u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 0u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
-
- // There is no way for the ticket's image attributes to be updated if the bitmap
- // reserves a buffer after ticket generation.
- // Probably not an issue - there is no public API in BufferImage to change the image size.
END_TEST;
}
END_TEST;
}
-int UtcDaliInternalGetBitmapImage01(void)
-{
- TestApplication application;
- tet_infoline("Testing GetBitmap() with valid ticket");
- testTicketObserver.Reset();
-
- Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
- Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
- bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 20, 20, 80, 80 );
- Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap );
-
- Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket);
- DALI_TEST_CHECK ( theBitmap != NULL );
- DALI_TEST_CHECK ( bitmap == theBitmap );
- DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 20u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 20u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
-
- imageTicket->AddObserver( testTicketObserver );
- application.SendNotification(); // Flush update queue
- application.Render(0); // Process message
- application.SendNotification(); // Send message to tickets
-
- theBitmap = resourceClient.GetBitmap(imageTicket);
- DALI_TEST_CHECK ( theBitmap != NULL );
- DALI_TEST_CHECK ( bitmap == theBitmap );
- DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 20u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 20u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
- DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
- END_TEST;
-}
-
-int UtcDaliInternalGetBitmapImage02(void)
-{
- TestApplication application;
- tet_infoline("Testing GetBitmap() with invalid ticket");
-
- Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
- Internal::ImageTicketPtr imageTicket;
- Integration::Bitmap* theBitmap = NULL;
- bool exceptionRaised = false;
- try
- {
- theBitmap = resourceClient.GetBitmap(imageTicket);
- } catch (DaliException& e)
- {
- exceptionRaised = true;
- }
- DALI_TEST_CHECK( exceptionRaised );
- DALI_TEST_CHECK( ! theBitmap );
- END_TEST;
-}
-
-int UtcDaliInternalGetBitmapImage03(void)
-{
- TestApplication application;
- tet_infoline("Testing GetBitmap() with valid ticket for incorrect type");
-
- Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); Internal::ResourceTicketPtr imageTicket = CheckLoadBitmap( application, "Stuff.png", 100, 100 );
-
- Integration::Bitmap* theBitmap = NULL;
- theBitmap = resourceClient.GetBitmap(imageTicket);
- DALI_TEST_CHECK( ! theBitmap );
-
- END_TEST;
-}
-
int UtcDaliInternalAllocateTexture01(void)
{
TestApplication application;
DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
-
- Integration::Bitmap* theBitmap = NULL;
- theBitmap = resourceClient.GetBitmap(imageTicket);
-
- DALI_TEST_CHECK ( theBitmap == NULL );
END_TEST;
}
DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
-
- Integration::Bitmap* theBitmap = NULL;
- theBitmap = resourceClient.GetBitmap(imageTicket);
- DALI_TEST_CHECK ( theBitmap == NULL );
END_TEST;
}
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * 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.
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/event/images/bitmap-packed-pixel.h>
#include <dali/internal/event/images/bitmap-compressed.h>
-#include <dali/internal/event/images/bitmap-external.h>
#include <dali/integration-api/gl-abstraction.h>
#include <dali/integration-api/gl-defines.h>
Bitmap::~Bitmap()
{
DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
-
- // If owned
- if( mDiscardable == ResourcePolicy::OWNED_DISCARD ||
- mDiscardable == ResourcePolicy::OWNED_RETAIN )
- {
- DeletePixelBuffer();
- }
+ DeletePixelBuffer();
}
/**
* and may released away after uploading to GPU.
* OWNED_RETAIN means that the data is owned and must be kept in CPU memory
* e.g. for an image that cannot be reloaded from disk.
- * NOT_OWNED means that the data is managed by an external component and is
- * guaranteed to remain dereferenceable at least as long as the Bitmap remains alive.
*/
static Bitmap* New( Profile profile, ResourcePolicy::Discardable discardable );
};
/**
- * The discardable policy describes whether a resource is owned or can be discarded.
+ * The discardable policy determines if a resource can be discarded.
* Discarded means that it can be released after uploading to GPU.
*/
enum Discardable
{
OWNED_DISCARD,
OWNED_RETAIN,
- NOT_OWNED
};
} // namespace ResourcePolicy
{
AllocateAtlas();
ResourceId destId = GetResourceId();
- ResourceId srcId = bufferImage.GetResourceId();
- if( destId && srcId )
+ if( destId )
{
- mResourceClient.UploadBitmap( destId, srcId, xOffset, yOffset );
+ bufferImage.UploadBitmap( destId, xOffset, yOffset );
uploadSuccess = true;
}
}
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * 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.
// CLASS HEADER
#include <dali/internal/event/images/buffer-image-impl.h>
+// EXTERNAL INCLUDES
+#include <string.h>
+
// INTERNAL INCLUDES
#include <dali/public-api/object/type-registry.h>
-#include <dali/integration-api/bitmap.h>
-#include <dali/internal/event/images/bitmap-external.h>
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/event/resources/resource-client.h>
#include <dali/internal/update/manager/update-manager.h>
#include <dali/internal/event/images/image-factory.h>
+using namespace Dali::Integration;
+
namespace Dali
{
namespace Internal
BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol)
: Image(releasePol),
- mIsDataExternal(false)
+ mInternalBuffer(NULL),
+ mExternalBuffer(NULL),
+ mBitmap(NULL)
{
ThreadLocalStorage& tls = ThreadLocalStorage::Get();
mResourceClient = &tls.GetResourceClient();
mWidth = width;
mHeight = height;
+ mPixelFormat = pixelformat;
+ mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat );
+ mByteStride = width * mBytesPerPixel;
+ mBufferSize = height * mByteStride;
- const ImageTicketPtr& t = mResourceClient->AllocateBitmapImage(width, height, width, height, pixelformat);
- mTicket = t.Get();
+ // Allocate a persistent internal buffer
+ mInternalBuffer = new PixelBuffer[ mBufferSize ];
- mTicket->AddObserver(*this);
+ // Respect the desired release policy
+ mResourcePolicy = releasePol == Dali::Image::UNUSED ? ResourcePolicy::OWNED_DISCARD : ResourcePolicy::OWNED_RETAIN;
}
-BufferImage::BufferImage(PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol)
+BufferImage::BufferImage(PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol )
: Image(releasePol),
- mIsDataExternal(true)
+ mInternalBuffer(NULL),
+ mExternalBuffer(pixBuf),
+ mBitmap(NULL)
{
ThreadLocalStorage& tls = ThreadLocalStorage::Get();
mResourceClient = &tls.GetResourceClient();
mWidth = width;
mHeight = height;
- Integration::Bitmap* bitmap = new BitmapExternal(pixBuf, width, height, pixelformat, stride);
- const ImageTicketPtr& t = mResourceClient->AddBitmapImage(bitmap);
- mTicket = t.Get();
+ mPixelFormat = pixelformat;
+ mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat );
+ mByteStride = ( stride ? stride : mWidth ) * mBytesPerPixel;
+ mBufferSize = height * mByteStride;
+
+ // Respect the desired release policy
+ mResourcePolicy = releasePol == Dali::Image::UNUSED ? ResourcePolicy::OWNED_DISCARD : ResourcePolicy::OWNED_RETAIN;
+
+ // Create a bitmap to hold copy of external buffer
+ ReserveBitmap();
- mTicket->AddObserver(*this);
+ // Take a copy of the external buffer immediately, so it can be released if desired
+ RectArea area;
+ MirrorExternal( area );
}
BufferImage::~BufferImage()
{
+ delete[] mInternalBuffer;
+}
+
+bool BufferImage::IsDataExternal() const
+{
+ return ( mExternalBuffer ? true : false );
}
void BufferImage::Update( RectArea& updateArea )
{
+ ValidateBitmap();
+ UpdateBitmap( updateArea );
+
if (mTicket)
{
- // TODO:
- // If updateArea is empty or same as image size, then pass on.
- // If updateArea is larger than image size, throw exception
- // Otherwise, copy updateArea window of pixelBuffer into newly
- // allocated buffer and pass that to resource client. (it will
- // tramp through to BitmapTexture eventually!)
+ DALI_ASSERT_DEBUG( updateArea.x + updateArea.width <= mWidth && updateArea.y + updateArea.height <= mHeight );
mResourceClient->UpdateBitmapArea( mTicket, updateArea );
- }
- else if (mIsDataExternal && mBitmapCached)
- {
- // previously freed up resource memory, dali was informed about external BufferImage put back on screen
- Integration::Bitmap* bitmap = mBitmapCached.Get();
- mTicket.Reset((mResourceClient->AddBitmapImage(bitmap)).Get());
- mTicket->AddObserver(*this);
+ // Bitmap ownership has been passed on, so any subsequent update will need another bitmap
+ mBitmap = NULL;
}
}
-bool BufferImage::IsDataExternal() const
+void BufferImage::UpdateBitmap( RectArea& updateArea )
{
- return mIsDataExternal;
-}
-
-PixelBuffer* BufferImage::GetBuffer()
-{
- PixelBuffer* buffer = NULL;
-
- Integration::Bitmap* const bitmap = GetBitmap();
-
- if(bitmap)
+ if ( mExternalBuffer )
+ {
+ MirrorExternal( updateArea );
+ }
+ else
{
- buffer = bitmap->GetBuffer();
+ // Copy the internal buffer to the bitmap area
+ memcpy( mBitmap->GetBuffer(), mInternalBuffer, mBufferSize );
}
- return buffer;
}
-unsigned int BufferImage::GetBufferSize() const
+void BufferImage::ValidateBitmap()
{
- unsigned int bufferSize = 0;
-
- Integration::Bitmap* const bitmap = GetBitmap();
-
- if(bitmap)
+ ReserveBitmap();
+ if ( !mTicket )
{
- bufferSize = bitmap->GetBufferSize();
+ mTicket = mResourceClient->AddBitmapImage( mBitmap );
+ mTicket->AddObserver(*this);
}
- return bufferSize;
}
-unsigned int BufferImage::GetBufferStride() const
+void BufferImage::ReserveBitmap()
{
- unsigned int bufferStride = 0;
-
- Integration::Bitmap* const bitmap = GetBitmap();
+ // Does a bitmap currently exist ?
+ if ( !mBitmap )
+ {
+ mBitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, mResourcePolicy );
+ }
- if(bitmap)
+ if ( !mBitmap->GetBuffer() )
{
- Integration::Bitmap::PackedPixelsProfile* packedBitmap = bitmap->GetPackedPixelsProfile();
+ Bitmap::PackedPixelsProfile* const packedBitmap = mBitmap->GetPackedPixelsProfile();
DALI_ASSERT_DEBUG(packedBitmap);
- bufferStride = packedBitmap->GetBufferStride();
- }
- return bufferStride;
+ packedBitmap->ReserveBuffer( mPixelFormat, mWidth, mHeight, mByteStride / mBytesPerPixel, mHeight );
+ DALI_ASSERT_DEBUG(mBitmap->GetBuffer() != 0);
+ DALI_ASSERT_DEBUG(mBitmap->GetBufferSize() >= mWidth * mHeight * Pixel::GetBytesPerPixel( mBitmap->GetPixelFormat() ) );
+ }
}
-Pixel::Format BufferImage::GetPixelFormat() const
+void BufferImage::UploadBitmap( ResourceId destId, std::size_t xOffset, std::size_t yOffset )
{
- Pixel::Format format( Pixel::RGBA8888 );
+ // Make sure we have a bitmap for transport
+ ReserveBitmap();
- Integration::Bitmap* const bitmap = GetBitmap();
+ // Copy source pixel data into bitmap
+ RectArea area;
+ UpdateBitmap( area );
- if( bitmap )
- {
- format = bitmap->GetPixelFormat();
- }
-
- return format;
+ mResourceClient->UploadBitmap( destId, mBitmap, xOffset, yOffset);
+ mBitmap = NULL;
}
-void BufferImage::Connect()
+void BufferImage::UpdateBufferArea( PixelBuffer* src, const RectArea& area )
{
- ++mConnectionCount;
+ DALI_ASSERT_DEBUG( area.x + area.width <= mWidth && area.y + area.height <= mHeight );
- // application owns bitmap buffer, don't do anything. Update() has to be called manually.
- if (mIsDataExternal)
- {
- return;
- }
+ PixelBuffer* dest = mBitmap->GetBuffer();
+ uint32_t width = area.width * mBytesPerPixel;
+ uint32_t stride = mWidth * mBytesPerPixel;
- if (mConnectionCount == 1)
+ src += ( area.y * mByteStride ) + ( area.x * mBytesPerPixel );
+ dest +=( ( area.y * mWidth ) + area.x ) * mBytesPerPixel;
+ for ( uint32_t i = 0; i < area.height; ++i )
{
- if (!mTicket && mBitmapCached)
- {
- const ImageTicketPtr& t = mResourceClient->AddBitmapImage(mBitmapCached.Get());
- mTicket = t.Get();
- mTicket->AddObserver(*this);
- }
+ memcpy( dest, src, width );
+ src += mByteStride;
+ dest += stride;
}
}
-void BufferImage::Disconnect()
+void BufferImage::MirrorExternal( const RectArea& area )
{
- if (!mTicket)
+ if( ( mByteStride == mWidth * mBytesPerPixel ) && area.IsEmpty() )
{
- return;
+ memcpy( mBitmap->GetBuffer(), mExternalBuffer, mBufferSize );
}
-
- --mConnectionCount;
-
- if (mConnectionCount == 0 && mReleasePolicy == Dali::Image::UNUSED)
+ else
{
- mBitmapCached = mResourceClient->GetBitmap(mTicket);
- // release image memory when it's not visible anymore (decrease ref. count of texture)
- mTicket->RemoveObserver(*this);
- mTicket.Reset();
+ UpdateBufferArea( mExternalBuffer, area );
}
}
-Integration::Bitmap * BufferImage::GetBitmap() const
+void BufferImage::Connect()
{
- Integration::Bitmap* bitmap = NULL;
-
- if (mTicket)
+ if ( !mConnectionCount++ )
{
- bitmap = mResourceClient->GetBitmap(mTicket);
+ RectArea area;
+ Update( area );
}
- else
+}
+
+void BufferImage::Disconnect()
+{
+ if ( mTicket )
{
- // off screen and freeing memory was requested
- bitmap = mBitmapCached.Get();
+ if ( !( --mConnectionCount ) && mReleasePolicy == Dali::Image::UNUSED )
+ {
+ mTicket->RemoveObserver(*this);
+ mTicket.Reset();
+ }
}
-
- DALI_ASSERT_DEBUG(bitmap);
-
- return bitmap;
}
} // namespace Internal
#define __DALI_INTERNAL_BUFFER_IMAGE_H__
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * 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.
/**
* Create a new BufferImage, which uses external data source.
* Pixel buffer has to be allocated by application.
- * Application holds ownership of the buffer.
+ * An internal copy is made of the Pixel Buffer, which can then be freed by the Application, unless if there will be a call to Update() later.
+ * The buffer should only be freed when there is no chance of an Update() being called again.
+ * Obtaining the buffer with GetBuffer() and altering the contents, then Update() will not work with externally owned buffers.
* For better performance and portability use power of two dimensions.
* The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
- * @note in case releasePol is "OffStage", application has to call Update() whenever image is re-added to the stage
+ *
+ * @deprecated Support for externally owned Pixel Buffers is due to be removed TBA.
+ * It is recommended that a BufferImage owned Buffer be used instead.
+
* @param [in] pixBuf pixel buffer. has to be allocated by application.
* @param [in] width image width in pixels
* @param [in] height image height in pixels
/**
* Create a new BufferImage, which uses external data source.
* Pixel buffer has to be allocated by application.
- * Application holds ownership of the buffer.
+ * An internal copy is made of the Pixel Buffer, which can then be freed by the Application, unless if there will be a call to Update() later.
+ * The buffer should only be freed when there is no chance of Update() being called again.
+ * Note: obtaining the buffer with GetBuffer(), writing changes, then Update() will cause any changes to be lost.
+ * In this case, the BufferImage will update from the external buffer and so changes should be written there.
* For better performance and portability use power of two dimensions.
* The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
- * @note in case releasePol is "OffStage", application has to call Update() whenever image is re-added to the stage
* @param [in] pixBuf pixel buffer. has to be allocated by application.
* @param [in] width image width in pixels
* @param [in] height image height in pixels
* Upload the modified contents with Update().
* @return the pixel buffer
*/
- PixelBuffer* GetBuffer();
+ PixelBuffer* GetBuffer() const
+ {
+ return ( mExternalBuffer ? mExternalBuffer : mInternalBuffer );
+ }
/**
* Returns buffer size in bytes.
* @return the buffer size in bytes
*/
- unsigned int GetBufferSize() const;
+ unsigned int GetBufferSize() const
+ {
+ return mBufferSize;
+ }
/**
* Returns buffer stride (in bytes).
* @return the buffer stride
*/
- unsigned int GetBufferStride() const;
+ unsigned int GetBufferStride() const
+ {
+ return mByteStride;
+ }
/**
* Get the pixel format
* @return The pixel format
*/
- Pixel::Format GetPixelFormat() const;
+ Pixel::Format GetPixelFormat() const
+ {
+ return mPixelFormat;
+ }
+
+ /**
+ * @brief Upload pixel data to another resource at an offset
+ *
+ * @param destId ResourceId of the destination
+ * @param xOffset x offset in the destination
+ * @param yOffset y offset in the destination
+ */
+ void UploadBitmap( ResourceId destId, std::size_t xOffset, std::size_t yOffset );
-protected: // From Resource
+protected: // From Image
/**
* @copydoc Dali::Internal::Image::Connect
*/
*/
virtual void Disconnect();
- /**
- * Get the bitmap from local cache or ticket.
- **/
- Integration::Bitmap * GetBitmap() const;
-
private:
- bool mIsDataExternal; ///< whether application holds ownership of pixel buffer or not
- ResourceClient* mResourceClient;
+ void ValidateBitmap();
-protected:
- Integration::BitmapPtr mBitmapCached;
+ void ReserveBitmap();
+
+ void UpdateBitmap( RectArea& updateArea );
+
+ void MirrorExternal( const RectArea& area );
+
+ void UpdateBufferArea( PixelBuffer* src, const RectArea& area );
+
+private:
+
+ PixelBuffer* mInternalBuffer; ///< NULL if the data is supplied by an external buffer.
+ PixelBuffer* mExternalBuffer; ///< NULL if there is no external pixel data (this is never owned by BufferImage).
+ ResourceClient* mResourceClient; ///< pointer to the resource client.
+ Integration::Bitmap* mBitmap; ///< pointer to the bitmap object containing the pixel buffer used to update GL.
+ uint32_t mBufferSize; ///< size of the pixel buffer.
+ uint32_t mByteStride; ///< width of the pixel buffer in bytes.
+ uint32_t mBytesPerPixel; ///< width of a pixel in bytes.
+ Pixel::Format mPixelFormat; ///< pixel format of bitmap.
+ ResourcePolicy::Discardable mResourcePolicy; ///< whether to discard the pixel buffer when removed from the stage or to retain the data.
};
} // namespace Internal
// INTERNAL INCLUDES
#include <dali/public-api/object/type-registry.h>
#include <dali/integration-api/bitmap.h>
-#include <dali/internal/event/images/bitmap-external.h>
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/event/resources/resource-client.h>
#include <dali/internal/update/manager/update-manager.h>
typedef TicketContainer::size_type TicketContainerSize;
typedef std::pair<ResourceId, ResourceTicket*> TicketPair;
-typedef std::map<ResourceId, Bitmap*> BitmapCache;
-typedef BitmapCache::iterator BitmapCacheIter;
-
struct ResourceClient::Impl
{
Impl()
ResourceId mNextId;
TicketContainer mTickets;
- BitmapCache mBitmaps;
};
ResourceClient::ResourceClient( ResourceManager& resourceManager,
return ticket;
}
-ImageTicketPtr ResourceClient::AllocateBitmapImage( unsigned int width,
- unsigned int height,
- unsigned int bufferWidth,
- unsigned int bufferHeight,
- Pixel::Format pixelformat )
-{
- /* buffer is available via public-api, therefore not discardable */
- Bitmap* const bitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
- Bitmap::PackedPixelsProfile* const packedBitmap = bitmap->GetPackedPixelsProfile();
- DALI_ASSERT_DEBUG(packedBitmap);
-
- packedBitmap->ReserveBuffer(pixelformat, width, height, bufferWidth, bufferHeight);
- DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
- DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= width * height);
-
- ImageTicketPtr ticket = AddBitmapImage(bitmap);
-
- DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
- DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= width * height);
- return ticket;
-}
-
ImageTicketPtr ResourceClient::AddBitmapImage(Bitmap* bitmap)
{
DALI_ASSERT_DEBUG( bitmap != NULL );
mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
- // Store bitmap for immediate access.
- mImpl->mBitmaps[newId] = bitmap;
-
DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddBitmapImage() New id = %u\n", newId);
RequestAddBitmapImageMessage( mEventThreadServices, mResourceManager, newId, bitmap );
yOffset );
}
-Bitmap* ResourceClient::GetBitmap(ResourceTicketPtr ticket)
-{
- DALI_ASSERT_DEBUG( ticket );
-
- Bitmap* bitmap = NULL;
- BitmapCacheIter iter = mImpl->mBitmaps.find(ticket->GetId());
-
- if( iter != mImpl->mBitmaps.end() )
- {
- bitmap = iter->second;
- }
- return bitmap;
-}
-
void ResourceClient::CreateGlTexture( ResourceId id )
{
RequestCreateGlTextureMessage( mEventThreadServices, mResourceManager, id );
const ResourceId deadId = ticket.GetId();
const ResourceTypePath& typePath = ticket.GetTypePath();
- // Ensure associated event owned resources are also removed
- mImpl->mBitmaps.erase(ticket.GetId());
-
// The ticket object is dead, remove from tickets container
TicketContainerSize erased = mImpl->mTickets.erase(deadId);
DALI_ASSERT_DEBUG(erased != 0);
ResourceTicketPtr RequestResourceTicket( ResourceId id );
/**
- * Reqeust allocation of a bitmap resource
- * @note Older hardware may require bufferWidth and bufferHeight to be a power of two
- * @param[in] width Image width in pixels
- * @param[in] height Image height in pixels
- * @param[in] bufferWidth Buffer width (stride) in pixels
- * @param[in] bufferHeight Buffer height in pixels
- * @param[in] pixelformat Pixel format
- * @return A ref-counted request object. Keep a copy until the resource is no longer required.
- */
- ImageTicketPtr AllocateBitmapImage ( unsigned int width,
- unsigned int height,
- unsigned int bufferWidth,
- unsigned int bufferHeight,
- Pixel::Format pixelformat );
-
- /**
* Injects a bitmap resource (does not require loading).
* @pre bitmap has to be initialized
* @param[in] bitmap an initialized bitmap
void UploadBitmap( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset);
/**
- * Find Bitmap by ticket.
- * @pre ticket has to identify a Bitmap
- * @param[in] ticket The ticket returned from AllocateBitmapImage() or AddBitmapImage()
- * @return The bitmap, or NULL if the ticket did not reference a bitmap
+ * @brief Trigger asynchronous creation of GL texture to back resource immediately.
+ * @param[in] id The resource ID to allocate a GL texture for.
*/
- Integration::Bitmap* GetBitmap(ResourceTicketPtr ticket);
- /**
- * @brief Trigger asynchronous creation of GL texture to back resource immediately.
- * @param[in] id The resource ID to allocate a GL texture for.
- */
- void CreateGlTexture( ResourceId id );
+ void CreateGlTexture( ResourceId id );
public: // From ResourceTicketLifetimeObserver.
$(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 \
$(internal_src_dir)/event/images/image-impl.cpp \
updateArea.x, updateArea.y, updateArea.width ,updateArea.height );
const unsigned int pitchPixels = mWidth;
- const unsigned int pixelDepth = GetBytesPerPixel( mPixelFormat );
+ const unsigned int pixelDepth = Dali::Pixel::GetBytesPerPixel( mPixelFormat );
// If the width of the source update area is the same as the pitch, then can
// copy the contents in a single contiguous TexSubImage call.
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);
+ // If the resource policy is to discard on upload then release buffer
+ DiscardBitmapBuffer();
+
if( pixels != NULL )
{
INCREASE_BY( PerformanceMonitor::TEXTURE_DATA_UPLOADED, GetBytesPerPixel(mPixelFormat) * mWidth * mHeight );
if( ResourcePolicy::OWNED_DISCARD == mDiscardPolicy )
{
DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, " Discarding bitmap\n");
- mBitmap->DiscardBuffer();
+ if ( mBitmap )
+ {
+ mBitmap->DiscardBuffer();
+ }
}
}
void DiscardBitmapBuffer();
private:
- Integration::BitmapPtr mBitmap; ///< The Bitmap the Texture was created from (may be NULL)
- bool mClearPixels; ///< true if initial texture should be cleared on creation
- ResourcePolicy::Discardable mDiscardPolicy; ///< The bitmap discard policy
- Pixel::Format mPixelFormat;
+ Integration::BitmapPtr mBitmap; ///< The Bitmap the Texture was created from (may be NULL)
+ bool mClearPixels:1; ///< true if initial texture should be cleared on creation
+ ResourcePolicy::Discardable mDiscardPolicy:2; ///< The bitmap discard policy
+ Pixel::Format mPixelFormat:5; ///< Pack pixel format into bitfield
// Changes scope, should be at end of class
DALI_LOG_OBJECT_STRING_DECLARATION;
if ( mId ) // If the texture is already bound
{
AssignBitmap( false, pixels, mBitmap->GetBufferSize() );
-
- if( mDiscardPolicy == ResourcePolicy::OWNED_DISCARD )
- {
- mBitmap->DiscardBuffer();
- }
}
}
}