- SceneView Capture Finished Signal uses CaptureResult struct as a return parameter.
- It is not easy to use.
- Remove State and check success or fail by using nullcheck of ImageUrl
- Make SceneView::Capture always emit CaptureFinished event
Change-Id: I7b99d74e95aaceb6d00ec1eda697b8148851049a
Signed-off-by: Seungho Baek <sbsh.baek@samsung.com>
*/
#include <dali-toolkit-test-suite-utils.h>
-#include <toolkit-event-thread-callback.h>
-#include <toolkit-timer.h>
-
#include <dali-toolkit/dali-toolkit.h>
#include <stdlib.h>
#include <iostream>
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
-
+#include <toolkit-event-thread-callback.h>
using namespace Dali;
using namespace Dali::Toolkit;
END_TEST;
}
-
-namespace
-{
-static bool gCaptureFinishedCalled{false};
-static int32_t gCaptureId{-1};
-static Toolkit::ImageUrl gCapturedImageUrl;
-static Scene3D::SceneView::CaptureFinishState gCaptureFinishState{Scene3D::SceneView::CaptureFinishState::FAILED};
-
-void OnCaptureFinished(Scene3D::SceneView sceneView, Scene3D::SceneView::CaptureResult& captureResult)
-{
- gCaptureFinishedCalled = true;
- gCaptureId = captureResult.captureId;
- gCapturedImageUrl = captureResult.imageUrl;
- gCaptureFinishState = captureResult.state;
-}
-
-static int32_t gCapturedCount{0};
-static std::vector<int32_t> gCaptureIds;
-static std::vector<Toolkit::ImageUrl> gCapturedImageUrls;
-static std::vector<Scene3D::SceneView::CaptureFinishState> gCaptureFinishStates;
-
-void OnCaptureMultipleFinished(Scene3D::SceneView sceneView, Scene3D::SceneView::CaptureResult& captureResult)
-{
- gCapturedCount++;
- gCaptureIds.push_back(captureResult.captureId);
- gCapturedImageUrls.push_back(captureResult.imageUrl);
- gCaptureFinishStates.push_back(captureResult.state);
-}
-} // namespace
-
-int UtcDaliSceneViewCapture01(void)
-{
- ToolkitTestApplication application;
-
- Scene3D::SceneView view = Scene3D::SceneView::New();
- view.CaptureFinishedSignal().Connect(OnCaptureFinished);
- view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
-
- application.GetScene().Add(view);
-
- application.SendNotification();
- application.Render();
-
- Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
- view.Add(modelView1);
-
- application.SendNotification();
- application.Render();
- DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
- application.SendNotification();
- application.Render();
-
- CameraActor camera = Dali::CameraActor::New();
- camera.SetProperty(Dali::Actor::Property::NAME, "camera");
- camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- camera.SetFieldOfView(0.5f);
- camera.SetNearClippingPlane(1.0f);
- camera.SetFarClippingPlane(5000.0f);
- camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
-
- view.Add(camera);
-
- gCaptureFinishedCalled = false;
- gCaptureId = -1;
- gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
- int32_t captureId = view.Capture(camera, Vector2(300, 300));
-
- application.SendNotification();
- application.Render();
- application.SendNotification();
- application.Render();
- application.SendNotification();
-
- DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureId, captureId, TEST_LOCATION);
- DALI_TEST_EQUALS(gCapturedImageUrl.GetUrl().empty(), false, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
-
- Toolkit::ImageUrl tempImageUrl = gCapturedImageUrl;
-
- gCaptureFinishedCalled = false;
- gCaptureId = -1;
- gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
- int32_t captureId2 = view.Capture(camera, Vector2(400, 400));
-
- application.SendNotification();
- application.Render();
- application.SendNotification();
- application.Render();
- application.SendNotification();
-
- DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
- DALI_TEST_NOT_EQUALS(captureId, captureId2, 0.1f, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureId, captureId2, TEST_LOCATION);
- DALI_TEST_EQUALS(gCapturedImageUrl.GetUrl().empty(), false, TEST_LOCATION);
- DALI_TEST_NOT_EQUALS(gCapturedImageUrl, tempImageUrl, 0.1f, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
-
- END_TEST;
-}
-
-int UtcDaliSceneViewCaptureCancel(void)
-{
- ToolkitTestApplication application;
-
- Scene3D::SceneView view = Scene3D::SceneView::New();
- view.CaptureFinishedSignal().Connect(OnCaptureFinished);
- view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
-
- application.GetScene().Add(view);
-
- application.SendNotification();
- application.Render();
-
- Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
- view.Add(modelView1);
-
- application.SendNotification();
- application.Render();
- DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
- application.SendNotification();
- application.Render();
-
- CameraActor camera = Dali::CameraActor::New();
- camera.SetProperty(Dali::Actor::Property::NAME, "camera");
- camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- camera.SetFieldOfView(0.5f);
- camera.SetNearClippingPlane(1.0f);
- camera.SetFarClippingPlane(5000.0f);
- camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
-
- view.Add(camera);
-
- gCaptureFinishedCalled = false;
- gCaptureId = -1;
- gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
- int32_t captureId = view.Capture(camera, Vector2(300, 300));
-
- view.Unparent();
-
- DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureId, captureId, TEST_LOCATION);
- DALI_TEST_EQUALS(!!gCapturedImageUrl, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::FAILED, TEST_LOCATION);
-
-
- gCaptureFinishedCalled = false;
- gCaptureId = -1;
- gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
-
- application.SendNotification();
- application.Render();
- application.SendNotification();
- application.Render();
- application.SendNotification();
-
- DALI_TEST_EQUALS(gCaptureFinishedCalled, false, TEST_LOCATION);
-
- END_TEST;
-}
-
-int UtcDaliSceneViewCaptureFailed(void)
-{
- ToolkitTestApplication application;
-
- Scene3D::SceneView view = Scene3D::SceneView::New();
- view.CaptureFinishedSignal().Connect(OnCaptureFinished);
- view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
-
- application.GetScene().Add(view);
-
- application.SendNotification();
- application.Render();
-
- Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
- view.Add(modelView1);
-
- application.SendNotification();
- application.Render();
- DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
- application.SendNotification();
- application.Render();
-
- CameraActor camera = Dali::CameraActor::New();
- camera.SetProperty(Dali::Actor::Property::NAME, "camera");
- camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- camera.SetFieldOfView(0.5f);
- camera.SetNearClippingPlane(1.0f);
- camera.SetFarClippingPlane(5000.0f);
- camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
-
- view.Add(camera);
-
- gCaptureFinishedCalled = false;
- gCaptureId = -1;
- gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
- int32_t captureId = view.Capture(camera, Vector2(300, 300));
-
- Test::EmitGlobalTimerSignal();
- Test::EmitGlobalTimerSignal();
- Test::EmitGlobalTimerSignal();
-
- DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureId, captureId, TEST_LOCATION);
- DALI_TEST_EQUALS(!!gCapturedImageUrl, false, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureFinishState, Scene3D::SceneView::CaptureFinishState::FAILED, TEST_LOCATION);
-
- gCaptureFinishedCalled = false;
- gCaptureId = -1;
- gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
-
- application.SendNotification();
- application.Render();
- application.SendNotification();
- application.Render();
- application.SendNotification();
-
- DALI_TEST_EQUALS(gCaptureFinishedCalled, false, TEST_LOCATION);
-
- END_TEST;
-}
-
-int UtcDaliSceneViewCapture02(void)
-{
- ToolkitTestApplication application;
-
- Scene3D::SceneView view = Scene3D::SceneView::New();
- view.CaptureFinishedSignal().Connect(OnCaptureMultipleFinished);
- view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
-
- application.GetScene().Add(view);
-
- application.SendNotification();
- application.Render();
-
- Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
- view.Add(modelView1);
-
- application.SendNotification();
- application.Render();
- DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
- application.SendNotification();
- application.Render();
-
- CameraActor camera = Dali::CameraActor::New();
- camera.SetProperty(Dali::Actor::Property::NAME, "camera");
- camera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
- camera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- camera.SetFieldOfView(0.5f);
- camera.SetNearClippingPlane(1.0f);
- camera.SetFarClippingPlane(5000.0f);
- camera.SetProperty(Dali::Actor::Property::POSITION, Vector3(20, 30, 40));
-
- view.Add(camera);
-
- gCapturedCount = 0;
- gCaptureIds.clear();
- gCapturedImageUrls.clear();
- gCaptureFinishStates.clear();
- int32_t captureId = view.Capture(camera, Vector2(300, 300));
- int32_t captureId2 = view.Capture(camera, Vector2(300, 300));
-
- application.SendNotification();
- application.Render();
- application.SendNotification();
- application.Render();
- application.SendNotification();
-
- DALI_TEST_EQUALS(gCapturedCount, 2, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureIds.size(), 2, TEST_LOCATION);
- auto idIter1 = std::find(gCaptureIds.begin(), gCaptureIds.end(), captureId);
- bool isIter1 = idIter1 != gCaptureIds.end();
- DALI_TEST_EQUALS(isIter1, true, TEST_LOCATION);
- auto idIter2 = std::find(gCaptureIds.begin(), gCaptureIds.end(), captureId2);
- bool isIter2 = idIter2 != gCaptureIds.end();
- DALI_TEST_EQUALS(isIter2, true, TEST_LOCATION);
-
- DALI_TEST_EQUALS(gCapturedImageUrls.size(), 2, TEST_LOCATION);
- DALI_TEST_NOT_EQUALS(gCapturedImageUrls[0], gCapturedImageUrls[1], 0.1f, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureFinishStates[0], Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
- DALI_TEST_EQUALS(gCaptureFinishStates[1], Scene3D::SceneView::CaptureFinishState::SUCCEEDED, TEST_LOCATION);
-
- END_TEST;
-}
\ No newline at end of file
DALI_TYPE_REGISTRATION_END()
Property::Index RENDERING_BUFFER = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1;
-constexpr int32_t DEFAULT_ORIENTATION = 0;
-constexpr int32_t INVALID_INDEX = -1;
-constexpr int32_t INVALID_CAPTURE_ID = -1;
-constexpr uint32_t MAXIMUM_SIZE_SHADOW_MAP = 2048;
+static constexpr float MIM_CAPTURE_SIZE = 1.0f;
+static constexpr int32_t DEFAULT_ORIENTATION = 0;
+static constexpr int32_t INVALID_INDEX = -1;
+static constexpr uint32_t MAXIMUM_SIZE_SHADOW_MAP = 2048;
static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity";
mSkybox(),
mSkyboxOrientation(Quaternion()),
mSkyboxIntensity(1.0f),
+ mFailedCaptureCallbacks(nullptr),
mShaderManager(new Scene3D::Loader::ShaderManager())
{
}
Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
mSkyboxLoadTask.Reset();
}
+
+ for(auto&& capture : mCaptureContainer)
+ {
+ ResetCaptureData(capture.second);
+ }
+ mCaptureContainer.clear();
+ ResetCaptureTimer();
+
+ if(mFailedCaptureCallbacks && Adaptor::IsAvailable())
+ {
+ // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
+ Adaptor::Get().RemoveIdle(mFailedCaptureCallbacks);
+ }
}
}
int32_t SceneView::Capture(Dali::CameraActor camera, const Vector2& size)
{
- if(size.x <= 0.0f || size.y <= 0.0f)
+ bool capturePossible = true;
+ if(size.x < MIM_CAPTURE_SIZE || size.y < MIM_CAPTURE_SIZE)
{
DALI_LOG_ERROR("The width and height should be positive.\n");
- return INVALID_CAPTURE_ID;
+ capturePossible = false;
}
if(!mRenderTask)
{
DALI_LOG_ERROR("Capture Should be requested after the SceneView is on scene.");
- return INVALID_CAPTURE_ID;
+ capturePossible = false;
}
- uint32_t width = unsigned(size.width);
- uint32_t height = unsigned(size.height);
+ uint32_t width = std::max(1u, unsigned(size.width));
+ uint32_t height = std::max(1u, unsigned(size.height));
if(width > Dali::GetMaxTextureSize() || height > Dali::GetMaxTextureSize())
{
DALI_LOG_ERROR("The input size is too large.\n");
- return INVALID_CAPTURE_ID;
+ capturePossible = false;
}
if(!mRootLayer.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
{
DALI_LOG_ERROR("Current SceneView is not connected on scene tree\n");
- return INVALID_CAPTURE_ID;
+ capturePossible = false;
}
- if(!camera.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
+ if(!capturePossible)
{
- mRootLayer.Add(camera);
+ mFailedCaptureRequests.push_back(mCaptureId);
+ if(!mFailedCaptureCallbacks && DALI_LIKELY(Adaptor::IsAvailable()))
+ {
+ mFailedCaptureCallbacks = MakeCallback(this, &SceneView::OnCaptureFailedIdle);
+ if(!Adaptor::Get().AddIdle(mFailedCaptureCallbacks, false))
+ {
+ mFailedCaptureCallbacks = nullptr;
+ }
+ }
}
+ else
+ {
+ if(!camera.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
+ {
+ mRootLayer.Add(camera);
+ }
- std::shared_ptr<CaptureData> captureData = std::make_shared<CaptureData>();
- captureData->mCaptureId = mCaptureId;
- captureData->mCaptureTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
- captureData->mCaptureFrameBuffer = Dali::FrameBuffer::New(captureData->mCaptureTexture.GetWidth(), captureData->mCaptureTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH_STENCIL);
- DevelFrameBuffer::SetMultiSamplingLevel(captureData->mCaptureFrameBuffer, mFrameBufferMultiSamplingLevel);
- captureData->mCaptureFrameBuffer.AttachColorTexture(captureData->mCaptureTexture);
-
- RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
- captureData->mCaptureTask = taskList.CreateTask();
- captureData->mCaptureTask.SetSourceActor(mRootLayer);
- captureData->mCaptureTask.SetExclusive(true);
- captureData->mCaptureTask.SetCullMode(false);
- captureData->mCaptureTask.SetCameraActor(camera);
- captureData->mCaptureTask.SetFrameBuffer(captureData->mCaptureFrameBuffer);
- captureData->mCaptureTask.SetClearEnabled(true);
- captureData->mCaptureTask.SetClearColor(Color::TRANSPARENT);
- captureData->mCaptureTask.SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
-
- captureData->mCaptureInvertCamera = Dali::CameraActor::New(size);
- captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
- captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
- captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::POSITION_X, size.x / 2.0f);
- captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::POSITION_Y, size.y / 2.0f);
-
- captureData->mCaptureUrl = Dali::Toolkit::Image::GenerateUrl(captureData->mCaptureFrameBuffer, 0u);
- captureData->mCaptureImageView = Dali::Toolkit::ImageView::New(captureData->mCaptureUrl.GetUrl());
- captureData->mCaptureImageView.SetProperty(Dali::Actor::Property::SIZE, size);
- captureData->mCaptureImageView.Add(captureData->mCaptureInvertCamera);
-
- mSceneHolder.Add(captureData->mCaptureImageView);
-
- captureData->mCaptureInvertTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
- captureData->mCaptureInvertFrameBuffer = Dali::FrameBuffer::New(captureData->mCaptureInvertTexture.GetWidth(), captureData->mCaptureInvertTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH_STENCIL);
- captureData->mCaptureInvertFrameBuffer.AttachColorTexture(captureData->mCaptureInvertTexture);
-
- captureData->mCaptureInvertTask = taskList.CreateTask();
- captureData->mCaptureInvertTask.SetSourceActor(captureData->mCaptureImageView);
- captureData->mCaptureInvertTask.SetExclusive(true);
- captureData->mCaptureInvertTask.SetCullMode(false);
- captureData->mCaptureInvertTask.SetCameraActor(captureData->mCaptureInvertCamera);
- captureData->mCaptureInvertTask.SetFrameBuffer(captureData->mCaptureInvertFrameBuffer);
- captureData->mCaptureInvertTask.SetClearEnabled(true);
- captureData->mCaptureInvertTask.SetClearColor(Color::TRANSPARENT);
- captureData->mCaptureInvertTask.SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
- captureData->mCaptureInvertTask.FinishedSignal().Connect(this, &SceneView::OnCaptureFinished);
-
- captureData->mStartTick = mTimerTickCount;
-
- mCaptureContainer.push_back(std::make_pair(captureData->mCaptureInvertTask, captureData));
-
- if(!mCaptureTimer)
- {
- mCaptureTimer = Dali::Timer::New(1000);
- mCaptureTimer.TickSignal().Connect(this, &SceneView::OnTimeOut);
- mCaptureTimer.Start();
+ std::shared_ptr<CaptureData> captureData = std::make_shared<CaptureData>();
+ captureData->mCaptureId = mCaptureId;
+ captureData->mCaptureTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+ captureData->mCaptureFrameBuffer = Dali::FrameBuffer::New(captureData->mCaptureTexture.GetWidth(), captureData->mCaptureTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH_STENCIL);
+ DevelFrameBuffer::SetMultiSamplingLevel(captureData->mCaptureFrameBuffer, mFrameBufferMultiSamplingLevel);
+ captureData->mCaptureFrameBuffer.AttachColorTexture(captureData->mCaptureTexture);
+
+ captureData->mCaptureCamera = camera;
+ captureData->mCaptureCameraOriginalAspectRatio = captureData->mCaptureCamera.GetAspectRatio();
+ captureData->mCaptureCamera.SetAspectRatio((float)width / (float)height);
+
+ RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
+ captureData->mCaptureTask = taskList.CreateTask();
+ captureData->mCaptureTask.SetSourceActor(mRootLayer);
+ captureData->mCaptureTask.SetExclusive(true);
+ captureData->mCaptureTask.SetCullMode(false);
+ captureData->mCaptureTask.SetCameraActor(captureData->mCaptureCamera);
+ captureData->mCaptureTask.SetFrameBuffer(captureData->mCaptureFrameBuffer);
+ captureData->mCaptureTask.SetClearEnabled(true);
+ captureData->mCaptureTask.SetClearColor(Color::TRANSPARENT);
+ captureData->mCaptureTask.SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
+
+ captureData->mCaptureInvertCamera = Dali::CameraActor::New(size);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::POSITION_X, size.x / 2.0f);
+ captureData->mCaptureInvertCamera.SetProperty(Dali::Actor::Property::POSITION_Y, size.y / 2.0f);
+
+ captureData->mCaptureUrl = Dali::Toolkit::Image::GenerateUrl(captureData->mCaptureFrameBuffer, 0u);
+ captureData->mCaptureImageView = Dali::Toolkit::ImageView::New(captureData->mCaptureUrl.GetUrl());
+ captureData->mCaptureImageView.SetProperty(Dali::Actor::Property::SIZE, size);
+ captureData->mCaptureImageView.Add(captureData->mCaptureInvertCamera);
+
+ mSceneHolder.Add(captureData->mCaptureImageView);
+
+ captureData->mCaptureInvertTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+ captureData->mCaptureInvertFrameBuffer = Dali::FrameBuffer::New(captureData->mCaptureInvertTexture.GetWidth(), captureData->mCaptureInvertTexture.GetHeight(), Dali::FrameBuffer::Attachment::DEPTH_STENCIL);
+ captureData->mCaptureInvertFrameBuffer.AttachColorTexture(captureData->mCaptureInvertTexture);
+
+ captureData->mCaptureInvertTask = taskList.CreateTask();
+ captureData->mCaptureInvertTask.SetSourceActor(captureData->mCaptureImageView);
+ captureData->mCaptureInvertTask.SetExclusive(true);
+ captureData->mCaptureInvertTask.SetCullMode(false);
+ captureData->mCaptureInvertTask.SetCameraActor(captureData->mCaptureInvertCamera);
+ captureData->mCaptureInvertTask.SetFrameBuffer(captureData->mCaptureInvertFrameBuffer);
+ captureData->mCaptureInvertTask.SetClearEnabled(true);
+ captureData->mCaptureInvertTask.SetClearColor(Color::TRANSPARENT);
+ captureData->mCaptureInvertTask.SetRefreshRate(Dali::RenderTask::REFRESH_ONCE);
+ captureData->mCaptureInvertTask.FinishedSignal().Connect(this, &SceneView::OnCaptureFinished);
+
+ captureData->mStartTick = mTimerTickCount;
+
+ mCaptureContainer.push_back(std::make_pair(captureData->mCaptureInvertTask, captureData));
+
+ if(!mCaptureTimer)
+ {
+ mCaptureTimer = Dali::Timer::New(1000);
+ mCaptureTimer.TickSignal().Connect(this, &SceneView::OnTimeOut);
+ mCaptureTimer.Start();
+ }
}
return mCaptureId++;
}
std::vector<std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>>> tempContainer(mCaptureContainer);
for(auto&& capture : tempContainer)
{
- Dali::Scene3D::SceneView::CaptureResult result{capture.second->mCaptureId, Dali::Toolkit::ImageUrl(), Dali::Scene3D::SceneView::CaptureFinishState::FAILED};
- mCaptureFinishedSignal.Emit(handle, result);
+ mCaptureFinishedSignal.Emit(handle, capture.second->mCaptureId, Dali::Toolkit::ImageUrl());
}
tempContainer.clear();
for(auto && capture : mCaptureContainer)
{
- if(mSceneHolder)
- {
- RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
- taskList.RemoveTask(capture.second->mCaptureTask);
- taskList.RemoveTask(capture.second->mCaptureInvertTask);
- }
- capture.second->mCaptureTask.Reset();
- capture.second->mCaptureInvertTask.Reset();
- capture.second->mCaptureTexture.Reset();
- capture.second->mCaptureInvertTexture.Reset();
- capture.second->mCaptureFrameBuffer.Reset();
- capture.second->mCaptureInvertFrameBuffer.Reset();
- capture.second->mCaptureUrl.Reset();
- capture.second->mCaptureImageView.Unparent();
- capture.second->mCaptureImageView.Reset();
- capture.second->mCaptureInvertCamera.Unparent();
- capture.second->mCaptureInvertCamera.Reset();
+ ResetCaptureData(capture.second);
}
mCaptureContainer.clear();
+ ResetCaptureTimer();
if(mSceneHolder)
{
void SceneView::OnCaptureFinished(Dali::RenderTask& task)
{
- int32_t captureId = INVALID_CAPTURE_ID;
- Dali::Toolkit::ImageUrl imageUrl;
-
auto iter = std::find_if(mCaptureContainer.begin(), mCaptureContainer.end(), [task](std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>> item)
{ return item.first == task; });
+ int32_t captureId = iter->second->mCaptureId;
+ Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(iter->second->mCaptureInvertTexture);
+
if(iter != mCaptureContainer.end())
{
- captureId = iter->second->mCaptureId;
- imageUrl = Dali::Toolkit::ImageUrl::New(iter->second->mCaptureInvertTexture);
- if(mSceneHolder)
- {
- RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
- taskList.RemoveTask(iter->second->mCaptureTask);
- taskList.RemoveTask(iter->second->mCaptureInvertTask);
- }
- iter->second->mCaptureTexture.Reset();
- iter->second->mCaptureInvertTexture.Reset();
- iter->second->mCaptureFrameBuffer.Reset();
- iter->second->mCaptureInvertFrameBuffer.Reset();
- iter->second->mCaptureUrl.Reset();
- iter->second->mCaptureImageView.Unparent();
- iter->second->mCaptureImageView.Reset();
+ captureId = iter->second->mCaptureId;
+ imageUrl = Dali::Toolkit::ImageUrl::New(iter->second->mCaptureInvertTexture);
+ ResetCaptureData(iter->second);
mCaptureContainer.erase(iter);
auto self = Self();
Dali::Scene3D::SceneView handle(Dali::Scene3D::SceneView::DownCast(self));
-
- Dali::Scene3D::SceneView::CaptureResult result{captureId, imageUrl, Dali::Scene3D::SceneView::CaptureFinishState::SUCCEEDED};
- mCaptureFinishedSignal.Emit(handle, result);
+ mCaptureFinishedSignal.Emit(handle, captureId, imageUrl);
}
- if(mCaptureContainer.empty() && mCaptureTimer)
- {
- mCaptureTimer.Stop();
- mCaptureTimer.Reset();
- mTimerTickCount = 0;
- }
+ ResetCaptureTimer();
}
bool SceneView::OnTimeOut()
for(auto&& capture : tempContainer)
{
- Dali::Scene3D::SceneView::CaptureResult result{capture.second->mCaptureId, Dali::Toolkit::ImageUrl(), Dali::Scene3D::SceneView::CaptureFinishState::FAILED};
- mCaptureFinishedSignal.Emit(handle, result);
+ mCaptureFinishedSignal.Emit(handle, capture.second->mCaptureId, Dali::Toolkit::ImageUrl());
+ }
+
+ for(auto && capture : tempContainer)
+ {
+ ResetCaptureData(capture.second);
}
+ tempContainer.clear();
int32_t tickCount = mTimerTickCount;
auto it = std::remove_if(mCaptureContainer.begin(), mCaptureContainer.end(), [tickCount](std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>> item) {
mCaptureContainer.erase(it, mCaptureContainer.end());
mCaptureContainer.shrink_to_fit();
+ ResetCaptureTimer();
+
+ return !mCaptureContainer.empty();
+}
+
+void SceneView::ResetCaptureData(std::shared_ptr<CaptureData> captureData)
+{
+ captureData->mCaptureCamera.SetAspectRatio(captureData->mCaptureCameraOriginalAspectRatio);
+ if(mSceneHolder)
+ {
+ RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
+ taskList.RemoveTask(captureData->mCaptureTask);
+ taskList.RemoveTask(captureData->mCaptureInvertTask);
+ }
+ captureData->mCaptureTask.Reset();
+ captureData->mCaptureInvertTask.Reset();
+ captureData->mCaptureTexture.Reset();
+ captureData->mCaptureInvertTexture.Reset();
+ captureData->mCaptureFrameBuffer.Reset();
+ captureData->mCaptureInvertFrameBuffer.Reset();
+ captureData->mCaptureUrl.Reset();
+ captureData->mCaptureImageView.Unparent();
+ captureData->mCaptureImageView.Reset();
+ captureData->mCaptureInvertCamera.Unparent();
+ captureData->mCaptureInvertCamera.Reset();
+}
+
+void SceneView::ResetCaptureTimer()
+{
if(mCaptureContainer.empty() && mCaptureTimer)
{
mCaptureTimer.Stop();
mCaptureTimer.Reset();
mTimerTickCount = 0;
}
+}
- return !mCaptureContainer.empty();
+void SceneView::OnCaptureFailedIdle()
+{
+ for(auto&& captureId : mFailedCaptureRequests)
+ {
+ auto self = Self();
+ Dali::Scene3D::SceneView handle(Dali::Scene3D::SceneView::DownCast(self));
+ mCaptureFinishedSignal.Emit(handle, captureId, Dali::Toolkit::ImageUrl());
+ }
+ mFailedCaptureCallbacks = nullptr;
}
} // namespace Internal
class SceneView : public Dali::Toolkit::Internal::Control
{
public:
+ /**
+ * Data to store Capture related objects.
+ */
+ struct CaptureData
+ {
+ int32_t mStartTick;
+ int32_t mCaptureId; // Unique Key to distinguish requested Captures.
+ float mCaptureCameraOriginalAspectRatio; // Original AspectRatio of the input cameras
+ Dali::Toolkit::ImageUrl mCaptureUrl; // URL for first captured buffer, but it is Y-inverted.
+ Dali::Toolkit::ImageView mCaptureImageView; // ImageView to draw first capture buffer to be transfered as input for invert.
+ Dali::CameraActor mCaptureCamera; // CameraActor to draw first capture buffer
+ Dali::RenderTask mCaptureTask; // RenderTask that is used to capture first buffer.
+ Dali::Texture mCaptureTexture; // First Captured texture, but it is Y-inverted.
+ Dali::FrameBuffer mCaptureFrameBuffer; // First Captured FBO, but it is Y-inverted.
+ Dali::CameraActor mCaptureInvertCamera; // CameraActor to invert first captured buffer by second pass.
+ Dali::RenderTask mCaptureInvertTask; // RenderTask to invert first captured buffer.
+ Dali::Texture mCaptureInvertTexture; // Result texture of second pass. This is final Texture result.
+ Dali::FrameBuffer mCaptureInvertFrameBuffer; // FBO for firnal Texture result
+ };
+
/**
* @brief Creates a new SceneView.
*
*/
bool OnTimeOut();
-private:
/**
- * Data to store Capture related objects.
+ * @brief Reset CaptureData when the capture is finished or failed.
+ * @param[in] captureData CaptureData to be reset.
*/
- struct CaptureData
- {
- int32_t mStartTick;
- int32_t mCaptureId; // Unique Key to distinguish requested Captures.
- Dali::Toolkit::ImageUrl mCaptureUrl; // URL for first captured buffer, but it is Y-inverted.
- Dali::Toolkit::ImageView mCaptureImageView; // ImageView to draw first capture buffer to be transfered as input for invert.
- Dali::RenderTask mCaptureTask; // RenderTask that is used to capture first buffer.
- Dali::Texture mCaptureTexture; // First Captured texture, but it is Y-inverted.
- Dali::FrameBuffer mCaptureFrameBuffer; // First Captured FBO, but it is Y-inverted.
- Dali::CameraActor mCaptureInvertCamera; // CameraActor to invert first captured buffer by second pass.
- Dali::RenderTask mCaptureInvertTask; // RenderTask to invert first captured buffer.
- Dali::Texture mCaptureInvertTexture; // Result texture of second pass. This is final Texture result.
- Dali::FrameBuffer mCaptureInvertFrameBuffer; // FBO for firnal Texture result
- };
+ void ResetCaptureData(std::shared_ptr<CaptureData> captureData);
+
+ /**
+ * @brief Reset Capture timer when there isn't any capture in progress.
+ */
+ void ResetCaptureTimer();
+ /**
+ * @brief Emit capture failed event on idle.
+ */
+ void OnCaptureFailedIdle();
+
+private:
Toolkit::Visual::Base mVisual;
/////////////////////////////////////////////////////////////
float mSkyboxIntensity{1.0f};
uint8_t mFrameBufferMultiSamplingLevel{4u};
Dali::Scene3D::SceneView::CaptureFinishedSignalType mCaptureFinishedSignal;
+ std::vector<int32_t> mFailedCaptureRequests;
+ CallbackBase* mFailedCaptureCallbacks;
int32_t mCaptureId{0}; // Capture ID for requested capture, this is incrementally increasing.
std::vector<std::pair<Dali::RenderTask, std::shared_ptr<CaptureData>>> mCaptureContainer; // Container that stores CaptureData until the Capture is finished.
};
};
- /**
- * @brief The enumerations used for checking capture success
- * @SINCE_2_3.25
- */
- enum class CaptureFinishState
- {
- SUCCEEDED, ///< Succeeded to capture
- FAILED ///< Failed to capture by time out
- };
-
public:
- struct CaptureResult
- {
- int32_t captureId;
- Dali::Toolkit::ImageUrl imageUrl;
- CaptureFinishState state;
- };
-
/**
* @brief Typedef for capture finished signals sent by this class.
- *
- * @SINCE_2_3.25
*/
- typedef Signal<void(SceneView, CaptureResult&)> CaptureFinishedSignalType;
+ typedef Signal<void(SceneView, int32_t, const Dali::Toolkit::ImageUrl&)> CaptureFinishedSignalType;
/**
* @brief Create an initialized SceneView.
/**
* @brief Requests to capture this SceneView with the Camera.
*
- * @SINCE_2_3.25
* @param[in] camera CameraActor to be used for capture.
* @param[in] size captured size.
- * @note The camera is required to be added in this SceneView. (Not need to be a selected camera)
+ * @note The input camera should not be used for any other purpose during Capture.
+ * (Simultaneous usage elsewhere may result in incorrect rendering.)
+ * @note The camera is required to be added in this SceneView. (But should not be a selected camera.)
* @note If the SceneView is disconnected from Scene, the left capture requests are canceled.
* @return capture id that id unique value to distinguish each requiest.
*/
/**
* @brief Get capture finished signal.
*
- * @SINCE_2_3.25
* @return finished signal instance.
*/
CaptureFinishedSignalType& CaptureFinishedSignal();