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