CameraActorPtr CameraActor::New( const Size& size )
{
- CameraActorPtr actor(new CameraActor());
+ CameraActorPtr actor( new CameraActor() );
// Second-phase construction
-
actor->Initialize();
- actor->SetName("DefaultCamera");
-
- // Create scene-object and keep raw pointer for message passing
- SceneGraph::Camera* camera = SceneGraph::Camera::New();
- actor->mSceneObject = camera;
- OwnerPointer< SceneGraph::Camera > transferOwnership( camera );
- AddCameraMessage( actor->GetEventThreadServices().GetUpdateManager(), transferOwnership );
-
+ actor->SetName( "DefaultCamera" );
actor->SetPerspectiveProjection( size );
// By default Actors face in the positive Z direction in world space
}
}
+void CameraActor::OnInitialize()
+{
+ // Create scene-object and keep raw pointer for message passing.
+ SceneGraph::Camera* sceneGraphCamera = SceneGraph::Camera::New();
+
+ // Store a pointer to this camera node inside the scene-graph camera.
+ sceneGraphCamera->SetNode( mNode );
+
+ mSceneObject = sceneGraphCamera;
+ OwnerPointer< SceneGraph::Camera > sceneGraphCameraOwner( sceneGraphCamera );
+
+ // Send message to inform update of this camera (and move ownership).
+ AddCameraMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphCameraOwner );
+}
+
void CameraActor::SetTarget( const Vector3& target )
{
if( target != mTarget ) // using range epsilon
-#ifndef __DALI_INTERNAL_CAMERA_ACTOR_H__
-#define __DALI_INTERNAL_CAMERA_ACTOR_H__
+#ifndef DALI_INTERNAL_CAMERA_ACTOR_H
+#define DALI_INTERNAL_CAMERA_ACTOR_H
/*
* Copyright (c) 2017 Samsung Electronics Co., Ltd.
*/
virtual ~CameraActor();
+
+ /**
+ * @copydoc Dali::Internal::Actor::OnInitialize()
+ */
+ virtual void OnInitialize();
+
+
private: // Data
const SceneGraph::Camera* mSceneObject; ///< Not owned
} // namespace Dali
-#endif // __DALI_INTERNAL_CAMERA_ACTOR_H__
+#endif // DALI_INTERNAL_CAMERA_ACTOR_H
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
samplerContainer(),
textureContainer(),
frameBufferContainer(),
- renderersAdded( false ),
+ lastFrameWasRendered( false ),
programController( glAbstraction )
{
}
PropertyBufferOwnerContainer propertyBufferContainer; ///< List of owned property buffers
GeometryOwnerContainer geometryContainer; ///< List of owned Geometries
- bool renderersAdded;
+ bool lastFrameWasRendered; ///< Keeps track of the last frame being rendered due to having render instructions
RenderTrackerContainer mRenderTrackers; ///< List of render trackers
renderer->Initialize( mImpl->context );
mImpl->rendererContainer.PushBack( renderer.Release() );
-
- if( !mImpl->renderersAdded )
- {
- mImpl->renderersAdded = true;
- }
}
void RenderManager::RemoveRenderer( Render::Renderer* renderer )
// Process messages queued during previous update
mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
- // switch rendering to adaptor provided (default) buffer
- mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
-
- mImpl->context.Viewport( mImpl->defaultSurfaceRect.x,
- mImpl->defaultSurfaceRect.y,
- mImpl->defaultSurfaceRect.width,
- mImpl->defaultSurfaceRect.height );
-
- mImpl->context.ClearColor( mImpl->backgroundColor.r,
- mImpl->backgroundColor.g,
- mImpl->backgroundColor.b,
- mImpl->backgroundColor.a );
-
- mImpl->context.ClearStencil( 0 );
-
- // Clear the entire color, depth and stencil buffers for the default framebuffer.
- // It is important to clear all 3 buffers, for performance on deferred renderers like Mali
- // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
- // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
- mImpl->context.SetScissorTest( false );
- mImpl->context.ColorMask( true );
- mImpl->context.DepthMask( true );
- mImpl->context.StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
- mImpl->context.Clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, Context::FORCE_CLEAR );
-
- // reset the program matrices for all programs once per frame
- // this ensures we will set view and projection matrix once per program per camera
- mImpl->programController.ResetProgramMatrices();
-
- size_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
- for ( size_t i = 0; i < count; ++i )
+ const size_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
+ const bool haveInstructions = count > 0u;
+
+ // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required).
+ if( haveInstructions || mImpl->lastFrameWasRendered )
{
- RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
+ // switch rendering to adaptor provided (default) buffer
+ mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
- DoRender( instruction );
- }
- GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
- mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
+ mImpl->context.Viewport( mImpl->defaultSurfaceRect.x,
+ mImpl->defaultSurfaceRect.y,
+ mImpl->defaultSurfaceRect.width,
+ mImpl->defaultSurfaceRect.height );
- mImpl->UpdateTrackers();
+ mImpl->context.ClearColor( mImpl->backgroundColor.r,
+ mImpl->backgroundColor.g,
+ mImpl->backgroundColor.b,
+ mImpl->backgroundColor.a );
- //Notify RenderGeometries that rendering has finished
- for ( GeometryOwnerIter iter = mImpl->geometryContainer.Begin(); iter != mImpl->geometryContainer.End(); ++iter )
- {
- (*iter)->OnRenderFinished();
+ mImpl->context.ClearStencil( 0 );
+
+ // Clear the entire color, depth and stencil buffers for the default framebuffer.
+ // It is important to clear all 3 buffers, for performance on deferred renderers like Mali
+ // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
+ // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
+ mImpl->context.SetScissorTest( false );
+ mImpl->context.ColorMask( true );
+ mImpl->context.DepthMask( true );
+ mImpl->context.StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
+ mImpl->context.Clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, Context::FORCE_CLEAR );
+
+ // reset the program matrices for all programs once per frame
+ // this ensures we will set view and projection matrix once per program per camera
+ mImpl->programController.ResetProgramMatrices();
+
+ for( size_t i = 0; i < count; ++i )
+ {
+ RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
+
+ DoRender( instruction );
+ }
+
+ GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
+ mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
+
+ mImpl->UpdateTrackers();
+
+ //Notify RenderGeometries that rendering has finished
+ for ( GeometryOwnerIter iter = mImpl->geometryContainer.Begin(); iter != mImpl->geometryContainer.End(); ++iter )
+ {
+ (*iter)->OnRenderFinished();
+ }
}
+ // If this frame was rendered due to instructions existing, we mark this so we know to clear the next frame.
+ mImpl->lastFrameWasRendered = haveInstructions;
+
/**
* The rendering has finished; swap to the next buffer.
* Ideally the update has just finished using this buffer; otherwise the render thread
frameCounter( 0 ),
animationFinishedDuringUpdate( false ),
previousUpdateScene( false ),
- renderTaskWaiting( false )
+ renderTaskWaiting( false ),
+ renderersAdded( false )
{
sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
+ bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
private:
{
renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
mImpl->renderers.PushBack( renderer.Release() );
+ mImpl->renderersAdded = true;
}
void UpdateManager::RemoveRenderer( Renderer* renderer )
//Process Property Notifications
ProcessPropertyNotifications( bufferIndex );
- //Process the RenderTasks; this creates the instructions for rendering the next frame.
- //reset the update buffer index and make sure there is enough room in the instruction container
- mImpl->renderInstructions.ResetAndReserve( bufferIndex,
- mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
+ //Update cameras
+ const CameraOwner::Iterator endCameraIterator = mImpl->cameras.End();
+ for( CameraOwner::Iterator cameraIterator = mImpl->cameras.Begin(); endCameraIterator != cameraIterator; ++cameraIterator )
+ {
+ ( *cameraIterator )->Update( bufferIndex );
+ }
- if ( NULL != mImpl->root )
+ //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
+ //reset the update buffer index and make sure there is enough room in the instruction container
+ if( mImpl->renderersAdded )
{
- mImpl->renderTaskProcessor.Process( bufferIndex,
- mImpl->taskList,
- *mImpl->root,
- mImpl->sortedLayers,
- mImpl->renderInstructions );
-
- // Process the system-level RenderTasks last
- if ( NULL != mImpl->systemLevelRoot )
+ mImpl->renderInstructions.ResetAndReserve( bufferIndex,
+ mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
+
+ if ( NULL != mImpl->root )
{
mImpl->renderTaskProcessor.Process( bufferIndex,
- mImpl->systemLevelTaskList,
- *mImpl->systemLevelRoot,
- mImpl->systemLevelSortedLayers,
+ mImpl->taskList,
+ *mImpl->root,
+ mImpl->sortedLayers,
mImpl->renderInstructions );
+
+ // Process the system-level RenderTasks last
+ if ( NULL != mImpl->systemLevelRoot )
+ {
+ mImpl->renderTaskProcessor.Process( bufferIndex,
+ mImpl->systemLevelTaskList,
+ *mImpl->systemLevelRoot,
+ mImpl->systemLevelSortedLayers,
+ mImpl->renderInstructions );
+ }
}
}
}
/**
* Add a camera on scene
- * @param[in] camera to add
+ * @param[in] camera The camera to add
*/
void AddCamera( OwnerPointer< Camera >& camera );
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
}
+void Camera::SetNode( const Node* node )
+{
+ mNode = node;
+}
+
void Camera::SetType( Dali::Camera::Type type )
{
mType = type;
return &mViewMatrix;
}
-void Camera::Update( BufferIndex updateBufferIndex, const Node& owningNode )
+void Camera::Update( BufferIndex updateBufferIndex )
{
// if owning node has changes in world position we need to update camera for next 2 frames
- if( owningNode.IsLocalMatrixDirty() )
+ if( mNode->IsLocalMatrixDirty() )
{
mUpdateViewFlag = UPDATE_COUNT;
}
- if( owningNode.GetDirtyFlags() & VisibleFlag )
+ if( mNode->GetDirtyFlags() & VisibleFlag )
{
// If the visibility changes, the projection matrix needs to be re-calculated.
// It may happen the first time an actor is rendered it's rendered only once and becomes invisible,
}
// if either matrix changed, we need to recalculate the inverse matrix for hit testing to work
- unsigned int viewUpdateCount = UpdateViewMatrix( updateBufferIndex, owningNode );
+ unsigned int viewUpdateCount = UpdateViewMatrix( updateBufferIndex );
unsigned int projectionUpdateCount = UpdateProjection( updateBufferIndex );
// if model or view matrix changed we need to either recalculate the inverse VP or copy previous
return 0u != mUpdateViewFlag;
}
-unsigned int Camera::UpdateViewMatrix( BufferIndex updateBufferIndex, const Node& owningNode )
+unsigned int Camera::UpdateViewMatrix( BufferIndex updateBufferIndex )
{
unsigned int retval( mUpdateViewFlag );
if( 0u != mUpdateViewFlag )
case Dali::Camera::FREE_LOOK:
{
Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex );
- viewMatrix = owningNode.GetWorldMatrix( updateBufferIndex );
+ viewMatrix = mNode->GetWorldMatrix( updateBufferIndex );
viewMatrix.Invert();
mViewMatrix.SetDirty( updateBufferIndex );
break;
// camera orientation constrained to look at a target
case Dali::Camera::LOOK_AT_TARGET:
{
- const Matrix& owningNodeMatrix( owningNode.GetWorldMatrix( updateBufferIndex ) );
+ const Matrix& owningNodeMatrix( mNode->GetWorldMatrix( updateBufferIndex ) );
Vector3 position, scale;
Quaternion orientation;
owningNodeMatrix.GetTransformComponents( position, orientation, scale );
-#ifndef __DALI_INTERNAL_SCENE_GRAPH_CAMERA_H__
-#define __DALI_INTERNAL_SCENE_GRAPH_CAMERA_H__
+#ifndef DALI_INTERNAL_SCENE_GRAPH_CAMERA_H
+#define DALI_INTERNAL_SCENE_GRAPH_CAMERA_H
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
~Camera();
/**
+ * Set the node this scene graph camera belongs to.
+ * @param[in] node The owning node.
+ */
+ void SetNode( const Node* node );
+
+ /**
* @copydoc Dali::Internal::CameraActor::SetType
*/
void SetType( Dali::Camera::Type type );
* Updates view and projection matrices.
* Called by the render task using the camera
* @param[in] updateBufferIndex The buffer to read from.
- * @param[in] owningNode The node that owns the camera
*/
- void Update( BufferIndex updateBufferIndex, const Node& owningNode );
+ void Update( BufferIndex updateBufferIndex );
/**
* @return true if the view matrix of camera is updated this or the previous frame
/**
* Recalculates the view matrix.
* @param[in] bufferIndex The current update buffer index.
- * @param[in] owningNode to use for calculations.
* @return count how many frames ago the matrix was changed.
*/
- unsigned int UpdateViewMatrix( BufferIndex updateBufferIndex, const Node& owningNode );
+ unsigned int UpdateViewMatrix( BufferIndex updateBufferIndex );
/**
* Recalculates the projection matrix.
unsigned int mUpdateViewFlag; ///< This is non-zero if the view matrix requires an update
unsigned int mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update
+ const Node* mNode; ///< The node this scene graph camera belongs to
public: // PROPERTIES
Dali::Camera::Type mType; // Non-animatable
} // namespace Dali
-#endif // __DALI_INTERNAL_SCENE_GRAPH_CAMERA_H__
+#endif // DALI_INTERNAL_SCENE_GRAPH_CAMERA_H
// If the source node of the render task is invisible we should still render
// We want the render task to complete and possible clear colors to happen
- // Check source node
- if ( NULL == mSourceNode ||
- ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
+ // Check the source node.
+ if( NULL == mSourceNode ||
+ ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
{
- TASK_LOG_FMT(Debug::General, " =F No source actor FC:%d\n", mFrameCounter );
+ TASK_LOG_FMT( Debug::General, " Source actor not on stage. Frame counter: %d\n", mFrameCounter );
- // Source node is missing or disconnected
+ // The source node is missing or disconnected.
return false;
}
// Check camera node
- if ( NULL == mCameraNode ||
- NULL == mCameraNode->GetParent() ||
- NULL == mCamera )
+ if( NULL == mCameraNode ||
+ NULL == mCameraNode->GetParent() ||
+ NULL == mCamera )
{
- // Camera node is missing or disconnected
+ // The camera node is missing or disconnected.
TASK_LOG_FMT(Debug::General, " =F No Camera FC:%d\n", mFrameCounter );
-
return false;
}
- mCamera->Update( updateBufferIndex, *mCameraNode );
return true;
}