[Tizen] Add screen and client rotation itself function
authorJoogab Yun <joogab.yun@samsung.com>
Mon, 12 Aug 2019 04:39:42 +0000 (13:39 +0900)
committerJoogab Yun <joogab.yun@samsung.com>
Mon, 12 Aug 2019 04:39:46 +0000 (13:39 +0900)
This reverts commit a06eafa8babd0523af3b6935e2c900347f96bfb8.

Change-Id: I42c0f2e88d9ab431373f458cb6e5c15e2d1e1607

19 files changed:
automated-tests/src/dali/dali-test-suite-utils/test-render-surface.cpp
automated-tests/src/dali/dali-test-suite-utils/test-render-surface.h
automated-tests/src/dali/utc-Dali-Scene.cpp
dali/integration-api/render-surface.h
dali/integration-api/scene.cpp
dali/integration-api/scene.h
dali/internal/event/actors/camera-actor-impl.cpp
dali/internal/event/actors/camera-actor-impl.h
dali/internal/event/common/scene-impl.cpp
dali/internal/event/common/scene-impl.h
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/render-algorithms.h
dali/internal/render/common/render-instruction.h
dali/internal/render/common/render-manager.cpp
dali/internal/render/common/render-manager.h
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/render-tasks/scene-graph-camera.cpp
dali/internal/update/render-tasks/scene-graph-camera.h

index 332d77e..066b37e 100644 (file)
@@ -40,6 +40,11 @@ void TestRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVe
   dpiHorizontal = dpiVertical = 96;
 };
 
+int TestRenderSurface::GetOrientation() const
+{
+  return 0;
+};
+
 void TestRenderSurface::InitializeGraphics()
 {
 }
index fba89c2..be38d00 100644 (file)
@@ -53,6 +53,11 @@ public:
   virtual void GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical );
 
   /**
+   * @copydoc Dali::Integration::RenderSurface::GetOrientation
+   */
+  virtual int GetOrientation() const;
+
+  /**
    * @copydoc Dali::Integration::RenderSurface::InitializeGraphics
    */
   virtual void InitializeGraphics();
index 8508728..e393366 100644 (file)
@@ -982,7 +982,7 @@ int UtcDaliSceneSurfaceResizedDefaultScene(void)
   Vector2 newSize( 1000.0f, 2000.0f );
   DALI_TEST_CHECK( stage.GetSize() != newSize );
   defaultSurface->MoveResize( PositionSize( 0, 0, newSize.width, newSize.height ) );
-  defaultScene.SurfaceResized();
+  defaultScene.SurfaceResized( false );
 
   DALI_TEST_EQUALS( stage.GetSize(), newSize, TEST_LOCATION );
   DALI_TEST_EQUALS( defaultScene.GetSize(), newSize, TEST_LOCATION );
@@ -1130,7 +1130,11 @@ int UtcDaliSceneSurfaceResizedAdditionalScene(void)
   Vector2 originalSurfaceSize( 500.0f, 1000.0f );
 
   TestRenderSurface surface( PositionSize( 0.0f, 0.0f, originalSurfaceSize.width, originalSurfaceSize.height ) );
+<<<<<<< HEAD
   auto scene = Integration::Scene::New( surface );
+=======
+  scene.SetSurface( surface, false );
+>>>>>>> e6df4fb... Support Client and Screen Rotation
 
   // Ensure stage size does NOT match the surface size
   auto stage = Stage::GetCurrent();
@@ -1142,7 +1146,7 @@ int UtcDaliSceneSurfaceResizedAdditionalScene(void)
   Vector2 newSize( 1000.0f, 2000.0f );
   DALI_TEST_CHECK( stage.GetSize() != newSize );
   surface.MoveResize( PositionSize( 0, 0, newSize.width, newSize.height ) );
-  scene.SurfaceResized();
+  scene.SurfaceResized( false );
 
   // Ensure the stage hasn't been resized
   DALI_TEST_EQUALS( stage.GetSize(), stageSize, TEST_LOCATION );
