Merge "Clean up the code to build successfully on macOS" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / rendering / vertex-buffer-impl.cpp
1 /*
2  * Copyright (c) 2020 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/rendering/vertex-buffer-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/rendering/vertex-buffer.h>
23 #include <dali/internal/update/manager/update-manager.h>
24
25 #if defined (ANDROID) || defined(WIN32) || defined(__APPLE__)
26 namespace std
27 {
28   uint64_t _Hash_bytes(const void* bytes, uint64_t size, uint64_t seed)
29   {
30     for (uint64_t i = 0; i < size; i++)
31     {
32       seed = seed * 31 + reinterpret_cast<const unsigned char*>(bytes)[i];
33     }
34
35     return seed;
36   }
37 }
38 #endif
39
40 namespace Dali
41 {
42 namespace Internal
43 {
44
45 namespace
46 {
47
48 /**
49  * Calculate the alignment requirements of a type
50  *
51  * This is used to calculate the memory alignment requirements of a type
52  * It creates a structure with a dummy char and a member of the type we want to check
53  * this will cause the second member to be aligned by it's alignment requirement.
54  */
55 template<Property::Type type>
56 struct PropertyImplementationTypeAlignment
57 {
58   // Create a structure that forces alignment of the data type
59   struct TestStructure
60   {
61     char oneChar;  ///< Member with sizeof() == 1
62     typename PropertyImplementationType<type>::Type data;
63   };
64   enum { VALUE = offsetof( TestStructure, data ) };
65 };
66
67 uint32_t GetPropertyImplementationAlignment( Property::Type& propertyType )
68 {
69   uint32_t alignment = 0u;
70
71   switch( propertyType )
72   {
73     case Property::BOOLEAN:
74     {
75       alignment = PropertyImplementationTypeAlignment< Property::BOOLEAN >::VALUE;
76       break;
77     }
78     case Property::INTEGER:
79     {
80       alignment = PropertyImplementationTypeAlignment< Property::INTEGER >::VALUE;
81       break;
82     }
83     case Property::FLOAT:
84     {
85       alignment = PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE;
86       break;
87     }
88     case Property::VECTOR2:
89     {
90       alignment = PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE;
91       break;
92     }
93     case Property::VECTOR3:
94     {
95       alignment = PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE;
96       break;
97     }
98     case Property::VECTOR4:
99     {
100       alignment = PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE;
101       break;
102     }
103     case Property::MATRIX3:
104     {
105       alignment = PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE;
106       break;
107     }
108     case Property::MATRIX:
109     {
110       alignment = PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE;
111       break;
112     }
113     case Property::RECTANGLE:
114     {
115       alignment = PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE;
116       break;
117     }
118     case Property::ROTATION:
119     {
120       alignment = PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE;
121       break;
122     }
123     case Property::NONE:
124     case Property::STRING:
125     case Property::ARRAY:
126     case Property::MAP:
127     case Property::EXTENTS:
128     {
129       // already handled by higher level code
130     }
131   }
132
133   return alignment;
134 }
135
136 } // unnamed namespace
137
138 VertexBufferPtr VertexBuffer::New( Dali::Property::Map& format )
139 {
140   DALI_ASSERT_ALWAYS( format.Count() && "Format cannot be empty." );
141
142   VertexBufferPtr vertexBuffer( new VertexBuffer() );
143   vertexBuffer->Initialize( format );
144
145   return vertexBuffer;
146 }
147
148 void VertexBuffer::SetData( const void* data, uint32_t size )
149 {
150   mSize = size; // size is the number of elements
151
152   uint32_t bufferSize = mBufferFormatSize * mSize;
153
154   // create a new DALi vector to store the buffer data
155   // the heap allocated vector will end up being owned by Render::VertexBuffer
156   OwnerPointer< Vector<uint8_t> > bufferCopy = new Dali::Vector<uint8_t>();
157   bufferCopy->Resize( bufferSize );
158
159   // copy the data
160   const uint8_t* source = static_cast<const uint8_t*>( data );
161   uint8_t* destination = &((*bufferCopy)[0]);
162   std::copy( source, source + bufferSize, destination );
163
164   // Ownership of the bufferCopy is passed to the message ( uses an owner pointer )
165   SceneGraph::SetVertexBufferData( mEventThreadServices.GetUpdateManager(), *mRenderObject, bufferCopy, mSize );
166 }
167
168 uint32_t VertexBuffer::GetSize() const
169 {
170   return mSize;
171 }
172
173 const Render::VertexBuffer* VertexBuffer::GetRenderObject() const
174 {
175   return mRenderObject;
176 }
177
178 VertexBuffer::~VertexBuffer()
179 {
180   if( EventThreadServices::IsCoreRunning() && mRenderObject)
181   {
182     SceneGraph::RemoveVertexBuffer( mEventThreadServices.GetUpdateManager(), *mRenderObject );
183   }
184 }
185
186 VertexBuffer::VertexBuffer()
187 : mEventThreadServices( EventThreadServices::Get() ),
188   mRenderObject( nullptr ),
189   mBufferFormatSize( 0 ),
190   mSize( 0 )
191 {
192 }
193
194 void VertexBuffer::Initialize( Dali::Property::Map& formatMap )
195 {
196   mRenderObject = new Render::VertexBuffer();
197   OwnerPointer< Render::VertexBuffer > transferOwnership( mRenderObject );
198   SceneGraph::AddVertexBuffer( mEventThreadServices.GetUpdateManager(), transferOwnership );
199
200   uint32_t numComponents = static_cast<uint32_t>( formatMap.Count() );
201
202   // Create the format
203   OwnerPointer< Render::VertexBuffer::Format> format = new Render::VertexBuffer::Format();
204   format->components.resize( numComponents );
205
206   uint32_t currentAlignment = 0u;
207   uint32_t maxAlignmentRequired = 0u;
208
209   for( uint32_t i = 0u; i < numComponents; ++i )
210   {
211     KeyValuePair component = formatMap.GetKeyValue( i );
212
213     // Get the name
214     if(component.first.type == Property::Key::INDEX)
215     {
216       continue;
217     }
218     format->components[i].name = component.first.stringKey;
219
220     // enums are stored in the map as int
221     Property::Type type = Property::Type( component.second.Get<int>() );
222
223     // Get the size and alignment
224     if( ( type == Property::NONE   ) ||
225         ( type == Property::STRING ) ||
226         ( type == Property::ARRAY  ) ||
227         ( type == Property::MAP    ) )
228     {
229       DALI_ABORT( "Property::Type not supported in VertexBuffer" );
230     }
231     uint32_t elementSize = GetPropertyImplementationSize( type );
232     uint32_t elementAlignment = GetPropertyImplementationAlignment( type );
233
234     // check if current alignment is compatible with new member
235     if( uint32_t offset = currentAlignment % elementAlignment )
236     {
237       // Not compatible, realign
238       currentAlignment = currentAlignment + elementSize - offset;
239     }
240
241     // write to the format
242     format->components[i].size = elementSize;
243     format->components[i].offset = currentAlignment;
244     format->components[i].type = type;
245
246     // update offset
247     currentAlignment += elementSize;
248
249     // update max alignment requirement
250     if( elementAlignment > maxAlignmentRequired )
251     {
252       maxAlignmentRequired = elementAlignment;
253     }
254
255   }
256
257   // Check the alignment for the maxAlignment required to calculate the size of the format
258   if( maxAlignmentRequired != 0 )
259   {
260     if( uint32_t offset = currentAlignment % maxAlignmentRequired )
261     {
262       // Not compatible, realign
263       currentAlignment = currentAlignment + maxAlignmentRequired - offset;
264     }
265   }
266
267   // Set the format size
268   format->size = currentAlignment;
269
270   mBufferFormatSize = format->size;
271
272   SceneGraph::SetVertexBufferFormat(mEventThreadServices.GetUpdateManager(), *mRenderObject, format );
273 }
274
275 uint32_t GetPropertyImplementationSize( Property::Type& propertyType )
276 {
277   uint32_t size = 0u;
278
279   switch( propertyType )
280   {
281     case Property::BOOLEAN:
282     {
283       size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
284       break;
285     }
286     case Property::INTEGER:
287     {
288       size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
289       break;
290     }
291     case Property::FLOAT:
292     {
293       size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
294       break;
295     }
296     case Property::VECTOR2:
297     {
298       size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
299       break;
300     }
301     case Property::VECTOR3:
302     {
303       size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
304       break;
305     }
306     case Property::VECTOR4:
307     {
308       size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
309       break;
310     }
311     case Property::MATRIX3:
312     {
313       size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
314       break;
315     }
316     case Property::MATRIX:
317     {
318       size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
319       break;
320     }
321     case Property::RECTANGLE:
322     {
323       size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
324       break;
325     }
326     case Property::ROTATION:
327     {
328       size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
329       break;
330     }
331     case Property::NONE:
332     case Property::STRING:
333     case Property::ARRAY:
334     case Property::MAP:
335     case Property::EXTENTS:
336     {
337       // already handled by higher level code
338     }
339   }
340
341   return size;
342 }
343
344
345 } // namespace Internal
346 } // namespace Dali