Texture image filtering
[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( Shader* shader = mParent->GetAppliedShader() )
112   {
113     Integration::ResourceId id = shader->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::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
207 {
208   scaling = Vector3::ONE;
209 }
210
211 void RenderableAttachment::GetReadyAndComplete(bool& ready, bool& complete) const
212 {
213   ready = mResourcesReady;
214   complete = false;
215
216   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
217
218   std::size_t numTrackedResources = mTrackedResources.Count();
219   if( mHasUntrackedResources || numTrackedResources == 0 )
220   {
221     complete = mFinishedResourceAcquisition;
222   }
223   else
224   {
225     // If there are tracked resources and no untracked resources, test the trackers
226     bool trackersComplete = true;
227     for( size_t i=0; i < numTrackedResources; ++i )
228     {
229       ResourceId id = mTrackedResources[i];
230       ResourceTracker* tracker = completeStatusManager.FindResourceTracker(id);
231       if( tracker  && ! tracker->IsComplete() )
232       {
233         trackersComplete = false;
234         break;
235       }
236     }
237
238     complete = mFinishedResourceAcquisition || trackersComplete;
239   }
240 }
241
242 bool RenderableAttachment::IsBlendingOn( BufferIndex updateBufferIndex )
243 {
244   // Check whether blending needs to be disabled / enabled
245   bool blend = false;
246   switch( mBlendingMode )
247   {
248     case BlendingMode::OFF:
249     {
250       // No blending.
251       blend = false;
252       break;
253     }
254     case BlendingMode::AUTO:
255     {
256       // Blending if the node is not fully opaque only.
257       blend = !IsFullyOpaque( updateBufferIndex );
258       break;
259     }
260     case BlendingMode::ON:
261     {
262       // Blending always.
263       blend = true;
264       break;
265     }
266     default:
267     {
268       DALI_ASSERT_ALWAYS( !"RenderableAttachment::PrepareRender. Wrong blending mode" );
269     }
270   }
271   return blend;
272 }
273
274 void RenderableAttachment::PrepareRender( BufferIndex updateBufferIndex )
275 {
276   // call the derived class first as it might change its state regarding blending
277   DoPrepareRender( updateBufferIndex );
278
279   bool blend = IsBlendingOn( updateBufferIndex );
280   ChangeBlending( updateBufferIndex, blend );
281 }
282
283 RenderableAttachment::RenderableAttachment( bool usesGeometryScaling )
284 : mSceneController(NULL),
285   mBlendingMode( Dali::RenderableActor::DEFAULT_BLENDING_MODE ),
286   mUsesGeometryScaling( usesGeometryScaling ),
287   mScaleForSizeDirty( true ),
288   mUseBlend( false ),
289   mHasSizeAndColorFlag( false ),
290   mResourcesReady( false ),
291   mFinishedResourceAcquisition( false ),
292   mHasUntrackedResources( false ),
293   mCullFaceMode( CullNone ),
294   mSortModifier( 0.0f )
295 {
296 }
297
298 RenderableAttachment::~RenderableAttachment()
299 {
300 }
301
302 void RenderableAttachment::ConnectToSceneGraph( SceneController& sceneController, BufferIndex updateBufferIndex )
303 {
304   mSceneController = &sceneController;
305
306   // Chain to derived attachments
307   ConnectToSceneGraph2( updateBufferIndex );
308
309   // After derived classes have (potentially) created their renderer
310   GetRenderer().SetCullFace( mCullFaceMode );
311 }
312
313 void RenderableAttachment::OnDestroy()
314 {
315   // Chain to derived attachments
316   OnDestroy2();
317
318   // SceneController is no longer valid
319   mSceneController = NULL;
320 }
321
322 RenderableAttachment* RenderableAttachment::GetRenderable()
323 {
324   return this;
325 }
326
327
328 } // namespace SceneGraph
329
330 } // namespace Internal
331
332 } // namespace Dali