index 2270fc2..b0a3b37 100644 (file)
@@ -103,6 +103,12 @@ public:
   virtual void GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ) = 0;
 
   /**
+   * @brief Return the orientation of the surface.
+   * @return The orientation
+   */
+  virtual int GetOrientation() const = 0;
+
+  /**
    * @brief InitializeGraphics the platform specific graphics surface interfaces
    */
   virtual void InitializeGraphics() = 0;
index 8fef6db..5126377 100644 (file)
@@ -124,9 +124,9 @@ void Scene::SetSurface( Integration::RenderSurface& surface )
   GetImplementation(*this).SetSurface( surface );
 }
 
-void Scene::SurfaceResized()
+void Scene::SurfaceResized( bool forceUpdate )
 {
-  GetImplementation( *this ).SurfaceResized();
+  GetImplementation( *this ).SurfaceResized( forceUpdate );
 }
 
 Integration::RenderSurface* Scene::GetSurface() const
index dca7cbc..0d8d044 100755 (executable)
@@ -205,7 +205,7 @@ public:
   /**
    * @brief Informs the scene that the set surface has been resized.
    */
-  void SurfaceResized();
+  void SurfaceResized( bool forceUpdate );
 
   /**
    * @brief Gets the rendering surface bound to the scene
index ae63c9f..715781e 100644 (file)
@@ -502,6 +502,12 @@ const SceneGraph::Camera* CameraActor::GetCamera() const
   return mSceneObject;
 }
 
+void CameraActor::RotateProjection( int rotationAngle )
+{
+  // sceneObject is being used in a separate thread; queue a message to set
+  RotateProjectionMessage( GetEventThreadServices(), *mSceneObject, rotationAngle );
+}
+
 void CameraActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
 {
   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
index 1694ba3..56a39e5 100644 (file)
@@ -195,6 +195,13 @@ public:
    */
   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
 
   /**
index c14470d..917f76a 100644 (file)
@@ -63,6 +63,7 @@ Scene::Scene()
   mSize(), // Don't set the proper value here, this will be set when the surface is set later
   mDpi(),
   mBackgroundColor( DEFAULT_BACKGROUND_COLOR ),
+  mSurfaceOrientation( 0 ),
   mDepthTreeDirty( false ),
   mEventProcessor( *this, ThreadLocalStorage::GetInternal()->GetGestureEventProcessor() )
 {
@@ -211,33 +212,39 @@ void Scene::SetSurface( Integration::RenderSurface& surface )
     mFrameBuffer = Dali::Internal::FrameBuffer::New( surface, Dali::FrameBuffer::Attachment::NONE );
     defaultRenderTask->SetFrameBuffer( mFrameBuffer );
 
-    SurfaceResized();
+    SurfaceResized( false );
   }
 }
 
-void Scene::SurfaceResized()
+void Scene::SurfaceResized( bool forceUpdate )
 {
   if( mSurface )
   {
     const PositionSize surfacePositionSize = mSurface->GetPositionSize();
     const float fWidth = static_cast< float >( surfacePositionSize.width );
     const float fHeight = static_cast< float >( surfacePositionSize.height );
+    const int orientation = mSurface->GetOrientation();
 
-    if( ( fabsf( mSize.width - fWidth ) > Math::MACHINE_EPSILON_1 ) || ( fabsf( mSize.height - fHeight ) > Math::MACHINE_EPSILON_1 ) )
+    if( ( ( fabsf( mSize.width - fWidth ) > Math::MACHINE_EPSILON_1 ) || ( fabsf( mSize.height - fHeight ) > Math::MACHINE_EPSILON_1 ) )
+            || ( orientation != mSurfaceOrientation )
+            || ( forceUpdate ) )
     {
       Rect< int32_t > newSize( 0, 0, static_cast< int32_t >( surfacePositionSize.width ), static_cast< int32_t >( surfacePositionSize.height ) ); // truncated
 
       mSize.width = fWidth;
       mSize.height = fHeight;
+      mSurfaceOrientation = orientation;
 
       // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
       mDefaultCamera->SetPerspectiveProjection( mSize );
+      mDefaultCamera->RotateProjection( mSurfaceOrientation );
 
       mRootLayer->SetSize( mSize.width, mSize.height );
 
       ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
       SceneGraph::UpdateManager& updateManager = tls->GetUpdateManager();
       SetDefaultSurfaceRectMessage( updateManager, newSize );
+      SetDefaultSurfaceOrientationMessage( updateManager, mSurfaceOrientation );
 
       // set default render-task viewport parameters
       RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u );
index f9db963..f339030 100644 (file)
@@ -122,7 +122,7 @@ public:
   /**
    * Notify the surface has been resized.
    */
-  void SurfaceResized();
+  void SurfaceResized( bool forceUpdate );
 
   /**
    * Notify the surface has been deleted.
@@ -285,6 +285,9 @@ private:
 
   Vector4 mBackgroundColor;
 
+  // The SurfaceOrientation
+  int mSurfaceOrientation;
+
   LayerPtr mRootLayer;
 
   // Ordered list of currently on-stage layers
index 0061b87..a8d2162 100644 (file)
@@ -231,7 +231,7 @@ inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool dep
  * @param[in]     item                     The current RenderItem about to be rendered
  * @param[in]     context                  The context
  */
-inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Context& context )
+inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Context& context, int orientation )
 {
   // Get the number of child scissors in the stack (do not include layer or root box).
   size_t childStackDepth = mScissorStack.size() - 1u;
@@ -292,7 +292,30 @@ inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Cont
     if( scissorEnabled )
     {
       ClippingBox useScissorBox( mScissorStack.back() );
-      context.Scissor( useScissorBox.x, useScissorBox.y, useScissorBox.width, useScissorBox.height );
+      GLint x = useScissorBox.x;
+      GLint y = useScissorBox.y;
+      if( orientation == 90 )
+      {
+        x = mViewportRectangle.height - (useScissorBox.y + useScissorBox.height);
+        y = useScissorBox.x;
+        context.Scissor( x, y, useScissorBox.height, useScissorBox.width );
+      }
+      else if( orientation == 180 )
+      {
+        x = mViewportRectangle.width - (useScissorBox.x + useScissorBox.width);
+        y = mViewportRectangle.height - (useScissorBox.y + useScissorBox.height);
+        context.Scissor( x, y, useScissorBox.width, useScissorBox.height );
+      }
+      else if( orientation == 270 )
+      {
+        x = useScissorBox.y;
+        y = mViewportRectangle.width - (useScissorBox.x + useScissorBox.width);
+        context.Scissor( x, y, useScissorBox.height, useScissorBox.width );
+      }
+      else
+      {
+        context.Scissor( x, y, useScissorBox.width, useScissorBox.height );
+      }
     }
   }
 }
@@ -302,7 +325,8 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item,
                                              bool& usedStencilBuffer,
                                              uint32_t& lastClippingDepth,
                                              uint32_t& lastClippingId,
