In Tizen embedded system, two types of rotation are supported.
One is Window Rotation and the other is Screen rotation
Although their use-case are different, their rotation itself almost works are same.
Real surface buffer is not rotated.
When rotation event is received from window server,
then internal contents are rotated and drawn with angle of the event.
This patch is to support the Tizen Rotation.
Change-Id: I1745b8cefaeb1bb6ff7639ac5d942aeb3216262f
END_TEST;
}
+#define CLIPPING_RECT_X (16)
+#define CLIPPING_RECT_Y (768)
+#define CLIPPING_RECT_WIDTH (32)
+#define CLIPPING_RECT_HEIGHT (32)
+
+int UtcDaliSceneSurfaceRotatedWithAngle0(void)
+{
+ tet_infoline("Ensure rotation of the surface is handled properly with Angle 0");
+
+ TestApplication application(
+ TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT,
+ TestApplication::DEFAULT_HORIZONTAL_DPI,
+ TestApplication::DEFAULT_VERTICAL_DPI,
+ true,
+ true);
+
+ const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+ std::vector<Rect<int>> damagedRects;
+ Rect<int> clippingRect;
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ Actor actor = CreateRenderableActor();
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+
+ damagedRects.clear();
+ application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT, 0);
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ clippingRect = Rect<int>(CLIPPING_RECT_X, CLIPPING_RECT_Y, CLIPPING_RECT_WIDTH, CLIPPING_RECT_HEIGHT); // in screen coordinates, includes 3 last frames updates
+ DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliSceneSurfaceRotatedWithAngle90(void)
+{
+ tet_infoline("Ensure rotation of the surface is handled properly with Angle 90");
+
+ TestApplication application(
+ TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT,
+ TestApplication::DEFAULT_HORIZONTAL_DPI,
+ TestApplication::DEFAULT_VERTICAL_DPI,
+ true,
+ true);
+
+ const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+ std::vector<Rect<int>> damagedRects;
+ Rect<int> clippingRect;
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ Actor actor = CreateRenderableActor();
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+
+ damagedRects.clear();
+ application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT, 90);
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ clippingRect = Rect<int>(CLIPPING_RECT_X, CLIPPING_RECT_Y, CLIPPING_RECT_WIDTH, CLIPPING_RECT_HEIGHT); // in screen coordinates, includes 3 last frames updates
+ DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // It is recalculation for glScissor.
+ // Because surface is rotated and glScissor is called with recalcurated value.
+ clippingRect.x = TestApplication::DEFAULT_SURFACE_HEIGHT - (CLIPPING_RECT_Y + CLIPPING_RECT_HEIGHT);
+ clippingRect.y = CLIPPING_RECT_X;
+ clippingRect.width = CLIPPING_RECT_HEIGHT;
+ clippingRect.height = CLIPPING_RECT_WIDTH;
+
+ DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliSceneSurfaceRotatedWithAngle180(void)
+{
+ tet_infoline("Ensure rotation of the surface is handled properly with Angle 180");
+
+ TestApplication application(
+ TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT,
+ TestApplication::DEFAULT_HORIZONTAL_DPI,
+ TestApplication::DEFAULT_VERTICAL_DPI,
+ true,
+ true);
+
+ const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+ std::vector<Rect<int>> damagedRects;
+ Rect<int> clippingRect;
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ Actor actor = CreateRenderableActor();
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+
+ damagedRects.clear();
+ application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT, 180);
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ clippingRect = Rect<int>(CLIPPING_RECT_X, CLIPPING_RECT_Y, CLIPPING_RECT_WIDTH, CLIPPING_RECT_HEIGHT); // in screen coordinates, includes 3 last frames updates
+ DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // It is recalculation for glScissor.
+ // Because surface is rotated and glScissor is called with recalcurated value.
+ clippingRect.x = TestApplication::DEFAULT_SURFACE_WIDTH - (CLIPPING_RECT_X + CLIPPING_RECT_WIDTH);
+ clippingRect.y = TestApplication::DEFAULT_SURFACE_HEIGHT - (CLIPPING_RECT_Y +CLIPPING_RECT_HEIGHT);
+ clippingRect.width = CLIPPING_RECT_WIDTH;
+ clippingRect.height = CLIPPING_RECT_HEIGHT;
+
+ DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliSceneSurfaceRotatedWithAngle270(void)
+{
+ tet_infoline("Ensure rotation of the surface is handled properly with Angle 270");
+
+ TestApplication application(
+ TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT,
+ TestApplication::DEFAULT_HORIZONTAL_DPI,
+ TestApplication::DEFAULT_VERTICAL_DPI,
+ true,
+ true);
+
+ const TestGlAbstraction::ScissorParams& glScissorParams(application.GetGlAbstraction().GetScissorParams());
+
+ std::vector<Rect<int>> damagedRects;
+ Rect<int> clippingRect;
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+
+ DALI_TEST_EQUALS(damagedRects.size(), 0, TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ Actor actor = CreateRenderableActor();
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
+ actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+
+ damagedRects.clear();
+ application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
+ TestApplication::DEFAULT_SURFACE_HEIGHT, 270);
+ application.SendNotification();
+ application.PreRenderWithPartialUpdate(TestApplication::RENDER_FRAME_INTERVAL, nullptr, damagedRects);
+ DALI_TEST_EQUALS(damagedRects.size(), 1, TEST_LOCATION);
+
+ clippingRect = Rect<int>(CLIPPING_RECT_X, CLIPPING_RECT_Y, CLIPPING_RECT_WIDTH, CLIPPING_RECT_HEIGHT); // in screen coordinates, includes 3 last frames updates
+ DALI_TEST_EQUALS<Rect<int>>(clippingRect, damagedRects[0], TEST_LOCATION);
+ application.RenderWithPartialUpdate(damagedRects, clippingRect);
+
+ // It is recalculation for glScissor.
+ // Because surface is rotated and glScissor is called with recalcurated value.
+ clippingRect.x = CLIPPING_RECT_Y;
+ clippingRect.y = TestApplication::DEFAULT_SURFACE_WIDTH - (CLIPPING_RECT_X + CLIPPING_RECT_WIDTH);
+ clippingRect.width = CLIPPING_RECT_HEIGHT;
+ clippingRect.height = CLIPPING_RECT_WIDTH;
+
+ DALI_TEST_EQUALS(clippingRect.x, glScissorParams.x, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.y, glScissorParams.y, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.width, glScissorParams.width, TEST_LOCATION);
+ DALI_TEST_EQUALS(clippingRect.height, glScissorParams.height, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliSceneKeyEventGeneratedSignalP(void)
{
TestApplication application;
{
namespace Integration
{
-Scene Scene::New(Size size)
+Scene Scene::New(Size size, int orientation)
{
- Internal::ScenePtr internal = Internal::Scene::New(size);
+ Internal::ScenePtr internal = Internal::Scene::New(size, orientation);
return Scene(internal.Get());
}
GetImplementation(*this).GetFramePresentedCallback(callbacks);
}
+void Scene::SurfaceRotated(float width, float height, int orientation)
+{
+ GetImplementation(*this).SurfaceRotated(width, height, orientation);
+}
+
Scene::EventProcessingFinishedSignalType& Scene::EventProcessingFinishedSignal()
{
return GetImplementation(*this).EventProcessingFinishedSignal();
* @brief Create an initialized Scene handle.
*
* @param[in] size The size of the set surface for this scene
+ * @param[in] orientation The rotated angle of the set surface for this scene
*
* @return a handle to a newly allocated Dali resource.
*/
- static Scene New(Size size);
+ static Scene New(Size size, int orientation = 0);
/**
* @brief Downcast an Object handle to Scene handle.
void GetFramePresentedCallback(FrameCallbackContainer& callbacks);
/**
+ * @brief Informs the scene that the set surface has been rotated.
+ *
+ * @param[in] width The width of rotated surface
+ * @param[in] height The height of rotated surface
+ * @param[in] orientation The orientation of rotated surface
+ */
+ void SurfaceRotated(float width, float height, int orientation);
+
+ /**
* @brief This signal is emitted just after the event processing is finished.
*
* @return The signal to connect to
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)
*/
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
/**
namespace Internal
{
-ScenePtr Scene::New( Size size )
+ScenePtr Scene::New(Size size, int orientation)
{
ScenePtr scene = new Scene;
// Second-phase construction
- scene->Initialize( size );
+ scene->Initialize(size, orientation);
return scene;
}
Scene::Scene()
-: mSceneObject( nullptr ),
+: mSceneObject(nullptr),
mSize(), // Don't set the proper value here, this will be set when the surface is set later
mDpi(),
- mBackgroundColor( DEFAULT_BACKGROUND_COLOR ),
- mDepthTreeDirty( false ),
- mEventProcessor( *this, ThreadLocalStorage::GetInternal()->GetGestureEventProcessor() )
+ mBackgroundColor(DEFAULT_BACKGROUND_COLOR),
+ mDepthTreeDirty(false),
+ mEventProcessor(*this, ThreadLocalStorage::GetInternal()->GetGestureEventProcessor()),
+ mSurfaceOrientation(0)
{
}
// When this destructor is called, the scene has either already been removed from Core or Core has already been destroyed
}
-void Scene::Initialize( Size size )
+void Scene::Initialize(Size size, int orientation)
{
ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
// Create the default render-task and ensure clear is enabled on it to show the background color
RenderTaskPtr renderTask = mRenderTaskList->CreateTask( mRootLayer.Get(), mDefaultCamera.Get() );
renderTask->SetClearEnabled(true);
+ mSurfaceOrientation = orientation;
- SurfaceResized( size.width, size.height );
+ SurfaceRotated( size.width, size.height, mSurfaceOrientation );
// Create scene graph object
mSceneObject = new SceneGraph::Scene();
return *mRootLayer;
}
-void Scene::SurfaceResized( float width, float height )
+void Scene::SurfaceResized(float width, float height)
{
- if( ( fabsf( mSize.width - width ) > Math::MACHINE_EPSILON_1 ) || ( fabsf( mSize.height - height ) > Math::MACHINE_EPSILON_1 ) )
+ if((fabsf(mSize.width - width) > Math::MACHINE_EPSILON_1) || (fabsf(mSize.height - height) > Math::MACHINE_EPSILON_1))
{
- Rect< int32_t > newSize( 0, 0, static_cast< int32_t >( width ), static_cast< int32_t >( height ) ); // truncated
-
- mSize.width = width;
- mSize.height = height;
-
- // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
- mDefaultCamera->SetPerspectiveProjection( mSize );
-
- mRootLayer->SetSize( mSize.width, mSize.height );
-
- ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
- SceneGraph::UpdateManager& updateManager = tls->GetUpdateManager();
- SetDefaultSurfaceRectMessage( updateManager, newSize );
-
- // set default render-task viewport parameters
- RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask( 0u );
- defaultRenderTask->SetViewport( newSize );
+ ChangedSurface(width, height, mSurfaceOrientation);
}
}
}
}
+void Scene::SurfaceRotated(float width, float height, int orientation)
+{
+ mSurfaceOrientation = orientation;
+ ChangedSurface(width, height, orientation);
+}
+
+int Scene::GetSurfaceOrientation()
+{
+ return mSurfaceOrientation;
+}
+
+void Scene::ChangedSurface(float width, float height, int orientation)
+{
+ Rect<int32_t> newSize(0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height)); // truncated
+
+ mSize.width = width;
+ mSize.height = height;
+
+ // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
+ mDefaultCamera->SetPerspectiveProjection(mSize);
+ // Set the surface orientation to Default camera for window/screen rotation
+ mDefaultCamera->RotateProjection(orientation);
+
+ mRootLayer->SetSize(width, height);
+
+ ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
+ SceneGraph::UpdateManager& updateManager = tls->GetUpdateManager();
+ SetDefaultSurfaceRectMessage(updateManager, newSize);
+
+ // Send the surface orientation to render manager for calculating glViewport/Scissor
+ SetDefaultSurfaceOrientationMessage(updateManager, orientation);
+
+ // set default render-task viewport parameters
+ RenderTaskPtr defaultRenderTask = mRenderTaskList->GetTask(0u);
+ defaultRenderTask->SetViewport(newSize);
+}
+
bool Scene::EmitKeyEventGeneratedSignal(const Dali::KeyEvent& event)
{
// Emit the KeyEventGenerated signal when KeyEvent is generated
/**
* @copydoc Dali::Integration::Scene::New
*/
- static ScenePtr New( Size size );
+ static ScenePtr New(Size size, int orientation = 0);
/**
* virtual destructor
SceneGraph::Scene* GetSceneObject() const;
/**
+ * Notify the surface has been rotated.
+ * When the device is rotated or the rotation event is received by display manager,
+ * this function will be called by window implementation.
+ *
+ * @param[in] width The width of rotated surface
+ * @param[in] height The height of rotated surface
+ * @param[in] orientation The orientation of rotated surface
+ */
+ void SurfaceRotated(float width, float height, int orientation);
+
+ /**
+ * @brief Get surface's current orientation
+ *
+ * @return surface orientation
+ */
+ int GetSurfaceOrientation();
+
+ /**
* Used by the EventProcessor to emit key event signals.
* @param[in] event The key event.
*/
* Second-phase constructor.
*
* @param[in] size The size of the set surface
+ * @param[in] orientation The orientation of the set surface for this scene
*/
- void Initialize( Size size );
+ void Initialize(Size size, int orientation);
// Undefined
Scene(const Scene&) = delete;
// Undefined
Scene& operator=(const Scene& rhs) = delete;
+ /**
+ * Informs the scene that the set surface has been resized or rotated.
+ *
+ * @param[in] width The width of rotated surface
+ * @param[in] height The height of rotated surface
+ * @param[in] orientation The orientation of rotated surface
+ */
+ void ChangedSurface(float width, float height, int orientation);
+
private:
Internal::SceneGraph::Scene* mSceneObject;
EventProcessor mEventProcessor;
+ // The Surface's orientation
+ int mSurfaceOrientation;
+
// The key event signal
Integration::Scene::KeyEventSignalType mKeyEventSignal;
Integration::Scene::KeyEventGeneratedSignalType mKeyEventGeneratedSignal;
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);
}
// for reflection effect
const Camera* GetCamera() const
programController( glAbstraction ),
depthBufferAvailable( depthBufferAvailableParam ),
stencilBufferAvailable( stencilBufferAvailableParam ),
- partialUpdateAvailable( partialUpdateAvailableParam )
+ partialUpdateAvailable( partialUpdateAvailableParam ),
+ 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() );
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,
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
Rect<int32_t> surfaceRect = mImpl->defaultSurfaceRect;
Integration::DepthBufferAvailable depthBufferAvailable = mImpl->depthBufferAvailable;
Integration::StencilBufferAvailable stencilBufferAvailable = mImpl->stencilBufferAvailable;
+ int surfaceOrientation = sceneInternal.GetSurfaceOrientation();
if ( instruction.mFrameBuffer )
{
{
viewportRect.Set( 0, 0, instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() );
}
+ surfaceOrientation = 0;
}
else // No Offscreen frame buffer rendering
{
}
}
+ // Set surface orientation
+ mImpl->currentContext->SetSurfaceOrientation(surfaceOrientation);
+
bool clearFullFrameRect = true;
if( instruction.mFrameBuffer != nullptr )
{
GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
mImpl->currentContext->InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
+
}
void RenderManager::PostRender( bool uploadOnly )
void SetDefaultSurfaceRect( const Rect<int>& rect );
/**
+ * Returns the orintation for the default surface (probably the application window).
+ * @param[in] orientation the surface's orientation.
+ */
+ void SetDefaultSurfaceOrientation(int orientation);
+
+ /**
* Add a Renderer to the render manager.
* @param[in] renderer The renderer to add.
* @post renderer is owned by RenderManager
mClearColor(Color::WHITE), // initial color, never used until it's been set by the user
mCullFaceMode( FaceCullingMode::NONE ),
mViewPort( 0, 0, 0, 0 ),
- mSceneContexts( contexts )
+ mSceneContexts( contexts ),
+ mSurfaceOrientation(0)
{
}
*/
void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
- LOG_GL("Scissor %d %d %d %d\n", x, y, width, height);
- CHECK_GL( mGlAbstraction, mGlAbstraction.Scissor(x, y, width, height) );
+ GLint cx, cy, cw, ch;
+
+ // scissor's value should be set based on the default system coordinates.
+ // when the surface is rotated, the input valus already were set with the rotated angle.
+ // So, re-calculation is needed.
+ if(mSurfaceOrientation == 90)
+ {
+ cx = mViewPort.height - (y + height);
+ cy = x;
+ cw = height;
+ ch = width;
+ }
+ else if(mSurfaceOrientation == 180)
+ {
+ cx = mViewPort.width - (x + width);
+ cy = mViewPort.height - (y + height);
+ cw = width;
+ ch = height;
+ }
+ else if(mSurfaceOrientation == 270)
+ {
+ cx = y;
+ cy = mViewPort.width - (x + width);
+ cw = height;
+ ch = width;
+ }
+ else
+ {
+ cx = x;
+ cy = y;
+ cw = width;
+ ch = height;
+ }
+
+ LOG_GL("Scissor %d %d %d %d\n", cx, cy, cw, ch);
+ CHECK_GL(mGlAbstraction, mGlAbstraction.Scissor(cx, cy, cw, ch));
}
/**
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
// check if its same as already set
- Rect<int> newViewport( x, y, width, height );
+ GLsizei cw, ch;
+
+ // viewport's value shoud be set based on the default system size.
+ // when the surface is rotated, the input width and height already were swapped.
+ // So, re-swapping is needed.
+ if(mSurfaceOrientation == 90 || mSurfaceOrientation == 270)
+ {
+ cw = height;
+ ch = width;
+ }
+ else
+ {
+ cw = width;
+ ch = height;
+ }
+
+ // User uses the rotated viewport size.
+ Rect<int> newViewport(x, y, width, height);
// Temporarily disable the viewport caching, as the implementation of GLES driver in Tizen platform
// share a global viewport between multiple contexts, therefore glViewport has to be called every
// time after glBindFramebuffer regardless of the same vewport size in the same context.
-// if( mViewPort != newViewport )
+ // if( mViewPort != newViewport )
{
// set new one
- LOG_GL("Viewport %d %d %d %d\n", x, y, width, height);
- CHECK_GL( mGlAbstraction, mGlAbstraction.Viewport(x, y, width, height) );
+ LOG_GL("Viewport %d %d %d %d\n", x, y, cw, ch);
+ CHECK_GL(mGlAbstraction, mGlAbstraction.Viewport(x, y, cw, ch));
mViewPort = newViewport; // remember new one
}
}
return mMaxTextureSize;
}
+ void SetSurfaceOrientation(int orientation)
+ {
+ LOG_GL( "SetSurfaceOrientation: orientation: %d\n", orientation );
+ mSurfaceOrientation = orientation;
+ }
+
/**
* Get the current viewport.
* @return Viewport rectangle.
FrameBufferStateCache mFrameBufferStateCache; ///< frame buffer state cache
OwnerContainer< Context* >* mSceneContexts; ///< The pointer of the container of contexts for surface rendering
+
+ int mSurfaceOrientation;
};
} // namespace Internal
new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SurfaceReplaced, scene );
}
+void UpdateManager::SetDefaultSurfaceOrientation(int orientation)
+{
+ using DerivedType = MessageValue1<RenderManager, int>;
+
+ // 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::SurfaceReplaced, &scene );
}
+inline void SetDefaultSurfaceOrientationMessage(UpdateManager& manager, int orientation)
+{
+ using LocalType = MessageValue1<UpdateManager, int>;
+
+ // 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 )
{
using LocalType = MessageValue1<UpdateManager, float>;
Camera::Camera()
: mUpdateViewFlag( UPDATE_COUNT ),
mUpdateProjectionFlag( UPDATE_COUNT ),
+ mProjectionRotation(0),
mNode( nullptr ),
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 VectorReflectedByPlane(Vector4 &out, Vector4 &in, Vector4 &plane)
{
float d = float(2.0) * plane.Dot(in);
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 );
+ 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 SetFarClippingPlane( float farClippingPlane );
/**
+ * @copydoc Dali::Internal::CameraActor::RotateProjection
+ */
+ void RotateProjection(int rotationAngle);
+
+ /**
* @copydoc Dali::Internal::CameraActor::SetTarget
*/
void SetTargetPosition( const Vector3& targetPosition );
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.
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
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