Integration::StencilBufferAvailable::TRUE );
mCore->ContextCreated();
- mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
+ mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight, 0, false );
mCore->SetDpi( mDpi.x, mDpi.y );
Dali::Integration::Log::LogFunction logFunction(&TestApplication::LogMessage);
mSurfaceWidth = width;
mSurfaceHeight = height;
- mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
+ mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight, 0, false );
}
void TestApplication::SetTopMargin( unsigned int margin )
mImpl->RecoverFromContextLoss();
}
-void Core::SurfaceResized(unsigned int width, unsigned int height)
+void Core::SurfaceResized( unsigned int width, unsigned int height, int orientation, bool forceUpdate )
{
- mImpl->SurfaceResized(width, height);
-}
-
-void Core::SurfaceResized( unsigned int width, unsigned int height, int orientation )
-{
- mImpl->SurfaceResized(width, height, orientation);
+ mImpl->SurfaceResized(width, height, orientation, forceUpdate );
}
void Core::SetTopMargin( unsigned int margin )
void RecoverFromContextLoss();
/**
- * Notify the Core that the GL surface has been resized.
- * This should be done at least once i.e. after the first call to ContextCreated().
- * The Core will use the surface size for camera calculations, and to set the GL viewport.
- * Multi-threading note: this method should be called from the main thread
- * @param[in] width The new surface width.
- * @param[in] height The new surface height.
- */
- void SurfaceResized(unsigned int width, unsigned int height);
-
-
- /**
* Notify the Core that the GL surface has been resized and rotated.
* This should be done at least once i.e. after the first call to ContextCreated().
* The Core will use the surface size or orientation for camera calculations, and to set the GL viewport.
* @param[in] width The new surface width.
* @param[in] height The new surface height.
* @param[in] orientation The new surface orientation.
+ * @param[in] forceUpdate The flag to update force.
*/
- void SurfaceResized( unsigned int width, unsigned int height, int orientation );
+ void SurfaceResized( unsigned int width, unsigned int height, int orientation, bool forceUpdate );
/**
* Notify the Core about the top margin size.
mRenderManager->ContextDestroyed();
}
-void Core::SurfaceResized( unsigned int width, unsigned int height )
+void Core::SurfaceResized( unsigned int width, unsigned int height, int orientation, bool forceUpdate )
{
- mStage->SurfaceResized( width, height );
-
- // The stage-size may be less than surface-size (reduced by top-margin)
- Vector2 size = mStage->GetSize();
- mRelayoutController->SetStageSize( size.width, size.height );
-}
-
-void Core::SurfaceResized( unsigned int width, unsigned int height, int orientation )
-{
- mStage->SurfaceResized( width, height, orientation );
+ mStage->SurfaceResized( width, height, orientation, forceUpdate );
// The stage-size may be less than surface-size (reduced by top-margin)
Vector2 size = mStage->GetSize();
void RecoverFromContextLoss();
/**
- * @copydoc Dali::Integration::Core::SurfaceResized(unsigned int, unsigned int)
+ * @copydoc Dali::Integration::Core::SurfaceResized(unsigned int, unsigned int, int orientation, bool forceUpdate )
*/
- void SurfaceResized(unsigned int width, unsigned int height);
-
- /**
- * @copydoc Dali::Integration::Core::SurfaceResized(unsigned int, unsigned int, int orientation)
- */
- void SurfaceResized( unsigned int width, unsigned int height, int orientation );
+ void SurfaceResized( unsigned int width, unsigned int height, int orientation, bool forceUpdate );
/**
* @copydoc Dali::Integration::Core::SetTopMargin( unsigned int margin )
return mSceneObject;
}
+void CameraActor::RotateProjection( int rotationAngle )
+{
+ // sceneObject is being used in a separate thread; queue a message to set
+ RotateProjectionMessage( GetEventThreadServices(), *mSceneObject, rotationAngle );
+}
+
unsigned int CameraActor::GetDefaultPropertyCount() const
{
return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
*/
const SceneGraph::Camera* GetCamera() const;
+ /**
+ * Rotate the projection.
+ * It is used in case that the target buffer direction is different from the window direction.
+ * @param [in] rotationAngle The rotation angle
+ */
+ void RotateProjection( int rotationAngle );
+
public: // properties
/**
// Create the default render-task
Dali::RenderTask defaultRenderTask = mRenderTaskList->CreateTask();
-
- // init current default camera orientation
- mNeedToRotation = false;
- mCurrentOrientation = 0;
}
void Stage::Uninitialize()
mRootLayer->Remove( actor );
}
-void Stage::SurfaceResized( float width, float height )
+void Stage::SurfaceResized( float width, float height, int orientation, bool forceUpdate )
{
if( ( fabs( width - mSurfaceSize.width ) > Math::MACHINE_EPSILON_1000 ) || ( fabs( height - mSurfaceSize.height ) > Math::MACHINE_EPSILON_1000 )
- || mNeedToRotation )
+ || ( orientation != mOrientation ) || ( forceUpdate ) )
{
- mNeedToRotation = false;
-
mSurfaceSize.width = width;
mSurfaceSize.height = height;
+ mOrientation = orientation;
// Internally we want to report the actual size of the stage.
mSize.width = width;
// Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
mDefaultCamera->SetPerspectiveProjection( mSurfaceSize );
+ mDefaultCamera->RotateProjection( orientation );
+
+ if( mSystemOverlay )
+ {
+ mSystemOverlay->GetImpl()->GetDefaultCameraActor().RotateProjection( orientation );
+ }
// Adjust the camera height to allow for top-margin
SetDefaultCameraPosition();
mSystemOverlay->GetImpl()->SetSize( width, height );
}
- if( mCurrentOrientation == 90 || mCurrentOrientation == 270)
- {
- SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int>( 0, 0, height, width ) );
- }
- else
- {
- SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int>( 0, 0, width, height ) );
- }
+ SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int>( 0, 0, width, height ) );
+ SetDefaultSurfaceOrientationMessage( mUpdateManager, orientation );
// if single render task to screen then set its viewport parameters
if( 1 == mRenderTaskList->GetTaskCount() )
if(!defaultRenderTask.GetTargetFrameBuffer())
{
- if( mCurrentOrientation == 90 || mCurrentOrientation == 270)
- {
- defaultRenderTask.SetViewport( Viewport(0, 0, height, width) );
- }
- else
- {
- defaultRenderTask.SetViewport( Viewport(0, 0, width, height) );
- }
+ defaultRenderTask.SetViewport( Viewport(0, 0, width, height) );
}
}
}
}
-void Stage::SurfaceResized( float width, float height, int orientation )
-{
- // Calculates the angle of rotation.
- int rotDelta = ( 360 + orientation - mCurrentOrientation ) % 360;
- Quaternion rotateAngle;
-
- switch( rotDelta )
- {
- case 90:
- {
- rotateAngle = Quaternion( Dali::ANGLE_270, Vector3::ZAXIS );
- break;
- }
- case 270:
- {
- rotateAngle = Quaternion( Dali::ANGLE_90, Vector3::ZAXIS );
- break;
- }
- case 180:
- {
- rotateAngle = Quaternion( Dali::ANGLE_180, Vector3::ZAXIS );
- break;
- }
- default:
- rotateAngle = Quaternion( Dali::ANGLE_0, Vector3::ZAXIS );
- break;
- }
-
- // set current orientation
- mCurrentOrientation = orientation;
- if( rotDelta )
- {
- mNeedToRotation = true;
- }
-
- // do surface resized
- SurfaceResized( width, height );
-
- // If we need to rotate, rotate the camera.
- if( rotDelta )
- {
- // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position depending on the orientation
- if( mCurrentOrientation == 90 || mCurrentOrientation == 270 )
- {
- mDefaultCamera->SetPerspectiveProjection( Vector2( height, width ) );
- if( mSystemOverlay )
- {
- mSystemOverlay->GetImpl()->GetDefaultCameraActor().SetPerspectiveProjection( Vector2( height, width ) );
- }
- }
-
- mDefaultCamera->RotateBy( rotateAngle );
-
- if( mSystemOverlay )
- {
- mSystemOverlay->GetImpl()->GetDefaultCameraActor().RotateBy( rotateAngle );
- }
- }
-}
-
Vector2 Stage::GetSize() const
{
return mSize;
mBackgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
mViewMode( MONO ),
mStereoBase( DEFAULT_STEREO_BASE ),
+ mOrientation( 0 ),
mTopMargin( 0 ),
mSystemOverlay( NULL ),
mRenderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
mDepthTreeDirty( false ),
mForceNextUpdate( false ),
- mRenderToFbo( false ),
- mNeedToRotation( false ),
- mCurrentOrientation( 0 )
+ mRenderToFbo( false )
{
}
void Remove( Actor& actor );
/**
- * Used to calculate the size of the stage and indirectly, the root actor.
- * @param [in] width The new surface width.
- * @param [in] height The new surface height.
- */
- void SurfaceResized( float width, float height );
-
- /**
* Used to calculate the size and orientation of the stage and indirectly, the root actor.
* @param [in] width The new surface width.
* @param [in] height The new surface height.
* @param [in] orientation The new surface orientation.
+ * @param [in] forceUpdate The flag to update force.
*/
- void SurfaceResized( float width, float height, int orientation );
+ void SurfaceResized( float width, float height, int orientation, bool forceUpdate );
/**
* Sets the top margin size.
ViewMode mViewMode;
float mStereoBase;
+ int mOrientation;
+
unsigned int mTopMargin;
Vector2 mDpi;
bool mDepthTreeDirty:1; ///< True if the depth tree needs recalculating
bool mForceNextUpdate:1; ///< True if the next rendering is really required.
bool mRenderToFbo:1; ///< Whether to render to a Frame Buffer Object.
-
- bool mNeedToRotation:1;
- int mCurrentOrientation;
};
} // namespace Internal
const Matrix* GetProjectionMatrix( BufferIndex index ) const
{
// inlined as this is called once per frame per render instruction
- return &mCamera->GetProjectionMatrix( index );
+ return &mCamera->GetFinalProjectionMatrix( index );
}
private:
lastFrameWasRendered( false ),
programController( glAbstraction ),
depthBufferAvailable( depthBufferAvailableParam ),
- stencilBufferAvailable( stencilBufferAvailableParam )
+ stencilBufferAvailable( stencilBufferAvailableParam ),
+ defaultSurfaceOrientation( 0 )
{
}
Integration::DepthBufferAvailable depthBufferAvailable; ///< Whether the depth buffer is available
Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
+ int defaultSurfaceOrientation; ///< defaultSurfaceOrientation for the default surface we are rendering to
+
};
RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
mImpl->defaultSurfaceRect = rect;
}
+void RenderManager::SetDefaultSurfaceOrientation( int orientation )
+{
+ mImpl->defaultSurfaceOrientation = orientation;
+}
+
void RenderManager::AddRenderer( OwnerPointer< Render::Renderer >& renderer )
{
// Initialize the renderer as we are now in render thread
{
viewportRect = mImpl->defaultSurfaceRect;
}
+
+ if ( mImpl->defaultSurfaceOrientation == 90 || mImpl->defaultSurfaceOrientation == 270 )
+ {
+ int temp = viewportRect.width;
+ viewportRect.width = viewportRect.height;
+ viewportRect.height = temp;
+ }
}
mImpl->context.Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
void SetDefaultSurfaceRect( const Rect<int>& rect );
/**
+ * Returns the orintation for the default surface (probably the application window).
+ * @return Orientation for the surface.
+ */
+ void SetDefaultSurfaceOrientation( int orientation );
+
+ /**
* Add a Renderer to the render manager.
* @param[in] renderer The renderer to add.
* @post renderer is owned by RenderManager
new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
}
+void UpdateManager::SetDefaultSurfaceOrientation( int orientation )
+{
+ typedef MessageValue1< RenderManager, int > DerivedType;
+
+ // Reserve some memory inside the render queue
+ unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+ // Construct message in the render queue memory; note that delete should not be called on the return value
+ new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceOrientation, orientation );
+}
+
void UpdateManager::KeepRendering( float durationSeconds )
{
mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
void SetDefaultSurfaceRect( const Rect<int>& rect );
/**
+ * Set the default surface orientation.
+ * @param[in] orientation The orientation value representing the surface.
+ */
+ void SetDefaultSurfaceOrientation( int orientation );
+
+ /**
* @copydoc Dali::Stage::KeepRendering()
*/
void KeepRendering( float durationSeconds );
new (slot) LocalType( &manager, &UpdateManager::SetDefaultSurfaceRect, rect );
}
+inline void SetDefaultSurfaceOrientationMessage( UpdateManager& manager, int orientation )
+{
+ typedef MessageValue1< UpdateManager, int > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &manager, &UpdateManager::SetDefaultSurfaceOrientation, orientation );
+}
+
inline void KeepRenderingMessage( UpdateManager& manager, float durationSeconds )
{
typedef MessageValue1< UpdateManager, float > LocalType;
Camera::Camera()
: mUpdateViewFlag( UPDATE_COUNT ),
mUpdateProjectionFlag( UPDATE_COUNT ),
+ mProjectionRotation( 0 ),
mNode( NULL ),
mType( DEFAULT_TYPE ),
mProjectionMode( DEFAULT_MODE ),
mTargetPosition( DEFAULT_TARGET_POSITION ),
mViewMatrix(),
mProjectionMatrix(),
- mInverseViewProjection( Matrix::IDENTITY )
+ mInverseViewProjection( Matrix::IDENTITY ),
+ mFinalProjection( Matrix::IDENTITY )
{
}
mUpdateViewFlag = UPDATE_COUNT;
}
+void Camera::RotateProjection( int rotationAngle )
+{
+ mProjectionRotation = rotationAngle;
+ mUpdateViewFlag = UPDATE_COUNT;
+}
+
const Matrix& Camera::GetProjectionMatrix( BufferIndex bufferIndex ) const
{
return mProjectionMatrix[ bufferIndex ];
return mInverseViewProjection[ bufferIndex ];
}
+const Matrix& Camera::GetFinalProjectionMatrix( BufferIndex bufferIndex ) const
+{
+ return mFinalProjection[ bufferIndex ];
+}
+
const PropertyInputImpl* Camera::GetProjectionMatrix() const
{
return &mProjectionMatrix;
}
mProjectionMatrix.SetDirty( updateBufferIndex );
+
+ Matrix &finalProjection = mFinalProjection[ updateBufferIndex ];
+ finalProjection.SetIdentity();
+
+ Quaternion rotationAngle;
+ switch( mProjectionRotation )
+ {
+ case 90:
+ {
+ rotationAngle = Quaternion( Dali::ANGLE_90, Vector3::ZAXIS );
+ break;
+ }
+ case 180:
+ {
+ rotationAngle = Quaternion( Dali::ANGLE_180, Vector3::ZAXIS );
+ break;
+ }
+ case 270:
+ {
+ rotationAngle = Quaternion( Dali::ANGLE_270, Vector3::ZAXIS );
+ break;
+ }
+ default:
+ rotationAngle = Quaternion( Dali::ANGLE_0, Vector3::ZAXIS );
+ break;
+ }
+
+ Matrix rotation;
+ rotation.SetIdentity();
+ rotation.SetTransformComponents( Vector3( 1.0f, 1.0f, 1.0f ), rotationAngle, Vector3( 0.0f, 0.0f, 0.0f ) );
+
+ Matrix::Multiply( finalProjection, mProjectionMatrix.Get( updateBufferIndex ), rotation );
}
--mUpdateProjectionFlag;
}
void SetTargetPosition( const Vector3& targetPosition );
/**
+ * @copydoc Dali::Internal::CameraActor::RotateProjection
+ */
+ void RotateProjection( int rotationAngle );
+
+ /**
* Retrieve the view-matrix; this is double buffered for input handling.
* @param[in] bufferIndex The buffer to read from.
* @return The view-matrix.
const Matrix& GetInverseViewProjectionMatrix( BufferIndex bufferIndex ) const;
/**
+ * Retrieve the final projection-matrix; this is double buffered for input handling.
+ * @param[in] bufferIndex The buffer to read from.
+ * @return The projection-matrix that should be used to render.
+ */
+ const Matrix& GetFinalProjectionMatrix( BufferIndex bufferIndex ) const;
+
+ /**
* Retrieve the projection-matrix property querying interface.
* @pre The camera is on-stage.
* @return The projection-matrix property querying interface.
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
+ int mProjectionRotation; ///< The rotaion angle of the projection
const Node* mNode; ///< The node this scene graph camera belongs to
public: // PROPERTIES
DoubleBuffered< FrustumPlanes > mFrustum; ///< Clipping frustum; double buffered for input handling
DoubleBuffered< Matrix > mInverseViewProjection; ///< Inverted viewprojection; double buffered for input handling
+ DoubleBuffered< Matrix > mFinalProjection; ///< Final projection matrix; double buffered for input handling
};
new (slot) LocalType( &camera, &Camera::SetInvertYAxis, parameter );
}
+inline void RotateProjectionMessage( EventThreadServices& eventThreadServices, const Camera& camera, int parameter )
+{
+ typedef MessageValue1< Camera, int > LocalType;
+
+ // Reserve some memory inside the message queue
+ unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &camera, &Camera::RotateProjection, parameter );
+}
+
} // namespace SceneGraph
} // namespace Internal
mRequiresSync = requiresSync;
}
-
RenderTask::RenderTask()
: mViewportPosition( Vector2::ZERO),
mViewportSize( Vector2::ZERO),
unsigned int mFrameCounter; ///< counter for rendering every N frames
unsigned int mRenderedOnceCounter; ///< Incremented whenever state changes to RENDERED_ONCE_AND_NOTIFIED
+
bool mRequiresSync; ///< Whether sync is needed to track the render
};