-                                             Integration::StencilBufferAvailable stencilBufferAvailable )
+                                             Integration::StencilBufferAvailable stencilBufferAvailable,
+                                             int orientation )
 {
   RenderMode::Type renderMode = RenderMode::AUTO;
   const Renderer *renderer = item.mRenderer;
@@ -324,7 +348,7 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item,
       // As both scissor and stencil clips can be nested, we may be simultaneously traversing up the scissor tree, requiring a scissor to be un-done. Whilst simultaneously adding a new stencil clip.
       // We process both based on our current and old clipping depths for each mode.
       // Both methods with return rapidly if there is nothing to be done for that type of clipping.
-      SetupScissorClipping( item, context );
+      SetupScissorClipping( item, context, orientation );
 
       if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE )
       {
@@ -390,7 +414,8 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
                                                  const Matrix& projectionMatrix,
                                                  Integration::DepthBufferAvailable depthBufferAvailable,
                                                  Integration::StencilBufferAvailable stencilBufferAvailable,
-                                                 Vector<GLuint>& boundTextures )
+                                                 Vector<GLuint>& boundTextures,
+                                                 int orientation )
 {
   DALI_PRINT_RENDER_LIST( renderList );
 
@@ -407,13 +432,45 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
   mViewportRectangle = context.GetViewport();
   mHasLayerScissor = false;
 
+  if( orientation == 90 || orientation == 270 )
+  {
+    int temp = mViewportRectangle.width;
+    mViewportRectangle.width = mViewportRectangle.height;
+    mViewportRectangle.height = temp;
+  }
+
   // Setup Scissor testing (for both viewport and per-node scissor)
   mScissorStack.clear();
   if( renderList.IsClipping() )
   {
     context.SetScissorTest( true );
     const ClippingBox& layerScissorBox = renderList.GetClippingBox();
-    context.Scissor( layerScissorBox.x, layerScissorBox.y, layerScissorBox.width, layerScissorBox.height );
+    GLint x = layerScissorBox.x;
+    GLint y = layerScissorBox.y;
+
+    if( orientation == 90 )
+    {
+      x = mViewportRectangle.height - (layerScissorBox.y + layerScissorBox.height);
+      y = layerScissorBox.x;
+      context.Scissor( x, y, layerScissorBox.height, layerScissorBox.width );
+    }
+    else if( orientation == 180 )
+    {
+      x = mViewportRectangle.width - (layerScissorBox.x + layerScissorBox.width);
+      y = mViewportRectangle.height - (layerScissorBox.y + layerScissorBox.height);
+      context.Scissor( x, y, layerScissorBox.width, layerScissorBox.height );
+    }
+    else if( orientation == 270 )
+    {
+      x = layerScissorBox.y;
+      y = mViewportRectangle.width - (layerScissorBox.x + layerScissorBox.width);
+      context.Scissor( x, y, layerScissorBox.height, layerScissorBox.width );
+    }
+    else
+    {
+      context.Scissor( x, y, layerScissorBox.width, layerScissorBox.height );
+    }
+
     mScissorStack.push_back( layerScissorBox );
     mHasLayerScissor = true;
   }
@@ -432,7 +489,7 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList,
 
     // Set up clipping based on both the Renderer and Actor APIs.
     // The Renderer API will be used if specified. If AUTO, the Actors automatic clipping feature will be used.
-    SetupClipping( item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable );
+    SetupClipping( item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, orientation );
 
     if( DALI_LIKELY( item.mRenderer ) )
     {
@@ -464,7 +521,8 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru
                                                  BufferIndex bufferIndex,
                                                  Integration::DepthBufferAvailable depthBufferAvailable,
                                                  Integration::StencilBufferAvailable stencilBufferAvailable,
-                                                 Vector<GLuint>& boundTextures )
+                                                 Vector<GLuint>& boundTextures,
+                                                 int orientation )
 {
   DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
 
@@ -493,7 +551,8 @@ void RenderAlgorithms::ProcessRenderInstruction( const RenderInstruction& instru
                            *projectionMatrix,
                             depthBufferAvailable,
                             stencilBufferAvailable,
-                            boundTextures );
+                            boundTextures,
+                            orientation );
       }
     }
   }
index 30c8041..98c219b 100644 (file)
@@ -65,7 +65,8 @@ class RenderAlgorithms
                                    BufferIndex bufferIndex,
                                    Integration::DepthBufferAvailable depthBufferAvailable,
                                    Integration::StencilBufferAvailable stencilBufferAvailable,
-                                   Vector<GLuint>& boundTextures );
+                                   Vector<GLuint>& boundTextures,
+                                   int orientation);
 
   private:
 
@@ -88,7 +89,7 @@ class RenderAlgorithms
      * @param[in] item     The current RenderItem (about to be rendered)
      * @param[in] context  The current Context
      */
