2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/internal/common/internal-constants.h>
26 #include <dali/internal/update/resources/resource-manager.h>
27 #include <dali/internal/update/resources/complete-status-manager.h>
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>
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>
40 #include <dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h>
48 // value types used by messages
49 template <> struct ParameterType< SceneGraph::ImageRenderer::MeshType >
50 : public BasicType< SceneGraph::ImageRenderer::MeshType > {};
55 ImageAttachment* ImageAttachment::New( unsigned int textureId )
57 return new ImageAttachment( textureId );
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 ),
73 void ImageAttachment::Initialize2( BufferIndex updateBufferIndex )
75 DALI_ASSERT_DEBUG( NULL != mSceneController );
77 // Create main renderer, passing ownership to the render-thread
78 mImageRenderer = ImageRenderer::New( *mParent );
80 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mImageRenderer );
82 ATTACHMENT_LOG_FMT(Debug::General, " renderer: %p\n", mImageRenderer);
86 typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
88 // Reserve some memory inside the render queue
89 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
95 // After derived classes have (potentially) created their renderer
96 Renderer& renderer = GetRenderer();
97 renderer.SetCullFace( mCullFaceMode );
99 // set the default shader here as well
100 renderer.SetShader( mShader );
103 void ImageAttachment::OnDestroy2()
105 DALI_ASSERT_DEBUG( NULL != mSceneController );
107 // Request deletion in the next Render
108 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mImageRenderer );
109 mImageRenderer = NULL;
112 void ImageAttachment::ConnectedToSceneGraph()
117 void ImageAttachment::DisconnectedFromSceneGraph()
122 ImageAttachment::~ImageAttachment()
126 Renderer& ImageAttachment::GetRenderer()
128 return *mImageRenderer;
131 const Renderer& ImageAttachment::GetRenderer() const
133 return *mImageRenderer;
136 void ImageAttachment::SetTextureId( BufferIndex updateBufferIndex, unsigned int textureId )
138 DALI_ASSERT_DEBUG(mSceneController);
139 ATTACHMENT_LOG_FMT(Debug::General, " textureid: %d)\n", textureId);
141 mTextureId = textureId;
143 // Loading is essentially finished if we don't have a resource ID
144 mFinishedResourceAcquisition = ( 0 == mTextureId );
148 typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
150 // Reserve some memory inside the render queue
151 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
158 void ImageAttachment::SetPixelArea( BufferIndex updateBufferIndex, const PixelArea& pixelArea )
160 // update the pixel area information
161 mIsPixelAreaSet = true;
164 typedef MessageValue1< ImageRenderer, ImageRenderer::PixelArea > DerivedType;
166 // Reserve some memory inside the render queue
167 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
173 // we rely on attachment to not call us unless it actually did change
174 mRefreshMeshData = true;
177 void ImageAttachment::ClearPixelArea()
179 mIsPixelAreaSet = false;
180 mRefreshMeshData = true;
183 void ImageAttachment::SetStyle( Dali::ImageActor::Style style )
188 mRefreshMeshData = true;
192 void ImageAttachment::SetBorder( BufferIndex updateBufferIndex, const Vector4& border, bool inPixels )
194 // update the 9 patch border information
196 typedef MessageValue2< ImageRenderer, Vector4, bool > DerivedType;
198 // Reserve some memory inside the render queue
199 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
204 if (mStyle != Dali::ImageActor::STYLE_QUAD)
206 mRefreshMeshData = true;
210 void ImageAttachment::SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options )
212 // Blending options are forwarded to renderer in render-thread
213 typedef MessageValue1< ImageRenderer, unsigned int > DerivedType;
215 // Reserve some memory inside the render queue
216 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
222 void ImageAttachment::SetBlendColor( BufferIndex updateBufferIndex, const Vector4& color )
224 // Blend color is forwarded to renderer in render-thread
225 typedef MessageValue1< ImageRenderer, Vector4 > DerivedType;
227 // Reserve some memory inside the render queue
228 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
234 void ImageAttachment::SetCullFace( BufferIndex updateBufferIndex, CullFaceMode mode )
236 DALI_ASSERT_DEBUG(mSceneController);
237 DALI_ASSERT_DEBUG(mode >= CullNone && mode <= CullFrontAndBack);
239 mCullFaceMode = mode;
241 typedef MessageValue1< Renderer, CullFaceMode > DerivedType;
243 // Reserve some memory inside the render queue
244 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
250 void ImageAttachment::SetSampler( BufferIndex updateBufferIndex, unsigned int samplerBitfield )
252 DALI_ASSERT_DEBUG(mSceneController);
254 typedef MessageValue1< Renderer, unsigned int > DerivedType;
256 // Reserve some memory inside the render queue
257 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
263 void ImageAttachment::ApplyShader( BufferIndex updateBufferIndex, Shader* shader )
267 // send the message to renderer
268 SendShaderChangeMessage( updateBufferIndex );
270 // tell derived class to do something
271 ShaderChanged( updateBufferIndex );
274 void ImageAttachment::RemoveShader( BufferIndex updateBufferIndex )
276 // return to default shader
279 // send the message to renderer
280 SendShaderChangeMessage( updateBufferIndex );
282 // tell derived class to do something
283 ShaderChanged( updateBufferIndex );
287 void ImageAttachment::ShaderChanged( BufferIndex updateBufferIndex )
289 DALI_ASSERT_DEBUG( mSceneController );
291 int hints = 0; // default shader hints are 0
294 hints = mShader->GetGeometryHints();
296 if ( hints != mPreviousRefreshHints )
298 mPreviousRefreshHints = hints;
299 // (may) need to change geometry
300 mRefreshMeshData = true;
304 void ImageAttachment::SizeChanged( BufferIndex updateBufferIndex )
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 )
311 mRefreshMeshData = true;
315 bool ImageAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
317 DALI_LOG_TRACE_METHOD_FMT(gImageAttachmentLogFilter, "this:%p", this);
320 if( 0 != mTextureId )
322 // The metadata is used by IsFullyOpaque(), below.
323 mBitmapMetadata = resourceManager.GetBitmapMetadata( mTextureId );
325 CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
326 CompleteStatusManager::CompleteState status = completeStatusManager.GetStatus( mTextureId );
330 case CompleteStatusManager::NOT_READY:
334 if( mBitmapMetadata.GetIsFramebuffer() )
338 mFinishedResourceAcquisition = false;
339 FollowTracker( mTextureId );
343 case CompleteStatusManager::COMPLETE:
346 mFinishedResourceAcquisition = true;
350 case CompleteStatusManager::NEVER:
353 mFinishedResourceAcquisition = true;
360 // Loading is essentially finished if we don't have a resource ID
361 mFinishedResourceAcquisition = true;
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");
371 void ImageAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
373 DALI_ASSERT_DEBUG( mSceneController && mImageRenderer );
375 ATTACHMENT_LOG_FMT(Debug::General, "ObjName:%s textureId:%d\n",
376 DALI_LOG_GET_OBJECT_C_STR(mParent),
379 // Check whether we need to refresh the vertex buffer.
380 if ( mRefreshMeshData )
382 const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
383 mGeometrySize.x = actorSize.x;
384 mGeometrySize.y = actorSize.y;
386 ImageRenderer::MeshType meshType = ImageRenderer::GRID_QUAD;
388 if ( !PreviousHintEnabled( Dali::ShaderEffect::HINT_GRID ) )
390 if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
392 meshType = ImageRenderer::NINE_PATCH;
394 else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
396 meshType = ImageRenderer::NINE_PATCH_NO_CENTER;
400 meshType = ImageRenderer::QUAD;
405 if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
407 meshType = ImageRenderer::GRID_NINE_PATCH;
409 else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
411 meshType = ImageRenderer::GRID_NINE_PATCH_NO_CENTER;
415 meshType = ImageRenderer::GRID_QUAD;
419 // Recalculate the mesh data in the next render
421 typedef MessageValue3< ImageRenderer, ImageRenderer::MeshType, Vector2, bool > DerivedType;
423 // Reserve some memory inside the render queue
424 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
430 mRefreshMeshData = false;
433 bool blend = !IsFullyOpaque( updateBufferIndex );
435 if ( mUseBlend != blend )
439 // Enable/disable blending in the next render
440 typedef MessageValue1< ImageRenderer, bool > DerivedType;
442 // Reserve some memory inside the render queue
443 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
450 void RenderableAttachment::SetBlendingMode( BlendingMode::Type mode )
452 mBlendingMode = mode;
455 BlendingMode::Type RenderableAttachment::GetBlendingMode() const
457 return mBlendingMode;
460 bool ImageAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
462 bool fullyOpaque = true;
464 switch( mBlendingMode )
466 case BlendingMode::OFF:
471 case BlendingMode::ON:
477 case BlendingMode::AUTO:
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
485 fullyOpaque = mBitmapMetadata.IsFullyOpaque();
487 if ( fullyOpaque && mParent )
489 fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
491 if ( fullyOpaque && mShader != NULL )
493 fullyOpaque = !PreviousHintEnabled( Dali::ShaderEffect::HINT_BLENDING );
501 void ImageAttachment::SendShaderChangeMessage( BufferIndex updateBufferIndex )
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 );
512 } // namespace SceneGraph
514 } // namespace Internal