[dali_1.0.9] Merge branch 'tizen'
[platform/core/uifw/dali-core.git] / dali / internal / update / node-attachments / scene-graph-renderable-attachment.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/node-attachments/scene-graph-renderable-attachment.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/resource-declarations.h>
23 #include <dali/public-api/actors/renderable-actor.h>
24 #include <dali/internal/update/nodes/node.h>
25 #include <dali/internal/update/resources/resource-manager.h>
26 #include <dali/internal/update/resources/complete-status-manager.h>
27 #include <dali/internal/update/resources/resource-tracker.h>
28 #include <dali/internal/render/queue/render-queue.h>
29 #include <dali/internal/render/renderers/scene-graph-renderer.h>
30 #include <dali/internal/render/shaders/shader.h>
31 #include <dali/internal/common/image-sampler.h>
32
33 using namespace std;
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace SceneGraph
42 {
43
44 void RenderableAttachment::SetSortModifier(float modifier)
45 {
46   // Setting sort modifier makes the node dirty, i.e. we cannot reuse previous frames render items
47   if( mParent )
48   {
49     // only do this if we are on-stage
50     mParent->SetDirtyFlag( SortModifierFlag );
51   }
52   mSortModifier = modifier;
53 }
54
55 void RenderableAttachment::SetBlendingMode( BlendingMode::Type mode )
56 {
57   mBlendingMode = mode;
58 }
59
60 BlendingMode::Type RenderableAttachment::GetBlendingMode() const
61 {
62   return mBlendingMode;
63 }
64
65 void RenderableAttachment::ChangeBlending( BufferIndex updateBufferIndex, bool useBlend )
66 {
67   if ( mUseBlend != useBlend )
68   {
69     mUseBlend = useBlend;
70
71     // Enable/disable blending in the next render
72     typedef MessageValue1< Renderer, bool > DerivedType;
73
74     // Reserve some memory inside the render queue
75     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
76
77     // Construct message in the render queue memory; note that delete should not be called on the return value
78     new (slot) DerivedType( &GetRenderer(), &Renderer::SetUseBlend, useBlend );
79   }
80 }
81
82 void RenderableAttachment::SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options )
83 {
84   // Blending options are forwarded to renderer in render-thread
85   typedef MessageValue1< Renderer, unsigned int > DerivedType;
86
87   // Reserve some memory inside the render queue
88   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
89
90   // Construct message in the render queue memory; note that delete should not be called on the return value
91   new (slot) DerivedType( &GetRenderer(), &Renderer::SetBlendingOptions, options );
92 }
93
94 void RenderableAttachment::SetBlendColor( BufferIndex updateBufferIndex, const Vector4& color )
95 {
96   // Blend color is forwarded to renderer in render-thread
97   typedef MessageValue1< Renderer, Vector4 > DerivedType;
98
99   // Reserve some memory inside the render queue
100   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
101
102   // Construct message in the render queue memory; note that delete should not be called on the return value
103   new (slot) DerivedType( &GetRenderer(), &Renderer::SetBlendColor, color );
104 }
105
106 void RenderableAttachment::PrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
107 {
108   mHasUntrackedResources = false; // Only need to know this if the resources are not yet complete
109   mTrackedResources.Clear(); // Resource trackers are only needed if not yet completea
110
111   if( mShader )
112   {
113     Integration::ResourceId id = mShader->GetEffectTextureResourceId();
114
115     if( id != 0 )
116     {
117       CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
118
119       if(CompleteStatusManager::COMPLETE != completeStatusManager.GetStatus( id ))
120       {
121         FollowTracker(id);
122         mFinishedResourceAcquisition = false;
123         mResourcesReady = false;
124
125         // If shader has effect texture and it's not complete and tracked, ensure
126         // we call DoPrepareResources, as the effect texture may become ready in
127         // the ProcessRenderTasks step.  Otherwise, may early out.
128         if( mHasUntrackedResources )
129         {
130           return;
131         }
132       }
133     }
134   }
135
136   mResourcesReady = DoPrepareResources( updateBufferIndex, resourceManager );
137 }
138
139 void RenderableAttachment::FollowTracker( Integration::ResourceId id )
140 {
141   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
142
143   if( completeStatusManager.FindResourceTracker(id) != NULL )
144   {
145     bool found = false;
146     std::size_t numTrackedResources = mTrackedResources.Count();
147     for( size_t i=0; i < numTrackedResources; ++i )
148     {
149       if(mTrackedResources[i] == id)
150       {
151         found = true;
152         break;
153       }
154     }
155     if( ! found )
156     {
157       mTrackedResources.PushBack( id );
158     }
159   }
160   else
161   {
162     mHasUntrackedResources = true;
163   }
164 }
165
166 void RenderableAttachment::SetCullFace( BufferIndex updateBufferIndex, CullFaceMode mode )
167 {
168   DALI_ASSERT_DEBUG(mSceneController);
169   DALI_ASSERT_DEBUG(mode >= CullNone && mode <= CullFrontAndBack);
170
171   mCullFaceMode = mode;
172
173   typedef MessageValue1< Renderer, CullFaceMode > DerivedType;
174
175   // Reserve some memory inside the render queue
176   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
177
178   // Construct message in the render queue memory; note that delete should not be called on the return value
179   new (slot) DerivedType( &GetRenderer(), &Renderer::SetCullFace, mode );
180 }
181
182 void RenderableAttachment::SetSampler( BufferIndex updateBufferIndex, unsigned int samplerBitfield )
183 {
184   DALI_ASSERT_DEBUG(mSceneController);
185
186   typedef MessageValue1< Renderer, unsigned int > DerivedType;
187
188   // Reserve some memory inside the render queue
189   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
190
191   // Construct message in the render queue memory; note that delete should not be called on the return value
192   new (slot) DerivedType( &GetRenderer(), &Renderer::SetSampler, samplerBitfield );
193 }
194
195 void RenderableAttachment::SetRecalculateScaleForSize()
196 {
197   mScaleForSizeDirty = true;
198 }
199
200 void RenderableAttachment::GetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
201 {
202   DoGetScaleForSize( nodeSize, scaling );
203   mScaleForSizeDirty = false;
204 }
205
206 void RenderableAttachment::ApplyShader( BufferIndex updateBufferIndex, Shader* shader )
207 {
208   mShader = shader;
209
210   // send the message to renderer
211   SendShaderChangeMessage( updateBufferIndex );
212
213   // tell derived class to do something
214   ShaderChanged( updateBufferIndex );
215 }
216
217 void RenderableAttachment::RemoveShader( BufferIndex updateBufferIndex )
218 {
219   // return to default shader
220   mShader = mSceneController->GetDefaultShader();
221
222   // send the message to renderer
223   SendShaderChangeMessage( updateBufferIndex );
224
225   // tell derived class to do something
226   ShaderChanged( updateBufferIndex );
227 }
228
229 void RenderableAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
230 {
231   scaling = Vector3::ONE;
232 }
233
234 void RenderableAttachment::GetReadyAndComplete(bool& ready, bool& complete) const
235 {
236   ready = mResourcesReady;
237   complete = false;
238
239   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
240
241   std::size_t numTrackedResources = mTrackedResources.Count();
242   if( mHasUntrackedResources || numTrackedResources == 0 )
243   {
244     complete = mFinishedResourceAcquisition;
245   }
246   else
247   {
248     // If there are tracked resources and no untracked resources, test the trackers
249     bool trackersComplete = true;
250     for( size_t i=0; i < numTrackedResources; ++i )
251     {
252       ResourceId id = mTrackedResources[i];
253       ResourceTracker* tracker = completeStatusManager.FindResourceTracker(id);
254       if( tracker  && ! tracker->IsComplete() )
255       {
256         trackersComplete = false;
257         break;
258       }
259     }
260
261     complete = mFinishedResourceAcquisition || trackersComplete;
262   }
263 }
264
265 bool RenderableAttachment::IsBlendingOn( BufferIndex updateBufferIndex )
266 {
267   // Check whether blending needs to be disabled / enabled
268   bool blend = false;
269   switch( mBlendingMode )
270   {
271     case BlendingMode::OFF:
272     {
273       // No blending.
274       blend = false;
275       break;
276     }
277     case BlendingMode::AUTO:
278     {
279       // Blending if the node is not fully opaque only.
280       blend = !IsFullyOpaque( updateBufferIndex );
281       break;
282     }
283     case BlendingMode::ON:
284     {
285       // Blending always.
286       blend = true;
287       break;
288     }
289     default:
290     {
291       DALI_ASSERT_ALWAYS( !"RenderableAttachment::PrepareRender. Wrong blending mode" );
292     }
293   }
294   return blend;
295 }
296
297 void RenderableAttachment::PrepareRender( BufferIndex updateBufferIndex )
298 {
299   // call the derived class first as it might change its state regarding blending
300   DoPrepareRender( updateBufferIndex );
301
302   bool blend = IsBlendingOn( updateBufferIndex );
303   ChangeBlending( updateBufferIndex, blend );
304 }
305
306 RenderableAttachment::RenderableAttachment( bool usesGeometryScaling )
307 : mSceneController(NULL),
308   mShader( NULL ),
309   mTrackedResources(),
310   mSortModifier( 0.0f ),
311   mBlendingMode( Dali::RenderableActor::DEFAULT_BLENDING_MODE ),
312   mUsesGeometryScaling( usesGeometryScaling ),
313   mScaleForSizeDirty( true ),
314   mUseBlend( false ),
315   mHasSizeAndColorFlag( false ),
316   mResourcesReady( false ),
317   mFinishedResourceAcquisition( false ),
318   mHasUntrackedResources( false ),
319   mCullFaceMode( CullNone )
320 {
321 }
322
323 RenderableAttachment::~RenderableAttachment()
324 {
325 }
326
327 void RenderableAttachment::ConnectToSceneGraph( SceneController& sceneController, BufferIndex updateBufferIndex )
328 {
329   mSceneController = &sceneController;
330   // get the default shader
331   mShader = mSceneController->GetDefaultShader();
332
333   // Chain to derived attachments
334   ConnectToSceneGraph2( updateBufferIndex );
335
336   // After derived classes have (potentially) created their renderer
337   Renderer& renderer = GetRenderer();
338   renderer.SetCullFace( mCullFaceMode );
339
340   // set the default shader here as well
341   renderer.SetShader( mShader );
342 }
343
344 void RenderableAttachment::OnDestroy()
345 {
346   // Chain to derived attachments
347   OnDestroy2();
348
349   // SceneController is no longer valid
350   mSceneController = NULL;
351 }
352
353 RenderableAttachment* RenderableAttachment::GetRenderable()
354 {
355   return this;
356 }
357
358 void RenderableAttachment::SendShaderChangeMessage( BufferIndex updateBufferIndex )
359 {
360   typedef MessageValue1< Renderer, Shader* > DerivedType;
361   // Reserve memory inside the render queue
362   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
363   // Construct message in the mRenderer queue memory; note that delete should not be called on the return value
364   new (slot) DerivedType( &GetRenderer(), &Renderer::SetShader, mShader );
365 }
366
367 } // namespace SceneGraph
368
369 } // namespace Internal
370
371 } // namespace Dali