mDisplayConnection(nullptr),
mScene(),
mFullSwapNextFrame(true),
- mIsResizing(false),
mDepthBufferRequired(Integration::DepthBufferAvailable::FALSE),
mStencilBufferRequired(Integration::StencilBufferAvailable::FALSE)
{
* @brief Return the orientation of the surface.
* @return The orientation
*/
- virtual int GetOrientation() const = 0;
+ virtual int GetSurfaceOrientation() const = 0;
+
+ /**
+ * @brief Return the orientation of the screen.
+ * @return The screen orientation
+ */
+ virtual int GetScreenOrientation() const = 0;
/**
* @brief InitializeGraphics the platform specific graphics surface interfaces
mFullSwapNextFrame = true;
}
- /**
- * @brief Sets whether this surface is being resized.
- */
- void SetIsResizing(bool isResizing)
- {
- mIsResizing = isResizing;
- }
-
private:
/**
* @brief Undefined copy constructor. RenderSurface cannot be copied
Dali::DisplayConnection* mDisplayConnection;
WeakHandle<Dali::Integration::Scene> mScene;
bool mFullSwapNextFrame; ///< Whether the full surface swap is required
- bool mIsResizing; ///< Whether the surface is being resized
private:
Integration::DepthBufferAvailable mDepthBufferRequired; ///< Whether the depth buffer is required
mScene.SurfaceReplaced();
- SurfaceResized();
+ PositionSize surfacePositionSize = surface->GetPositionSize();
+
+ SurfaceResized(static_cast<float>(surfacePositionSize.width), static_cast<float>(surfacePositionSize.height));
InitializeDpi();
OnSurfaceSet(surface);
}
-void SceneHolder::SurfaceResized()
+void SceneHolder::SurfaceResized(float width, float height)
{
- PositionSize surfacePositionSize = mSurface->GetPositionSize();
- mScene.SurfaceResized(static_cast<float>(surfacePositionSize.width), static_cast<float>(surfacePositionSize.height));
+ mScene.SurfaceResized(width, height);
mSurface->SetFullSwapNextFrame();
// Create the scene
PositionSize surfacePositionSize = mSurface->GetPositionSize();
- int orientation = mSurface->GetOrientation();
- mScene = Dali::Integration::Scene::New(Size(static_cast<float>(surfacePositionSize.width), static_cast<float>(surfacePositionSize.height)), orientation);
+ int windowOrientation = mSurface->GetSurfaceOrientation();
+ int screenOrientation = mSurface->GetScreenOrientation();
+
+ mScene = Dali::Integration::Scene::New(Size(static_cast<float>(surfacePositionSize.width), static_cast<float>(surfacePositionSize.height)), windowOrientation, screenOrientation);
Internal::Adaptor::Adaptor& adaptorImpl = Internal::Adaptor::Adaptor::GetImplementation(adaptor);
mAdaptor = &adaptorImpl;
OnResume();
}
-void SceneHolder::SurfaceRotated(float width, float height, int orientation)
+void SceneHolder::SurfaceRotated(float width, float height, int32_t windowOrientation, int32_t screenOrientation)
{
- mScene.SurfaceRotated(width, height, orientation);
+ mScene.SurfaceRotated(width, height, windowOrientation, screenOrientation);
}
void SceneHolder::SetRotationCompletedAcknowledgement()
/**
* @brief Called when the surface set is resized.
+ * @param[in] width the resized window's width
+ * @param[in] height the resized window's height
*/
- void SurfaceResized();
+ void SurfaceResized(float width, float height);
/**
* @brief Get the render surface
*
* @param[in] width The width of rotated surface
* @param[in] height The height of rotated surface
- * @param[in] orientation The orientation of rotated surface
+ * @param[in] windowOrientation the current window orientation
+ * @param[in] screenOrientation the current screen orientation
*/
- void SurfaceRotated(float width, float height, int orientation);
+ void SurfaceRotated(float width, float height, int32_t windowOrientation, int32_t screenOrientation);
/**
* @brief Send message to acknowledge window rotation with current window orientation.
WindowContainer windows;
mAdaptorInterfaces.GetWindowContainerInterface(windows);
- bool sceneSurfaceResized;
-
for(auto&& window : windows)
{
Dali::Integration::Scene scene = window->GetScene();
{
Integration::RenderStatus windowRenderStatus;
- // Get Surface Resized flag
- sceneSurfaceResized = scene.IsSurfaceRectChanged();
- windowSurface->SetIsResizing(sceneSurfaceResized);
+ const bool sceneSurfaceResized = scene.IsSurfaceRectChanged();
// clear previous frame damaged render items rects, buffer history is tracked on surface level
mDamagedRects.clear();
} // namespace
+EglGraphicsController::EglGraphicsController()
+: mTextureDependencyChecker(*this),
+ mSyncPool(*this)
+{
+}
+
EglGraphicsController::~EglGraphicsController()
{
while(!mPresentationCommandBuffers.empty())
}
}
+void EglGraphicsController::PostRender()
+{
+ mTextureDependencyChecker.Reset();
+ mSyncPool.AgeSyncObjects();
+}
+
Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
{
DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
}
case GLES::CommandType::DRAW:
{
- mCurrentContext->Flush(false, cmd.draw);
+ mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
break;
}
case GLES::CommandType::DRAW_INDEXED:
{
- mCurrentContext->Flush(false, cmd.draw);
+ mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
break;
}
case GLES::CommandType::DRAW_INDEXED_INDIRECT:
{
- mCurrentContext->Flush(false, cmd.draw);
+ mCurrentContext->Flush(false, cmd.draw, mTextureDependencyChecker);
break;
}
case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
}
mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
+
break;
}
case GLES::CommandType::END_RENDERPASS:
{
- mCurrentContext->EndRenderPass();
+ mCurrentContext->EndRenderPass(mTextureDependencyChecker);
+ // This sync object is to enable cpu to wait for rendering to complete, not gpu.
+ // It's only needed for reading the framebuffer texture in the client.
auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
if(syncObject)
{
#include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
+#include <dali/internal/graphics/gles-impl/gles-sync-pool.h>
+#include <dali/internal/graphics/gles-impl/gles-texture-dependency-checker.h>
#include <dali/internal/graphics/gles-impl/gles2-graphics-memory.h>
namespace Dali
{
class CommandBuffer;
class PipelineCache;
+class SyncPool;
+class TextureDependencyChecker;
} // namespace GLES
/**
{
public:
/**
- * @brief Deault constructor
+ * @brief Constructor
*/
- EglGraphicsController() = default;
+ EglGraphicsController();
/**
* @brief Destructor
void ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget);
/**
+ * Invoked after all rendering has finished. Used to clean up sync resources
+ */
+ void PostRender();
+
+ /**
* Creates a GLES context for the given render surface
*
* @param[in] surface The surface whose GLES context to be created.
return mSharedContext;
}
+ GLES::SyncPool& GetSyncPool()
+ {
+ return mSyncPool;
+ }
+
private:
Integration::GlAbstraction* mGlAbstraction{nullptr};
Integration::GlContextHelperAbstraction* mGlContextHelperAbstraction{nullptr};
std::queue<const GLES::CommandBuffer*> mPresentationCommandBuffers{}; ///< Queue of reusable command buffers used by presentation engine
void* mSharedContext{nullptr}; ///< Shared EGL context
+
+ GLES::TextureDependencyChecker mTextureDependencyChecker; // Checks if FBO textures need syncing
+ GLES::SyncPool mSyncPool;
};
} // namespace Graphics
${adaptor_graphics_dir}/gles-impl/gles-graphics-texture.cpp
${adaptor_graphics_dir}/gles-impl/gles-graphics-pipeline-cache.cpp
${adaptor_graphics_dir}/gles-impl/gles-context.cpp
+ ${adaptor_graphics_dir}/gles-impl/gles-sync-pool.cpp
${adaptor_graphics_dir}/gles-impl/gles-sync-object.cpp
${adaptor_graphics_dir}/gles-impl/gles-framebuffer-state-cache.cpp
+ ${adaptor_graphics_dir}/gles-impl/gles-texture-dependency-checker.cpp
)
#include "gles-graphics-program.h"
#include "gles-graphics-render-pass.h"
#include "gles-graphics-render-target.h"
+#include "gles-texture-dependency-checker.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
}
}
-void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
+void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall, GLES::TextureDependencyChecker& dependencyChecker)
{
auto& gl = *mImpl->mController.GetGL();
{
// Attempt to reinitialize
// @todo need to put this somewhere else where it isn't const.
- // Maybe post it back on end of initialize queue if initialization fails?
+ // Maybe post it bac/k on end of initialize queue if initialization fails?
texture->InitializeResource();
}
+ // Warning, this may cause glWaitSync to occur on the GPU.
+ dependencyChecker.CheckNeedsSync(this, texture);
+
texture->Bind(binding);
texture->Prepare(); // @todo also non-const.
mImpl->FlushVertexAttributeLocations();
}
+ //@todo Wait if textures need syncing
gl.DrawArrays(GLESTopology(ia->topology),
drawCall.draw.firstVertex,
drawCall.draw.vertexCount);
else if(targetInfo.framebuffer)
{
// bind framebuffer and swap.
- renderTarget.GetFramebuffer()->Bind();
+ auto framebuffer = renderTarget.GetFramebuffer();
+ framebuffer->Bind();
}
// clear (ideally cache the setup)
const auto& attachments = *renderPass.GetCreateInfo().attachments;
const auto& color0 = attachments[0];
GLuint mask = 0;
+
if(color0.loadOp == AttachmentLoadOp::CLEAR)
{
mask |= GL_COLOR_BUFFER_BIT;
mImpl->mCurrentRenderTarget = &renderTarget;
}
-void Context::EndRenderPass()
+void Context::EndRenderPass(GLES::TextureDependencyChecker& dependencyChecker)
{
if(mImpl->mCurrentRenderTarget)
{
- if(mImpl->mCurrentRenderTarget->GetFramebuffer())
+ GLES::Framebuffer* framebuffer = mImpl->mCurrentRenderTarget->GetFramebuffer();
+ if(framebuffer)
{
auto& gl = *mImpl->mController.GetGL();
gl.Flush();
+
+ /* @todo Full dependency checking would need to store textures in Begin, and create
+ * fence objects here; but we're going to draw all fbos on shared context in serial,
+ * so no real need (yet). Might want to consider ensuring order of render passes,
+ * but that needs doing in the controller, and would need doing before ProcessCommandQueues.
+ *
+ * Currently up to the client to create render tasks in the right order.
+ */
+
+ /* Create fence sync objects. Other contexts can then wait on these fences before reading
+ * textures.
+ */
+ dependencyChecker.AddTextures(this, framebuffer);
}
}
}
class RenderPass;
class RenderTarget;
class Texture;
+class TextureDependencyChecker;
/**
* @brief Context represents single GLES context
* @brief Flushes the context
*
* Flushes the context by issuing GL calls to set the required
- * state.
+ * state. Causes a glWaitSync if any drawn textures are dependent
+ * on another context.
*
* @param[in] reset If true then state is reset unconditionally
+ * @param[in] drawCall the draws that need flushing
+ * @param[in] dependencyChecker The texture dependecy checker
*/
- void Flush(bool reset, const GLES::DrawCallDescriptor& drawCall);
+ void Flush(bool reset, const GLES::DrawCallDescriptor& drawCall, GLES::TextureDependencyChecker& dependencyChecker);
/**
* @brief Returns context Id
void ResolveStandaloneUniforms();
/**
- * @brief Begins render pass for sepcified render target
+ * @brief Begins render pass for specified render target
*
* @param[in] renderPass render pass object to begin
- * @param[in] renderTarget render target to be drawn onto
*/
void BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin);
* @brief Ends render pass
*
* Ending render pass is necessary in order to ensure
- * proper implicit synchronization is in place
+ * proper explicit synchronization is in place
*/
- void EndRenderPass();
+ void EndRenderPass(TextureDependencyChecker& checker);
/**
* @brief Returns the cache of GL state in the context
void SetSamplerParameter(uint32_t param, uint32_t& cacheValue, uint32_t value) const;
+ uint32_t GetDependencyIndex() const
+ {
+ return mDependencyIndex;
+ }
+ void SetDependencyIndex(uint32_t dependencyIndex)
+ {
+ mDependencyIndex = dependencyIndex;
+ }
+
private:
mutable struct SamplerStateCache
{
uint32_t mTextureId{0u};
GLenum mGlTarget{0u};
uint32_t mMaxMipMapLevel{0u};
+ uint32_t mDependencyIndex{0xFFFFFFFF};
void* mGLOwnerContext{nullptr};
bool mIsCompressed{false};
};
--- /dev/null
+/*
+ * Copyright (c) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Class header
+#include <dali/internal/graphics/gles-impl/gles-sync-pool.h>
+
+// External Headers
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+
+// Internal Headers
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+
+namespace Dali::Graphics::GLES
+{
+AgingSyncObject::AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext)
+: controller(controller),
+ writeContext(writeContext)
+{
+ auto gl = controller.GetGL();
+ if(gl)
+ {
+ glSyncObject = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+}
+
+AgingSyncObject::~AgingSyncObject()
+{
+ auto gl = controller.GetGL();
+ if(gl && glSyncObject != nullptr)
+ {
+ gl->DeleteSync(glSyncObject);
+ }
+}
+
+SyncPool::~SyncPool() = default;
+
+AgingSyncObject* SyncPool::AllocateSyncObject(const Context* writeContext)
+{
+ std::unique_ptr<AgingSyncObject> syncObject = std::make_unique<AgingSyncObject>(mController, writeContext);
+ mSyncObjects.push_back(std::move(syncObject));
+ return mSyncObjects.back().get();
+}
+
+void SyncPool::Wait(AgingSyncObject* syncPoolObject)
+{
+ auto gl = mController.GetGL();
+ if(gl && syncPoolObject->glSyncObject != nullptr)
+ {
+ syncPoolObject->syncing = true;
+ gl->WaitSync(syncPoolObject->glSyncObject, 0, GL_TIMEOUT_IGNORED);
+ }
+}
+
+void SyncPool::FreeSyncObject(AgingSyncObject* agingSyncObject)
+{
+ auto iter = std::find_if(mSyncObjects.begin(), mSyncObjects.end(), [&agingSyncObject](AgingSyncPtrRef agingSyncPtr) { return agingSyncPtr.get() == agingSyncObject; });
+ if(iter != mSyncObjects.end())
+ {
+ iter->reset();
+ }
+}
+
+/**
+ * Age sync objects. Call at the end of each frame.
+ * When a sync object is older than 2 frames, delete it.
+ */
+void SyncPool::AgeSyncObjects()
+{
+ if(!mSyncObjects.empty())
+ {
+ // Age the remaining sync objects.
+ for(auto& agingSyncObject : mSyncObjects)
+ {
+ if(agingSyncObject != nullptr && agingSyncObject->glSyncObject != 0)
+ {
+ if(agingSyncObject->age > 0)
+ {
+ agingSyncObject->age--;
+ }
+ else
+ {
+ agingSyncObject.reset();
+ }
+ }
+ }
+ }
+ // Move any old sync objects to the end of the list, and then remove them all.
+ mSyncObjects.erase(std::remove_if(mSyncObjects.begin(), mSyncObjects.end(), [&](std::unique_ptr<AgingSyncObject>& agingSyncObject) { return agingSyncObject == nullptr; }),
+ mSyncObjects.end());
+}
+
+} // namespace Dali::Graphics::GLES
--- /dev/null
+#ifndef DALI_GRAPHICS_GLES_SYNC_POOL_H
+#define DALI_GRAPHICS_GLES_SYNC_POOL_H
+
+/*
+ * Copyright (c) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/graphics-api/graphics-types.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali::Graphics
+{
+class EglGraphicsController;
+
+namespace GLES
+{
+class Context;
+
+struct AgingSyncObject
+{
+ AgingSyncObject(Graphics::EglGraphicsController& controller, const Context* writeContext);
+ ~AgingSyncObject();
+
+ EglGraphicsController& controller;
+ const Context* writeContext;
+ GLsync glSyncObject{0};
+ uint8_t age{2};
+ bool syncing{false};
+};
+using AgingSyncPtrRef = std::unique_ptr<AgingSyncObject>&;
+
+/**
+ * A vector of current fence syncs. They only age if glWaitSync is called on them in the
+ * same frame they are created, otherwise they are deleted.
+ * They must be created in the writeContext, but can be synced from a readContext.
+ * (Pool per context? - probably only ever used in resource context!)
+ */
+class SyncPool
+{
+public:
+ explicit SyncPool(Graphics::EglGraphicsController& graphicsController)
+ : mController(graphicsController)
+ {
+ }
+
+ ~SyncPool();
+
+ /**
+ * Allocate a sync object in the writeContext
+ * @param writeContext
+ * @return An owned ptr to a sync object
+ */
+ AgingSyncObject* AllocateSyncObject(const Context* writeContext);
+
+ /**
+ * Wait on a sync object in any context
+ * @param syncPoolObject The object to wait on.
+ */
+ void Wait(AgingSyncObject* syncPoolObject);
+
+ /**
+ * Delete the sync object if it's not needed.
+ *
+ */
+ void FreeSyncObject(AgingSyncObject* agingSyncObject);
+
+ /**
+ * Age outstanding sync objects. Call at the end of each frame.
+ * When a sync object is older than 2 frames, delete it.
+ */
+ void AgeSyncObjects();
+
+private:
+ std::vector<std::unique_ptr<AgingSyncObject>> mSyncObjects;
+ EglGraphicsController& mController;
+};
+
+} // namespace GLES
+} // namespace Dali::Graphics
+
+#endif //DALI_GRAPHICS_GLES_SYNC_POOL_H
--- /dev/null
+/*
+ * Copyright (c) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include "gles-texture-dependency-checker.h"
+
+// EXTERNAL INCLUDES
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+
+namespace Dali::Graphics::GLES
+{
+void TextureDependencyChecker::Reset()
+{
+ for(auto& textureDependency : mTextureDependencies)
+ {
+ for(auto texture : textureDependency.textures)
+ {
+ texture->SetDependencyIndex(0xffffffff);
+ }
+ if(!textureDependency.syncing)
+ {
+ mController.GetSyncPool().FreeSyncObject(textureDependency.agingSyncObject);
+ }
+ }
+ mTextureDependencies.clear();
+}
+
+void TextureDependencyChecker::AddTextures(const GLES::Context* writeContext, const GLES::Framebuffer* framebuffer)
+{
+ uint32_t index = mTextureDependencies.size();
+ mTextureDependencies.emplace_back();
+ TextureDependency& textureDependency = mTextureDependencies.back();
+
+ for(int i = 0; i < 3; ++i)
+ {
+ GLES::Texture* texture{nullptr};
+ switch(i)
+ {
+ case 0:
+ texture = static_cast<GLES::Texture*>(framebuffer->GetCreateInfo().colorAttachments[0].texture);
+ break;
+ case 1:
+ texture = static_cast<GLES::Texture*>(framebuffer->GetCreateInfo().depthStencilAttachment.depthTexture);
+ break;
+ case 2:
+ texture = static_cast<GLES::Texture*>(framebuffer->GetCreateInfo().depthStencilAttachment.stencilTexture);
+ break;
+ }
+ if(texture != nullptr)
+ {
+ textureDependency.textures.push_back(texture);
+ texture->SetDependencyIndex(index);
+ }
+ }
+ textureDependency.writeContext = const_cast<GLES::Context*>(writeContext);
+ textureDependency.framebuffer = const_cast<GLES::Framebuffer*>(framebuffer);
+ textureDependency.agingSyncObject = mController.GetSyncPool().AllocateSyncObject(writeContext);
+}
+
+void TextureDependencyChecker::CheckNeedsSync(const GLES::Context* readContext, const GLES::Texture* texture)
+{
+ uint32_t dependencyIndex = texture->GetDependencyIndex();
+ if(dependencyIndex < mTextureDependencies.size())
+ {
+ auto& textureDependency = mTextureDependencies[dependencyIndex];
+ if(!textureDependency.syncing && textureDependency.writeContext != readContext)
+ {
+ // Needs syncing!
+ textureDependency.syncing = true;
+
+ // Wait on the sync object in GPU. This will ensure that the writeContext completes its tasks prior
+ // to the sync point.
+ mController.GetSyncPool().Wait(textureDependency.agingSyncObject);
+ }
+ }
+}
+
+} // namespace Dali::Graphics::GLES
--- /dev/null
+#ifndef DALI_GLES_TEXTURE_DEPENDENCY_CHECKER_H
+#define DALI_GLES_TEXTURE_DEPENDENCY_CHECKER_H
+
+/*
+ * Copyright (c) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali::Graphics
+{
+class EglGraphicsController;
+
+namespace GLES
+{
+class Context;
+class Framebuffer;
+class Texture;
+class AgingSyncObject;
+
+/**
+ * Class to handle dependency checks between textures on different
+ * GL Contexts.
+ *
+ * We have a shared (resource) context for writing to offscreen framebuffers,
+ * and separate contexts for each window/scene.
+ * If a framebuffer attachment is used in a scene, then it needs a sync point
+ * in the GPU in order to ensure that the first context finishes writing to the
+ * texture before it is read in the scene context.
+ */
+class TextureDependencyChecker
+{
+public:
+ explicit TextureDependencyChecker(EglGraphicsController& controller)
+ : mController(controller)
+ {
+ }
+
+ /**
+ * Clear all the textures. Call at the start of a frame
+ */
+ void Reset();
+
+ /**
+ * Add Texture dependencies
+ *
+ * @param[in] writeContext The context of the framebuffer's render pass
+ * @param[in] framebuffer The framebuffer to collect textures from
+ */
+ void AddTextures(const Context* writeContext, const Framebuffer* framebuffer);
+
+ /**
+ * Check if the given texture needs syncing before being read. This
+ * will perform a glWaitSync() (GPU side semaphore) if the texture
+ * needs syncing.
+ * @param[in] readContext The context that the texture is being read (drawn with)
+ * @param[in] texture The texture being read
+ */
+ void CheckNeedsSync(const Context* readContext, const Texture* texture);
+
+private:
+ struct TextureDependency
+ {
+ std::vector<Texture*> textures;
+ Context* writeContext{nullptr};
+ Framebuffer* framebuffer{nullptr};
+ AgingSyncObject* agingSyncObject;
+ bool syncing{false};
+ };
+ std::vector<TextureDependency> mTextureDependencies;
+ EglGraphicsController& mController;
+};
+
+} // namespace GLES
+} // namespace Dali::Graphics
+
+#endif //DALI_GLES_TEXTURE_DEPENDENCY_CHECKER_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
{
mGraphicsController.GetCurrentContext()->InvalidateDepthStencilBuffers();
}
+
+ mGraphicsController.PostRender();
}
void EglGraphics::SetFirstFrameAfterResume()
return -1;
}
-int WindowBaseAndroid::GetOrientation() const
+int WindowBaseAndroid::GetWindowRotationAngle() const
{
return 0;
}
int CreateFramePresentedSyncFence() override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::Internal::Adaptor::WindowBase::GetWindowRotationAngle()
*/
- int GetOrientation() const override;
+ int GetWindowRotationAngle() const override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetPositionSizeWithAngle()
WindowOrientation GlWindow::GetCurrentOrientation() const
{
- DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), GetCurrentOrientation(): %d\n", this, mNativeWindowId, mTotalRotationAngle);
return ConvertToOrientation(mTotalRotationAngle);
}
virtual void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) = 0;
/**
- * @brief Return the orientation of the surface.
- * @return The orientation
+ * @brief Return the angle of the window's rotation.
+ * @return The window orientation
*/
- virtual int GetOrientation() const = 0;
+ virtual int GetWindowRotationAngle() const = 0;
/**
- * @brief Get the screen rotation angle of the window
+ * @brief Get the angle of screen rotation for the window
+ * @return The screen orientation
*/
virtual int GetScreenRotationAngle() = 0;
/**
- * @brief Set the rotation angle of the window
+ * @brief Set the screen rotation angle of the window
*/
virtual void SetWindowRotationAngle(int degree) = 0;
mIconified(false),
mOpaqueState(false),
mWindowRotationAcknowledgement(false),
- mFocused(false)
+ mFocused(false),
+ mIsWindowRotating(false)
{
}
mWindowBase->AuxiliaryMessageSignal().Connect(this, &Window::OnAuxiliaryMessage);
mWindowSurface->OutputTransformedSignal().Connect(this, &Window::OnOutputTransformed);
+ mWindowSurface->RotationFinishedSignal().Connect(this, &Window::OnRotationFinished);
AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
{
mOrientationMode = Internal::Adaptor::Window::OrientationMode::PORTRAIT;
}
+
+ if(positionSize.width <= 0 || positionSize.height <= 0)
+ {
+ mWindowWidth = screenWidth;
+ mWindowHeight = screenHeight;
+ }
+ else
+ {
+ mWindowWidth = positionSize.width;
+ mWindowHeight = positionSize.height;
+ }
+
// For Debugging
mNativeWindowId = mWindowBase->GetNativeWindowId();
}
void Window::SetSize(Dali::Window::WindowSize size)
{
- PositionSize oldRect = mSurface->GetPositionSize();
-
- mWindowSurface->MoveResize(PositionSize(oldRect.x, oldRect.y, size.GetWidth(), size.GetHeight()));
+ PositionSize oldRect = GetPositionSize();
- PositionSize newRect = mSurface->GetPositionSize();
+ PositionSize newRect;
+ newRect.width = size.GetWidth();
+ newRect.height = size.GetHeight();
// When surface size is updated, inform adaptor of resizing and emit ResizeSignal
if((oldRect.width != newRect.width) || (oldRect.height != newRect.height))
{
+ mWindowSurface->MoveResize(PositionSize(oldRect.x, oldRect.y, newRect.width, newRect.height));
+
Uint16Pair newSize(newRect.width, newRect.height);
mWindowWidth = newRect.width;
mWindowHeight = newRect.height;
- SurfaceResized();
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), current angle (%d), SetSize(): (%d, %d), [%d x %d]\n", this, mNativeWindowId, mRotationAngle, oldRect.x, oldRect.y, newRect.width, newRect.height);
- mAdaptor->SurfaceResizePrepare(mSurface.get(), newSize);
+ SurfaceResized(static_cast<float>(mWindowWidth), static_cast<float>(mWindowHeight));
- DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), current angle (%d), SetSize(): resize signal [%d x %d]\n", this, mNativeWindowId, mRotationAngle, newRect.width, newRect.height);
+ mAdaptor->SurfaceResizePrepare(mSurface.get(), newSize);
Dali::Window handle(this);
mResizeSignal.Emit(handle, newSize);
Dali::Window::WindowSize Window::GetSize() const
{
- PositionSize positionSize = mSurface->GetPositionSize();
-
- return Dali::Window::WindowSize(positionSize.width, positionSize.height);
+ return Dali::Window::WindowSize(mWindowWidth, mWindowHeight);
}
void Window::SetPosition(Dali::Window::WindowPosition position)
Dali::Window::WindowPosition Window::GetPosition() const
{
- PositionSize positionSize = mSurface->GetPositionSize();
-
+ PositionSize positionSize = GetPositionSize();
return Dali::Window::WindowPosition(positionSize.x, positionSize.y);
}
PositionSize Window::GetPositionSize() const
{
- return mSurface->GetPositionSize();
+ PositionSize positionSize = mSurface->GetPositionSize();
+ positionSize.width = mWindowWidth;
+ positionSize.height = mWindowHeight;
+ return positionSize;
}
void Window::SetPositionSize(PositionSize positionSize)
{
- PositionSize oldRect = mSurface->GetPositionSize();
+ bool moved = false;
+ bool resize = false;
+
+ PositionSize oldRect = GetPositionSize();
Dali::Window handle(this);
- mWindowSurface->MoveResize(positionSize);
+ if((oldRect.x != positionSize.x) || (oldRect.y != positionSize.y))
+ {
+ moved = true;
+ }
- PositionSize newRect = mSurface->GetPositionSize();
+ if((oldRect.width != positionSize.width) || (oldRect.height != positionSize.height))
+ {
+ resize = true;
+ }
- if((oldRect.x != newRect.x) || (oldRect.y != newRect.y))
+ if(moved || resize)
{
- Dali::Window::WindowPosition position(newRect.x, newRect.y);
+ mWindowSurface->MoveResize(positionSize);
+ }
+
+ // When window is moved, emit Moved Signal
+ if(moved)
+ {
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Moved signal emit (%d, %d)\n", this, mNativeWindowId, positionSize.x, positionSize.y);
+ Dali::Window::WindowPosition position(positionSize.x, positionSize.y);
mMovedSignal.Emit(handle, position);
}
// When surface size is updated, inform adaptor of resizing and emit ResizeSignal
- if((oldRect.width != newRect.width) || (oldRect.height != newRect.height))
+ if(resize)
{
- Uint16Pair newSize(newRect.width, newRect.height);
+ Uint16Pair newSize(positionSize.width, positionSize.height);
- mWindowWidth = newRect.width;
- mWindowHeight = newRect.height;
+ mWindowWidth = positionSize.width;
+ mWindowHeight = positionSize.height;
- SurfaceResized();
+ SurfaceResized(static_cast<float>(mWindowWidth), static_cast<float>(mWindowHeight));
mAdaptor->SurfaceResizePrepare(mSurface.get(), newSize);
- DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), current angle (%d), SetPositionSize():resize signal [%d x %d]\n", this, mNativeWindowId, mRotationAngle, newRect.width, newRect.height);
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Resize signal emit [%d x %d]\n", this, mNativeWindowId, positionSize.width, positionSize.height);
+
mResizeSignal.Emit(handle, newSize);
mAdaptor->SurfaceResizeComplete(mSurface.get(), newSize);
}
void Window::OnOutputTransformed()
{
- PositionSize positionSize = mSurface->GetPositionSize();
+ PositionSize positionSize = GetPositionSize();
- int orientation = (mRotationAngle + mWindowBase->GetScreenRotationAngle()) % 360;
- SurfaceRotated(static_cast<float>(positionSize.width), static_cast<float>(positionSize.height), orientation);
+ SurfaceRotated(static_cast<float>(positionSize.width), static_cast<float>(positionSize.height), mRotationAngle, mWindowBase->GetScreenRotationAngle());
mAdaptor->SurfaceResizePrepare(mSurface.get(), Adaptor::SurfaceSize(positionSize.width, positionSize.height));
mAdaptor->SurfaceResizeComplete(mSurface.get(), Adaptor::SurfaceSize(positionSize.width, positionSize.height));
void Window::OnUpdatePositionSize(Dali::PositionSize& positionSize)
{
- bool resized = false;
- bool moved = false;
- Dali::Window handle(this);
- PositionSize oldRect = mSurface->GetPositionSize();
+ bool moved = false;
+ bool resize = false;
- mWindowSurface->UpdatePositionSize(positionSize);
+ Dali::Window handle(this);
+ PositionSize oldRect = GetPositionSize();
PositionSize newRect = positionSize;
if((oldRect.x != newRect.x) || (oldRect.y != newRect.y))
if((oldRect.width != newRect.width) || (oldRect.height != newRect.height))
{
- resized = true;
+ resize = true;
}
- if(moved)
+ if(moved || resize)
+ {
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), current angle (%d), position or size is updated by server , (%d, %d) [%d x %d]\n", this, mNativeWindowId, mRotationAngle, newRect.x, newRect.y, newRect.width, newRect.height);
+ mWindowSurface->UpdatePositionSize(positionSize);
+ }
+
+ if((oldRect.x != newRect.x) || (oldRect.y != newRect.y))
{
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Moved signal emit (%d, %d)\n", this, mNativeWindowId, newRect.x, newRect.y);
Dali::Window::WindowPosition position(newRect.x, newRect.y);
mMovedSignal.Emit(handle, position);
}
// When surface size is updated, inform adaptor of resizing and emit ResizeSignal
- if(resized)
+ if((oldRect.width != newRect.width) || (oldRect.height != newRect.height))
{
Uint16Pair newSize(newRect.width, newRect.height);
mWindowWidth = newRect.width;
mWindowHeight = newRect.height;
- SurfaceResized();
+ SurfaceResized(static_cast<float>(mWindowWidth), static_cast<float>(mWindowHeight));
mAdaptor->SurfaceResizePrepare(mSurface.get(), newSize);
- DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Updated PositionSize by server :resize signal [%d x %d]\n", this, mNativeWindowId, newRect.width, newRect.height);
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), Resized signal emit [%d x %d]\n", this, mNativeWindowId, newRect.width, newRect.height);
mResizeSignal.Emit(handle, newSize);
mAdaptor->SurfaceResizeComplete(mSurface.get(), newSize);
}
mWindowWidth = rotation.width;
mWindowHeight = rotation.height;
+ mIsWindowRotating = true;
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), angle(%d), Window Rotation (%d , %d) [%d x %d]\n", this, mNativeWindowId, mRotationAngle, newPositionSize.x, newPositionSize.y, mWindowWidth, mWindowHeight);
+
// Notify that the orientation is changed
mOrientation->OnOrientationChange(rotation);
mWindowSurface->RequestRotation(mRotationAngle, newPositionSize);
- int orientation = (mRotationAngle + mWindowBase->GetScreenRotationAngle()) % 360;
- SurfaceRotated(mWindowWidth, mWindowHeight, orientation);
+ SurfaceRotated(static_cast<float>(mWindowWidth), static_cast<float>(mWindowHeight), mRotationAngle, mWindowBase->GetScreenRotationAngle());
mAdaptor->SurfaceResizePrepare(mSurface.get(), Adaptor::SurfaceSize(mWindowWidth, mWindowHeight));
- DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), OnRotation(): x[%d], y[%d], resize signal emit [%d x %d]\n", this, mNativeWindowId, newPositionSize.x, newPositionSize.y, mWindowWidth, mWindowHeight);
- // Emit signal
Dali::Window handle(this);
mResizeSignal.Emit(handle, Dali::Window::WindowSize(mWindowWidth, mWindowHeight));
mAdaptor->SurfaceResizeComplete(mSurface.get(), Adaptor::SurfaceSize(mWindowWidth, mWindowHeight));
}
+void Window::OnRotationFinished()
+{
+ mIsWindowRotating = false;
+ DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), window rotation is finised\n", this, mNativeWindowId);
+}
+
void Window::OnPause()
{
if(mEventHandler)
bool Window::IsWindowRotating() const
{
- return mWindowSurface->IsWindowRotating();
+ return mIsWindowRotating;
}
const Dali::KeyEvent& Window::GetLastKeyEvent() const
void OnAccessibilityDisabled();
/**
+ * Called when the window rotation is finished.
+ *
+ * This signal is emmit when window rotation is finisehd and WindowRotationCompleted() is called.
+ */
+ void OnRotationFinished();
+
+ /**
* @brief Set available orientation to window base.
*/
void SetAvailableAnlges(const std::vector<int>& angles);
bool mOpaqueState : 1;
bool mWindowRotationAcknowledgement : 1;
bool mFocused : 1;
+ bool mIsWindowRotating : 1; ///< The window rotating flag.
};
} // namespace Adaptor
mEGLContext(nullptr),
mColorDepth(isTransparent ? COLOR_DEPTH_32 : COLOR_DEPTH_24),
mOutputTransformedSignal(),
+ mWindowRotationFinishedSignal(),
mFrameCallbackInfoContainer(),
mBufferDamagedRects(),
mMutex(),
mDpiHorizontal(0),
mDpiVertical(0),
mOwnSurface(false),
- mWindowRotationFinished(true),
- mScreenRotationFinished(true),
- mResizeFinished(true),
- mDefaultScreenRotationAvailable(false),
mIsImeWindowSurface(false),
- mNeedWindowRotationAcknowledgement(false)
+ mNeedWindowRotationAcknowledgement(false),
+ mIsWindowOrientationChanging(false)
{
DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "Creating Window\n");
Initialize(surface);
mWindowBase->OutputTransformedSignal().Connect(this, &WindowRenderSurface::OutputTransformed);
// Check screen rotation
- mScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
- if(mScreenRotationAngle != 0)
+ int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
+ if(screenRotationAngle != 0)
{
- mScreenRotationFinished = false;
- mResizeFinished = false;
- mDefaultScreenRotationAvailable = true;
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::Initialize, screen rotation is enabled, screen rotation angle:[%d]\n", mScreenRotationAngle);
+ OutputTransformed();
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::Initialize, screen rotation is enabled, screen rotation angle:[%d]\n", screenRotationAngle);
}
}
TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
}
- mPositionSize = positionSize;
-
- mWindowRotationAngle = angle;
- mWindowRotationFinished = false;
- mResizeFinished = false;
+ mPositionSize.x = positionSize.x;
+ mPositionSize.y = positionSize.y;
- mWindowBase->SetWindowRotationAngle(mWindowRotationAngle);
+ mWindowBase->SetWindowRotationAngle(angle);
- DALI_LOG_RELEASE_INFO("angle = %d screen rotation = %d, flag = %d\n", mWindowRotationAngle, mScreenRotationAngle, mWindowRotationFinished);
+ DALI_LOG_RELEASE_INFO("start window rotation angle = %d screen rotation = %d\n", angle, mScreenRotationAngle);
}
WindowBase* WindowRenderSurface::GetWindowBase()
return mOutputTransformedSignal;
}
+WindowRenderSurface::RotationFinishedSignalType& WindowRenderSurface::RotationFinishedSignal()
+{
+ return mWindowRotationFinishedSignal;
+}
+
PositionSize WindowRenderSurface::GetPositionSize() const
{
return mPositionSize;
dpiVertical = mDpiVertical;
}
-int WindowRenderSurface::GetOrientation() const
+int WindowRenderSurface::GetSurfaceOrientation() const
{
- return mWindowBase->GetOrientation();
+ return mWindowBase->GetWindowRotationAngle();
+}
+
+int WindowRenderSurface::GetScreenOrientation() const
+{
+ return mWindowBase->GetScreenRotationAngle();
}
void WindowRenderSurface::InitializeGraphics()
// Create the EGL window
EGLNativeWindowType window = mWindowBase->CreateEglWindow(width, height);
- // Set screen rotation
- mScreenRotationFinished = false;
-
auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
void WindowRenderSurface::UpdatePositionSize(Dali::PositionSize positionSize)
{
- bool needToMove = false;
- bool needToResize = false;
-
// Check moving
if((fabs(positionSize.x - mPositionSize.x) >= MINIMUM_DIMENSION_CHANGE) ||
(fabs(positionSize.y - mPositionSize.y) >= MINIMUM_DIMENSION_CHANGE))
{
- needToMove = true;
- }
+ mPositionSize.x = positionSize.x;
+ mPositionSize.y = positionSize.y;
- // Check resizing
- if((fabs(positionSize.width - mPositionSize.width) >= MINIMUM_DIMENSION_CHANGE) ||
- (fabs(positionSize.height - mPositionSize.height) >= MINIMUM_DIMENSION_CHANGE))
- {
- needToResize = true;
- }
-
- if(needToResize)
- {
- mResizeFinished = false;
- mPositionSize = positionSize;
+ DALI_LOG_RELEASE_INFO("Update Position by server (%d, %d)\n", mPositionSize.x, mPositionSize.y);
}
- else
- {
- if(needToMove)
- {
- mPositionSize = positionSize;
- }
- }
-
- DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height);
}
void WindowRenderSurface::MoveResize(Dali::PositionSize positionSize)
{
- bool needToMove = false;
- bool needToResize = false;
-
- // Check moving
- if((fabs(positionSize.x - mPositionSize.x) >= MINIMUM_DIMENSION_CHANGE) ||
- (fabs(positionSize.y - mPositionSize.y) >= MINIMUM_DIMENSION_CHANGE))
- {
- needToMove = true;
- }
-
- // Check resizing
- if((fabs(positionSize.width - mPositionSize.width) >= MINIMUM_DIMENSION_CHANGE) ||
- (fabs(positionSize.height - mPositionSize.height) >= MINIMUM_DIMENSION_CHANGE))
- {
- needToResize = true;
- }
-
- if(needToResize)
- {
- if(needToMove)
- {
- mWindowBase->MoveResize(positionSize);
- }
- else
- {
- mWindowBase->Resize(positionSize);
- }
+ mPositionSize.x = positionSize.x;
+ mPositionSize.y = positionSize.y;
- mResizeFinished = false;
- mPositionSize = positionSize;
- }
- else
- {
- if(needToMove)
- {
- mWindowBase->Move(positionSize);
-
- mPositionSize = positionSize;
- }
- }
+ DALI_LOG_RELEASE_INFO("Update Position by client (%d, %d)\n", positionSize.x, positionSize.y);
- DALI_LOG_INFO(gWindowRenderSurfaceLogFilter, Debug::Verbose, "WindowRenderSurface::MoveResize: %d, %d, %d, %d\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height);
+ mWindowBase->MoveResize(positionSize);
}
void WindowRenderSurface::StartRender()
Dali::Integration::Scene::FrameCallbackContainer callbacks;
Dali::Integration::Scene scene = mScene.GetHandle();
+
if(scene)
{
bool needFrameRenderedTrigger = false;
* Notice : PreRotation is not used in the latest tizen,
* because output transform event should be occured before egl window is not created.
*/
-
- if(mIsResizing || mDefaultScreenRotationAvailable)
+ if(scene && resizingSurface)
{
- int totalAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
+ int totalAngle = 0;
+ bool isScreenOrientationChanging = false;
- // Window rotate or screen rotate
- if(!mWindowRotationFinished || !mScreenRotationFinished)
+ if(mWindowRotationAngle != scene.GetCurrentSurfaceOrientation())
{
- mWindowBase->SetEglWindowBufferTransform(totalAngle);
+ mWindowRotationAngle = scene.GetCurrentSurfaceOrientation();
+ mIsWindowOrientationChanging = true;
+ }
+
+ if(mScreenRotationAngle != scene.GetCurrentScreenOrientation())
+ {
+ mScreenRotationAngle = scene.GetCurrentScreenOrientation();
+ isScreenOrientationChanging = true;
+ }
+ totalAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
- // Reset only screen rotation flag
- mScreenRotationFinished = true;
+ DALI_LOG_RELEASE_INFO("Window/Screen orientation ard changed, WinOrientation[%d],flag[%d], ScreenOrientation[%d],flag[%d], total[%d]\n", mWindowRotationAngle, mIsWindowOrientationChanging, mScreenRotationAngle, isScreenOrientationChanging, totalAngle);
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set rotation [%d] [%d]\n", mWindowRotationAngle, mScreenRotationAngle);
+ Rect<int> surfaceSize = scene.GetCurrentSurfaceRect();
+ //update surface size
+ mPositionSize.width = surfaceSize.width;
+ mPositionSize.height = surfaceSize.height;
+
+ DALI_LOG_RELEASE_INFO("Window is resizing, (%d, %d), [%d x %d]\n", mPositionSize.x, mPositionSize.y, mPositionSize.width, mPositionSize.height);
+
+ // Window rotate or screen rotate
+ if(mIsWindowOrientationChanging || isScreenOrientationChanging)
+ {
+ mWindowBase->SetEglWindowBufferTransform(totalAngle);
}
// Only window rotate
- if(!mWindowRotationFinished)
+ if(mIsWindowOrientationChanging)
{
mWindowBase->SetEglWindowTransform(mWindowRotationAngle);
}
// Resize case
- if(!mResizeFinished)
- {
- Dali::PositionSize positionSize;
- positionSize.x = mPositionSize.x;
- positionSize.y = mPositionSize.y;
- if(totalAngle == 0 || totalAngle == 180)
- {
- positionSize.width = mPositionSize.width;
- positionSize.height = mPositionSize.height;
- }
- else
- {
- positionSize.width = mPositionSize.height;
- positionSize.height = mPositionSize.width;
- }
- mWindowBase->ResizeEglWindow(positionSize);
- mResizeFinished = true;
+ Dali::PositionSize positionSize;
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::PreRender: Set resize, totalAngle: %d, x: %d, y: %d, w: %d, h:%d\n", totalAngle, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
+ // Some native resize API(wl_egl_window_resize) has the input parameters of x, y, width and height.
+ // So, position data should be set.
+ positionSize.x = mPositionSize.x;
+ positionSize.y = mPositionSize.y;
+ if(totalAngle == 0 || totalAngle == 180)
+ {
+ positionSize.width = mPositionSize.width;
+ positionSize.height = mPositionSize.height;
+ }
+ else
+ {
+ positionSize.width = mPositionSize.height;
+ positionSize.height = mPositionSize.width;
}
+ mWindowBase->ResizeEglWindow(positionSize);
+
SetFullSwapNextFrame();
- mDefaultScreenRotationAvailable = false;
}
SetBufferDamagedRects(damagedRects, clippingRect);
bool needWindowRotationCompleted = false;
- if(!mWindowRotationFinished)
+ if(mIsWindowOrientationChanging)
{
if(mNeedWindowRotationAcknowledgement)
{
}
else
{
- if(mIsResizing)
- {
- needWindowRotationCompleted = true;
- }
+ needWindowRotationCompleted = true;
}
}
mThreadSynchronization->PostRenderStarted();
}
- if(!mWindowRotationFinished || mIsImeWindowSurface)
+ if(mIsWindowOrientationChanging || mIsImeWindowSurface)
{
mPostRenderTrigger->Trigger();
}
if(mScreenRotationAngle != screenRotationAngle)
{
- mScreenRotationAngle = screenRotationAngle;
- mScreenRotationFinished = false;
- mResizeFinished = false;
-
mOutputTransformedSignal.Emit();
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::OutputTransformed: window = %d screen = %d\n", mWindowRotationAngle, mScreenRotationAngle);
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::OutputTransformed: window = %d new screen angle = %d\n", mWindowRotationAngle, screenRotationAngle);
}
else
{
}
}
-bool WindowRenderSurface::IsWindowRotating() const
-{
- return !(mWindowRotationFinished);
-}
-
void WindowRenderSurface::ProcessPostRender()
{
- if(!mWindowRotationFinished)
+ if(mIsWindowOrientationChanging)
{
+ mWindowRotationFinishedSignal.Emit();
mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
- mWindowRotationFinished = true;
- DALI_LOG_RELEASE_INFO("WindowRenderSurface::ProcessPostRender: Rotation Done, flag = %d\n", mWindowRotationFinished);
+ mIsWindowOrientationChanging = false;
+ DALI_LOG_RELEASE_INFO("WindowRenderSurface::ProcessPostRender: Rotation Done, flag = %d\n", mIsWindowOrientationChanging);
}
if(mIsImeWindowSurface)
class WindowRenderSurface : public Dali::RenderSurfaceInterface, public ConnectionTracker
{
public:
- using OutputSignalType = Signal<void()>;
- using DamagedRectsContainer = std::vector<Rect<int>>;
+
+ using RotationFinishedSignalType = Signal<void()> ; ///<The signal of window rotation's finished.
+ using OutputSignalType = Signal<void()>;
+ using DamagedRectsContainer = std::vector<Rect<int>>;
/**
* Uses an window surface to render to.
void UpdatePositionSize(Dali::PositionSize positionSize);
/**
- * @brief Query whether window is rotating or not.
- *
- * @return true if window is rotating, false otherwise.
+ * @brief This signal is emitted when the output is transformed.
*/
- bool IsWindowRotating() const;
+ OutputSignalType& OutputTransformedSignal();
/**
- * @brief This signal is emitted when the output is transformed.
+ * @brief This signal is emitted when a rotation job is finished.
*/
- OutputSignalType& OutputTransformedSignal();
+ RotationFinishedSignalType& RotationFinishedSignal();
public: // from Dali::RenderSurfaceInterface
/**
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::RenderSurfaceInterface::GetOrientation()
+ * @copydoc Dali::RenderSurfaceInterface::GetSurfaceOrientation()
+ */
+ int GetSurfaceOrientation() const override;
+
+ /**
+ * @copydoc Dali::RenderSurfaceInterface::GetScreenOrientation()
*/
- int GetOrientation() const override;
+ int GetScreenOrientation() const override;
/**
* @copydoc Dali::RenderSurfaceInterface::InitializeGraphics()
EGLSurface mEGLSurface;
EGLContext mEGLContext;
ColorDepth mColorDepth; ///< Color depth of surface (32 bit or 24 bit)
- OutputSignalType mOutputTransformedSignal;
+ OutputSignalType mOutputTransformedSignal; ///< The signal of screen rotation occurs
+ RotationFinishedSignalType mWindowRotationFinishedSignal; ///< The signal of window rotation's finished
FrameCallbackInfoContainer mFrameCallbackInfoContainer;
DamagedRectsContainer mBufferDamagedRects;
Dali::Mutex mMutex;
uint32_t mDpiVertical;
std::vector<Rect<int>> mDamagedRects{}; ///< Keeps collected damaged render items rects for one render pass. These rects are rotated by scene orientation.
bool mOwnSurface; ///< Whether we own the surface (responsible for deleting it)
- bool mWindowRotationFinished;
- bool mScreenRotationFinished;
- bool mResizeFinished;
- bool mDefaultScreenRotationAvailable;
bool mIsImeWindowSurface;
bool mNeedWindowRotationAcknowledgement;
+ bool mIsWindowOrientationChanging;
}; // class WindowRenderSurface
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::Internal::Adaptor::WindowBase::GetWindowRotationAngle()
*/
- int GetOrientation() const override;
+ int GetWindowRotationAngle() const override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenRotationAngle()
dpiVertical = res.height;
}
-int WindowBaseCocoa::GetOrientation() const
+int WindowBaseCocoa::GetWindowRotationAngle() const
{
return 0;
}
dpiVertical = int(yres + 0.5f);
}
-int WindowBaseEcoreWl::GetOrientation() const
+int WindowBaseEcoreWl::GetWindowRotationAngle() const
{
- int orientation = (mScreenRotationAngle + mWindowRotationAngle) % 360;
+ int orientation = mWindowRotationAngle;
if(mSupportedPreProtation)
{
orientation = 0;
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::Internal::Adaptor::WindowBase::GetWindowRotationAngle()
*/
- int GetOrientation() const override;
+ int GetWindowRotationAngle() const override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenRotationAngle()
ecore_wl2_window_geometry_set(mEcoreWindow, mWindowPositionSize.x, mWindowPositionSize.y, mWindowPositionSize.width, mWindowPositionSize.height);
Dali::PositionSize newPositionSize = RecalculatePositionSizeToCurrentOrientation(mWindowPositionSize);
- DALI_LOG_RELEASE_INFO("emit signal to update window's position and size, x[%d] y[%d] w[%d] h[%d]\n", newPositionSize.x, newPositionSize.y, newPositionSize.width, newPositionSize.height);
mUpdatePositionSizeSignal.Emit(newPositionSize);
}
}
}
+ DALI_LOG_RELEASE_INFO("wl_egl_window_tizen_set_buffer_transform() with buffer Transform [%d]\n", bufferTransform);
wl_egl_window_tizen_set_buffer_transform(mEglWindow, bufferTransform);
}
}
}
+ DALI_LOG_RELEASE_INFO("wl_egl_window_tizen_set_window_transform() with window Transform [%d]\n", windowTransform);
wl_egl_window_tizen_set_window_transform(mEglWindow, windowTransform);
}
void WindowBaseEcoreWl2::ResizeEglWindow(PositionSize positionSize)
{
+ DALI_LOG_RELEASE_INFO("wl_egl_window_resize(), (%d, %d) [%d x %d]\n", positionSize.x, positionSize.y, positionSize.width, positionSize.height);
wl_egl_window_resize(mEglWindow, positionSize.width, positionSize.height, positionSize.x, positionSize.y);
// Note: Both "Resize" and "MoveResize" cases can reach here, but only "MoveResize" needs to submit serial number
newPositionSize.height = positionSize.height;
}
- DALI_LOG_RELEASE_INFO("input coord x[%d], y[%d], w{%d], h[%d], screen w[%d], h[%d]\n", positionSize.x, positionSize.y, positionSize.width, positionSize.height, mScreenWidth, mScreenHeight);
- DALI_LOG_RELEASE_INFO("recalc coord x[%d], y[%d], w{%d], h[%d]\n", newPositionSize.x, newPositionSize.y, newPositionSize.width, newPositionSize.height);
-
return newPositionSize;
}
newPositionSize.height = positionSize.height;
}
- DALI_LOG_RELEASE_INFO("input coord x[%d], y[%d], w{%d], h[%d], screen w[%d], h[%d]\n", positionSize.x, positionSize.y, positionSize.width, positionSize.height, mScreenWidth, mScreenHeight);
- DALI_LOG_RELEASE_INFO("recalc by current orientation coord x[%d], y[%d], w{%d], h[%d]\n", newPositionSize.x, newPositionSize.y, newPositionSize.width, newPositionSize.height);
-
return newPositionSize;
}
dpiVertical = int(yres + 0.5f);
}
-int WindowBaseEcoreWl2::GetOrientation() const
+int WindowBaseEcoreWl2::GetWindowRotationAngle() const
{
- int orientation = (mScreenRotationAngle + mWindowRotationAngle) % 360;
+ int orientation = mWindowRotationAngle;
if(mSupportedPreProtation)
{
orientation = 0;
int WindowBaseEcoreWl2::GetScreenRotationAngle()
{
- int transform = 0;
-
+ if(mSupportedPreProtation)
+ {
+ DALI_LOG_RELEASE_INFO("Support PreRotation and return 0\n");
+ return 0;
+ }
+ int transform;
if(ecore_wl2_window_ignore_output_transform_get(mEcoreWindow))
{
transform = 0;
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::Internal::Adaptor::WindowBase::GetWindowRotationAngle()
*/
- int GetOrientation() const override;
+ int GetWindowRotationAngle() const override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenRotationAngle()
dpiVertical = int(yres + 0.5f);
}
-int NativeRenderSurfaceEcoreWl::GetOrientation() const
+int NativeRenderSurfaceEcoreWl::GetSurfaceOrientation() const
+{
+ return 0;
+}
+
+int NativeRenderSurfaceEcoreWl::GetScreenOrientation() const
{
return 0;
}
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::RenderSurfaceInterface::GetOrientation()
+ * @copydoc Dali::RenderSurfaceInterface::GetSurfaceOrientation()
*/
- int GetOrientation() const override;
+ int GetSurfaceOrientation() const override;
+
+ /**
+ * @copydoc Dali::RenderSurfaceInterface::GetScreenOrientation()
+ */
+ int GetScreenOrientation() const override;
/**
* @copydoc Dali::RenderSurfaceInterface::InitializeGraphics()
dpiVertical = int(yres + 0.5f);
}
-int PixmapRenderSurfaceEcoreX::GetOrientation() const
+int PixmapRenderSurfaceEcoreX::GetSurfaceOrientation() const
+{
+ return 0;
+}
+
+int PixmapRenderSurfaceEcoreX::GetScreenOrientation() const
{
return 0;
}
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::RenderSurfaceInterface::GetSurfaceOrientation()
*/
- int GetOrientation() const override;
+ int GetSurfaceOrientation() const override;
+
+ /**
+ * @copydoc Dali::RenderSurfaceInterface::GetScreenOrientation()
+ */
+ int GetScreenOrientation() const override;
/**
* @copydoc Dali::RenderSurfaceInterface::InitializeGraphics()
dpiVertical = ecore_x_dpi_get();
}
-int WindowBaseEcoreX::GetOrientation() const
+int WindowBaseEcoreX::GetWindowRotationAngle() const
{
return 0;
}
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::Internal::Adaptor::WindowBase::GetWindowRotationAngle()
*/
- int GetOrientation() const override;
+ int GetWindowRotationAngle() const override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenRotationAngle()
{
}
-int WindowBaseWin::GetOrientation() const
+int WindowBaseWin::GetWindowRotationAngle() const
{
return 0;
}
void SetTransparency(bool transparent) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::Internal::Adaptor::WindowBase::GetWindowRotationAngle()
*/
- int GetOrientation() const override;
+ int GetWindowRotationAngle() const override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetParent()
WindowSystem::GetImplementation().GetDPI(dpiHorizontal, dpiVertical);
}
-int PixmapRenderSurfaceX::GetOrientation() const
+int PixmapRenderSurfaceX::GetSurfaceOrientation() const
+{
+ return 0;
+}
+
+int PixmapRenderSurfaceX::GetScreenOrientation() const
{
return 0;
}
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::RenderSurfaceInterface::GetSurfaceOrientation()
*/
- int GetOrientation() const override;
+ int GetSurfaceOrientation() const override;
+
+ /**
+ * @copydoc Dali::RenderSurfaceInterface::GetScreenOrientation()
+ */
+ int GetScreenOrientation() const override;
/**
* @copydoc Dali::RenderSurfaceInterface::InitializeGraphics()
WindowSystem::GetImplementation().GetDPI(dpiHorizontal, dpiVertical);
}
-int WindowBaseX::GetOrientation() const
+int WindowBaseX::GetWindowRotationAngle() const
{
return 0;
}
void GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical) override;
/**
- * @copydoc Dali::Internal::Adaptor::WindowBase::GetOrientation()
+ * @copydoc Dali::Internal::Adaptor::WindowBase::GetWindowRotationAngle()
*/
- int GetOrientation() const override;
+ int GetWindowRotationAngle() const override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenRotationAngle()