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/shader.h>
40 #include <dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h>
50 // value types used by messages
51 template <> struct ParameterType< SceneGraph::ImageRenderer::MeshType >
52 : public BasicType< SceneGraph::ImageRenderer::MeshType > {};
57 ImageAttachment* ImageAttachment::New( unsigned int textureId )
59 return new ImageAttachment( textureId );
62 ImageAttachment::ImageAttachment( unsigned int textureId )
63 : RenderableAttachment( false ), // no scaling
64 mImageRenderer( NULL ),
65 mTextureId( textureId ),
66 mRefreshMeshData( true ),
67 mIsPixelAreaSet( false ),
68 mPreviousRefreshHints( 0 ),
69 mStyle( Dali::ImageActor::STYLE_QUAD )
73 void ImageAttachment::ConnectToSceneGraph2( 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 );
96 void ImageAttachment::OnDestroy2()
98 DALI_ASSERT_DEBUG( NULL != mSceneController );
100 // Request deletion in the next Render
101 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mImageRenderer );
102 mImageRenderer = NULL;
105 ImageAttachment::~ImageAttachment()
109 Renderer& ImageAttachment::GetRenderer()
111 return *mImageRenderer;
114 const Renderer& ImageAttachment::GetRenderer() const
116 return *mImageRenderer;
119 void ImageAttachment::SetTextureId( BufferIndex updateBufferIndex, unsigned int textureId )
121 DALI_ASSERT_DEBUG(mSceneController);
122 ATTACHMENT_LOG_FMT(Debug::General, " textureid: %d)\n", textureId);
124 mTextureId = textureId;
125 mFinishedResourceAcquisition = false;
129 typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
131 // Reserve some memory inside the render queue
132 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
134 // Construct message in the render queue memory; note that delete should not be called on the return value
135 new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetTextureId, mTextureId );
139 void ImageAttachment::SetPixelArea( BufferIndex updateBufferIndex, const PixelArea& pixelArea )
141 // update the pixel area information
142 mIsPixelAreaSet = true;
145 typedef MessageValue1< ImageRenderer, ImageRenderer::PixelArea > DerivedType;
147 // Reserve some memory inside the render queue
148 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
150 // Construct message in the render queue memory; note that delete should not be called on the return value
151 new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetPixelArea, pixelArea );
154 // we rely on attachment to not call us unless it actually did change
155 mRefreshMeshData = true;
158 void ImageAttachment::ClearPixelArea()
160 mIsPixelAreaSet = false;
161 mRefreshMeshData = true;
164 void ImageAttachment::SetStyle( Dali::ImageActor::Style style )
169 mRefreshMeshData = true;
173 void ImageAttachment::SetBorder( BufferIndex updateBufferIndex, const Vector4& border, bool inPixels )
175 // update the 9 patch border information
177 typedef MessageValue2< ImageRenderer, Vector4, bool > DerivedType;
179 // Reserve some memory inside the render queue
180 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
182 // Construct message in the render queue memory; note that delete should not be called on the return value
183 new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetNinePatchBorder, border, inPixels );
185 if (mStyle != Dali::ImageActor::STYLE_QUAD)
187 mRefreshMeshData = true;
191 void ImageAttachment::ShaderChanged( BufferIndex updateBufferIndex )
193 DALI_ASSERT_DEBUG( mShader != NULL );
194 DALI_ASSERT_DEBUG( mSceneController );
196 int hints = mShader->GetGeometryHints();
198 if ( hints != mPreviousRefreshHints )
200 mPreviousRefreshHints = hints;
201 // (may) need to change geometry
202 mRefreshMeshData = true;
206 void ImageAttachment::SizeChanged( BufferIndex updateBufferIndex )
208 // avoid regenerating geometry if the size did not actually change (visibility change can accumulate a false SizeChanged)
209 const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
210 if( fabsf( actorSize.width - mGeometrySize.width ) > Math::MACHINE_EPSILON_1 ||
211 fabsf( actorSize.height - mGeometrySize.height ) > Math::MACHINE_EPSILON_1 )
213 mRefreshMeshData = true;
217 bool ImageAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
219 DALI_LOG_TRACE_METHOD_FMT(gImageAttachmentLogFilter, "this:%p", this);
222 // The metadata is used by IsFullyOpaque(), below.
223 mBitmapMetadata = resourceManager.GetBitmapMetadata( mTextureId );
225 CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
226 CompleteStatusManager::CompleteState status = completeStatusManager.GetStatus( mTextureId );
230 case CompleteStatusManager::NOT_READY:
234 if( mBitmapMetadata.GetIsFramebuffer() )
238 mFinishedResourceAcquisition = false;
239 FollowTracker( mTextureId );
243 case CompleteStatusManager::COMPLETE:
246 mFinishedResourceAcquisition = true;
250 case CompleteStatusManager::NEVER:
253 mFinishedResourceAcquisition = true;
258 ATTACHMENT_LOG_FMT(Debug::General, " finished:%s ready:%s \n", mFinishedResourceAcquisition?"T":"F", ready?"T":"F");
263 void ImageAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
265 DALI_ASSERT_DEBUG( mSceneController && mImageRenderer );
267 ATTACHMENT_LOG_FMT(Debug::General, " textureId:%d\n", mTextureId);
269 // Check whether we need to refresh the vertex buffer.
270 if ( mRefreshMeshData )
272 const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
273 mGeometrySize.x = actorSize.x;
274 mGeometrySize.y = actorSize.y;
276 ImageRenderer::MeshType meshType = ImageRenderer::GRID_QUAD;
278 if ( !PreviousHintEnabled( Dali::ShaderEffect::HINT_GRID ) )
280 if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
282 meshType = ImageRenderer::NINE_PATCH;
284 else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
286 meshType = ImageRenderer::NINE_PATCH_NO_CENTER;
290 meshType = ImageRenderer::QUAD;
295 if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
297 meshType = ImageRenderer::GRID_NINE_PATCH;
299 else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
301 meshType = ImageRenderer::GRID_NINE_PATCH_NO_CENTER;
305 meshType = ImageRenderer::GRID_QUAD;
309 // Recalculate the mesh data in the next render
311 typedef MessageValue3< ImageRenderer, ImageRenderer::MeshType, Vector2, bool > DerivedType;
313 // Reserve some memory inside the render queue
314 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
316 // Construct message in the render queue memory; note that delete should not be called on the return value
317 new (slot) DerivedType( mImageRenderer, &ImageRenderer::CalculateMeshData, meshType, mGeometrySize, mIsPixelAreaSet );
320 mRefreshMeshData = false;
324 bool ImageAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
327 * Fully opaque when...
328 * 1) not using the alpha channel from the image data
329 * 2) the inherited color is not transparent nor semi-transparent
330 * 3) the shader doesn't require blending
332 bool opaque = mBitmapMetadata.IsFullyOpaque();
334 if ( opaque && mParent )
336 opaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
338 if ( opaque && mShader != NULL )
340 opaque = !PreviousHintEnabled( Dali::ShaderEffect::HINT_BLENDING );
347 } // namespace SceneGraph
349 } // namespace Internal