Change Epsilon 0 and 1 to use the compiler provided values
[platform/core/uifw/dali-core.git] / dali / internal / update / node-attachments / scene-graph-image-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-image-attachment.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/internal/common/internal-constants.h>
25
26 #include <dali/internal/update/resources/resource-manager.h>
27 #include <dali/internal/update/resources/complete-status-manager.h>
28
29 #include <dali/internal/update/controllers/render-message-dispatcher.h>
30 #include <dali/internal/update/controllers/scene-controller.h>
31 #include <dali/internal/update/nodes/node.h>
32
33 #include <dali/internal/render/queue/render-queue.h>
34 #include <dali/internal/render/common/vertex.h>
35 #include <dali/internal/render/common/performance-monitor.h>
36 #include <dali/internal/render/renderers/scene-graph-image-renderer.h>
37 #include <dali/internal/render/renderers/scene-graph-renderer-declarations.h>
38 #include <dali/internal/render/shaders/scene-graph-shader.h>
39
40 #include <dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h>
41
42 namespace Dali
43 {
44
45 namespace Internal
46 {
47
48 // value types used by messages
49 template <> struct ParameterType< SceneGraph::ImageRenderer::MeshType >
50 : public BasicType< SceneGraph::ImageRenderer::MeshType > {};
51
52 namespace SceneGraph
53 {
54
55 ImageAttachment* ImageAttachment::New( unsigned int textureId )
56 {
57   return new ImageAttachment( textureId );
58 }
59
60 ImageAttachment::ImageAttachment( unsigned int textureId )
61 : RenderableAttachment( false ), // no scaling
62   mImageRenderer( NULL ),
63   mTextureId( textureId ),
64   mRefreshMeshData( true ),
65   mIsPixelAreaSet( false ),
66   mPreviousRefreshHints( 0 ),
67   mStyle( Dali::ImageActor::STYLE_QUAD ),
68   mCullFaceMode( CullNone )
69 {
70 }
71
72 void ImageAttachment::Initialize2( BufferIndex updateBufferIndex )
73 {
74   DALI_ASSERT_DEBUG( NULL != mSceneController );
75
76   // Create main renderer, passing ownership to the render-thread
77   mImageRenderer = ImageRenderer::New( *mParent );
78
79   mSceneController->GetRenderMessageDispatcher().AddRenderer( *mImageRenderer );
80
81   ATTACHMENT_LOG_FMT(Debug::General, " renderer: %p\n", mImageRenderer);
82
83   if( mTextureId != 0 )
84   {
85     typedef MessageValue1< ImageRenderer, ResourceId > 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( mImageRenderer, &ImageRenderer::SetTextureId, mTextureId );
92   }
93
94   // After derived classes have (potentially) created their renderer
95   Renderer& renderer = GetRenderer();
96   renderer.SetCullFace( mCullFaceMode );
97
98   // set the default shader here as well
99   renderer.SetShader( mShader );
100 }
101
102 void ImageAttachment::OnDestroy2()
103 {
104   DALI_ASSERT_DEBUG( NULL != mSceneController );
105
106   // Request deletion in the next Render
107   mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mImageRenderer );
108   mImageRenderer = NULL;
109 }
110
111 void ImageAttachment::ConnectedToSceneGraph()
112 {
113   // Do nothing
114 }
115
116 void ImageAttachment::DisconnectedFromSceneGraph()
117 {
118   // Do nothing
119 }
120
121 ImageAttachment::~ImageAttachment()
122 {
123 }
124
125 Renderer& ImageAttachment::GetRenderer()
126 {
127   return *mImageRenderer;
128 }
129
130 const Renderer& ImageAttachment::GetRenderer() const
131 {
132   return *mImageRenderer;
133 }
134
135 void ImageAttachment::SetTextureId( BufferIndex updateBufferIndex, unsigned int textureId )
136 {
137   DALI_ASSERT_DEBUG(mSceneController);
138   ATTACHMENT_LOG_FMT(Debug::General, " textureid: %d)\n", textureId);
139
140   mTextureId = textureId;
141
142   // Loading is essentially finished if we don't have a resource ID
143   mFinishedResourceAcquisition = ( 0 == mTextureId );
144
145   if( mImageRenderer )
146   {
147     typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
148
149     // Reserve some memory inside the render queue
150     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
151
152     // Construct message in the render queue memory; note that delete should not be called on the return value
153     new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetTextureId, mTextureId );
154   }
155 }
156
157 void ImageAttachment::SetPixelArea( BufferIndex updateBufferIndex, const PixelArea& pixelArea )
158 {
159   // update the pixel area information
160   mIsPixelAreaSet = true;
161
162   {
163     typedef MessageValue1< ImageRenderer, ImageRenderer::PixelArea > DerivedType;
164
165     // Reserve some memory inside the render queue
166     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
167
168     // Construct message in the render queue memory; note that delete should not be called on the return value
169     new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetPixelArea, pixelArea );
170   }
171
172   // we rely on attachment to not call us unless it actually did change
173   mRefreshMeshData = true;
174 }
175
176 void ImageAttachment::ClearPixelArea()
177 {
178   mIsPixelAreaSet = false;
179   mRefreshMeshData = true;
180 }
181
182 void ImageAttachment::SetStyle( Dali::ImageActor::Style style )
183 {
184   if (mStyle != style)
185   {
186     mStyle = style;
187     mRefreshMeshData = true;
188   }
189 }
190
191 void ImageAttachment::SetBorder( BufferIndex updateBufferIndex, const Vector4& border, bool inPixels )
192 {
193   // update the 9 patch border information
194
195   typedef MessageValue2< ImageRenderer, Vector4, bool > DerivedType;
196
197   // Reserve some memory inside the render queue
198   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
199
200   // Construct message in the render queue memory; note that delete should not be called on the return value
201   new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetNinePatchBorder, border, inPixels );
202
203   if (mStyle != Dali::ImageActor::STYLE_QUAD)
204   {
205     mRefreshMeshData = true;
206   }
207 }
208
209 void ImageAttachment::SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options )
210 {
211   // Blending options are forwarded to renderer in render-thread
212   typedef MessageValue1< Renderer, unsigned int > DerivedType;
213
214   // Reserve some memory inside the render queue
215   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
216
217   // Construct message in the render queue memory; note that delete should not be called on the return value
218   new (slot) DerivedType( &GetRenderer(), &Renderer::SetBlendingOptions, options );
219 }
220
221 void ImageAttachment::SetBlendColor( BufferIndex updateBufferIndex, const Vector4& color )
222 {
223   // Blend color is forwarded to renderer in render-thread
224   typedef MessageValue1< Renderer, Vector4 > DerivedType;
225
226   // Reserve some memory inside the render queue
227   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
228
229   // Construct message in the render queue memory; note that delete should not be called on the return value
230   new (slot) DerivedType( &GetRenderer(), &Renderer::SetBlendColor, color );
231 }
232
233 void ImageAttachment::SetCullFace( BufferIndex updateBufferIndex, CullFaceMode mode )
234 {
235   DALI_ASSERT_DEBUG(mSceneController);
236   DALI_ASSERT_DEBUG(mode >= CullNone && mode <= CullFrontAndBack);
237
238   mCullFaceMode = mode;
239
240   typedef MessageValue1< Renderer, CullFaceMode > DerivedType;
241
242   // Reserve some memory inside the render queue
243   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
244
245   // Construct message in the render queue memory; note that delete should not be called on the return value
246   new (slot) DerivedType( &GetRenderer(), &Renderer::SetCullFace, mode );
247 }
248
249 void ImageAttachment::SetSampler( BufferIndex updateBufferIndex, unsigned int samplerBitfield )
250 {
251   DALI_ASSERT_DEBUG(mSceneController);
252
253   typedef MessageValue1< Renderer, unsigned int > DerivedType;
254
255   // Reserve some memory inside the render queue
256   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
257
258   // Construct message in the render queue memory; note that delete should not be called on the return value
259   new (slot) DerivedType( &GetRenderer(), &Renderer::SetSampler, samplerBitfield );
260 }
261
262 void ImageAttachment::ApplyShader( BufferIndex updateBufferIndex, Shader* shader )
263 {
264   mShader = shader;
265
266   // send the message to renderer
267   SendShaderChangeMessage( updateBufferIndex );
268
269   // tell derived class to do something
270   ShaderChanged( updateBufferIndex );
271 }
272
273 void ImageAttachment::RemoveShader( BufferIndex updateBufferIndex )
274 {
275   // return to default shader
276   mShader = NULL;
277
278   // send the message to renderer
279   SendShaderChangeMessage( updateBufferIndex );
280
281   // tell derived class to do something
282   ShaderChanged( updateBufferIndex );
283 }
284
285
286 void ImageAttachment::ShaderChanged( BufferIndex updateBufferIndex )
287 {
288   DALI_ASSERT_DEBUG( mSceneController );
289
290   int hints = 0; // default shader hints are 0
291   if( mShader )
292   {
293     hints = mShader->GetGeometryHints();
294   }
295   if ( hints != mPreviousRefreshHints )
296   {
297     mPreviousRefreshHints = hints;
298     // (may) need to change geometry
299     mRefreshMeshData = true;
300   }
301 }
302
303 void ImageAttachment::SizeChanged( BufferIndex updateBufferIndex )
304 {
305   // avoid regenerating geometry if the size did not actually change (visibility change can accumulate a false SizeChanged)
306   const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
307   if( fabsf( actorSize.width  - mGeometrySize.width  ) > Math::MACHINE_EPSILON_1 ||
308       fabsf( actorSize.height - mGeometrySize.height ) > Math::MACHINE_EPSILON_1 )
309   {
310     mRefreshMeshData = true;
311   }
312 }
313
314 bool ImageAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
315 {
316   DALI_LOG_TRACE_METHOD_FMT(gImageAttachmentLogFilter, "this:%p", this);
317   bool ready = false;
318
319   if( 0 != mTextureId )
320   {
321     // The metadata is used by IsFullyOpaque(), below.
322     mBitmapMetadata = resourceManager.GetBitmapMetadata( mTextureId );
323
324     CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
325     CompleteStatusManager::CompleteState status = completeStatusManager.GetStatus( mTextureId );
326
327     switch( status )
328     {
329       case CompleteStatusManager::NOT_READY:
330       {
331         ready = false;
332
333         if( mBitmapMetadata.GetIsFramebuffer() )
334         {
335           ready = true;
336         }
337         mFinishedResourceAcquisition = false;
338         FollowTracker( mTextureId );
339       }
340       break;
341
342       case CompleteStatusManager::COMPLETE:
343       {
344         ready = true;
345         mFinishedResourceAcquisition = true;
346       }
347       break;
348
349       case CompleteStatusManager::NEVER:
350       {
351         ready = false;
352         mFinishedResourceAcquisition = true;
353       }
354       break;
355     }
356   }
357   else
358   {
359     // Loading is essentially finished if we don't have a resource ID
360     mFinishedResourceAcquisition = true;
361   }
362
363   ATTACHMENT_LOG_FMT(Debug::General, " ObjName:%s finished:%s ready:%s \n",
364                      DALI_LOG_GET_OBJECT_C_STR(mParent),
365                      mFinishedResourceAcquisition?"T":"F", ready?"T":"F");
366
367   return ready;
368 }
369
370 void ImageAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
371 {
372   DALI_ASSERT_DEBUG( mSceneController && mImageRenderer );
373
374   ATTACHMENT_LOG_FMT(Debug::General, "ObjName:%s textureId:%d\n",
375                      DALI_LOG_GET_OBJECT_C_STR(mParent),
376                      mTextureId);
377
378   // Check whether we need to refresh the vertex buffer.
379   if ( mRefreshMeshData )
380   {
381     const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
382     mGeometrySize.x = actorSize.x;
383     mGeometrySize.y = actorSize.y;
384
385     ImageRenderer::MeshType meshType = ImageRenderer::GRID_QUAD;
386
387     if ( !PreviousHintEnabled( Dali::ShaderEffect::HINT_GRID ) )
388     {
389       if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
390       {
391         meshType = ImageRenderer::NINE_PATCH;
392       }
393       else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
394       {
395         meshType = ImageRenderer::NINE_PATCH_NO_CENTER;
396       }
397       else
398       {
399         meshType = ImageRenderer::QUAD;
400       }
401     }
402     else
403     {
404       if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
405       {
406         meshType = ImageRenderer::GRID_NINE_PATCH;
407       }
408       else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
409       {
410         meshType = ImageRenderer::GRID_NINE_PATCH_NO_CENTER;
411       }
412       else
413       {
414         meshType = ImageRenderer::GRID_QUAD;
415       }
416     }
417
418     // Recalculate the mesh data in the next render
419     {
420       typedef MessageValue3< ImageRenderer, ImageRenderer::MeshType, Vector2, bool > DerivedType;
421
422       // Reserve some memory inside the render queue
423       unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
424
425       // Construct message in the render queue memory; note that delete should not be called on the return value
426       new (slot) DerivedType( mImageRenderer, &ImageRenderer::CalculateMeshData, meshType, mGeometrySize, mIsPixelAreaSet );
427     }
428
429     mRefreshMeshData = false;
430   }
431 }
432
433 void RenderableAttachment::SetBlendingMode( BlendingMode::Type mode )
434 {
435   mBlendingMode = mode;
436 }
437
438 BlendingMode::Type RenderableAttachment::GetBlendingMode() const
439 {
440   return mBlendingMode;
441 }
442
443 bool ImageAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
444 {
445   bool fullyOpaque = true;
446
447   switch( mBlendingMode )
448   {
449     case BlendingMode::OFF:
450     {
451       fullyOpaque = true;
452       break;
453     }
454     case BlendingMode::ON:
455     {
456       // Blending always.
457       fullyOpaque = false;
458       break;
459     }
460     case BlendingMode::AUTO:
461     {
462       /**
463        * Fully opaque when...
464        *   1) not using the alpha channel from the image data
465        *   2) the inherited color is not transparent nor semi-transparent
466        *   3) the shader doesn't require blending
467        */
468       fullyOpaque = mBitmapMetadata.IsFullyOpaque();
469
470       if ( fullyOpaque && mParent )
471       {
472         fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
473
474         if ( fullyOpaque && mShader != NULL )
475         {
476           fullyOpaque = !PreviousHintEnabled( Dali::ShaderEffect::HINT_BLENDING );
477         }
478       }
479     }
480   }
481   return fullyOpaque;
482 }
483
484 void ImageAttachment::SendShaderChangeMessage( BufferIndex updateBufferIndex )
485 {
486   typedef MessageValue1< Renderer, Shader* > DerivedType;
487   // Reserve memory inside the render queue
488   unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
489   // Construct message in the mRenderer queue memory; note that delete should not be called on the return value
490   new (slot) DerivedType( &GetRenderer(), &Renderer::SetShader, mShader );
491 }
492
493
494
495 } // namespace SceneGraph
496
497 } // namespace Internal
498
499 } // namespace Dali