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