X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fimages%2Fbuffer-image-impl.cpp;h=c34dede406a3343b26c1e6152d8bf4da432fbb93;hb=d2d43506df25b63d0385270b2cbd6ccc2ca16ccb;hp=e87f0a172aa29e66bb2cb27d2de5eb15d2d6e295;hpb=b3355d3e24c02b29c0ffd6d98c996cf45946d276;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/images/buffer-image-impl.cpp b/dali/internal/event/images/buffer-image-impl.cpp index e87f0a1..c34dede 100644 --- a/dali/internal/event/images/buffer-image-impl.cpp +++ b/dali/internal/event/images/buffer-image-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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. @@ -18,14 +18,16 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include -#include -#include +#include #include -#include #include -#include + +using namespace Dali::Integration; namespace Dali { @@ -37,193 +39,154 @@ namespace TypeRegistration mType( typeid( Dali::BufferImage ), typeid( Dali::Image ), NULL ); } // unnamed namespace -BufferImagePtr BufferImage::New( unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol ) +BufferImagePtr BufferImage::New( unsigned int width, + unsigned int height, + Pixel::Format pixelformat ) { - BufferImagePtr internal = new BufferImage( width, height, pixelformat, releasePol ); + BufferImagePtr internal = new BufferImage( width, height, pixelformat ); internal->Initialize(); + internal->Update( RectArea() ); return internal; } -BufferImagePtr BufferImage::New( PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol ) +BufferImagePtr BufferImage::New( PixelBuffer* pixBuf, + unsigned int width, + unsigned int height, + Pixel::Format pixelformat, + unsigned int stride ) { - BufferImagePtr internal = new BufferImage( pixBuf, width, height, pixelformat, stride, releasePol ); + BufferImagePtr internal = new BufferImage( pixBuf, width, height, pixelformat, stride ); internal->Initialize(); + internal->Update( RectArea() ); return internal; } -BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol) -: Image(releasePol), - mIsDataExternal(false) -{ - ThreadLocalStorage& tls = ThreadLocalStorage::Get(); - mResourceClient = &tls.GetResourceClient(); - mWidth = width; - mHeight = height; - - const ImageTicketPtr& t = mResourceClient->AllocateBitmapImage(width, height, width, height, pixelformat); - mTicket = t.Get(); - - mTicket->AddObserver(*this); +BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat) +: Image(), + mInternalBuffer( NULL ), + mExternalBuffer( NULL ), + mBufferSize( 0 ), + mByteStride( 0 ), + mBytesPerPixel( 0 ), + mBufferWidth( 0 ), + mPixelFormat( pixelformat ), + mResourcePolicy( ResourcePolicy::OWNED_DISCARD ) +{ + SetupBuffer( width, height, pixelformat, width ); + + // Allocate a persistent internal buffer + mInternalBuffer = new PixelBuffer[ mBufferSize ]; } -BufferImage::BufferImage(PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol) -: Image(releasePol), - mIsDataExternal(true) -{ - 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(); - - mTicket->AddObserver(*this); +BufferImage::BufferImage(PixelBuffer* pixBuf, + unsigned int width, + unsigned int height, + Pixel::Format pixelformat, + unsigned int stride) +: Image(), + mInternalBuffer( NULL ), + mExternalBuffer( pixBuf ), + mBufferSize( 0 ), + mByteStride( 0 ), + mBytesPerPixel( 0 ), + mBufferWidth( 0 ), + mPixelFormat( pixelformat ), + mResourcePolicy( ResourcePolicy::OWNED_DISCARD ) +{ + SetupBuffer( width, height, pixelformat, stride ? stride: width ); } BufferImage::~BufferImage() { + delete[] mInternalBuffer; } -void BufferImage::Update( RectArea& 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!) - 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); - } -} - -bool BufferImage::IsDataExternal() const -{ - return mIsDataExternal; -} - -PixelBuffer* BufferImage::GetBuffer() -{ - PixelBuffer* buffer = NULL; - - Integration::Bitmap* const bitmap = GetBitmap(); - - if(bitmap) - { - buffer = bitmap->GetBuffer(); - } - return buffer; -} - -unsigned int BufferImage::GetBufferSize() const +void BufferImage::SetupBuffer( unsigned int width, + unsigned int height, + Pixel::Format pixelformat, + unsigned int byteStride ) { - unsigned int bufferSize = 0; + mWidth = width; + mHeight = height; + mPixelFormat = pixelformat; + mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat ); - Integration::Bitmap* const bitmap = GetBitmap(); + mByteStride = byteStride * mBytesPerPixel; + mBufferSize = height * mByteStride; - if(bitmap) - { - bufferSize = bitmap->GetBufferSize(); - } - return bufferSize; + // Respect the desired release policy + mResourcePolicy = ResourcePolicy::OWNED_RETAIN; } -unsigned int BufferImage::GetBufferStride() const +bool BufferImage::IsDataExternal() const { - unsigned int bufferStride = 0; - - Integration::Bitmap* const bitmap = GetBitmap(); - - if(bitmap) - { - Integration::Bitmap::PackedPixelsProfile* packedBitmap = bitmap->GetPackedPixelsProfile(); - DALI_ASSERT_DEBUG(packedBitmap); - bufferStride = packedBitmap->GetBufferStride(); - } - - return bufferStride; + return ( mExternalBuffer ? true : false ); } -Pixel::Format BufferImage::GetPixelFormat() const +void BufferImage::Update( const RectArea& updateArea ) { - Pixel::Format format( Pixel::RGBA8888 ); - - Integration::Bitmap* const bitmap = GetBitmap(); - - if( bitmap ) + if ( !mTexture ) { - format = bitmap->GetPixelFormat(); + mTexture = Texture::New( Dali::TextureType::TEXTURE_2D, mPixelFormat, mWidth, mHeight ); } - - return format; + DALI_ASSERT_DEBUG( updateArea.x + updateArea.width <= mWidth && updateArea.y + updateArea.height <= mHeight ); + UploadArea( updateArea ); } -void BufferImage::Connect() +void BufferImage::UploadArea( const RectArea& area ) { - ++mConnectionCount; + DALI_ASSERT_DEBUG( area.width <= mWidth && area.height <= mHeight ); - // application owns bitmap buffer, don't do anything. Update() has to be called manually. - if (mIsDataExternal) - { - return; - } + mBufferWidth = area.width ? area.width : mWidth; + uint32_t bufferHeight = area.height ? area.height : mHeight; + size_t bufferSize = mBytesPerPixel * mBufferWidth * bufferHeight; + unsigned char* buffer = reinterpret_cast< Dali::Integration::PixelBuffer* >( malloc( bufferSize ) ); + DALI_ASSERT_DEBUG(buffer != 0); - if (mConnectionCount == 1) + // Are we uploading from an external or internal buffer ? + if ( mExternalBuffer ) { - if (!mTicket && mBitmapCached) + // Check if we're doing the entire area without stride mismatch between source and dest ? + if( ( mByteStride == mWidth * mBytesPerPixel ) && area.IsEmpty() ) + { + memcpy( buffer, mExternalBuffer, mBufferSize ); + } + else { - const ImageTicketPtr& t = mResourceClient->AddBitmapImage(mBitmapCached.Get()); - mTicket = t.Get(); - mTicket->AddObserver(*this); + UpdateBufferArea( mExternalBuffer, buffer, area ); } } -} - -void BufferImage::Disconnect() -{ - if (!mTicket) + else { - return; + // Check if we're doing the entire internal buffer ? + if( area.IsEmpty() ) + { + memcpy( buffer, mInternalBuffer, bufferSize ); + } + else + { + UpdateBufferArea( mInternalBuffer, buffer, area ); + } } + PixelDataPtr pixelData = PixelData::New( buffer, bufferSize, mBufferWidth, bufferHeight, mPixelFormat, Dali::PixelData::FREE ); + mTexture->Upload( pixelData, 0u, 0u, area.x, area.y, mBufferWidth, bufferHeight ); - --mConnectionCount; - - if (mConnectionCount == 0 && mReleasePolicy == Dali::Image::UNUSED) - { - mBitmapCached = mResourceClient->GetBitmap(mTicket); - // release image memory when it's not visible anymore (decrease ref. count of texture) - mTicket->RemoveObserver(*this); - mTicket.Reset(); - } + UploadedSignal().Emit( Dali::Image( this ) ); } -Integration::Bitmap * BufferImage::GetBitmap() const +void BufferImage::UpdateBufferArea( PixelBuffer* src, PixelBuffer* dest, const RectArea& area ) { - Integration::Bitmap* bitmap = NULL; + DALI_ASSERT_DEBUG( area.x + area.width <= mWidth && area.y + area.height <= mHeight ); - if (mTicket) - { - bitmap = mResourceClient->GetBitmap(mTicket); - } - else + uint32_t width = mBufferWidth * mBytesPerPixel; + + src += ( area.y * mByteStride ) + ( area.x * mBytesPerPixel ); + for ( uint32_t i = 0; i < area.height; ++i ) { - // off screen and freeing memory was requested - bitmap = mBitmapCached.Get(); + memcpy( dest, src, width ); + src += mByteStride; + dest += width; } - - DALI_ASSERT_DEBUG(bitmap); - - return bitmap; } } // namespace Internal