Allow multiple renderers per Actor and sharing renderers between actors
[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
18 // CLASS HEADER
19 #include <dali/internal/render/renderers/render-renderer.h>
20
21
22 // INTERNAL INCLUDES
23 #include <dali/internal/render/gl-resources/context.h>
24 #include <dali/internal/render/shaders/scene-graph-shader.h>
25 #include <dali/internal/render/shaders/program.h>
26 #include <dali/internal/render/data-providers/node-data-provider.h>
27 #include <dali/public-api/actors/blending.h>
28 #include <dali/internal/common/image-sampler.h>
29 #include <dali/internal/render/renderers/render-new-renderer.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
41 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
42
43 /**
44  * Helper to set view and projection matrices once per program
45  * @param program to set the matrices to
46  * @param modelMatrix to set
47  * @param viewMatrix to set
48  * @param projectionMatrix to set
49  * @param modelViewMatrix to set
50  * @param modelViewProjectionMatrix to set
51  */
52 inline void SetMatrices( Program& program,
53                          const Matrix& modelMatrix,
54                          const Matrix& viewMatrix,
55                          const Matrix& projectionMatrix,
56                          const Matrix& modelViewMatrix,
57                          const Matrix& modelViewProjectionMatrix )
58 {
59   GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
60   if( Program::UNIFORM_UNKNOWN != loc )
61   {
62     program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
63   }
64   loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
65   if( Program::UNIFORM_UNKNOWN != loc )
66   {
67     if( program.GetViewMatrix() != &viewMatrix )
68     {
69       program.SetViewMatrix( &viewMatrix );
70       program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
71     }
72   }
73   // set projection matrix if program has not yet received it this frame or if it is dirty
74   loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
75   if( Program::UNIFORM_UNKNOWN != loc )
76   {
77     if( program.GetProjectionMatrix() != &projectionMatrix )
78     {
79       program.SetProjectionMatrix( &projectionMatrix );
80       program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
81     }
82   }
83   loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
84   if( Program::UNIFORM_UNKNOWN != loc )
85   {
86     program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
87   }
88
89   loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
90   if( Program::UNIFORM_UNKNOWN != loc )
91   {
92     program.SetUniformMatrix4fv( loc, 1, modelViewProjectionMatrix.AsFloat() );
93   }
94
95   loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
96   if( Program::UNIFORM_UNKNOWN != loc )
97   {
98     gNormalMatrix = modelViewMatrix;
99     gNormalMatrix.Invert();
100     gNormalMatrix.Transpose();
101     program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
102   }
103 }
104
105 }
106
107 namespace Render
108 {
109
110 void Renderer::Initialize( Context& context, SceneGraph::TextureCache& textureCache )
111 {
112   mContext = &context;
113   mTextureCache = &textureCache;
114 }
115
116 Renderer::~Renderer()
117 {
118 }
119
120 void Renderer::SetShader( SceneGraph::Shader* shader )
121 {
122   mShader = shader;
123 }
124
125 void Renderer::SetCullFace( CullFaceMode mode )
126 {
127   DALI_ASSERT_DEBUG(mode >= CullNone && mode <= CullFrontAndBack);
128   mCullFaceMode = mode;
129 }
130
131 void Renderer::SetSampler( unsigned int samplerBitfield )
132 {
133   mSamplerBitfield = samplerBitfield;
134 }
135
136 void Renderer::Render( Context& context,
137                        SceneGraph::TextureCache& textureCache,
138                        BufferIndex bufferIndex,
139                        const SceneGraph::NodeDataProvider& node,
140                        SceneGraph::Shader& defaultShader,
141                        const Matrix& modelViewMatrix,
142                        const Matrix& viewMatrix,
143                        const Matrix& projectionMatrix,
144                        float frametime,
145                        bool cull,
146                        bool blend)
147 {
148   // @todo MESH_REWORK Fix when merging! :D
149
150   NewRenderer* renderer = dynamic_cast<NewRenderer*>(this);
151
152   if( renderer )
153   {
154     // Get the shader from the material:
155     mShader = &renderer->mRenderDataProvider->GetShader();
156   }
157
158   // if mShader is NULL it means we're set to default
159   if( !mShader )
160   {
161     mShader = &defaultShader;
162   }
163
164   if( !CheckResources() )
165   {
166     // CheckResources() is overriden in derived classes.
167     // Prevents modify the GL state if resources are not ready and nothing is to be rendered.
168     return;
169   }
170
171   // Calculate the MVP matrix first so we can do the culling test
172   const Matrix& modelMatrix = node.GetModelMatrix( bufferIndex );
173   Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
174
175   // Get the program to use:
176   Program* program = mShader->GetProgram();
177   if( !program )
178   {
179     // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
180     program = defaultShader.GetProgram();
181     DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
182     if( !program )
183     {
184       DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*) &*mShader );
185       return;
186     }
187
188   }
189
190   // Check culling (does not need the program to be in use)
191   if( cull && ! program->ModifiesGeometry() )
192   {
193     if( IsOutsideClipSpace( context, gModelViewProjectionMatrix ) )
194     {
195       // don't do any further gl state changes as this renderer is not visible
196       return;
197     }
198   }
199
200   // Take the program into use so we can send uniforms to it
201   program->Use();
202
203   DoSetCullFaceMode( context, bufferIndex );
204
205   DoSetBlending( context, bufferIndex, blend );
206
207   // Ignore missing uniforms - custom shaders and flat color shaders don't have SAMPLER
208   // set projection and view matrix if program has not yet received them yet this frame
209   SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix, gModelViewProjectionMatrix );
210
211   // set color uniform
212   GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
213   if( Program::UNIFORM_UNKNOWN != loc )
214   {
215     const Vector4& color = node.GetRenderColor( bufferIndex );
216     program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
217   }
218   loc = program->GetUniformLocation(Program::UNIFORM_TIME_DELTA);
219   if( Program::UNIFORM_UNKNOWN != loc )
220   {
221     program->SetUniform1f( loc, frametime );
222   }
223
224   //@todo MESH_REWORK Remove after removing ImageRenderer
225   DoSetUniforms(context, bufferIndex, mShader, program );
226
227   // subclass rendering and actual draw call
228   DoRender( context, textureCache, node, bufferIndex, *program, modelViewMatrix, viewMatrix );
229 }
230
231 void Renderer::SetSortAttributes( SceneGraph::RendererWithSortAttributes& sortAttributes ) const
232 {
233   sortAttributes.shader = mShader;
234   sortAttributes.material = NULL;
235   sortAttributes.geometry = NULL;
236 }
237
238 // can be overridden by deriving class
239 void Renderer::DoSetUniforms(Context& context, BufferIndex bufferIndex, SceneGraph::Shader* shader, Program* program )
240 {
241   shader->SetUniforms( context, *program, bufferIndex );
242 }
243
244 // can be overridden by deriving class
245 void Renderer::DoSetCullFaceMode(Context& context, BufferIndex bufferIndex )
246 {
247   // Set face culling mode
248   context.CullFace( mCullFaceMode );
249 }
250
251 Renderer::Renderer()
252 : mContext(NULL),
253   mTextureCache( NULL ),
254   mShader( NULL ),
255   mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
256   mCullFaceMode( CullNone )
257 {
258 }
259
260 } // namespace SceneGraph
261
262 } // namespace Internal
263
264 } // namespace Dali