2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/images/buffer-image-impl.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/internal/event/common/thread-local-storage.h>
27 #include <dali/internal/event/resources/resource-client.h>
28 #include <dali/internal/update/manager/update-manager.h>
29 #include <dali/internal/event/images/image-factory.h>
31 using namespace Dali::Integration;
40 TypeRegistration mType( typeid( Dali::BufferImage ), typeid( Dali::Image ), NULL );
41 } // unnamed namespace
43 BufferImagePtr BufferImage::New( unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol )
45 BufferImagePtr internal = new BufferImage( width, height, pixelformat, releasePol );
46 internal->Initialize();
50 BufferImagePtr BufferImage::New( PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol )
52 BufferImagePtr internal = new BufferImage( pixBuf, width, height, pixelformat, stride, releasePol );
53 internal->Initialize();
57 BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol)
59 mInternalBuffer(NULL),
60 mExternalBuffer(NULL),
63 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
64 mResourceClient = &tls.GetResourceClient();
67 mPixelFormat = pixelformat;
68 mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat );
69 mByteStride = width * mBytesPerPixel;
70 mBufferSize = height * mByteStride;
72 // Allocate a persistent internal buffer
73 mInternalBuffer = new PixelBuffer[ mBufferSize ];
75 // Respect the desired release policy
76 mResourcePolicy = releasePol == Dali::Image::UNUSED ? ResourcePolicy::OWNED_DISCARD : ResourcePolicy::OWNED_RETAIN;
79 BufferImage::BufferImage(PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol )
81 mInternalBuffer(NULL),
82 mExternalBuffer(pixBuf),
85 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
86 mResourceClient = &tls.GetResourceClient();
89 mPixelFormat = pixelformat;
90 mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat );
91 mByteStride = ( stride ? stride : mWidth ) * mBytesPerPixel;
92 mBufferSize = height * mByteStride;
94 // Respect the desired release policy
95 mResourcePolicy = releasePol == Dali::Image::UNUSED ? ResourcePolicy::OWNED_DISCARD : ResourcePolicy::OWNED_RETAIN;
97 // Create a bitmap to hold copy of external buffer
100 // Take a copy of the external buffer immediately, so it can be released if desired
102 MirrorExternal( area );
105 BufferImage::~BufferImage()
107 delete[] mInternalBuffer;
110 bool BufferImage::IsDataExternal() const
112 return ( mExternalBuffer ? true : false );
115 void BufferImage::Update( RectArea& updateArea )
118 UpdateBitmap( updateArea );
122 DALI_ASSERT_DEBUG( updateArea.x + updateArea.width <= mWidth && updateArea.y + updateArea.height <= mHeight );
123 mResourceClient->UpdateBitmapArea( mTicket, updateArea );
125 // Bitmap ownership has been passed on, so any subsequent update will need another bitmap
130 void BufferImage::UpdateBitmap( RectArea& updateArea )
132 if ( mExternalBuffer )
134 MirrorExternal( updateArea );
138 // Copy the internal buffer to the bitmap area
139 memcpy( mBitmap->GetBuffer(), mInternalBuffer, mBufferSize );
143 void BufferImage::ValidateBitmap()
148 mTicket = mResourceClient->AddBitmapImage( mBitmap );
149 mTicket->AddObserver(*this);
153 void BufferImage::ReserveBitmap()
155 // Does a bitmap currently exist ?
158 mBitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, mResourcePolicy );
161 if ( !mBitmap->GetBuffer() )
163 Bitmap::PackedPixelsProfile* const packedBitmap = mBitmap->GetPackedPixelsProfile();
164 DALI_ASSERT_DEBUG(packedBitmap);
166 packedBitmap->ReserveBuffer( mPixelFormat, mWidth, mHeight, mByteStride / mBytesPerPixel, mHeight );
167 DALI_ASSERT_DEBUG(mBitmap->GetBuffer() != 0);
168 DALI_ASSERT_DEBUG(mBitmap->GetBufferSize() >= mWidth * mHeight * Pixel::GetBytesPerPixel( mBitmap->GetPixelFormat() ) );
172 void BufferImage::UploadBitmap( ResourceId destId, std::size_t xOffset, std::size_t yOffset )
174 // Make sure we have a bitmap for transport
177 // Copy source pixel data into bitmap
179 UpdateBitmap( area );
181 mResourceClient->UploadBitmap( destId, mBitmap, xOffset, yOffset);
185 void BufferImage::UpdateBufferArea( PixelBuffer* src, const RectArea& area )
187 DALI_ASSERT_DEBUG( area.x + area.width <= mWidth && area.y + area.height <= mHeight );
189 PixelBuffer* dest = mBitmap->GetBuffer();
190 uint32_t width = area.width * mBytesPerPixel;
191 uint32_t stride = mWidth * mBytesPerPixel;
193 src += ( area.y * mByteStride ) + ( area.x * mBytesPerPixel );
194 dest +=( ( area.y * mWidth ) + area.x ) * mBytesPerPixel;
195 for ( uint32_t i = 0; i < area.height; ++i )
197 memcpy( dest, src, width );
203 void BufferImage::MirrorExternal( const RectArea& area )
205 if( ( mByteStride == mWidth * mBytesPerPixel ) && area.IsEmpty() )
207 memcpy( mBitmap->GetBuffer(), mExternalBuffer, mBufferSize );
211 UpdateBufferArea( mExternalBuffer, area );
215 void BufferImage::Connect()
217 if ( !mConnectionCount++ )
224 void BufferImage::Disconnect()
228 if ( !( --mConnectionCount ) && mReleasePolicy == Dali::Image::UNUSED )
230 mTicket->RemoveObserver(*this);
236 } // namespace Internal