2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/rendering/vertex-buffer-impl.h>
22 #include <dali/internal/update/manager/update-manager.h>
23 #include <dali/public-api/rendering/vertex-buffer.h>
25 #if defined(ANDROID) || defined(WIN32) || defined(__APPLE__)
28 uint64_t _Hash_bytes(const void* bytes, uint64_t size, uint64_t seed)
30 for(uint64_t i = 0; i < size; i++)
32 seed = seed * 31 + reinterpret_cast<const unsigned char*>(bytes)[i];
47 * Calculate the alignment requirements of a type
49 * This is used to calculate the memory alignment requirements of a type
50 * It creates a structure with a dummy char and a member of the type we want to check
51 * this will cause the second member to be aligned by it's alignment requirement.
53 template<Property::Type type>
54 struct PropertyImplementationTypeAlignment
56 // Create a structure that forces alignment of the data type
59 char oneChar; ///< Member with sizeof() == 1
60 typename PropertyImplementationType<type>::Type data;
64 VALUE = offsetof(TestStructure, data)
68 uint32_t GetPropertyImplementationAlignment(Property::Type& propertyType)
70 uint32_t alignment = 0u;
74 case Property::BOOLEAN:
76 alignment = PropertyImplementationTypeAlignment<Property::BOOLEAN>::VALUE;
79 case Property::INTEGER:
81 alignment = PropertyImplementationTypeAlignment<Property::INTEGER>::VALUE;
86 alignment = PropertyImplementationTypeAlignment<Property::FLOAT>::VALUE;
89 case Property::VECTOR2:
91 alignment = PropertyImplementationTypeAlignment<Property::VECTOR2>::VALUE;
94 case Property::VECTOR3:
96 alignment = PropertyImplementationTypeAlignment<Property::VECTOR3>::VALUE;
99 case Property::VECTOR4:
101 alignment = PropertyImplementationTypeAlignment<Property::VECTOR4>::VALUE;
104 case Property::MATRIX3:
106 alignment = PropertyImplementationTypeAlignment<Property::MATRIX3>::VALUE;
109 case Property::MATRIX:
111 alignment = PropertyImplementationTypeAlignment<Property::MATRIX>::VALUE;
114 case Property::RECTANGLE:
116 alignment = PropertyImplementationTypeAlignment<Property::RECTANGLE>::VALUE;
119 case Property::ROTATION:
121 alignment = PropertyImplementationTypeAlignment<Property::ROTATION>::VALUE;
125 case Property::STRING:
126 case Property::ARRAY:
128 case Property::EXTENTS:
130 // already handled by higher level code
137 } // unnamed namespace
139 VertexBufferPtr VertexBuffer::New(Dali::Property::Map& format)
141 DALI_ASSERT_ALWAYS(format.Count() && "Format cannot be empty.");
143 VertexBufferPtr vertexBuffer(new VertexBuffer());
144 vertexBuffer->Initialize(format);
149 void VertexBuffer::SetData(const void* data, uint32_t size)
151 mSize = size; // size is the number of elements
153 uint32_t bufferSize = mBufferFormatSize * mSize;
155 // create a new DALi vector to store the buffer data
156 // the heap allocated vector will end up being owned by Render::VertexBuffer
157 OwnerPointer<Vector<uint8_t> > bufferCopy = new Dali::Vector<uint8_t>();
158 bufferCopy->Resize(bufferSize);
161 const uint8_t* source = static_cast<const uint8_t*>(data);
162 uint8_t* destination = &((*bufferCopy)[0]);
163 std::copy(source, source + bufferSize, destination);
165 // Ownership of the bufferCopy is passed to the message ( uses an owner pointer )
166 SceneGraph::SetVertexBufferData(mEventThreadServices.GetUpdateManager(), *mRenderObject, bufferCopy, mSize);
169 uint32_t VertexBuffer::GetSize() const
174 const Render::VertexBuffer* VertexBuffer::GetRenderObject() const
176 return mRenderObject;
179 VertexBuffer::~VertexBuffer()
181 if(EventThreadServices::IsCoreRunning() && mRenderObject)
183 SceneGraph::RemoveVertexBuffer(mEventThreadServices.GetUpdateManager(), *mRenderObject);
187 VertexBuffer::VertexBuffer()
188 : mEventThreadServices(EventThreadServices::Get()),
189 mRenderObject(nullptr),
190 mBufferFormatSize(0),
195 void VertexBuffer::Initialize(Dali::Property::Map& formatMap)
197 mRenderObject = new Render::VertexBuffer();
198 OwnerPointer<Render::VertexBuffer> transferOwnership(mRenderObject);
199 SceneGraph::AddVertexBuffer(mEventThreadServices.GetUpdateManager(), transferOwnership);
201 uint32_t numComponents = static_cast<uint32_t>(formatMap.Count());
204 OwnerPointer<Render::VertexBuffer::Format> format = new Render::VertexBuffer::Format();
205 format->components.resize(numComponents);
207 uint32_t currentAlignment = 0u;
208 uint32_t maxAlignmentRequired = 0u;
210 for(uint32_t i = 0u; i < numComponents; ++i)
212 KeyValuePair component = formatMap.GetKeyValue(i);
215 if(component.first.type == Property::Key::INDEX)
219 format->components[i].name = ConstString(component.first.stringKey);
221 // enums are stored in the map as int
222 Property::Type type = Property::Type(component.second.Get<int>());
224 // Get the size and alignment
225 if((type == Property::NONE) ||
226 (type == Property::STRING) ||
227 (type == Property::ARRAY) ||
228 (type == Property::MAP))
230 DALI_ABORT("Property::Type not supported in VertexBuffer");
232 uint32_t elementSize = GetPropertyImplementationSize(type);
233 uint32_t elementAlignment = GetPropertyImplementationAlignment(type);
235 // check if current alignment is compatible with new member
236 if(uint32_t offset = currentAlignment % elementAlignment)
238 // Not compatible, realign
239 currentAlignment = currentAlignment + elementSize - offset;
242 // write to the format
243 format->components[i].size = elementSize;
244 format->components[i].offset = currentAlignment;
245 format->components[i].type = type;
248 currentAlignment += elementSize;
250 // update max alignment requirement
251 if(elementAlignment > maxAlignmentRequired)
253 maxAlignmentRequired = elementAlignment;
257 // Check the alignment for the maxAlignment required to calculate the size of the format
258 if(maxAlignmentRequired != 0)
260 if(uint32_t offset = currentAlignment % maxAlignmentRequired)
262 // Not compatible, realign
263 currentAlignment = currentAlignment + maxAlignmentRequired - offset;
267 // Set the format size
268 format->size = currentAlignment;
270 mBufferFormatSize = format->size;
272 SceneGraph::SetVertexBufferFormat(mEventThreadServices.GetUpdateManager(), *mRenderObject, format);
275 uint32_t GetPropertyImplementationSize(Property::Type& propertyType)
281 case Property::BOOLEAN:
283 size = sizeof(PropertyImplementationType<Property::BOOLEAN>::Type);
286 case Property::INTEGER:
288 size = sizeof(PropertyImplementationType<Property::INTEGER>::Type);
291 case Property::FLOAT:
293 size = sizeof(PropertyImplementationType<Property::FLOAT>::Type);
296 case Property::VECTOR2:
298 size = sizeof(PropertyImplementationType<Property::VECTOR2>::Type);
301 case Property::VECTOR3:
303 size = sizeof(PropertyImplementationType<Property::VECTOR3>::Type);
306 case Property::VECTOR4:
308 size = sizeof(PropertyImplementationType<Property::VECTOR4>::Type);
311 case Property::MATRIX3:
313 size = sizeof(PropertyImplementationType<Property::MATRIX3>::Type);
316 case Property::MATRIX:
318 size = sizeof(PropertyImplementationType<Property::MATRIX>::Type);
321 case Property::RECTANGLE:
323 size = sizeof(PropertyImplementationType<Property::RECTANGLE>::Type);
326 case Property::ROTATION:
328 size = sizeof(PropertyImplementationType<Property::ROTATION>::Type);
332 case Property::STRING:
333 case Property::ARRAY:
335 case Property::EXTENTS:
337 // already handled by higher level code
344 } // namespace Internal