- 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
Change-Id: I32b885d93c670d5ad90601872e47f8c4fd6c03f9
Signed-off-by: Seungho Baek <sbsh.baek@samsung.com>
namespace
{
-static bool gCaptureFinishedCalled{false};
-static int32_t gCaptureId{-1};
-static Toolkit::ImageUrl gCapturedImageUrl;
-static Scene3D::SceneView::CaptureFinishState gCaptureFinishState{Scene3D::SceneView::CaptureFinishState::FAILED};
+static bool gCaptureFinishedCalled{false};
+static int32_t gCaptureId{-1};
+static Toolkit::ImageUrl gCapturedImageUrl;
-void OnCaptureFinished(Scene3D::SceneView sceneView, Scene3D::SceneView::CaptureResult& captureResult)
+void OnCaptureFinished(Scene3D::SceneView sceneView, int32_t captureId, const Toolkit::ImageUrl& capturedImageUrl)
{
gCaptureFinishedCalled = true;
- gCaptureId = captureResult.captureId;
- gCapturedImageUrl = captureResult.imageUrl;
- gCaptureFinishState = captureResult.state;
+ gCaptureId = captureId;
+ gCapturedImageUrl = capturedImageUrl;
}
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)
+void OnCaptureMultipleFinished(Scene3D::SceneView sceneView, int32_t captureId, const Toolkit::ImageUrl& capturedImageUrl)
{
gCapturedCount++;
- gCaptureIds.push_back(captureResult.captureId);
- gCapturedImageUrls.push_back(captureResult.imageUrl);
- gCaptureFinishStates.push_back(captureResult.state);
+ gCaptureIds.push_back(captureId);
+ gCapturedImageUrls.push_back(capturedImageUrl);
}
} // namespace
gCaptureFinishedCalled = false;
gCaptureId = -1;
gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
int32_t captureId = view.Capture(camera, Vector2(300, 300));
application.SendNotification();
DALI_TEST_EQUALS(gCaptureFinishedCalled, true, TEST_LOCATION);
DALI_TEST_EQUALS(gCaptureId, captureId, TEST_LOCATION);
+ DALI_TEST_EQUALS(!!gCapturedImageUrl, true, 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();
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, true, 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;
}
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();
gCaptureFinishedCalled = false;
gCaptureId = -1;
gCapturedImageUrl.Reset();
- gCaptureFinishState = Scene3D::SceneView::CaptureFinishState::FAILED;
int32_t captureId = view.Capture(camera, Vector2(300, 300));
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();
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));
DALI_TEST_EQUALS(isIter2, true, TEST_LOCATION);
DALI_TEST_EQUALS(gCapturedImageUrls.size(), 2, TEST_LOCATION);
+ DALI_TEST_EQUALS(!!gCapturedImageUrls[0], true, TEST_LOCATION);
+ DALI_TEST_EQUALS(!!gCapturedImageUrls[1], true, 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;
}
ResetTransition();
}
+ for(auto&& capture : mCaptureContainer)
+ {
+ ResetCaptureData(capture.second);
+ }
+ mCaptureContainer.clear();
+ ResetCaptureTimer();
+
// Request image resource GC
Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
int32_t SceneView::Capture(Dali::CameraActor camera, const Vector2& size)
{
- if(size.x <= 0.0f || size.y <= 0.0f)
+ if(size.x < 0.0f || size.y < 0.0f)
{
DALI_LOG_ERROR("The width and height should be positive.\n");
return INVALID_CAPTURE_ID;
}
- 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");
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.SetOrderIndex(SCENE_ORDER_INDEX + 1);
- captureData->mCaptureTask.SetCameraActor(camera);
+ captureData->mCaptureTask.SetCameraActor(captureData->mCaptureCamera);
captureData->mCaptureTask.SetFrameBuffer(captureData->mCaptureFrameBuffer);
captureData->mCaptureTask.SetClearEnabled(true);
captureData->mCaptureTask.SetClearColor(Color::TRANSPARENT);
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)
{
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) {
return item.second->mStartTick + 1 < tickCount;
mCaptureContainer.erase(it, mCaptureContainer.end());
mCaptureContainer.shrink_to_fit();
- if(mCaptureContainer.empty() && mCaptureTimer)
- {
- mCaptureTimer.Stop();
- mCaptureTimer.Reset();
- mTimerTickCount = 0;
- }
+ ResetCaptureTimer();
return !mCaptureContainer.empty();
}
mCameraTransitionFinishedSignal.Emit(handle);
}
+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;
+ }
+}
+
void SceneView::Process(bool postProcessor)
{
CameraActor selectedCamera = GetSelectedCamera();
*/
class SceneView : public Dali::Toolkit::Internal::Control, public Integration::Processor
{
+
+private:
+ /**
+ * 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
+ };
+
public:
/**
* @brief Creates a new SceneView.
*/
void OnTransitionFinished(Animation& animation);
+ /**
+ * @brief Reset CaptureData when the capture is finished or failed.
+ * @param[in] captureData CaptureData to be reset.
+ */
+ void ResetCaptureData(std::shared_ptr<CaptureData> captureData);
+
+ /**
+ * @brief Reset Capture timer when there isn't any capture in progress.
+ */
+ void ResetCaptureTimer();
+
private: // Implementation of Processor
/**
return "SceneViewImpl";
}
-private:
- /**
- * Data to store Capture related objects.
- */
- 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
- };
-
Toolkit::Visual::Base mVisual;
/////////////////////////////////////////////////////////////
};
};
- /**
- * @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
+ * @SINCE_2_3.37
*/
- typedef Signal<void(SceneView, CaptureResult&)> CaptureFinishedSignalType;
+ typedef Signal<void(SceneView, int32_t, const Dali::Toolkit::ImageUrl&)> CaptureFinishedSignalType;
/**
* @brief Typedef for camera transition finished signals sent by this class.
* @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.
*/