Merge branch 'devel/master' into tizen
[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/public-api/images/pixel-data.h>
27 #include <dali/internal/event/common/thread-local-storage.h>
28 #include <dali/internal/update/manager/update-manager.h>
29
30 using namespace Dali::Integration;
31
32 namespace Dali
33 {
34 namespace Internal
35 {
36
37 namespace
38 {
39 TypeRegistration mType( typeid( Dali::BufferImage ), typeid( Dali::Image ), NULL );
40 } // unnamed namespace
41
42 BufferImagePtr BufferImage::New( unsigned int width,
43                                  unsigned int height,
44                                  Pixel::Format pixelformat )
45 {
46   BufferImagePtr internal = new BufferImage( width, height, pixelformat );
47   internal->Initialize();
48   internal->Update( RectArea() );
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   internal->Update( RectArea() );
61   return internal;
62 }
63
64 BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat)
65 : Image(),
66   mInternalBuffer( NULL ),
67   mExternalBuffer( NULL ),
68   mResourceClient( NULL ),
69   mBufferSize( 0 ),
70   mByteStride( 0 ),
71   mBytesPerPixel( 0 ),
72   mBufferWidth( 0 ),
73   mPixelFormat( pixelformat ),
74   mResourcePolicy( ResourcePolicy::OWNED_DISCARD )
75 {
76   SetupBuffer( width, height, pixelformat, width );
77
78   // Allocate a persistent internal buffer
79   mInternalBuffer = new PixelBuffer[ mBufferSize ];
80 }
81
82 BufferImage::BufferImage(PixelBuffer* pixBuf,
83                          unsigned int width,
84                          unsigned int height,
85                          Pixel::Format pixelformat,
86                          unsigned int stride)
87 : Image(),
88   mInternalBuffer( NULL ),
89   mExternalBuffer( pixBuf ),
90   mResourceClient( NULL ),
91   mBufferSize( 0 ),
92   mByteStride( 0 ),
93   mBytesPerPixel( 0 ),
94   mBufferWidth( 0 ),
95   mPixelFormat( pixelformat ),
96   mResourcePolicy( ResourcePolicy::OWNED_DISCARD )
97 {
98   SetupBuffer( width, height, pixelformat, stride ? stride: width );
99 }
100
101 BufferImage::~BufferImage()
102 {
103   delete[] mInternalBuffer;
104 }
105
106 void BufferImage::SetupBuffer( unsigned int width,
107                                unsigned int height,
108                                Pixel::Format pixelformat,
109                                unsigned int byteStride )
110 {
111   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
112   mResourceClient = &tls.GetResourceClient();
113   mWidth  = width;
114   mHeight = height;
115   mPixelFormat = pixelformat;
116   mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat );
117
118   mByteStride = byteStride * mBytesPerPixel;
119   mBufferSize = height * mByteStride;
120
121   // Respect the desired release policy
122   mResourcePolicy = ResourcePolicy::OWNED_RETAIN;
123 }
124
125 bool BufferImage::IsDataExternal() const
126 {
127   return ( mExternalBuffer ? true : false );
128 }
129
130 void BufferImage::Update( const RectArea& updateArea )
131 {
132   if ( !mTexture )
133   {
134     mTexture = NewTexture::New( Dali::TextureType::TEXTURE_2D, mPixelFormat, mWidth, mHeight );
135   }
136   DALI_ASSERT_DEBUG( updateArea.x + updateArea.width <= mWidth && updateArea.y + updateArea.height <= mHeight );
137   UploadArea( updateArea );
138 }
139
140 void BufferImage::UploadArea( const RectArea& area )
141 {
142   DALI_ASSERT_DEBUG( area.width <= mWidth && area.height <= mHeight );
143
144   mBufferWidth = area.width ? area.width : mWidth;
145   uint32_t bufferHeight = area.height ? area.height : mHeight;
146   size_t bufferSize = mBytesPerPixel * mBufferWidth * bufferHeight;
147   unsigned char* buffer = reinterpret_cast< Dali::Integration::PixelBuffer* >( malloc( bufferSize ) );
148   DALI_ASSERT_DEBUG(buffer != 0);
149
150   // Are we uploading from an external or internal buffer ?
151   if ( mExternalBuffer )
152   {
153     // Check if we're doing the entire area without stride mismatch between source and dest ?
154     if( ( mByteStride == mWidth * mBytesPerPixel ) && area.IsEmpty() )
155     {
156       memcpy( buffer, mExternalBuffer, mBufferSize );
157     }
158     else
159     {
160       UpdateBufferArea( mExternalBuffer, buffer, area );
161     }
162   }
163   else
164   {
165     // Check if we're doing the entire internal buffer ?
166     if( area.IsEmpty() )
167     {
168       memcpy( buffer, mInternalBuffer, bufferSize );
169     }
170     else
171     {
172       UpdateBufferArea( mInternalBuffer, buffer, area );
173     }
174   }
175   PixelDataPtr pixelData = PixelData::New( buffer, bufferSize, mBufferWidth, bufferHeight, mPixelFormat, Dali::PixelData::FREE );
176   mTexture->Upload( pixelData, 0u, 0u, area.x, area.y, mBufferWidth, bufferHeight );
177 }
178
179 void BufferImage::UpdateBufferArea( PixelBuffer* src, PixelBuffer* dest, const RectArea& area )
180 {
181   DALI_ASSERT_DEBUG( area.x + area.width <= mWidth && area.y + area.height <= mHeight );
182
183   uint32_t width = mBufferWidth * mBytesPerPixel;
184
185   src += ( area.y * mByteStride ) + ( area.x * mBytesPerPixel );
186   for ( uint32_t i = 0; i < area.height; ++i )
187   {
188     memcpy( dest, src, width );
189     src += mByteStride;
190     dest += width;
191   }
192 }
193
194 } // namespace Internal
195
196 } // namespace Dali