-    inline void SetupScissorClipping( const Dali::Internal::SceneGraph::RenderItem& item, Context& context );
+    inline void SetupScissorClipping( const Dali::Internal::SceneGraph::RenderItem& item, Context& context, int orientation );
 
     /**
      * @brief Set up the clipping based on the specified clipping settings.
@@ -104,7 +105,8 @@ class RenderAlgorithms
                                bool& usedStencilBuffer,
                                uint32_t& lastClippingDepth,
                                uint32_t& lastClippingId,
-                               Integration::StencilBufferAvailable stencilBufferAvailable );
+                               Integration::StencilBufferAvailable stencilBufferAvailable,
+                               int orientation );
 
     /**
      * @brief Process a render-list.
@@ -124,7 +126,8 @@ class RenderAlgorithms
                                    const Matrix& projectionMatrix,
                                    Integration::DepthBufferAvailable depthBufferAvailable,
                                    Integration::StencilBufferAvailable stencilBufferAvailable,
-                                   Vector<GLuint>& boundTextures );
+                                   Vector<GLuint>& boundTextures,
+                                   int orientation );
 
     // Prevent copying:
     RenderAlgorithms( RenderAlgorithms& rhs );
index 3157f85..3d0d64b 100644 (file)
@@ -121,7 +121,7 @@ public:
   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:
index 7c56dfb..d9c2ea0 100644 (file)
@@ -91,7 +91,8 @@ struct RenderManager::Impl
     lastFrameWasRendered( false ),
     programController( glAbstraction ),
     depthBufferAvailable( depthBufferAvailableParam ),
-    stencilBufferAvailable( stencilBufferAvailableParam )
+    stencilBufferAvailable( stencilBufferAvailableParam ),
+    defaultSurfaceOrientation( 0 )
   {
      // Create thread pool with just one thread ( there may be a need to create more threads in the future ).
     threadPool = std::unique_ptr<Dali::ThreadPool>( new Dali::ThreadPool() );
@@ -174,6 +175,8 @@ struct RenderManager::Impl
   std::unique_ptr<Dali::ThreadPool>         threadPool;               ///< The thread pool
   Vector<GLuint>                            boundTextures;            ///< The textures bound for rendering
   Vector<GLuint>                            textureDependencyList;    ///< The dependency list of binded textures
+  int                                       defaultSurfaceOrientation; ///< defaultSurfaceOrientation for the default surface we are rendering to
+
 };
 
 RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction,
@@ -259,6 +262,11 @@ void RenderManager::SetDefaultSurfaceRect(const Rect<int32_t>& rect)
   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
@@ -599,6 +607,7 @@ void RenderManager::DoRender( RenderInstruction& instruction )
   }
 
   Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
+  int surfaceOrientation = mImpl->defaultSurfaceOrientation;
   Vector4 backgroundColor = mImpl->backgroundColor;
   Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
   Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
@@ -715,7 +724,7 @@ void RenderManager::DoRender( RenderInstruction& instruction )
         // For glViewport the lower-left corner is (0,0)
         // For glViewport the lower-left corner is (0,0)
         const int32_t y = ( surfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
-        viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
+        viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
       }
       else
       {
@@ -734,6 +743,7 @@ void RenderManager::DoRender( RenderInstruction& instruction )
       {
         viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
       }
+      surfaceOrientation = 0;
     }
   }
   else // No Offscreen frame buffer rendering
@@ -745,7 +755,7 @@ void RenderManager::DoRender( RenderInstruction& instruction )
       {
         // For glViewport the lower-left corner is (0,0)
         const int32_t y = ( instruction.mFrameBuffer->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
-        viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
+        viewportRect.Set( instruction.mViewport.x, y, instruction.mViewport.width, instruction.mViewport.height );
       }
       else
       {
@@ -758,6 +768,13 @@ void RenderManager::DoRender( RenderInstruction& instruction )
     }
   }
 
+  if ( surfaceOrientation == 90 || surfaceOrientation == 270 )
+  {
+    int temp = viewportRect.width;
+    viewportRect.width = viewportRect.height;
+    viewportRect.height = temp;
+  }
+
   mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
 
   if ( instruction.mIsClearColorSet )
@@ -784,7 +801,8 @@ void RenderManager::DoRender( RenderInstruction& instruction )
       mImpl->renderBufferIndex,
       depthBufferAvailable,
       stencilBufferAvailable,
-      mImpl->boundTextures );
+      mImpl->boundTextures,
+      surfaceOrientation );
 
   // Synchronise the FBO/Texture access when there are multiple contexts
   if ( mImpl->currentContext->IsSurfacelessContextSupported() )
index fd3e35c..248c9fd 100644 (file)
@@ -141,6 +141,12 @@ public:
   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
index 852d5d4..571e8b3 100644 (file)
@@ -1103,6 +1103,17 @@ void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
   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 );
index 039e054..3983bdb 100644 (file)
@@ -606,6 +606,12 @@ public:
   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 );
@@ -1030,6 +1036,17 @@ inline void SetDefaultSurfaceRectMessage( UpdateManager& manager, const Rect<int
   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;
index f6ecce5..7aca9cb 100644 (file)
@@ -157,6 +157,7 @@ const Vector3 Camera::DEFAULT_TARGET_POSITION( 0.0f, 0.0f, 0.0f );
 Camera::Camera()
 : mUpdateViewFlag( UPDATE_COUNT ),
   mUpdateProjectionFlag( UPDATE_COUNT ),
+  mProjectionRotation( 0 ),
   mNode( NULL ),
   mType( DEFAULT_TYPE ),
   mProjectionMode( DEFAULT_MODE ),
@@ -172,7 +173,8 @@ Camera::Camera()
   mTargetPosition( DEFAULT_TARGET_POSITION ),
   mViewMatrix(),
   mProjectionMatrix(),
-  mInverseViewProjection( Matrix::IDENTITY )
+  mInverseViewProjection( Matrix::IDENTITY ),
+  mFinalProjection( Matrix::IDENTITY )
 {
 }
 
@@ -261,6 +263,12 @@ void Camera::SetTargetPosition( const Vector3& targetPosition )
   mUpdateViewFlag = UPDATE_COUNT;
 }
 
+void Camera::RotateProjection( int rotationAngle )
+{
+  mProjectionRotation = rotationAngle;
+  mUpdateViewFlag = UPDATE_COUNT;
+}
+
 const Matrix& Camera::GetProjectionMatrix( BufferIndex bufferIndex ) const
 {
   return mProjectionMatrix[ bufferIndex ];
@@ -276,6 +284,11 @@ const Matrix& Camera::GetInverseViewProjectionMatrix( BufferIndex bufferIndex )
   return mInverseViewProjection[ bufferIndex ];
 }
 
+const Matrix& Camera::GetFinalProjectionMatrix( BufferIndex bufferIndex ) const
+{
+  return mFinalProjection[ bufferIndex ];
+}
+
 const PropertyInputImpl* Camera::GetProjectionMatrix() const
 {
   return &mProjectionMatrix;
@@ -508,6 +521,38 @@ uint32_t Camera::UpdateProjection( BufferIndex updateBufferIndex )
       }
 
       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;
   }
index d17120f..37aead6 100644 (file)
@@ -155,6 +155,11 @@ public:
   void SetFarClippingPlane( float farClippingPlane );
 
   /**
+   * @copydoc Dali::Internal::CameraActor::RotateProjection
+   */
+  void RotateProjection( int rotationAngle );
+
+  /**
    * @copydoc Dali::Internal::CameraActor::SetTarget
    */
   void SetTargetPosition( const Vector3& targetPosition );
@@ -203,6 +208,13 @@ public:
   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.
@@ -267,6 +279,7 @@ private:
 
   uint32_t                  mUpdateViewFlag;       ///< This is non-zero if the view matrix requires an update
   uint32_t                  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
@@ -289,6 +302,7 @@ 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
 
 };
 
@@ -426,6 +440,17 @@ inline void SetInvertYAxisMessage( EventThreadServices& eventThreadServices, con
   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