Merge "Remove API to set if a geometry requires writing to the depth buffer" into...
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-geometry.cpp
1 /*
2  * Copyright (c) 2015 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 #include <dali/internal/render/renderers/render-geometry.h>
18 #include <dali/internal/common/buffer-index.h>
19 #include <dali/internal/render/gl-resources/context.h>
20 #include <dali/internal/render/gl-resources/gpu-buffer.h>
21 #include <dali/internal/render/renderers/render-property-buffer.h>
22 #include <dali/internal/render/shaders/program.h>
23
24 namespace Dali
25 {
26 namespace Internal
27 {
28 namespace Render
29 {
30
31 Geometry::Geometry()
32 : mIndices(),
33   mIndexBuffer(NULL),
34   mGeometryType( Dali::Geometry::TRIANGLES ),
35   mIndicesChanged(false),
36   mHasBeenUpdated(false),
37   mAttributesChanged(true)
38 {
39 }
40
41 Geometry::~Geometry()
42 {
43 }
44
45 void Geometry::GlContextCreated( Context& context )
46 {
47 }
48
49 void Geometry::GlContextDestroyed()
50 {
51 }
52
53 void Geometry::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
54 {
55   mVertexBuffers.PushBack( propertyBuffer );
56   mAttributesChanged = true;
57 }
58
59 void Geometry::SetIndexBuffer( Dali::Vector<unsigned short>& indices )
60 {
61   mIndices.Swap( indices );
62   mIndicesChanged = true;
63 }
64
65 void Geometry::RemovePropertyBuffer( const Render::PropertyBuffer* propertyBuffer )
66 {
67   size_t bufferCount = mVertexBuffers.Size();
68   for( size_t i(0); i<bufferCount; ++i )
69   {
70     if( propertyBuffer == mVertexBuffers[i] )
71     {
72       //This will delete the gpu buffer associated to the RenderPropertyBuffer if there is one
73       mVertexBuffers.Remove( mVertexBuffers.Begin()+i);
74       mAttributesChanged = true;
75       break;
76     }
77   }
78 }
79
80 void Geometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const
81 {
82   attributeLocation.Clear();
83
84   for( size_t i(0); i< mVertexBuffers.Size(); ++i )
85   {
86     unsigned int attributeCount = mVertexBuffers[i]->GetAttributeCount();
87     for( unsigned int j = 0; j < attributeCount; ++j )
88     {
89       const std::string& attributeName = mVertexBuffers[i]->GetAttributeName( j );
90       unsigned int index = program.RegisterCustomAttribute( attributeName );
91       GLint location = program.GetCustomAttributeLocation( index );
92
93       if( -1 == location )
94       {
95         DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.c_str() );
96       }
97
98       attributeLocation.PushBack( location );
99     }
100   }
101 }
102
103 void Geometry::OnRenderFinished()
104 {
105   mHasBeenUpdated = false;
106   mAttributesChanged = false;
107 }
108
109 void Geometry::UploadAndDraw(
110     Context& context,
111     BufferIndex bufferIndex,
112     Vector<GLint>& attributeLocation,
113     size_t elementBufferOffset,
114     size_t elementBufferCount )
115 {
116   if( !mHasBeenUpdated )
117   {
118     // Update buffers
119     if( mIndicesChanged )
120     {
121       if( mIndices.Empty() )
122       {
123         mIndexBuffer = NULL;
124       }
125       else
126       {
127         if ( mIndexBuffer == NULL )
128         {
129           mIndexBuffer = new GpuBuffer( context );
130         }
131
132         std::size_t bufferSize =  sizeof( unsigned short ) * mIndices.Size();
133         mIndexBuffer->UpdateDataBuffer( bufferSize, &mIndices[0], GpuBuffer::STATIC_DRAW, GpuBuffer::ELEMENT_ARRAY_BUFFER );
134       }
135
136       mIndicesChanged = false;
137     }
138
139     for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
140     {
141       if( !mVertexBuffers[i]->Update( context ) )
142       {
143         //Vertex buffer is not ready ( Size, data or format has not been specified yet )
144         return;
145       }
146     }
147
148     mHasBeenUpdated = true;
149   }
150
151   //Bind buffers to attribute locations
152   unsigned int base = 0u;
153   size_t vertexBufferCount(mVertexBuffers.Count());
154   for( unsigned int i = 0; i < vertexBufferCount; ++i )
155   {
156     mVertexBuffers[i]->BindBuffer( GpuBuffer::ARRAY_BUFFER );
157     base += mVertexBuffers[i]->EnableVertexAttributes( context, attributeLocation, base );
158   }
159
160   GLenum geometryGLType(0);
161   unsigned int numIndices(0u);
162   intptr_t firstIndexOffset(0u);
163   if( mIndexBuffer )
164   {
165     numIndices = mIndices.Size();
166
167     if( elementBufferOffset )
168     {
169       elementBufferOffset = elementBufferOffset >= numIndices ? numIndices- 1 : elementBufferOffset;
170       firstIndexOffset = elementBufferOffset * sizeof(GLushort);
171     }
172     if ( elementBufferCount )
173     {
174       numIndices = std::min( elementBufferCount, numIndices - elementBufferOffset );
175     }
176   }
177
178   switch(mGeometryType)
179   {
180     case Dali::Geometry::TRIANGLES:
181     {
182       geometryGLType = GL_TRIANGLES;
183       break;
184     }
185     case Dali::Geometry::LINES:
186     {
187       geometryGLType = GL_LINES;
188       break;
189     }
190     case Dali::Geometry::POINTS:
191     {
192       geometryGLType = GL_POINTS;
193       break;
194     }
195     case Dali::Geometry::TRIANGLE_STRIP:
196     {
197       geometryGLType = GL_TRIANGLE_STRIP;
198       break;
199     }
200     case Dali::Geometry::TRIANGLE_FAN:
201     {
202       geometryGLType = GL_TRIANGLE_FAN;
203       break;
204     }
205     case Dali::Geometry::LINE_LOOP:
206     {
207       geometryGLType = GL_LINE_LOOP;
208       break;
209     }
210     case Dali::Geometry::LINE_STRIP:
211     {
212       geometryGLType = GL_LINE_STRIP;
213       break;
214     }
215     default:
216     {
217       DALI_ASSERT_ALWAYS( 0 && "Geometry type not supported (yet)" );
218       break;
219     }
220   }
221
222   //Draw call
223   if( mIndexBuffer && geometryGLType != GL_POINTS )
224   {
225     //Indexed draw call
226     mIndexBuffer->Bind( GpuBuffer::ELEMENT_ARRAY_BUFFER );
227     context.DrawElements(geometryGLType, numIndices, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(firstIndexOffset));
228   }
229   else
230   {
231     //Unindex draw call
232     unsigned int numVertices(0u);
233     if( vertexBufferCount > 0 )
234     {
235       numVertices = mVertexBuffers[0]->GetElementCount();
236     }
237
238     context.DrawArrays( geometryGLType, 0, numVertices );
239   }
240
241   //Disable attributes
242   for( unsigned int i = 0; i < attributeLocation.Count(); ++i )
243   {
244     if( attributeLocation[i] != -1 )
245     {
246       context.DisableVertexAttributeArray( attributeLocation[i] );
247     }
248   }
249 }
250
251 } // namespace SceneGraph
252 } // namespace Internal
253 } // namespace Dali