Created renderer objects.
[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 "render-geometry.h"
18
19 #include <dali/internal/common/buffer-index.h>
20 #include <dali/internal/update/geometry/scene-graph-geometry.h>
21 #include <dali/internal/update/common/scene-graph-property-buffer.h>
22 #include <dali/internal/render/gl-resources/context.h>
23 #include <dali/internal/render/gl-resources/gpu-buffer.h>
24 #include <dali/internal/render/shaders/program.h>
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30 namespace SceneGraph
31 {
32
33 RenderGeometry::RenderGeometry()
34 : mDataNeedsUploading( true )
35 {
36 }
37
38 RenderGeometry::~RenderGeometry()
39 {
40 }
41
42 void RenderGeometry::GlContextCreated( Context& context )
43 {
44   mDataNeedsUploading = true;
45 }
46
47 void RenderGeometry::GlContextDestroyed()
48 {
49   for( GpuBuffers::Iterator iter=mVertexBuffers.Begin(); iter != mVertexBuffers.End(); ++iter )
50   {
51     GpuBuffer* gpuBuffer = *iter;
52     if( gpuBuffer )
53     {
54       gpuBuffer->GlContextDestroyed();
55     }
56   }
57
58   if( mIndexBuffer )
59   {
60     mIndexBuffer->GlContextDestroyed();
61   }
62 }
63
64 void RenderGeometry::UploadAndDraw(
65   Context* context,
66   Program& program,
67   BufferIndex bufferIndex,
68   const GeometryDataProvider& geometryDataProvider )
69 {
70   UploadVertexData( context, bufferIndex, geometryDataProvider );
71   BindBuffers();
72   EnableVertexAttributes( context, program );
73   Draw( context, bufferIndex, geometryDataProvider );
74   DisableVertexAttributes( context, program );
75 }
76
77 void RenderGeometry::GeometryUpdated()
78 {
79   mDataNeedsUploading = true;
80 }
81
82 void RenderGeometry::UploadVertexData(
83   Context* context,
84   BufferIndex bufferIndex,
85   const GeometryDataProvider& geometry )
86 {
87   if( mDataNeedsUploading ) // @todo Or if any of the property buffers are dirty
88   {
89     DoUpload( context, bufferIndex, geometry );
90
91     mDataNeedsUploading = false;
92   }
93 }
94
95 void RenderGeometry::DoUpload(
96   Context* context,
97   BufferIndex bufferIndex,
98   const GeometryDataProvider& geometry)
99 {
100   // @todo MESH_REWORK Add support for multiple vertex buffers and attrs
101
102   // Vertex buffer
103   const Geometry::VertexBuffers& vertexBuffers = geometry.GetVertexBuffers();
104   DALI_ASSERT_DEBUG( vertexBuffers.Count() > 0 && "Need vertex buffers to upload" );
105
106   PropertyBuffer* firstVertexBuffer = vertexBuffers[0];
107
108   // @todo MESH_REWORK STATIC_DRAW or DYNAMIC_DRAW depends on property buffer type (static / animated)
109   GpuBuffer* vertexGpuBuffer = new GpuBuffer( *context, GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
110
111   std::size_t dataSize = firstVertexBuffer->GetDataSize( bufferIndex );
112   vertexGpuBuffer->UpdateDataBuffer( dataSize, firstVertexBuffer->GetData( bufferIndex ) );
113   vertexGpuBuffer->SetStride( firstVertexBuffer->GetElementSize( bufferIndex ) );
114
115   mVertexBuffers.PushBack( vertexGpuBuffer );
116
117   // Index buffer
118   const PropertyBuffer* indexBuffer = geometry.GetIndexBuffer();
119   if( indexBuffer )
120   {
121     GpuBuffer* indexGpuBuffer = new GpuBuffer( *context, GpuBuffer::ELEMENT_ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
122
123     dataSize = indexBuffer->GetDataSize( bufferIndex );
124     indexGpuBuffer->UpdateDataBuffer( dataSize, indexBuffer->GetData( bufferIndex ) );
125
126     mIndexBuffer.Reset();
127     mIndexBuffer = indexGpuBuffer;
128   }
129 }
130
131 void RenderGeometry::BindBuffers()
132 {
133   for( GpuBuffers::Iterator iter=mVertexBuffers.Begin(); iter != mVertexBuffers.End(); ++iter )
134   {
135     (*iter)->Bind();
136   }
137
138   if( mIndexBuffer )
139   {
140     mIndexBuffer->Bind();
141   }
142 }
143
144 void RenderGeometry::EnableVertexAttributes( Context* context, Program& program )
145 {
146   // @todo Loop thru the array of vertex buffers
147   // @todo Use AttributeDataProvider to get the attrs and enable them
148   // Need mapping from gpu buffers index to a particular attributes
149   Vector4 *vertex=0;
150
151   unsigned int gpuBufferIndex = 0;
152
153   GLint positionLoc = program.GetAttribLocation( Program::ATTRIB_POSITION );
154   context->VertexAttribPointer( positionLoc,
155                                 2,         // 2D position
156                                 GL_FLOAT,
157                                 GL_FALSE,  // Not normalized
158                                 mVertexBuffers[gpuBufferIndex]->GetStride(),
159                                 &vertex->x );
160
161   context->EnableVertexAttributeArray( positionLoc );
162
163   GLint textureCoordsLoc = program.GetAttribLocation( Program::ATTRIB_TEXCOORD );
164   context->VertexAttribPointer( textureCoordsLoc,
165                                 2,         // Texture Coords = U, V
166                                 GL_FLOAT,
167                                 GL_FALSE,
168                                 mVertexBuffers[gpuBufferIndex]->GetStride(),
169                                 &vertex->z );
170   context->EnableVertexAttributeArray( textureCoordsLoc );
171 }
172
173 void RenderGeometry::DisableVertexAttributes( Context* context, Program& program )
174 {
175   // @todo Loop thru the array of vertex buffers
176   // @todo Use AttributeDataProvider to get the attrs and disable them
177   GLint positionLoc = program.GetAttribLocation( Program::ATTRIB_POSITION );
178   GLint textureCoordsLoc = program.GetAttribLocation( Program::ATTRIB_TEXCOORD );
179   context->DisableVertexAttributeArray( positionLoc );
180   context->DisableVertexAttributeArray( textureCoordsLoc );
181 }
182
183 void RenderGeometry::Draw( Context* context, BufferIndex bufferIndex, const GeometryDataProvider& geometry )
184 {
185   GeometryDataProvider::GeometryType type = geometry.GetGeometryType( bufferIndex );
186
187   unsigned int numIndices = 0;
188   const PropertyBuffer* indexBuffer = geometry.GetIndexBuffer();
189
190   if( indexBuffer )
191   {
192     numIndices = indexBuffer->GetDataSize(bufferIndex) / indexBuffer->GetElementSize(bufferIndex);
193   }
194
195   switch(type)
196   {
197     case Dali::Geometry::TRIANGLES:
198     {
199       context->DrawElements(GL_TRIANGLES, numIndices/3, GL_UNSIGNED_SHORT, 0);
200       break;
201     }
202     case Dali::Geometry::LINES:
203     {
204       context->DrawElements(GL_LINES, numIndices/2, GL_UNSIGNED_SHORT, 0);
205       break;
206     }
207     case Dali::Geometry::POINTS:
208     {
209       GpuBuffer* firstVertexBuffer = mVertexBuffers[0];
210
211       unsigned int numVertices = 0;
212       GLuint stride = firstVertexBuffer->GetStride();
213       if( stride != 0 )
214       {
215         numVertices = firstVertexBuffer->GetBufferSize() / stride;
216       }
217
218       context->DrawArrays(GL_POINTS, 0, numVertices );
219       break;
220     }
221     default:
222     {
223       DALI_ASSERT_ALWAYS( 0 && "Geometry type not supported (yet)" );
224       break;
225     }
226   }
227 }
228
229 } // namespace SceneGraph
230 } // namespace Internal
231 } // namespace Dali