Fix various klocwork issues
[platform/core/uifw/dali-core.git] / dali / internal / event / images / buffer-image-impl.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/images/buffer-image-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <string.h>
23
24 // INTERNAL INCLUDES
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>
30
31 using namespace Dali::Integration;
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37
38 namespace
39 {
40 TypeRegistration mType( typeid( Dali::BufferImage ), typeid( Dali::Image ), NULL );
41 } // unnamed namespace
42
43 BufferImagePtr BufferImage::New( unsigned int width,
44                                  unsigned int height,
45                                  Pixel::Format pixelformat,
46                                  ReleasePolicy releasePol )
47 {
48   BufferImagePtr internal = new BufferImage( width, height, pixelformat, releasePol );
49   internal->Initialize();
50   return internal;
51 }
52
53 BufferImagePtr BufferImage::New( PixelBuffer* pixBuf,
54                                  unsigned int width,
55                                  unsigned int height,
56                                  Pixel::Format pixelformat,
57                                  unsigned int stride,
58                                  ReleasePolicy releasePol )
59 {
60   BufferImagePtr internal = new BufferImage( pixBuf, width, height, pixelformat, stride, releasePol );
61   internal->Initialize();
62   return internal;
63 }
64
65 BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol)
66 : Image( releasePol ),
67   mInternalBuffer( NULL ),
68   mExternalBuffer( NULL ),
69   mResourceClient( NULL ),
70   mBufferSize( 0 ),
71   mByteStride( 0 ),
72   mBytesPerPixel( 0 ),
73   mBufferWidth( 0 ),
74   mPixelFormat( pixelformat ),
75   mResourcePolicy( ResourcePolicy::OWNED_DISCARD )
76 {
77   SetupBuffer( width, height, pixelformat, width, releasePol );
78
79   // Allocate a persistent internal buffer
80   mInternalBuffer = new PixelBuffer[ mBufferSize ];
81 }
82
83 BufferImage::BufferImage(PixelBuffer* pixBuf,
84                          unsigned int width,
85                          unsigned int height,
86                          Pixel::Format pixelformat,
87                          unsigned int stride,
88                          ReleasePolicy releasePol )
89 : Image( releasePol ),
90   mInternalBuffer( NULL ),
91   mExternalBuffer( pixBuf ),
92   mResourceClient( NULL ),
93   mBufferSize( 0 ),
94   mByteStride( 0 ),
95   mBytesPerPixel( 0 ),
96   mBufferWidth( 0 ),
97   mPixelFormat( pixelformat ),
98   mResourcePolicy( ResourcePolicy::OWNED_DISCARD )
99 {
100   SetupBuffer( width, height, pixelformat, stride ? stride: width, releasePol );
101 }
102
103 BufferImage::~BufferImage()
104 {
105   delete[] mInternalBuffer;
106 }
107
108 void BufferImage::SetupBuffer( unsigned int width,
109                                unsigned int height,
110                                Pixel::Format pixelformat,
111                                unsigned int byteStride,
112                                ReleasePolicy releasePol )
113 {
114   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
115   mResourceClient = &tls.GetResourceClient();
116   mWidth  = width;
117   mHeight = height;
118   mPixelFormat = pixelformat;
119   mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat );
120
121   mByteStride = byteStride * mBytesPerPixel;
122   mBufferSize = height * mByteStride;
123
124   // Respect the desired release policy
125   mResourcePolicy = releasePol == Dali::Image::UNUSED ? ResourcePolicy::OWNED_DISCARD : ResourcePolicy::OWNED_RETAIN;
126 }
127
128 bool BufferImage::IsDataExternal() const
129 {
130   return ( mExternalBuffer ? true : false );
131 }
132
133 void BufferImage::Update( RectArea& updateArea )
134 {
135   if ( !mTicket )
136   {
137     CreateHostBitmap();
138   }
139   DALI_ASSERT_DEBUG( updateArea.x + updateArea.width <= mWidth && updateArea.y + updateArea.height <= mHeight );
140   UploadArea( mTicket->GetId(), updateArea );
141 }
142
143 void BufferImage::CreateHostBitmap()
144 {
145   Integration::Bitmap* bitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, mResourcePolicy );
146   Bitmap::PackedPixelsProfile* const packedBitmap = bitmap->GetPackedPixelsProfile();
147   DALI_ASSERT_DEBUG(packedBitmap);
148
149   packedBitmap->ReserveBuffer( mPixelFormat, mWidth, mHeight );
150   DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
151   DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= mHeight * mWidth * mBytesPerPixel );
152
153   mTicket = mResourceClient->AddBitmapImage( bitmap );
154   mTicket->AddObserver(*this);
155 }
156
157 void BufferImage::UploadArea( ResourceId destId, const RectArea& area )
158 {
159   Integration::Bitmap* bitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, mResourcePolicy );
160   Bitmap::PackedPixelsProfile* const packedBitmap = bitmap->GetPackedPixelsProfile();
161   DALI_ASSERT_DEBUG(packedBitmap);
162   DALI_ASSERT_DEBUG( area.width <= mWidth && area.height <= mHeight );
163
164   mBufferWidth = area.width ? area.width : mWidth;
165   packedBitmap->ReserveBuffer( mPixelFormat, mBufferWidth, area.height ? area.height : mHeight );
166   DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
167   DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= mBufferWidth * ( area.height ? area.height : mHeight ) * mBytesPerPixel );
168
169   // Are we uploading from an external or internal buffer ?
170   if ( mExternalBuffer )
171   {
172     // Check if we're doing the entire area without stride mismatch between source and dest ?
173     if( ( mByteStride == mWidth * mBytesPerPixel ) && area.IsEmpty() )
174     {
175       memcpy( bitmap->GetBuffer(), mExternalBuffer, mBufferSize );
176     }
177     else
178     {
179       UpdateBufferArea( mExternalBuffer, bitmap->GetBuffer(), area );
180     }
181   }
182   else
183   {
184     // Check if we're doing the entire internal buffer ?
185     if( area.IsEmpty() )
186     {
187       memcpy( bitmap->GetBuffer(), mInternalBuffer, bitmap->GetBufferSize() );
188     }
189     else
190     {
191       UpdateBufferArea( mInternalBuffer, bitmap->GetBuffer(), area );
192     }
193   }
194   mResourceClient->UploadBitmap( destId, bitmap, area.x, area.y );
195
196 }
197
198 void BufferImage::UploadBitmap( ResourceId destId, std::size_t xOffset, std::size_t yOffset )
199 {
200   RectArea area( xOffset, yOffset, 0, 0 );
201   if ( !mTicket )
202   {
203     CreateHostBitmap();
204   }
205
206   UploadArea( destId, area );
207 }
208
209 void BufferImage::UpdateBufferArea( PixelBuffer* src, PixelBuffer* dest, const RectArea& area )
210 {
211   DALI_ASSERT_DEBUG( area.x + area.width <= mWidth && area.y + area.height <= mHeight );
212
213   uint32_t width = mBufferWidth * mBytesPerPixel;
214
215   src += ( area.y * mByteStride ) + ( area.x * mBytesPerPixel );
216   for ( uint32_t i = 0; i < area.height; ++i )
217   {
218     memcpy( dest, src, width );
219     src += mByteStride;
220     dest += width;
221   }
222 }
223
224 void BufferImage::Connect()
225 {
226   if ( !mConnectionCount++ )
227   {
228     RectArea area;
229     Update( area );
230   }
231 }
232
233 void BufferImage::Disconnect()
234 {
235   if ( mTicket )
236   {
237     if ( !( --mConnectionCount ) && mReleasePolicy == Dali::Image::UNUSED )
238     {
239       mTicket->RemoveObserver(*this);
240       mTicket.Reset();
241     }
242   }
243 }
244
245 } // namespace Internal
246
247 } // namespace Dali