Merge branch 'tizen' of platform/core/uifw/dali-core into devel/new_mesh
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-renderer.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-renderer.h"
18
19 #include <dali/internal/common/image-sampler.h>
20 #include <dali/internal/render/data-providers/geometry-data-provider.h>
21 #include <dali/internal/render/data-providers/material-data-provider.h>
22 #include <dali/internal/render/data-providers/node-data-provider.h>
23 #include <dali/internal/render/data-providers/sampler-data-provider.h>
24 #include <dali/internal/render/gl-resources/texture.h>
25 #include <dali/internal/render/gl-resources/texture-cache.h>
26 #include <dali/internal/render/shaders/program.h>
27
28
29 namespace Dali
30 {
31 namespace Internal
32 {
33 namespace SceneGraph
34 {
35
36 NewRenderer* NewRenderer::New( NodeDataProvider& nodeDataProvider,
37                                const GeometryDataProvider* geometryDataProvider,
38                                const MaterialDataProvider* materialDataProvider)
39 {
40   return new NewRenderer(nodeDataProvider, geometryDataProvider, materialDataProvider);
41 }
42
43
44 NewRenderer::NewRenderer( NodeDataProvider& nodeDataProvider,
45                           const GeometryDataProvider* geometryDataProvider,
46                           const MaterialDataProvider* materialDataProvider)
47 : Renderer( nodeDataProvider ),
48   //mShaderDataProvider( shaderDataProvider ), //@todo Add in after merge with parent class
49   mMaterialDataProvider( materialDataProvider ),
50   mGeometryDataProvider( geometryDataProvider )
51 {
52 }
53
54 NewRenderer::~NewRenderer()
55 {
56 }
57
58 // @todo MESH_REWORK Should we consider changing the providers, or should we instead
59 // create a new renderer when these change?
60 void NewRenderer::SetGeometryDataProvider( const GeometryDataProvider* geometryDataProvider )
61 {
62   mGeometryDataProvider = geometryDataProvider;
63 }
64
65 void NewRenderer::SetMaterialDataProvider( const MaterialDataProvider* materialDataProvider )
66 {
67   mMaterialDataProvider = materialDataProvider;
68 }
69
70
71 // Note - this is currently called from UpdateThread, PrepareRenderInstructions,
72 // as an optimisation.
73 // @todo MESH_REWORK Should use Update thread objects only in PrepareRenderInstructions.
74 bool NewRenderer::RequiresDepthTest() const
75 {
76   return true;
77 }
78
79 bool NewRenderer::CheckResources()
80 {
81   // Query material to check it has texture pointers & image has size
82   // Query geometry to check it has vertex buffers
83
84   // General point though - why would we have a render item in RenderThread with no ready
85   // resources in UpdateThread?
86   return true;
87 }
88
89 void NewRenderer::ResolveGeometryTypes( BufferIndex bufferIndex, GeometryType& outType, ShaderSubTypes& outSubType )
90 {
91   // @todo MESH_REWORK Remove after merge
92
93   // Do nothing
94 }
95
96 bool NewRenderer::IsOutsideClipSpace( const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix )
97 {
98   // @todo MESH_REWORK Add clipping
99   return false;
100 }
101
102 void NewRenderer::DoRender( BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix )
103 {
104   BindTextures( bufferIndex, program, mMaterialDataProvider->GetSamplers() );
105
106   SetUniforms( bufferIndex, program );
107
108   mRenderGeometry.UploadAndDraw( mContext, program, bufferIndex, *mGeometryDataProvider );
109 }
110
111 void NewRenderer::GlContextDestroyed()
112 {
113   mRenderGeometry.GlContextDestroyed();
114 }
115
116 void NewRenderer::GlCleanup()
117 {
118 }
119
120 void NewRenderer::SetUniforms( BufferIndex bufferIndex, Program& program )
121 {
122   // @todo MESH_REWORK Implement uniform map
123
124   // @todo Base class is currently setting MVP, Color etc.
125   GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
126   if( -1 != sizeLoc )
127   {
128     Vector3 size = mDataProvider.GetRenderSize( bufferIndex );
129     program.SetUniform3f( sizeLoc, size.x, size.y, size.z );
130   }
131 }
132
133 void NewRenderer::BindTextures(
134   BufferIndex bufferIndex,
135   Program& program,
136   const MaterialDataProvider::Samplers& samplers )
137 {
138   // @todo MESH_REWORK Write a cache of texture units to commonly used sampler textures
139   unsigned int textureUnit = 0;
140
141   for( MaterialDataProvider::Samplers::Iterator iter = samplers.Begin();
142        iter != samplers.End();
143        ++iter )
144   {
145     const SamplerDataProvider* sampler = *iter;
146     ResourceId textureId = sampler->GetTextureId(bufferIndex);
147     Texture* texture = mTextureCache->GetTexture( textureId );
148     if( texture != NULL )
149     {
150       unsigned int textureUnitUniformIndex = GetTextureUnitUniformIndex( program, *sampler );
151       TextureUnit theTextureUnit = static_cast<TextureUnit>(textureUnit);
152       BindTexture( program, textureId, texture, theTextureUnit, textureUnitUniformIndex );
153       ApplySampler( bufferIndex, texture, theTextureUnit, *sampler );
154     }
155
156     ++textureUnit;
157   }
158 }
159
160 void NewRenderer::BindTexture(
161   Program& program,
162   ResourceId id,
163   Texture* texture,
164   TextureUnit textureUnit,
165   unsigned int textureUnitUniformIndex )
166 {
167   DALI_ASSERT_DEBUG( NULL != mTextureCache );
168
169   if( texture != NULL )
170   {
171     mTextureCache->BindTexture( texture, id, GL_TEXTURE_2D, textureUnit );
172
173     // Set sampler uniform location for the texture
174     GLint textureUnitLoc = program.GetUniformLocation( textureUnitUniformIndex );
175     if( Program::UNIFORM_UNKNOWN != textureUnitLoc )
176     {
177       program.SetUniform1i( textureUnitLoc, textureUnit );
178     }
179   }
180 }
181
182 void NewRenderer::ApplySampler(
183   BufferIndex bufferIndex,
184   Texture*    texture,
185   TextureUnit textureUnit,
186   const SamplerDataProvider& sampler )
187 {
188   unsigned int samplerBitfield = ImageSampler::PackBitfield(
189     static_cast< FilterMode::Type >(sampler.GetMinifyFilterMode(bufferIndex)),
190     static_cast< FilterMode::Type >(sampler.GetMagnifyFilterMode(bufferIndex)) );
191
192   texture->ApplySampler( textureUnit, samplerBitfield );
193
194   // @todo MESH_REWORK add support for wrap modes
195 }
196
197 unsigned int NewRenderer::GetTextureUnitUniformIndex(
198   Program& program,
199   const SamplerDataProvider& sampler )
200 {
201   // Find sampler in mSamplerNameCache
202   // If it doesn't exist,
203   //   get the index by calling program.RegisterUniform and store it
204   // If it exists, it's index should be set.
205   // @todo Cache should be reset on scene change
206
207   unsigned int uniformIndex = 0;
208   bool found = false;
209
210   for( unsigned int i=0; i< mTextureUnitUniforms.Count(); ++i )
211   {
212     if( mTextureUnitUniforms[i].sampler == &sampler )
213     {
214       uniformIndex = mTextureUnitUniforms[i].index;
215       found = true;
216     }
217   }
218
219   if( ! found )
220   {
221     TextureUnitUniformIndex textureUnitUniformIndex;
222     textureUnitUniformIndex.sampler = &sampler;
223     textureUnitUniformIndex.index = program.RegisterUniform( sampler.GetUnitName() );
224     mTextureUnitUniforms.PushBack( textureUnitUniformIndex );
225     uniformIndex = textureUnitUniformIndex.index;
226   }
227
228   return uniformIndex;
229 }
230
231
232 } // SceneGraph
233 } // Internal
234 } // Dali