(TapGesture) Added min/max taps, removed touches as it's unsupported
[platform/core/uifw/dali-core.git] / dali / internal / update / modeling / scene-graph-mesh.cpp
1 /*
2  * Copyright (c) 2014 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/update/modeling/scene-graph-mesh.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/render/common/post-process-resource-dispatcher.h>
23 #include <dali/internal/render/gl-resources/context.h>
24 #include <dali/internal/render/queue/render-queue.h>
25
26 namespace Dali
27 {
28
29 namespace Internal
30 {
31
32 namespace SceneGraph
33 {
34
35 Mesh::Mesh( ResourceId id,
36             PostProcessResourceDispatcher& postProcessResourceDispatcher,
37             RenderQueue& renderQueue,
38             MeshData* meshData )
39 :
40   mPostProcessResourceDispatcher(postProcessResourceDispatcher),
41   mRenderQueue(renderQueue),
42   mUpdateMeshData(meshData),
43   mRenderMeshData(meshData),
44   mVertexBuffer(NULL),
45   mIndicesBuffer(NULL),
46   mNumberOfVertices(0u),
47   mNumberOfFaces(0u),
48   mResourceId ( id ),
49   mRefreshVertexBuffer(true)
50 {
51 }
52
53 Mesh::~Mesh()
54 {
55 }
56
57 void Mesh::SetMeshData(MeshData* meshData)
58 {
59   mUpdateMeshData = meshData;
60 }
61
62 MeshData& Mesh::GetMeshData( Mesh::ThreadBuffer threadBuffer )
63 {
64   return const_cast<MeshData&>(static_cast<const Mesh*>(this)->GetMeshData(threadBuffer));
65 }
66
67 const MeshData& Mesh::GetMeshData( Mesh::ThreadBuffer threadBuffer ) const
68 {
69   MeshData* meshDataPtr = NULL;
70
71   switch(threadBuffer)
72   {
73     case Mesh::UPDATE_THREAD:
74     {
75
76       meshDataPtr = mUpdateMeshData;
77     }
78     break;
79
80     case Mesh::RENDER_THREAD:
81     {
82       meshDataPtr = &(*mRenderMeshData);
83     }
84     break;
85   }
86
87   DALI_ASSERT_DEBUG( meshDataPtr );
88   return *meshDataPtr;
89 }
90
91 void Mesh::RefreshVertexBuffer()
92 {
93     mRefreshVertexBuffer = true;
94 }
95
96 void Mesh::MeshDataUpdated( BufferIndex bufferIndex, Mesh::ThreadBuffer threadBuffer, MeshData* meshData )
97 {
98   if ( threadBuffer == Mesh::RENDER_THREAD )
99   {
100     // Called from a message, the old MeshData will be release and the new one is saved.
101     mRenderMeshData = meshData;
102     RefreshVertexBuffer();
103   }
104   else
105   {
106     // Dynamics and animatable meshes don't create new mesh data
107     DALI_ASSERT_DEBUG( threadBuffer == Mesh::UPDATE_THREAD );
108     DALI_ASSERT_DEBUG( meshData == NULL );
109
110     // Send a message to self in render thread
111     typedef Message< Mesh > LocalType;
112     unsigned int* slot = mRenderQueue.ReserveMessageSlot( bufferIndex, sizeof( LocalType ) );
113     new (slot) LocalType( this, &Mesh::RefreshVertexBuffer);
114   }
115 }
116
117 void Mesh::UploadVertexData( Context& context, BufferIndex renderBufferIndex )
118 {
119   // Short-circuit if nothing has changed
120   if ( !mRefreshVertexBuffer )
121   {
122     return;
123   }
124
125   DoUpload(context);
126
127   // Note, dispatcher should only be used in Render Thread (as should the rest of this method!)
128   ResourcePostProcessRequest ppRequest( mResourceId, ResourcePostProcessRequest::UPLOADED );
129   mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
130
131   mRenderMeshData->Discard();
132   mRefreshVertexBuffer = false;
133 }
134
135 void Mesh::DoUpload( Context& context )
136 {
137   const MeshData::VertexContainer& vertices = mRenderMeshData->GetVertices();
138
139   DALI_ASSERT_DEBUG( !vertices.empty() );
140   if ( !mVertexBuffer )
141   {
142     mVertexBuffer = new GpuBuffer(context,GpuBuffer::ARRAY_BUFFER,GpuBuffer::STATIC_DRAW);
143   }
144   DALI_ASSERT_DEBUG(mVertexBuffer);
145
146   mVertexBuffer->UpdateDataBuffer( vertices.size() * sizeof(MeshData::Vertex), &vertices.at(0) );
147   mNumberOfVertices = mRenderMeshData->GetVertexCount();
148
149   if ( size_t numberOfIndices = mRenderMeshData->GetFaceIndexCount() )
150   {
151     const MeshData::FaceIndices& faces = mRenderMeshData->GetFaces();
152     DALI_ASSERT_DEBUG(!faces.empty());
153
154     if ( !mIndicesBuffer )
155     {
156       mIndicesBuffer = new GpuBuffer(context,GpuBuffer::ELEMENT_ARRAY_BUFFER,GpuBuffer::STATIC_DRAW);
157     }
158
159     mIndicesBuffer->UpdateDataBuffer( numberOfIndices * sizeof(GLushort), &(faces.at(0)) );
160     mNumberOfFaces = mRenderMeshData->GetFaceCount();
161   }
162 }
163
164 void Mesh::BindBuffers(Context& context)
165 {
166   // Short-circuit if nothing has changed
167   if ( !mVertexBuffer )
168   {
169     return;
170   }
171
172   DALI_ASSERT_DEBUG( mIndicesBuffer || mRenderMeshData->GetVertexGeometryType() == Dali::MeshData::POINTS );
173
174   // Try and recover from context loss using retained data.
175   if( ! mVertexBuffer->BufferIsValid() && ! mRenderMeshData->GetVertices().empty() )
176   {
177     DoUpload( context );
178   }
179
180   if( mVertexBuffer->BufferIsValid() )
181   {
182     mVertexBuffer->Bind();
183   }
184
185   if( mIndicesBuffer && mIndicesBuffer->BufferIsValid())
186   {
187     mIndicesBuffer->Bind();
188   }
189 }
190
191 size_t Mesh::GetFaceIndexCount( ThreadBuffer threadBuffer ) const
192 {
193   DALI_ASSERT_DEBUG( threadBuffer == Mesh::RENDER_THREAD );
194   size_t faceCount= 0;
195   switch( GetMeshData(threadBuffer).GetVertexGeometryType() )
196   {
197     case Dali::MeshData::POINTS:
198       faceCount = mNumberOfVertices;
199       break;
200     case Dali::MeshData::LINES:
201       faceCount = mNumberOfFaces*2;
202       break;
203     case Dali::MeshData::TRIANGLES:
204       faceCount = mNumberOfFaces*3;
205       break;
206   }
207
208   return faceCount;
209 }
210
211 bool Mesh::HasGeometry( ThreadBuffer threadBuffer ) const
212 {
213   return GetMeshData(threadBuffer).GetVertexCount() > 0;
214 }
215
216 void Mesh::GlContextDestroyed()
217 {
218   if( mVertexBuffer )
219   {
220     mVertexBuffer->GlContextDestroyed();
221   }
222   if( mIndicesBuffer )
223   {
224     mIndicesBuffer->GlContextDestroyed();
225   }
226 }
227
228 void Mesh::GlCleanup()
229 {
230   mVertexBuffer = NULL;
231   mIndicesBuffer = NULL;
232 }
233
234 } // namespace SceneGraph
235
236 } // namespace Internal
237
238 } // namespace Dali