7ad879b9f05c7c6357b70570be022a5befd889b9
[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 BufferImagePtr BufferImage::New( unsigned int width,
38                                  unsigned int height,
39                                  Pixel::Format pixelformat )
40 {
41   BufferImagePtr internal = new BufferImage( width, height, pixelformat );
42   internal->Initialize();
43   internal->Update( RectArea() );
44   return internal;
45 }
46
47 BufferImagePtr BufferImage::New( PixelBuffer* pixBuf,
48                                  unsigned int width,
49                                  unsigned int height,
50                                  Pixel::Format pixelformat,
51                                  unsigned int stride )
52 {
53   BufferImagePtr internal = new BufferImage( pixBuf, width, height, pixelformat, stride );
54   internal->Initialize();
55   internal->Update( RectArea() );
56   return internal;
57 }
58
59 BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat)
60 : Image(),
61   mInternalBuffer( NULL ),
62   mExternalBuffer( NULL ),
63   mBufferSize( 0 ),
64   mByteStride( 0 ),
65   mBytesPerPixel( 0 ),
66   mBufferWidth( 0 ),
67   mPixelFormat( pixelformat ),
68   mResourcePolicy( ResourcePolicy::OWNED_DISCARD )
69 {
70   SetupBuffer( width, height, pixelformat, width );
71
72   // Allocate a persistent internal buffer
73   mInternalBuffer = new PixelBuffer[ mBufferSize ];
74 }
75
76 BufferImage::BufferImage(PixelBuffer* pixBuf,
77                          unsigned int width,
78                          unsigned int height,
79                          Pixel::Format pixelformat,
80                          unsigned int stride)
81 : Image(),
82   mInternalBuffer( NULL ),
83   mExternalBuffer( pixBuf ),
84   mBufferSize( 0 ),
85   mByteStride( 0 ),
86   mBytesPerPixel( 0 ),
87   mBufferWidth( 0 ),
88   mPixelFormat( pixelformat ),
89   mResourcePolicy( ResourcePolicy::OWNED_DISCARD )
90 {
91   SetupBuffer( width, height, pixelformat, stride ? stride: width );
92 }
93
94 BufferImage::~BufferImage()
95 {
96   delete[] mInternalBuffer;
97 }
98
99 void BufferImage::SetupBuffer( unsigned int width,
100                                unsigned int height,
101                                Pixel::Format pixelformat,
102                                unsigned int byteStride )
103 {
104   mWidth  = width;
105   mHeight = height;
106   mPixelFormat = pixelformat;
107   mBytesPerPixel = Pixel::GetBytesPerPixel( pixelformat );
108
109   mByteStride = byteStride * mBytesPerPixel;
110   mBufferSize = height * mByteStride;
111
112   // Respect the desired release policy
113   mResourcePolicy = ResourcePolicy::OWNED_RETAIN;
114 }
115
116 bool BufferImage::IsDataExternal() const
117 {
118   return ( mExternalBuffer ? true : false );
119 }
120
121 void BufferImage::Update( const RectArea& updateArea )
122 {
123   if ( !mTexture )
124   {
125     mTexture = Texture::New( Dali::TextureType::TEXTURE_2D, mPixelFormat, mWidth, mHeight );
126   }
127   DALI_ASSERT_DEBUG( updateArea.x + updateArea.width <= mWidth && updateArea.y + updateArea.height <= mHeight );
128   UploadArea( updateArea );
129 }
130
131 void BufferImage::UploadArea( const RectArea& area )
132 {
133   DALI_ASSERT_DEBUG( area.width <= mWidth && area.height <= mHeight );
134
135   mBufferWidth = area.width ? area.width : mWidth;
136   uint32_t bufferHeight = area.height ? area.height : mHeight;
137   uint32_t bufferSize = mBytesPerPixel * mBufferWidth * bufferHeight;
138   Dali::Integration::PixelBuffer* buffer = reinterpret_cast< Dali::Integration::PixelBuffer* >( malloc( bufferSize ) );
139   DALI_ASSERT_DEBUG(buffer != 0);
140
141   // Are we uploading from an external or internal buffer ?
142   if ( mExternalBuffer )
143   {
144     // Check if we're doing the entire area without stride mismatch between source and dest ?
145     if( ( mByteStride == mWidth * mBytesPerPixel ) && area.IsEmpty() )
146     {
147       memcpy( buffer, mExternalBuffer, mBufferSize );
148     }
149     else
150     {
151       UpdateBufferArea( mExternalBuffer, buffer, area );
152     }
153   }
154   else
155   {
156     // Check if we're doing the entire internal buffer ?
157     if( area.IsEmpty() )
158     {
159       memcpy( buffer, mInternalBuffer, bufferSize );
160     }
161     else
162     {
163       UpdateBufferArea( mInternalBuffer, buffer, area );
164     }
165   }
166   PixelDataPtr pixelData = PixelData::New( buffer, bufferSize, mBufferWidth, bufferHeight, mPixelFormat, Dali::PixelData::FREE );
167   mTexture->Upload( pixelData, 0u, 0u, area.x, area.y, mBufferWidth, bufferHeight );
168
169   UploadedSignal().Emit( Dali::Image( this ) );
170 }
171
172 void BufferImage::UpdateBufferArea( PixelBuffer* src, PixelBuffer* dest, const RectArea& area )
173 {
174   DALI_ASSERT_DEBUG( area.x + area.width <= mWidth && area.y + area.height <= mHeight );
175
176   uint32_t width = mBufferWidth * mBytesPerPixel;
177
178   src += ( area.y * mByteStride ) + ( area.x * mBytesPerPixel );
179   for ( uint32_t i = 0; i < area.height; ++i )
180   {
181     memcpy( dest, src, width );
182     src += mByteStride;
183     dest += width;
184   }
185 }
186
187 } // namespace Internal
188
189 } // namespace Dali