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 )
72 void ImageAttachment::Initialize2( BufferIndex updateBufferIndex )
74 DALI_ASSERT_DEBUG( NULL != mSceneController );
76 // Create main renderer, passing ownership to the render-thread
77 mImageRenderer = ImageRenderer::New( *mParent );
79 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mImageRenderer );
81 ATTACHMENT_LOG_FMT(Debug::General, " renderer: %p\n", mImageRenderer);
85 typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
87 // Reserve some memory inside the render queue
88 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
94 // After derived classes have (potentially) created their renderer
95 Renderer& renderer = GetRenderer();
96 renderer.SetCullFace( mCullFaceMode );
98 // set the default shader here as well
99 renderer.SetShader( mShader );
102 void ImageAttachment::OnDestroy2()
104 DALI_ASSERT_DEBUG( NULL != mSceneController );
106 // Request deletion in the next Render
107 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mImageRenderer );
108 mImageRenderer = NULL;
111 void ImageAttachment::ConnectedToSceneGraph()
116 void ImageAttachment::DisconnectedFromSceneGraph()
121 ImageAttachment::~ImageAttachment()
125 Renderer& ImageAttachment::GetRenderer()
127 return *mImageRenderer;
130 const Renderer& ImageAttachment::GetRenderer() const
132 return *mImageRenderer;
135 void ImageAttachment::SetTextureId( BufferIndex updateBufferIndex, unsigned int textureId )
137 DALI_ASSERT_DEBUG(mSceneController);
138 ATTACHMENT_LOG_FMT(Debug::General, " textureid: %d)\n", textureId);
140 mTextureId = textureId;
142 // Loading is essentially finished if we don't have a resource ID
143 mFinishedResourceAcquisition = ( 0 == mTextureId );
147 typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
149 // Reserve some memory inside the render queue
150 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
157 void ImageAttachment::SetPixelArea( BufferIndex updateBufferIndex, const PixelArea& pixelArea )
159 // update the pixel area information
160 mIsPixelAreaSet = true;
163 typedef MessageValue1< ImageRenderer, ImageRenderer::PixelArea > DerivedType;
165 // Reserve some memory inside the render queue
166 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
172 // we rely on attachment to not call us unless it actually did change
173 mRefreshMeshData = true;
176 void ImageAttachment::ClearPixelArea()
178 mIsPixelAreaSet = false;
179 mRefreshMeshData = true;
182 void ImageAttachment::SetStyle( Dali::ImageActor::Style style )
187 mRefreshMeshData = true;
191 void ImageAttachment::SetBorder( BufferIndex updateBufferIndex, const Vector4& border, bool inPixels )
193 // update the 9 patch border information
195 typedef MessageValue2< ImageRenderer, Vector4, bool > DerivedType;
197 // Reserve some memory inside the render queue
198 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
203 if (mStyle != Dali::ImageActor::STYLE_QUAD)
205 mRefreshMeshData = true;
209 void ImageAttachment::SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options )
211 // Blending options are forwarded to renderer in render-thread
212 typedef MessageValue1< Renderer, unsigned int > DerivedType;
214 // Reserve some memory inside the render queue
215 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
221 void ImageAttachment::SetBlendColor( BufferIndex updateBufferIndex, const Vector4& color )
223 // Blend color is forwarded to renderer in render-thread
224 typedef MessageValue1< Renderer, Vector4 > DerivedType;
226 // Reserve some memory inside the render queue
227 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
233 void ImageAttachment::SetCullFace( BufferIndex updateBufferIndex, CullFaceMode mode )
235 DALI_ASSERT_DEBUG(mSceneController);
236 DALI_ASSERT_DEBUG(mode >= CullNone && mode <= CullFrontAndBack);
238 mCullFaceMode = mode;
240 typedef MessageValue1< Renderer, CullFaceMode > DerivedType;
242 // Reserve some memory inside the render queue
243 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
249 void ImageAttachment::SetSampler( BufferIndex updateBufferIndex, unsigned int samplerBitfield )
251 DALI_ASSERT_DEBUG(mSceneController);
253 typedef MessageValue1< Renderer, unsigned int > DerivedType;
255 // Reserve some memory inside the render queue
256 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
262 void ImageAttachment::ApplyShader( BufferIndex updateBufferIndex, Shader* shader )
266 // send the message to renderer
267 SendShaderChangeMessage( updateBufferIndex );
269 // tell derived class to do something
270 ShaderChanged( updateBufferIndex );
273 void ImageAttachment::RemoveShader( BufferIndex updateBufferIndex )
275 // return to default shader
278 // send the message to renderer
279 SendShaderChangeMessage( updateBufferIndex );
281 // tell derived class to do something
282 ShaderChanged( updateBufferIndex );
286 void ImageAttachment::ShaderChanged( BufferIndex updateBufferIndex )
288 DALI_ASSERT_DEBUG( mSceneController );
290 int hints = 0; // default shader hints are 0
293 hints = mShader->GetGeometryHints();
295 if ( hints != mPreviousRefreshHints )
297 mPreviousRefreshHints = hints;
298 // (may) need to change geometry
299 mRefreshMeshData = true;
303 void ImageAttachment::SizeChanged( BufferIndex updateBufferIndex )
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 )
310 mRefreshMeshData = true;
314 bool ImageAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
316 DALI_LOG_TRACE_METHOD_FMT(gImageAttachmentLogFilter, "this:%p", this);
319 if( 0 != mTextureId )
321 // The metadata is used by IsFullyOpaque(), below.
322 mBitmapMetadata = resourceManager.GetBitmapMetadata( mTextureId );
324 CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
325 CompleteStatusManager::CompleteState status = completeStatusManager.GetStatus( mTextureId );
329 case CompleteStatusManager::NOT_READY:
333 if( mBitmapMetadata.GetIsFramebuffer() )
337 mFinishedResourceAcquisition = false;
338 FollowTracker( mTextureId );
342 case CompleteStatusManager::COMPLETE:
345 mFinishedResourceAcquisition = true;
349 case CompleteStatusManager::NEVER:
352 mFinishedResourceAcquisition = true;
359 // Loading is essentially finished if we don't have a resource ID
360 mFinishedResourceAcquisition = true;
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");
370 void ImageAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
372 DALI_ASSERT_DEBUG( mSceneController && mImageRenderer );
374 ATTACHMENT_LOG_FMT(Debug::General, "ObjName:%s textureId:%d\n",
375 DALI_LOG_GET_OBJECT_C_STR(mParent),
378 // Check whether we need to refresh the vertex buffer.
379 if ( mRefreshMeshData )
381 const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
382 mGeometrySize.x = actorSize.x;
383 mGeometrySize.y = actorSize.y;
385 ImageRenderer::MeshType meshType = ImageRenderer::GRID_QUAD;
387 if ( !PreviousHintEnabled( Dali::ShaderEffect::HINT_GRID ) )
389 if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
391 meshType = ImageRenderer::NINE_PATCH;
393 else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
395 meshType = ImageRenderer::NINE_PATCH_NO_CENTER;
399 meshType = ImageRenderer::QUAD;
404 if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
406 meshType = ImageRenderer::GRID_NINE_PATCH;
408 else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
410 meshType = ImageRenderer::GRID_NINE_PATCH_NO_CENTER;
414 meshType = ImageRenderer::GRID_QUAD;
418 // Recalculate the mesh data in the next render
420 typedef MessageValue3< ImageRenderer, ImageRenderer::MeshType, Vector2, bool > DerivedType;
422 // Reserve some memory inside the render queue
423 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
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 );
429 mRefreshMeshData = false;
433 void RenderableAttachment::SetBlendingMode( BlendingMode::Type mode )
435 mBlendingMode = mode;
438 BlendingMode::Type RenderableAttachment::GetBlendingMode() const
440 return mBlendingMode;
443 bool ImageAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
445 bool fullyOpaque = true;
447 switch( mBlendingMode )
449 case BlendingMode::OFF:
454 case BlendingMode::ON:
460 case BlendingMode::AUTO:
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
468 fullyOpaque = mBitmapMetadata.IsFullyOpaque();
470 if ( fullyOpaque && mParent )
472 fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
474 if ( fullyOpaque && mShader != NULL )
476 fullyOpaque = !PreviousHintEnabled( Dali::ShaderEffect::HINT_BLENDING );
484 void ImageAttachment::SendShaderChangeMessage( BufferIndex updateBufferIndex )
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 );
495 } // namespace SceneGraph
497 } // namespace Internal