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