[dali_2.3.42] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-vertex-buffer.h
1 #ifndef DALI_INTERNAL_RENDER_VERTEX_BUFFER_H
2 #define DALI_INTERNAL_RENDER_VERTEX_BUFFER_H
3
4 /*
5  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // INTERNAL INCLUDES
21 #include <dali/public-api/common/vector-wrapper.h>
22 #include <dali/public-api/object/property.h>
23
24 #include <dali/graphics-api/graphics-types.h>
25 #include <dali/internal/common/const-string.h>
26 #include <dali/internal/common/owner-pointer.h>
27 #include <dali/internal/render/renderers/gpu-buffer.h>
28
29 namespace Dali
30 {
31 class VertexBufferUpdateCallback;
32 namespace Internal
33 {
34 namespace Render
35 {
36 /**
37  * Helper class using atomic swaps for lockless synchronization
38  */
39 template<class T>
40 struct StateLock
41 {
42   StateLock(T v)
43   {
44     value = v;
45   }
46
47   /**
48    * Attempts to change state 'from' to 'to' and repeats
49    * when no success
50    */
51   void ChangeState(T from, T to)
52   {
53     // using spin lock
54     T expected = from;
55     while(!value.compare_exchange_weak(expected, to, std::memory_order_release, std::memory_order_relaxed))
56     {
57       expected = from; // it's needed to revert the value of 'expected'
58     };
59   }
60
61   std::atomic<T> value{};
62 };
63
64 class VertexBuffer
65 {
66 public:
67   struct Component
68   {
69     ConstString    name;
70     uint32_t       offset;
71     uint32_t       size;
72     Property::Type type;
73   };
74
75   /**
76    * Structure that holds the meta-data of the format of VertexBuffer.
77    */
78   struct Format
79   {
80     std::vector<Component> components;
81     uint32_t               size;
82   };
83
84   /**
85    * @brief Default constructor
86    */
87   VertexBuffer();
88
89   /**
90    * @brief Destructor
91    */
92   ~VertexBuffer();
93
94   /**
95    * @brief Set the format of the buffer
96    *
97    * This function takes ownership of the pointer
98    *
99    * @param[in] format The format for the VertexBuffer
100    */
101   void SetFormat(VertexBuffer::Format* format);
102
103   /**
104    * @brief Set the data of the VertexBuffer
105    *
106    * This function takes ownership of the pointer
107    * @param[in] data The new data of the VertexBuffer
108    * @param[in] size The new size of the buffer
109    */
110   void SetData(Dali::Vector<uint8_t>* data, uint32_t size);
111
112   /**
113    * @brief Sets vertex buffer update callback
114    *
115    * This function takes ownership over the callback object.
116    *
117    * The callback will run during rendering on the update/render thread.
118    * @param[in] callback Valid update callback
119    */
120   void SetVertexBufferUpdateCallback(Dali::VertexBufferUpdateCallback* callback);
121
122   /**
123    * Perform the upload of the buffer only when required
124    * @param[in] graphicsController The controller
125    */
126   bool Update(Graphics::Controller& graphicsController);
127
128   /**
129    * @brief Set the divisor of the buffer for instanced drawing
130    * @param[in] divisor The divisor (0 = not instanced, >=1 = instanced)
131    */
132   void SetDivisor(uint32_t divisor);
133
134   /**
135    * Get the divisor for the vertex buffer
136    */
137   [[nodiscard]] uint32_t GetDivisor();
138
139   /**
140    * Get the number of attributes present in the buffer
141    * @return The number of attributes stored in this buffer
142    */
143   [[nodiscard]] inline uint32_t GetAttributeCount() const
144   {
145     DALI_ASSERT_DEBUG(mFormat && "Format should be set ");
146     return static_cast<uint32_t>(mFormat->components.size());
147   }
148
149   /**
150    * Retrieve the i-essim attribute name
151    * @param[in] index The index of the attribute
152    * @return The name of the attribute
153    */
154   [[nodiscard]] inline ConstString GetAttributeName(uint32_t index) const
155   {
156     DALI_ASSERT_DEBUG(mFormat && "Format should be set ");
157     return mFormat->components[index].name;
158   }
159
160   /**
161    * Retrieve the size of the buffer in bytes
162    * @return The total size of the buffer
163    */
164   [[nodiscard]] inline uint32_t GetDataSize() const
165   {
166     DALI_ASSERT_DEBUG(mFormat && "Format should be set ");
167     return mFormat->size * mSize;
168   }
169
170   /**
171    * Retrieve the size of one element of the buffer
172    * @return The size of one element
173    */
174   [[nodiscard]] inline uint32_t GetElementSize() const
175   {
176     DALI_ASSERT_DEBUG(mFormat && "Format should be set ");
177     return mFormat->size;
178   }
179
180   /**
181    * Retrieve the number of elements in the buffer
182    * @return The total number of elements
183    */
184   [[nodiscard]] inline uint32_t GetElementCount() const
185   {
186     return mSize;
187   }
188
189   /**
190    * Retrieves number of renderable elements when vertex update callback
191    * is used. If there is no callback set the total number of elements
192    * is returned.
193    */
194   [[nodiscard]] inline uint32_t GetRenderableElementCount() const
195   {
196     return mVertexBufferUpdateCallback ? mElementCount : mSize;
197   }
198
199   [[nodiscard]] inline const VertexBuffer::Format* GetFormat() const
200   {
201     return mFormat.Get();
202   }
203
204   [[nodiscard]] inline const GpuBuffer* GetGpuBuffer() const
205   {
206     return mGpuBuffer.Get();
207   }
208
209 private:
210   OwnerPointer<VertexBuffer::Format>   mFormat;    ///< Format of the buffer
211   OwnerPointer<Dali::Vector<uint8_t> > mData;      ///< Data
212   OwnerPointer<GpuBuffer>              mGpuBuffer; ///< Pointer to the GpuBuffer associated with this RenderVertexBuffer
213
214   uint32_t                                          mSize;         ///< Number of Elements in the buffer
215   uint32_t                                          mDivisor{0};   ///< The divisor (0:not instanced, >=1:instanced)
216   uint32_t                                          mElementCount; ///< Number of valid elements in the buffer
217   std::unique_ptr<Dali::VertexBufferUpdateCallback> mVertexBufferUpdateCallback;
218
219   /**
220    * Enum values for locking mechanism.
221    *
222    * Locking mechanism uses synchronized state machine. From 'UNLOCKED' state
223    * it's either LOCKED_FOR_EVENT or LOCKED_FOR_UPDATE states possible.
224    * Both states can be reverted only to UNLOCKED.
225    */
226   enum class VertexBufferSyncState : int
227   {
228     UNLOCKED,          ///< Currently unlocked
229     LOCKED_FOR_EVENT,  ///< Locked for Event thread to access
230     LOCKED_FOR_UPDATE, ///< Locked for Update thread to access
231   };
232
233   StateLock<VertexBufferSyncState> mVertexBufferStateLock{VertexBufferSyncState::UNLOCKED};
234
235   bool mDataChanged; ///< Flag to know if data has changed in a frame
236 };
237
238 } // namespace Render
239
240 } // namespace Internal
241
242 } // namespace Dali
243
244 #endif //  DALI_INTERNAL_RENDER_VERTEX_BUFFER_H