Merge remote-tracking branch 'origin/tizen' into devel/new_mesh
[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/scene-graph-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 RenderableAttachment::RenderableAttachment( bool usesGeometryScaling )
43 : mSceneController(NULL), //@todo MESH_REWORK Pass in where required rather than store
44   mShader( NULL ),
45   mTrackedResources(),
46   mSortModifier( 0.0f ),
47   mBlendingMode( Dali::RenderableActor::DEFAULT_BLENDING_MODE ),
48   mUsesGeometryScaling( usesGeometryScaling ),
49   mScaleForSizeDirty( true ),
50   mUseBlend( false ),
51   mHasSizeAndColorFlag( false ),
52   mResourcesReady( false ),
53   mFinishedResourceAcquisition( false ),
54   mHasUntrackedResources( false )
55 {
56 }
57
58 RenderableAttachment::~RenderableAttachment()
59 {
60 }
61
62 void RenderableAttachment::Initialize( SceneController& sceneController, BufferIndex updateBufferIndex )
63 {
64   mSceneController = &sceneController;
65
66   // Chain to derived attachments
67   Initialize2( updateBufferIndex );
68 }
69
70 void RenderableAttachment::OnDestroy()
71 {
72   // Chain to derived attachments
73   OnDestroy2();
74
75   // SceneController is no longer valid
76   mSceneController = NULL;
77 }
78
79 void RenderableAttachment::SetRecalculateScaleForSize()
80 {
81   mScaleForSizeDirty = true;
82 }
83
84 void RenderableAttachment::GetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
85 {
86   DoGetScaleForSize( nodeSize, scaling );
87   mScaleForSizeDirty = false;
88 }
89
90 bool RenderableAttachment::ResolveVisibility( BufferIndex updateBufferIndex )
91 {
92   mHasSizeAndColorFlag = false;
93   const Vector4& color = mParent->GetWorldColor( updateBufferIndex );
94   if( color.a > FULLY_TRANSPARENT )               // not fully transparent
95   {
96     const float MAX_NODE_SIZE = float(1u<<30);
97     const Vector3& size = mParent->GetSize( updateBufferIndex );
98     if( ( size.width > Math::MACHINE_EPSILON_1000 ) &&  // width is greater than a very small number
99         ( size.height > Math::MACHINE_EPSILON_1000 ) )  // height is greater than a very small number
100     {
101       if( ( size.width < MAX_NODE_SIZE ) &&             // width is smaller than the maximum allowed size
102           ( size.height < MAX_NODE_SIZE ) )             // height is smaller than the maximum allowed size
103       {
104         mHasSizeAndColorFlag = true;
105       }
106       else
107       {
108         DALI_LOG_ERROR("Actor size should not be bigger than %f.\n", MAX_NODE_SIZE );
109         DALI_LOG_ACTOR_TREE( mParent );
110       }
111     }
112   }
113   return mHasSizeAndColorFlag;
114 }
115
116 void RenderableAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
117 {
118   scaling = Vector3::ONE;
119 }
120
121 void RenderableAttachment::PrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
122 {
123   mHasUntrackedResources = false; // Only need to know this if the resources are not yet complete
124   mTrackedResources.Clear(); // Resource trackers are only needed if not yet completea
125
126   if( mShader )
127   {
128     Integration::ResourceId id = mShader->GetEffectTextureResourceId();
129
130     if( id != 0 )
131     {
132       CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
133
134       if(CompleteStatusManager::COMPLETE != completeStatusManager.GetStatus( id ))
135       {
136         FollowTracker(id);
137         mFinishedResourceAcquisition = false;
138         mResourcesReady = false;
139
140         // If shader has effect texture and it's not complete and tracked, ensure
141         // we call DoPrepareResources, as the effect texture may become ready in
142         // the ProcessRenderTasks step.  Otherwise, may early out.
143         if( mHasUntrackedResources )
144         {
145           return;
146         }
147       }
148     }
149   }
150
151   mResourcesReady = DoPrepareResources( updateBufferIndex, resourceManager );
152 }
153
154 void RenderableAttachment::FollowTracker( Integration::ResourceId id )
155 {
156   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
157
158   if( completeStatusManager.FindResourceTracker(id) != NULL )
159   {
160     bool found = false;
161     std::size_t numTrackedResources = mTrackedResources.Count();
162     for( size_t i=0; i < numTrackedResources; ++i )
163     {
164       if(mTrackedResources[i] == id)
165       {
166         found = true;
167         break;
168       }
169     }
170     if( ! found )
171     {
172       mTrackedResources.PushBack( id );
173     }
174   }
175   else
176   {
177     mHasUntrackedResources = true;
178   }
179 }
180
181
182 void RenderableAttachment::GetReadyAndComplete(bool& ready, bool& complete) const
183 {
184   ready = mResourcesReady;
185   complete = false;
186
187   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
188
189   std::size_t numTrackedResources = mTrackedResources.Count();
190   if( mHasUntrackedResources || numTrackedResources == 0 )
191   {
192     complete = mFinishedResourceAcquisition;
193   }
194   else
195   {
196     // If there are tracked resources and no untracked resources, test the trackers
197     bool trackersComplete = true;
198     for( size_t i=0; i < numTrackedResources; ++i )
199     {
200       ResourceId id = mTrackedResources[i];
201       ResourceTracker* tracker = completeStatusManager.FindResourceTracker(id);
202       if( tracker  && ! tracker->IsComplete() )
203       {
204         trackersComplete = false;
205         break;
206       }
207     }
208
209     complete = mFinishedResourceAcquisition || trackersComplete;
210   }
211 }
212
213 void RenderableAttachment::PrepareRender( BufferIndex updateBufferIndex )
214 {
215   // call the derived class first as it might change its state regarding blending
216   DoPrepareRender( updateBufferIndex );
217
218   // @todo MESH_REWORK Remove remainder of method after removing ImageAttachment
219
220   bool blend = !IsFullyOpaque( updateBufferIndex );
221
222   if ( mUseBlend != blend )
223   {
224     mUseBlend = blend;
225
226     // Enable/disable blending in the next render
227     typedef MessageValue1< Renderer, bool > DerivedType;
228
229     // Reserve some memory inside the render queue
230     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
231
232     // Construct message in the render queue memory; note that delete should not be called on the return value
233     new (slot) DerivedType( &GetRenderer(), &Renderer::SetUseBlend, blend );
234   }
235 }
236
237 RenderableAttachment* RenderableAttachment::GetRenderable()
238 {
239   return this;
240 }
241
242 void RenderableAttachment::SetSortModifier(float modifier)
243 {
244   // Setting sort modifier makes the node dirty, i.e. we cannot reuse previous frames render items
245   if( mParent )
246   {
247     // only do this if we are on-stage
248     mParent->SetDirtyFlag( SortModifierFlag );
249   }
250   mSortModifier = modifier;
251 }
252
253
254 } // namespace SceneGraph
255
256 } // namespace Internal
257
258 } // namespace Dali