#define TEST_GL_ABSTRACTION_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
inline void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) override
{
+ std::stringstream out;
+ out << mode << ", " << first << ", " << count << ", " << instanceCount;
+ TraceCallStack::NamedParams namedParams;
+ namedParams["mode"] << std::hex << mode;
+ namedParams["first"] << first;
+ namedParams["count"] << count;
+ namedParams["instanceCount"] << instanceCount;
+ mDrawTrace.PushCall("DrawArraysInstanced", out.str(), namedParams);
}
inline void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) override
{
+ std::stringstream out;
+ out << mode << ", " << count << ", " << type << ", " << instanceCount;
+ TraceCallStack::NamedParams namedParams;
+ namedParams["mode"] << std::hex << mode;
+ namedParams["count"] << count;
+ namedParams["type"] << std::hex << type;
+ namedParams["indexCount"] << instanceCount;
+ mDrawTrace.PushCall("DrawElementsInstanced", out.str(), namedParams);
}
inline GLsync FenceSync(GLenum condition, GLbitfield flags) override
inline void VertexAttribDivisor(GLuint index, GLuint divisor) override
{
+ std::stringstream out;
+ out << index << ", " << divisor;
+ TraceCallStack::NamedParams namedParams;
+ namedParams["index"] << index;
+ namedParams["divisor"] << divisor;
+ mBufferTrace.PushCall("VertexAttribDivisor", out.str(), namedParams);
}
inline void BindTransformFeedback(GLenum target, GLuint id) override
{
if(currentPipeline)
{
- mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
- 0,
- cmd.data.draw.draw.vertexCount);
+ if(cmd.data.draw.draw.instanceCount == 0)
+ {
+ mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
+ 0,
+ cmd.data.draw.draw.vertexCount);
+ }
+ else
+ {
+ mGl.DrawArraysInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
+ 0,
+ cmd.data.draw.draw.vertexCount,
+ cmd.data.draw.draw.instanceCount);
+ }
}
break;
}
{
if(currentPipeline)
{
- mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
- static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
- GL_UNSIGNED_SHORT,
- reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+ if(cmd.data.draw.draw.instanceCount == 0)
+ {
+ mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
+ static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+ GL_UNSIGNED_SHORT,
+ reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+ }
+ else
+ {
+ mGl.DrawElementsInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
+ static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+ GL_UNSIGNED_SHORT,
+ reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex),
+ cmd.data.draw.drawIndexed.instanceCount);
+ }
}
break;
}
uint32_t attributeOffset = attribute.offset;
GLsizei stride = vi.bufferBindings[attribute.binding].stride;
+ auto rate = vi.bufferBindings[attribute.binding].inputRate;
+
mGl.VertexAttribPointer(attribute.location,
GetNumComponents(attribute.format),
GetGlType(attribute.format),
GL_FALSE, // Not normalized
stride,
reinterpret_cast<void*>(attributeOffset));
+ if(rate == Graphics::VertexInputRate::PER_VERTEX)
+ {
+ mGl.VertexAttribDivisor(attribute.location, 0);
+ }
+ else if(rate == Graphics::VertexInputRate::PER_INSTANCE)
+ {
+ mGl.VertexAttribDivisor(attribute.location, 1);
+ }
}
// Cull face setup
#include <dali-test-suite-utils.h>
#include <dali/public-api/dali-core.h>
+#include <mesh-builder.h>
#include <stdlib.h>
#include <iostream>
ComponentTest::CheckComponentProperty(application, actor, Actor::Property::COLOR_ALPHA); // Component 3
END_TEST;
+}
+
+
+namespace PostConstraintTest
+{
+void CheckComponentProperty(TestApplication& application, Actor& actor, Handle target)
+{
+ actor.SetProperty(Actor::Property::POSITION, Vector3::ONE);
+ DALI_TEST_EQUALS(actor.GetProperty<Vector3>(Actor::Property::POSITION), Vector3::ONE, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ actor.SetProperty(Actor::Property::POSITION, Vector3::ONE * 2.0f);
+
+ DALI_TEST_EQUALS(actor.GetProperty<Vector3>(Actor::Property::POSITION), Vector3::ONE * 2.0f, TEST_LOCATION);
+ DALI_TEST_EQUALS(actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION), Vector3::ONE, TEST_LOCATION);
+
+ Property::Index prePropertyIndex = target.RegisterProperty("testPreProperty", Vector3::ZERO);
+ Constraint preConstraint = Constraint::New<Vector3>(target, prePropertyIndex, [](Vector3& output, const PropertyInputContainer& inputs) {
+ output = inputs[0]->GetVector3();
+ });
+ preConstraint.AddSource(Source{actor, Actor::Property::WORLD_POSITION});
+ preConstraint.Apply();
+
+ Property::Index postPropertyIndex = target.RegisterProperty("testPostProperty", Vector3::ZERO);
+ Constraint postConstraint = Constraint::New<Vector3>(target, postPropertyIndex, [](Vector3& output, const PropertyInputContainer& inputs) {
+ output = inputs[0]->GetVector3();
+ });
+ postConstraint.AddSource(Source{actor, Actor::Property::WORLD_POSITION});
+ postConstraint.ApplyPost();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS(target.GetCurrentProperty<Vector3>(prePropertyIndex), Vector3(-239.0, -399.0, 1.0), TEST_LOCATION);
+ DALI_TEST_EQUALS(target.GetCurrentProperty<Vector3>(postPropertyIndex), Vector3(-238.0, -398.0, 2.0), TEST_LOCATION);
+
+ preConstraint.Remove();
+ postConstraint.Remove();
+}
+}
+
+int UtcDaliConstraintApplyPost(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ application.GetScene().Add(actor);
+
+ Geometry targetGeometry = CreateQuadGeometry();
+ Shader targetShader = CreateShader();
+ Renderer targetRenderer = Renderer::New(targetGeometry, targetShader);
+ Actor targetActor = Actor::New();
+ RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+
+ application.GetScene().Add(targetActor);
+ PostConstraintTest::CheckComponentProperty(application, actor, targetShader); // Shader
+ PostConstraintTest::CheckComponentProperty(application, actor, targetRenderer); // Renderer
+ PostConstraintTest::CheckComponentProperty(application, actor, targetActor); // Actor(Node)
+ PostConstraintTest::CheckComponentProperty(application, actor, taskList.GetTask(0u)); // RenderTask
+
+ END_TEST;
}
\ No newline at end of file
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
END_TEST;
}
+
+int UtcDaliTapGestureSetRecognizerTime(void)
+{
+ TestApplication application;
+
+ TapGestureDetector detector = TapGestureDetector::New();
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ detector.Attach(actor);
+
+ try
+ {
+ Integration::SetTapRecognizerTime(0);
+ }
+ catch(...)
+ {
+ DALI_TEST_CHECK(false); // Should not get here
+ }
+
+ // Reduce the recognizer time. 500 -> 100
+ Integration::SetTapRecognizerTime(100);
+
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+ detector.DetectedSignal().Connect(&application, functor);
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
+
+ application.SendNotification();
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 300));
+
+ application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 450));
+
+ application.SendNotification();
+
+ // The tap fails because the recognizer time has been exceeded
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+ // reset recognizer time
+ Integration::SetTapRecognizerTime(500);
+
+ END_TEST;
+}
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
actor.AddRenderer(renderer);
application.GetScene().Add(actor);
+ auto& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+ drawTrace.Enable(true);
+
application.SendNotification();
application.Render(0);
application.Render();
const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
application.GetGlAbstraction().GetBufferDataCalls();
+ DALI_TEST_CHECK(drawTrace.FindMethod("DrawArrays"));
+
DALI_TEST_EQUALS(bufferDataCalls.size(), 3u, TEST_LOCATION);
DALI_TEST_EQUALS(bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION);
application.SendNotification();
application.Render(0);
- {
- const TestGlAbstraction::BufferSubDataCalls& bufferSubDataCalls =
- application.GetGlAbstraction().GetBufferSubDataCalls();
+ END_TEST;
+}
- const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
- application.GetGlAbstraction().GetBufferDataCalls();
+int UtcDaliVertexBufferMapInitializerList(void)
+{
+ TestApplication application;
- // Should be 3 (2 Render + 1 vertexBuffer reload)
- DALI_TEST_EQUALS(bufferSubDataCalls.size(), 3u, TEST_LOCATION);
- DALI_TEST_EQUALS(bufferDataCalls.size(), 3u, TEST_LOCATION);
+ Property::Map texturedQuadVertexFormat = Property::Map{{"aPosition", Property::VECTOR2},
+ {"aTexCoord", Property::VECTOR2},
+ {"aColor", Property::VECTOR4}};
- if(bufferSubDataCalls.size() >= 2)
- {
- DALI_TEST_EQUALS(bufferSubDataCalls[1], sizeof(texturedQuadVertexData), TEST_LOCATION);
- }
+ try
+ {
+ VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
+ tet_result(TET_PASS);
+ }
+ catch(Dali::DaliException& e)
+ {
+ // Shouldn't assert any more
+ tet_result(TET_FAIL);
}
-
END_TEST;
}
-int UtcDaliVertexBufferInvalidTypeN(void)
+int UtcDaliVertexBufferInvalidTypeN01(void)
{
TestApplication application;
END_TEST;
}
+int UtcDaliVertexBufferInvalidTypeN02(void)
+{
+ TestApplication application;
+
+ Property::Map texturedQuadVertexFormat = Property::Map{{"aPosition", Property::MAP},
+ {"aTexCoord", Property::STRING},
+ {"aColor", Property::VECTOR4}};
+
+ try
+ {
+ VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
+ tet_result(TET_FAIL);
+ }
+ catch(Dali::DaliException& e)
+ {
+ DALI_TEST_ASSERT(e, "Property::Type not supported in VertexBuffer", TEST_LOCATION);
+ }
+ END_TEST;
+}
+
int UtcDaliVertexBufferSetDataNegative(void)
{
TestApplication application;
}
END_TEST;
}
+
+int UtcDaliVertexBufferSetDivisor(void)
+{
+ TestApplication application;
+
+ Property::Map texturedQuadVertexFormat;
+ texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+ texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
+
+ Property::Map instanceFormat{{"aTranslate", Property::VECTOR2}, {"aColor", Property::VECTOR4}};
+
+ VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
+ DALI_TEST_EQUALS((bool)vertexBuffer, true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(0, vertexBuffer.GetDivisor(), TEST_LOCATION);
+
+ VertexBuffer instanceBuffer = VertexBuffer::New(instanceFormat);
+ DALI_TEST_EQUALS((bool)instanceBuffer, true, TEST_LOCATION);
+
+ const float halfQuadSize = .5f;
+ struct TexturedQuadVertex
+ {
+ Vector2 position;
+ Vector2 textureCoordinates;
+ };
+ TexturedQuadVertex texturedQuadVertexData[4] = {
+ {Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f)},
+ {Vector2(halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f)},
+ {Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f)},
+ {Vector2(halfQuadSize, halfQuadSize), Vector2(1.f, 1.f)}};
+
+ vertexBuffer.SetData(texturedQuadVertexData, 4);
+
+ struct InstanceData
+ {
+ Vector2 translate;
+ Vector4 color;
+ };
+
+ InstanceData instanceData[] = {{Vector2(12, 33), Color::WHITE},
+ {Vector2(-2000, 43), Color::BLUE},
+ {Vector2(200, 43), Color::GREEN},
+ {Vector2(-243, 43), Color::TURQUOISE},
+ {Vector2(192, 43), Color::CYAN},
+ {Vector2(-2000, 43), Color::MAGENTA},
+ {Vector2(-292, 393), Color::BLUE},
+ {Vector2(-499, 128), Color::BLUE},
+ {Vector2(328, 43), Color::BLUE},
+ {Vector2(726, 43), Color::BLUE}};
+ instanceBuffer.SetData(instanceData, sizeof(instanceData) / sizeof(InstanceData));
+ instanceBuffer.SetDivisor(1);
+ DALI_TEST_EQUALS(1, instanceBuffer.GetDivisor(), TEST_LOCATION);
+
+ Geometry geometry = Geometry::New();
+ geometry.AddVertexBuffer(vertexBuffer);
+ geometry.AddVertexBuffer(instanceBuffer);
+
+ Shader shader = CreateShader();
+ Renderer renderer = Renderer::New(geometry, shader);
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector3::ONE * 100.f);
+ actor.AddRenderer(renderer);
+ application.GetScene().Add(actor);
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ auto& bufferTrace = gl.GetBufferTrace();
+ auto& drawTrace = gl.GetDrawTrace();
+ bufferTrace.Enable(true);
+ drawTrace.Enable(true);
+
+ application.SendNotification();
+ application.Render();
+
+ TraceCallStack::NamedParams params;
+ params["divisor"] << "1";
+ DALI_TEST_CHECK(bufferTrace.FindMethodAndParams("VertexAttribDivisor", params));
+
+ TraceCallStack::NamedParams params2;
+ DALI_TEST_CHECK(drawTrace.FindMethodAndGetParameters("DrawArraysInstanced", params2));
+ std::ostringstream oss;
+ oss << sizeof(instanceData) / sizeof(InstanceData);
+ DALI_TEST_EQUALS(params2["instanceCount"].str(), oss.str(), TEST_LOCATION);
+ END_TEST;
+}
#define DALI_GRAPHICS_REFLECTION_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
// Sampler
/**
- * @brief Gets all the sampler uniforms
+ * @brief Gets all the sampler uniforms. In the case of arrays of samplers,
+ * it contains only the name of the sampler array without the [N] size, but,
+ * the element count is set to N.
*
* @return A vector of the sampler uniforms
*/
}
uint32_t stride;
VertexInputRate inputRate;
+ //@todo Add actual rate...
};
/**
uint32_t bufferIndex{0u};
uint32_t offset{0u};
uint32_t location{0u};
+ uint32_t elementCount{0u};
bool operator==(const UniformInfo& rhs)
{
binding == rhs.binding &&
bufferIndex == rhs.bufferIndex &&
offset == rhs.offset &&
- location == rhs.location;
+ location == rhs.location &&
+ elementCount == rhs.elementCount;
}
};
eventProcessor.SetTapMaximumAllowedTime(time);
}
+void SetTapRecognizerTime(uint32_t time)
+{
+ GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+ eventProcessor.SetTapRecognizerTime(time);
+}
+
} // namespace Integration
} // namespace Dali
#define DALI_INTEGRATION_INPUT_OPTIONS_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
/**
* @brief Sets the maximum allowed time required to be recognized as a multi tap gesture (millisecond)
*
+ * Recognizes how many tap gestures occurred within the maximum allowed time interval.
+ * If there are two tap gestures within this time, it is a double tap gesture.
+ *
+ * @note If it's a double tap, it's like this:
+ * |<--- maximumAllowedTime --->|
+ * |(touch down <--recognizerTime--> touch up) <-- maximumAllowedTime --> (touch down <--recognizerTime--> touch up)|
+ *
+ * @see SetTapRecognizerTime()
+ *
* @param[in] time The time value in milliseconds
*/
DALI_CORE_API void SetTapMaximumAllowedTime(uint32_t time);
+/**
+ * @brief Sets the recognizer time required to be recognized as a tap gesture (millisecond)
+ *
+ * This time is from touch down to touch up to recognize the tap gesture.
+ *
+ * @note The tab is like below:
+ * touch down <--recognizerTime--> touch up
+ * If the time between touch down and touch up is longer than recognizer time, it is not recognized as a tap gesture.
+ *
+ * @see SetTapMaximumAllowedTime()
+ *
+ * @param[in] time The time value in milliseconds
+ */
+DALI_CORE_API void SetTapRecognizerTime(uint32_t time);
+
} // namespace Integration
} // namespace Dali
mRemoveAction(Dali::Constraint::DEFAULT_REMOVE_ACTION),
mTag(0),
mApplied(false),
- mSourceDestroyed(false)
+ mSourceDestroyed(false),
+ mIsPreConstraint(true)
{
ObserveObject(object);
}
}
}
-void ConstraintBase::Apply()
+void ConstraintBase::Apply(bool isPreConstraint)
{
if(mTargetObject && !mApplied && !mSourceDestroyed)
{
mApplied = true;
- ConnectConstraint();
+ mIsPreConstraint = isPreConstraint;
+ ConnectConstraint(mIsPreConstraint);
mTargetObject->ApplyConstraint(*this);
}
+ else
+ {
+ DALI_LOG_ERROR("Fail to apply constraint\n");
+ }
+}
+
+void ConstraintBase::ApplyPost()
+{
+ Apply(false);
}
void ConstraintBase::Remove()
{
mTargetObject->RemoveConstraint(*this);
}
+ mIsPreConstraint = true;
}
void ConstraintBase::RemoveInternal()
{
const SceneGraph::PropertyOwner& propertyOwner = mTargetObject->GetSceneObject();
// Remove from scene-graph
- RemoveConstraintMessage(GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint));
+ if(mIsPreConstraint)
+ {
+ RemoveConstraintMessage(GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint));
+ }
+ else
+ {
+ RemovePostConstraintMessage(GetEventThreadServices(), propertyOwner, *(mSceneGraphConstraint));
+ }
// mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
mSceneGraphConstraint = nullptr;
}
(nullptr == mSceneGraphConstraint) &&
mTargetObject)
{
- ConnectConstraint();
+ ConnectConstraint(mIsPreConstraint);
}
}
/**
* @copydoc Dali::Constraint::Apply()
*/
- void Apply();
+ void Apply(bool isPreConstraint = true);
+
+ /**
+ * @copydoc Dali::Constraint::ApplyPost()
+ */
+ void ApplyPost();
/**
* @copydoc Dali::Constraint::Remove()
/**
* Connect the constraint
*/
- virtual void ConnectConstraint() = 0;
+ virtual void ConnectConstraint(bool isPreConstraint = true) = 0;
protected:
/**
uint32_t mTag;
bool mApplied : 1; ///< Whether the constraint has been applied
bool mSourceDestroyed : 1; ///< Is set to true if any of our input source objects are destroyed
+ bool mIsPreConstraint : 1; ///< Is set to true if this constraint is run before transform.
};
} // namespace Internal
/**
* @copydoc ConstraintBase::ConnectConstraint()
*/
- void ConnectConstraint() final
+ void ConnectConstraint(bool isPreConstraint) final
{
// Should not come here if target object has been destroyed
DALI_ASSERT_DEBUG(nullptr != mTargetObject);
resetter = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
}
OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
- ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
+ if(isPreConstraint)
+ {
+ ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
+ }
+ else
+ {
+ ApplyPostConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
+ }
if(resetter)
{
AddResetterMessage(GetEventThreadServices().GetUpdateManager(), resetter);
/**
* @copydoc ConstraintBase::ConnectConstraint()
*/
- void ConnectConstraint() final
+ void ConnectConstraint(bool isPreConstraint) final
{
// Should not come here if target object has been destroyed
DALI_ASSERT_DEBUG(nullptr != mTargetObject);
if(mSceneGraphConstraint)
{
OwnerPointer<SceneGraph::ConstraintBase> transferOwnership(const_cast<SceneGraph::ConstraintBase*>(mSceneGraphConstraint));
- ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
+ if(isPreConstraint)
+ {
+ ApplyConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
+ }
+ else
+ {
+ ApplyPostConstraintMessage(GetEventThreadServices(), targetObject, transferOwnership);
+ }
if(resetterRequired)
{
OwnerPointer<SceneGraph::PropertyResetterBase> resetter = SceneGraph::ConstraintResetter::New(targetObject, *targetProperty, *mSceneGraphConstraint);
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
mTapGestureProcessor.SetMaximumAllowedTime(time);
}
+void GestureEventProcessor::SetTapRecognizerTime(uint32_t time)
+{
+ mTapGestureProcessor.SetRecognizerTime(time);
+}
+
} // namespace Internal
} // namespace Dali
#define DALI_INTERNAL_GESTURE_EVENT_PROCESSOR_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
*/
void SetTapMaximumAllowedTime(uint32_t time);
+ /**
+ * @brief Sets the recognizer time required to be recognized as a tap gesture (millisecond)
+ *
+ * This time is from touch down to touch up to recognize the tap gesture.
+ *
+ * @param[in] time The time value in milliseconds
+ */
+ void SetTapRecognizerTime(uint32_t time);
+
public: // needed for PanGesture
/**
* @return the pan gesture processor
{
DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
constexpr uint32_t DEFAULT_MAXIMUM_ALLOWED_TIME = 500u;
+constexpr uint32_t DEFAULT_RECOGNIZER_TIME = 500u;
/**
* Creates a TapGesture and asks the specified detector to emit its detected signal.
mMaxTouchesRequired(1),
mCurrentTapEvent(nullptr),
mPossibleProcessed(false),
- mMaximumAllowedTime(DEFAULT_MAXIMUM_ALLOWED_TIME)
+ mMaximumAllowedTime(DEFAULT_MAXIMUM_ALLOWED_TIME),
+ mRecognizerTime(DEFAULT_RECOGNIZER_TIME)
{
}
request.maxTouches = mMaxTouchesRequired;
Size size = scene.GetSize();
- mGestureRecognizer = new TapGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const TapGestureRequest&>(request), mMaximumAllowedTime);
+ mGestureRecognizer = new TapGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const TapGestureRequest&>(request), mMaximumAllowedTime, mRecognizerTime);
}
else
{
}
}
+void TapGestureProcessor::SetRecognizerTime(uint32_t time)
+{
+ if(time == 0u)
+ {
+ DALI_LOG_WARNING("RecognizerTime must be greater than zero.");
+ return;
+ }
+ if(mRecognizerTime != time)
+ {
+ mRecognizerTime = time;
+
+ if(mGestureRecognizer)
+ {
+ TapGestureRecognizer* tapRecognizer = dynamic_cast<TapGestureRecognizer*>(mGestureRecognizer.Get());
+ if(tapRecognizer)
+ {
+ tapRecognizer->SetRecognizerTime(time);
+ }
+ }
+ }
+}
+
void TapGestureProcessor::UpdateDetection()
{
DALI_ASSERT_DEBUG(!mTapGestureDetectors.empty());
#define DALI_INTERNAL_TAP_GESTURE_EVENT_PROCESSOR_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
*/
void SetMaximumAllowedTime(uint32_t time);
+ /**
+ * @brief This method sets the recognizer time required to be recognized as a tap gesture (millisecond)
+ *
+ * This time is from touch down to touch up to recognize the tap gesture.
+ *
+ * @param[in] time The time value in milliseconds
+ */
+ void SetRecognizerTime(uint32_t time);
+
private:
// Undefined
TapGestureProcessor(const TapGestureProcessor&);
bool mPossibleProcessed; ///< Indication of whether we've processed a touch down for this gestuee
uint32_t mMaximumAllowedTime; ///< The maximum allowed time required to be recognized as a multi tap gesture (millisecond)
+ uint32_t mRecognizerTime; ///< The recognizer time required to be recognized as a tap gesture (millisecond)
};
} // namespace Internal
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
constexpr float MAXIMUM_MOTION_ALLOWED = 20.0f;
} // unnamed namespace
-TapGestureRecognizer::TapGestureRecognizer(Observer& observer, Vector2 screenSize, const TapGestureRequest& request, uint32_t maximumAllowedTime)
+TapGestureRecognizer::TapGestureRecognizer(Observer& observer, Vector2 screenSize, const TapGestureRequest& request, uint32_t maximumAllowedTime, uint32_t recognizerTime)
: GestureRecognizer(screenSize, GestureType::TAP),
mObserver(observer),
mState(CLEAR),
mTouchTime(0u),
mLastTapTime(0u),
mLastTouchTime(0u),
- mMaximumAllowedTime(maximumAllowedTime)
+ mMaximumAllowedTime(maximumAllowedTime),
+ mRecognizerTime(recognizerTime)
{
}
if(pointState == PointState::UP)
{
- if(deltaBetweenTouchDownTouchUp < mMaximumAllowedTime)
+ if(deltaBetweenTouchDownTouchUp < mRecognizerTime)
{
mLastTapTime = event.time;
EmitSingleTap(event.time, point);
{
uint32_t deltaBetweenLastTouchDownTouchUp = event.time - mLastTouchTime;
// Clear if the time between touch down and touch up is long.
- if(deltaBetweenLastTouchDownTouchUp > mMaximumAllowedTime)
+ if(deltaBetweenLastTouchDownTouchUp > mRecognizerTime)
{
mState = CLEAR;
}
mMaximumAllowedTime = time;
}
+void TapGestureRecognizer::SetRecognizerTime(uint32_t time)
+{
+ mRecognizerTime = time;
+}
+
void TapGestureRecognizer::EmitGesture(GestureState state, uint32_t time)
{
if((state == GestureState::CANCELLED) ||
#define DALI_INTERNAL_EVENT_EVENTS_TAP_GESTURE_RECOGNIZER_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
* @param[in] screenSize The size of the screen.
* @param[in] request The tap gesture request.
* @param[in] maximumAllowedTime The maximum allowed time required in milliseconds.
+ * @param[in] recognizerTime This recognizer time required in milliseconds.
*/
- TapGestureRecognizer(Observer& observer, Vector2 screenSize, const TapGestureRequest& request, uint32_t maximumAllowedTime);
+ TapGestureRecognizer(Observer& observer, Vector2 screenSize, const TapGestureRequest& request, uint32_t maximumAllowedTime, uint32_t recognizerTime);
/**
* Virtual destructor.
*/
void SetMaximumAllowedTime(uint32_t time);
+ /**
+ * @brief This method sets the recognizer time required to be recognized as a tap gesture (millisecond)
+ *
+ * @param[in] time The time value in milliseconds
+ */
+ void SetRecognizerTime(uint32_t time);
+
private:
/**
* Checks if registered taps are within required bounds and emits tap gesture if they are.
uint32_t mLastTouchTime; ///< The last touch down time.
uint32_t mMaximumAllowedTime; ///< The maximum allowed time required to be recognized as a multi tap gesture (millisecond)
+ uint32_t mRecognizerTime; ///< The recognizer time required to be recognized as a tap gesture (millisecond)
};
} // namespace Internal
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
return mSize;
}
+void VertexBuffer::SetDivisor(uint32_t divisor)
+{
+ SceneGraph::SetVertexBufferDivisorMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, divisor);
+ mDivisor = divisor;
+}
+
+uint32_t VertexBuffer::GetDivisor() const
+{
+ return mDivisor;
+}
+
const Render::VertexBuffer* VertexBuffer::GetRenderObject() const
{
return mRenderObject;
Property::Type type = Property::Type(component.second.Get<int>());
// Get the size and alignment
+ if(type == Property::NONE)
+ {
+ /* Note, Property::Value() has an explicit constructor using Property::Type enum,
+ * which will generate a property value of that type. This constructor is used when
+ * using C++ initializer lists.
+ */
+ type = component.second.GetType();
+ }
+
if((type == Property::NONE) ||
(type == Property::STRING) ||
(type == Property::ARRAY) ||
{
DALI_ABORT("Property::Type not supported in VertexBuffer");
}
+
uint32_t elementSize = GetPropertyImplementationSize(type);
uint32_t elementAlignment = GetPropertyImplementationAlignment(type);
#define DALI_INTERNAL_VERTEX_BUFFER_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
{
public:
/**
- * @copydoc PropertBuffer::New()
+ * @copydoc Dali::VertexBuffer::New()
*/
static VertexBufferPtr New(Dali::Property::Map& format);
/**
- * @copydoc PropertBuffer::SetData()
+ * @copydoc Dali::VertexBuffer::SetData()
*/
void SetData(const void* data, uint32_t size);
/**
- * @copydoc PropertBuffer::GetSize()
+ * @copydoc Dali::VertexBuffer::GetSize()
*/
uint32_t GetSize() const;
+ /**
+ * @copydoc Dali::VertexBuffer::SetDivisor()
+ */
+ void SetDivisor(uint32_t divisor);
+
+ /**
+ * @copydoc Dali::VertexBuffer::GetDivisor()
+ */
+ uint32_t GetDivisor() const;
+
public: // Default property extensions from Object
/**
* @brief Get the render thread side of the VertexBuffer
VertexBuffer(const VertexBuffer&);
VertexBuffer& operator=(const VertexBuffer&);
-private: // data
- EventThreadServices& mEventThreadServices; ///<Used to send messages to the render thread via update thread
- Render::VertexBuffer* mRenderObject; ///<Render side object
- uint32_t mBufferFormatSize;
- uint32_t mSize; ///< Number of elements in the buffer
+private: // data
+ EventThreadServices& mEventThreadServices; ///<Used to send messages to the render thread via update thread
+ Render::VertexBuffer* mRenderObject{nullptr}; ///<Render side object
+ uint32_t mBufferFormatSize{0};
+ uint32_t mSize{0}; ///< Number of elements in the buffer
+ uint32_t mDivisor{0}; ///< How many elements to skip in instanced draw
};
/**
{
const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
+ uint32_t divisor = vertexBuffer->GetDivisor();
+ Graphics::VertexInputRate vertexInputRate = (divisor == 0
+ ? Graphics::VertexInputRate::PER_VERTEX
+ : Graphics::VertexInputRate::PER_INSTANCE);
+
vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
- Graphics::VertexInputRate::PER_VERTEX);
+ vertexInputRate);
+ //@todo Add the actual rate to the graphics struct
const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
uint32_t lastBoundAttributeIndex = 0;
void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
{
const auto&& end = mVertexBuffers.End();
+ // @todo if this buffer is the only instance buffer, reduce instance count to 1.
for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
{
if(*iter == vertexBuffer)
for(uint32_t i = 0; i < vertexBufferCount; ++i)
{
+ if(mVertexBuffers[i]->GetDivisor() > 0)
+ {
+ mInstanceCount = mVertexBuffers[i]->GetElementCount();
+ }
+
const GpuBuffer* gpuBuffer = mVertexBuffers[i]->GetGpuBuffer();
if(gpuBuffer)
{
commandBuffer.BindIndexBuffer(*ibo, 0, mIndexType);
}
- commandBuffer.DrawIndexed(numIndices, 1, firstIndexOffset, 0, 0);
+ commandBuffer.DrawIndexed(numIndices, mInstanceCount, firstIndexOffset, 0, 0);
}
else
{
numVertices = static_cast<uint32_t>(mVertexBuffers[0]->GetElementCount());
}
- commandBuffer.Draw(numVertices, 1, 0, 0);
+ commandBuffer.Draw(numVertices, mInstanceCount, 0, 0);
}
return true;
}
OwnerPointer<GpuBuffer> mIndexBuffer;
IndexType mIndexType;
Type mGeometryType;
+ uint32_t mInstanceCount{0};
// Booleans
bool mIndicesChanged : 1;
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
return true;
}
+void VertexBuffer::SetDivisor(uint32_t divisor)
+{
+ mDivisor = divisor;
+}
+
+uint32_t VertexBuffer::GetDivisor()
+{
+ return mDivisor;
+}
+
} // namespace Render
} // namespace Internal
} // namespace Dali
#define DALI_INTERNAL_RENDER_VERTEX_BUFFER_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
bool Update(Graphics::Controller& graphicsController);
/**
+ * @brief Set the divisor of the buffer for instanced drawing
+ * @param[in] divisor The divisor (0 = not instanced, >=1 = instanced)
+ */
+ void SetDivisor(uint32_t divisor);
+
+ /**
+ * Get the divisor for the vertex buffer
+ */
+ [[nodiscard]] uint32_t GetDivisor();
+
+ /**
* Get the number of attributes present in the buffer
* @return The number of attributes stored in this buffer
*/
OwnerPointer<GpuBuffer> mGpuBuffer; ///< Pointer to the GpuBuffer associated with this RenderVertexBuffer
uint32_t mSize; ///< Number of Elements in the buffer
+ uint32_t mDivisor{0}; ///< The divisor (0:not instanced, >=1:instanced)
bool mDataChanged; ///< Flag to know if data has changed in a frame
};
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
}
// add samplers
- auto samplers = graphicsReflection.GetSamplers();
+ auto samplers = graphicsReflection.GetSamplers(); // Only holds first element of arrays without [].
for(const auto& sampler : samplers)
{
mReflection.emplace_back(ReflectionUniformInfo{CalculateHash(sampler.name), false, sampler});
new(slot) LocalType(&owner, &PropertyOwner::RemoveConstraint, &constraint);
}
+inline void ApplyPostConstraintMessage(EventThreadServices& eventThreadServices, const PropertyOwner& owner, OwnerPointer<ConstraintBase>& constraint)
+{
+ using LocalType = MessageValue1<PropertyOwner, OwnerPointer<ConstraintBase> >;
+
+ // Reserve some memory inside the message queue
+ uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new(slot) LocalType(&owner, &PropertyOwner::ApplyPostConstraint, constraint);
+}
+
+inline void RemovePostConstraintMessage(EventThreadServices& eventThreadServices, const PropertyOwner& owner, const ConstraintBase& constConstraint)
+{
+ // The update-thread can modify this object.
+ ConstraintBase& constraint = const_cast<ConstraintBase&>(constConstraint);
+
+ using LocalType = MessageValue1<PropertyOwner, ConstraintBase*>;
+
+ // Reserve some memory inside the message queue
+ uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new(slot) LocalType(&owner, &PropertyOwner::RemovePostConstraint, &constraint);
+}
+
inline void AddUniformMapMessage(EventThreadServices& eventThreadServices, const PropertyOwner& owner, UniformPropertyMapping map)
{
using LocalType = MessageValue1<PropertyOwner, UniformPropertyMapping>;
// Remove all constraints when disconnected from scene-graph
mConstraints.Clear();
+ mPostConstraints.Clear();
}
void PropertyOwner::ConnectToSceneGraph()
// Remove all constraints when disconnected from scene-graph
mConstraints.Clear();
+ mPostConstraints.Clear();
}
void PropertyOwner::ReserveProperties(int propertyCount)
//it may be that the constraint has already been removed e.g. from disconnection from scene graph, so nothing needs to be done
}
+ConstraintOwnerContainer& PropertyOwner::GetPostConstraints()
+{
+ return mPostConstraints;
+}
+
+void PropertyOwner::ApplyPostConstraint(OwnerPointer<ConstraintBase>& constraint)
+{
+ constraint->OnConnect();
+ mPostConstraints.PushBack(constraint.Release());
+}
+
+void PropertyOwner::RemovePostConstraint(ConstraintBase* constraint)
+{
+ const ConstraintIter constraintEndIter = mPostConstraints.End();
+ for(ConstraintIter iter = mPostConstraints.Begin(); constraintEndIter != iter; ++iter)
+ {
+ if(*iter == constraint)
+ {
+ mPostConstraints.Erase(iter);
+ return; // We're finished
+ }
+ }
+
+ //it may be that the constraint has already been removed e.g. from disconnection from scene graph, so nothing needs to be done
+}
+
PropertyOwner::PropertyOwner()
: mUpdated(false),
mIsConnectedToSceneGraph(false)
void RemoveConstraint(ConstraintBase* constraint);
/**
+ * Apply a post constraint.
+ * @param[in] constraint The constraint to apply.
+ */
+ void ApplyPostConstraint(OwnerPointer<ConstraintBase>& constraint);
+
+ /**
+ * Begin removal of post constraints.
+ * @param[in] constraint The constraint to remove.
+ */
+ void RemovePostConstraint(ConstraintBase* constraint);
+
+ /**
* Retrieve the constraints that are currently applied.
* @return A container of constraints.
*/
ConstraintOwnerContainer& GetConstraints();
/**
+ * Retrieve the post constraints that are currently applied.
+ * @return A container of post constraints.
+ */
+ ConstraintOwnerContainer& GetPostConstraints();
+
+ /**
* @copydoc UniformMap::Add
*/
virtual void AddUniformMapping(const UniformPropertyMapping& map);
ObserverContainer mObservers; ///< Container of observer raw-pointers (not owned)
ConstraintOwnerContainer mConstraints; ///< Container of owned constraints
+ ConstraintOwnerContainer mPostConstraints; ///< Container of owned constraints
};
} // namespace SceneGraph
* @param propertyOwner to constrain
* @param updateBufferIndex buffer index to use
*/
-void ConstrainPropertyOwner(PropertyOwner& propertyOwner, BufferIndex updateBufferIndex)
+void ConstrainPropertyOwner(PropertyOwner& propertyOwner, BufferIndex updateBufferIndex, bool isPreConstraint)
{
- ConstraintOwnerContainer& constraints = propertyOwner.GetConstraints();
+ ConstraintOwnerContainer& constraints = (isPreConstraint) ? propertyOwner.GetConstraints() : propertyOwner.GetPostConstraints();
const ConstraintIter endIter = constraints.End();
for(ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter)
/**
* This is called recursively for all children of the root Node
*/
-inline NodePropertyFlags UpdateNodes(Node& node,
- NodePropertyFlags parentFlags,
- BufferIndex updateBufferIndex,
- RenderQueue& renderQueue,
- bool updated)
+inline NodePropertyFlags UpdateNodes(Node& node,
+ NodePropertyFlags parentFlags,
+ BufferIndex updateBufferIndex,
+ RenderQueue& renderQueue,
+ PropertyOwnerContainer& postPropertyOwners,
+ bool updated)
{
// Apply constraints to the node
ConstrainPropertyOwner(node, updateBufferIndex);
+ if(!node.GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(&node);
+ }
// Some dirty flags are inherited from parent
NodePropertyFlags nodeDirtyFlags = node.GetDirtyFlags() | node.GetInheritedDirtyFlags(parentFlags);
nodeDirtyFlags,
updateBufferIndex,
renderQueue,
+ postPropertyOwners,
updated);
}
/**
* The root node is treated separately; it cannot inherit values since it has no parent
*/
-NodePropertyFlags UpdateNodeTree(Layer& rootNode,
- BufferIndex updateBufferIndex,
- RenderQueue& renderQueue)
+NodePropertyFlags UpdateNodeTree(Layer& rootNode,
+ BufferIndex updateBufferIndex,
+ RenderQueue& renderQueue,
+ PropertyOwnerContainer& postPropertyOwners)
{
DALI_ASSERT_DEBUG(rootNode.IsRoot());
nodeDirtyFlags,
updateBufferIndex,
renderQueue,
+ postPropertyOwners,
updated);
}
class PropertyOwner;
class RenderQueue;
+using PropertyOwnerContainer = Dali::Vector<PropertyOwner*>;
+
/**
* Constrain the local properties of the PropertyOwner.
* @param[in] propertyOwner The PropertyOwner to constrain
* @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] isPreConstraint True if the constraint is performed before transform.
*/
-void ConstrainPropertyOwner(PropertyOwner& propertyOwner, BufferIndex updateBufferIndex);
+void ConstrainPropertyOwner(PropertyOwner& propertyOwner, BufferIndex updateBufferIndex, bool isPreConstraint = true);
/**
* Update a tree of nodes
* @param[in] rootNode The root of a tree of nodes.
* @param[in] updateBufferIndex The current update buffer index.
* @param[in] renderQueue Used to query messages for the next Render.
+ * @param[out] postPropertyOwner property owners those have post constraint.
* @return The cumulative (ORed) dirty flags for the updated nodes
*/
-NodePropertyFlags UpdateNodeTree(Layer& rootNode,
- BufferIndex updateBufferIndex,
- RenderQueue& renderQueue);
+NodePropertyFlags UpdateNodeTree(Layer& rootNode,
+ BufferIndex updateBufferIndex,
+ RenderQueue& renderQueue,
+ PropertyOwnerContainer& postPropertyOwners);
/**
* This updates all the sub-layer's reusability flags without affecting
* the root layer.
#include <dali/internal/render/common/render-manager.h>
#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/renderers/render-vertex-buffer.h>
// Un-comment to enable node tree debug logging
//#define NODE_TREE_LOGGING 1
return animationActive;
}
-void UpdateManager::ConstrainCustomObjects(BufferIndex bufferIndex)
+void UpdateManager::ConstrainCustomObjects(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
// Constrain custom objects (in construction order)
for(auto&& object : mImpl->customObjects)
{
ConstrainPropertyOwner(*object, bufferIndex);
+ if(!object->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(object);
+ }
}
}
-void UpdateManager::ConstrainRenderTasks(BufferIndex bufferIndex)
+void UpdateManager::ConstrainRenderTasks(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
// Constrain render-tasks
for(auto&& scene : mImpl->scenes)
for(auto&& task : tasks)
{
ConstrainPropertyOwner(*task, bufferIndex);
+ if(!task->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(task);
+ }
}
}
}
}
-void UpdateManager::ConstrainShaders(BufferIndex bufferIndex)
+void UpdateManager::ConstrainShaders(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
// constrain shaders... (in construction order)
for(auto&& shader : mImpl->shaders)
{
ConstrainPropertyOwner(*shader, bufferIndex);
+ if(!shader->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(shader);
+ }
}
}
}
}
-void UpdateManager::UpdateRenderers(BufferIndex bufferIndex)
+void UpdateManager::UpdateRenderers(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
for(const auto& rendererKey : mImpl->renderers)
{
// Apply constraints
auto renderer = rendererKey.Get();
ConstrainPropertyOwner(*renderer, bufferIndex);
+ if(!renderer->GetPostConstraints().Empty())
+ {
+ postPropertyOwners.PushBack(renderer);
+ }
mImpl->renderingRequired = renderer->PrepareRender(bufferIndex) || mImpl->renderingRequired;
}
}
-void UpdateManager::UpdateNodes(BufferIndex bufferIndex)
+void UpdateManager::UpdateNodes(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex)
{
mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
// And add the renderers to the sorted layers. Start from root, which is also a layer
mImpl->nodeDirtyFlags |= UpdateNodeTree(*scene->root,
bufferIndex,
- mImpl->renderQueue);
+ mImpl->renderQueue,
+ postPropertyOwners);
}
}
}
// Animate
bool animationActive = Animate(bufferIndex, elapsedSeconds);
+ PropertyOwnerContainer postPropertyOwners;
// Constraint custom objects
- ConstrainCustomObjects(bufferIndex);
+ ConstrainCustomObjects(postPropertyOwners, bufferIndex);
// Clear the lists of renderers from the previous update
for(auto&& scene : mImpl->scenes)
}
// Update node hierarchy, apply constraints,
- UpdateNodes(bufferIndex);
+ UpdateNodes(postPropertyOwners, bufferIndex);
// Apply constraints to RenderTasks, shaders
- ConstrainRenderTasks(bufferIndex);
- ConstrainShaders(bufferIndex);
+ ConstrainRenderTasks(postPropertyOwners, bufferIndex);
+ ConstrainShaders(postPropertyOwners, bufferIndex);
// Update renderers and apply constraints
- UpdateRenderers(bufferIndex);
+ UpdateRenderers(postPropertyOwners, bufferIndex);
// Update the transformations of all the nodes
if(mImpl->transformManager.Update())
mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM;
}
+ // Constraint applied after transform manager updated. Only required property owner processed.
+ for(auto&& propertyOwner : postPropertyOwners)
+ {
+ ConstrainPropertyOwner(*propertyOwner, bufferIndex, false);
+ }
+
// Initialise layer renderable reuse
UpdateLayers(bufferIndex);
new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetVertexBufferData, vertexBuffer, data, size);
}
+void UpdateManager::SetVertexBufferDivisor(Render::VertexBuffer* vertexBuffer, uint32_t divisor)
+{
+ using LocalType = MessageValue1<Render::VertexBuffer, uint32_t>;
+ uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(LocalType));
+ new(slot) LocalType(vertexBuffer, &Render::VertexBuffer::SetDivisor, divisor);
+}
+
void UpdateManager::AddGeometry(OwnerPointer<Render::Geometry>& geometry)
{
// Message has ownership of format while in transit from update -> render
void SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size);
/**
+ * Sets the divisor of a vertex buffer. This is used by the GPU to provide
+ * instanced drawing.
+ * @param[in] vertexBuffer The property buffer.
+ * @param[in] divisor The instance divisor. 0 to turn instancing off.
+ */
+ void SetVertexBufferDivisor(Render::VertexBuffer* vertexBuffer, uint32_t divisor);
+
+ /**
* Adds a geometry to the RenderManager
* @param[in] geometry The geometry to add
* @post Sends a message to RenderManager to add the Geometry
/**
* Applies constraints to CustomObjects
+ * @param[out] postPropertyOwner property owners those have post constraint.
* @param[in] bufferIndex to use
*/
- void ConstrainCustomObjects(BufferIndex bufferIndex);
+ void ConstrainCustomObjects(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex);
/**
* Applies constraints to RenderTasks
+ * @param[out] postPropertyOwner property owners those have post constraint.
* @param[in] bufferIndex to use
*/
- void ConstrainRenderTasks(BufferIndex bufferIndex);
+ void ConstrainRenderTasks(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex);
/**
* Applies constraints to Shaders
+ * @param[out] postPropertyOwner property owners those have post constraint.
* @param[in] bufferIndex to use
*/
- void ConstrainShaders(BufferIndex bufferIndex);
+ void ConstrainShaders(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex);
/**
* Perform property notification updates
/**
* Update node shaders, opacity, geometry etc.
+ * @param[out] postPropertyOwner property owners those have post constraint.
* @param[in] bufferIndex to use
*/
- void UpdateNodes(BufferIndex bufferIndex);
+ void UpdateNodes(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex);
/**
* initialize layer renderables
/**
* Update Renderers
+ * @param[out] postPropertyOwner property owners those have post constraint.
* @param[in] bufferIndex to use
*/
- void UpdateRenderers(BufferIndex bufferIndex);
+ void UpdateRenderers(PropertyOwnerContainer& postPropertyOwners, BufferIndex bufferIndex);
private:
// needs to be direct member so that getter for event buffer can be inlined
new(slot) LocalType(&manager, &UpdateManager::SetVertexBufferData, &vertexBuffer, data, size);
}
+inline void SetVertexBufferDivisorMessage(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, uint32_t divisor)
+{
+ using LocalType = MessageValue2<UpdateManager, Render::VertexBuffer*, uint32_t>;
+ uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType));
+ new(slot) LocalType(&manager, &UpdateManager::SetVertexBufferDivisor, &vertexBuffer, divisor);
+}
+
inline void AddGeometry(UpdateManager& manager, OwnerPointer<Render::Geometry>& geometry)
{
// Message has ownership of Geometry while in transit from event -> update
GetImplementation(*this).Apply();
}
+void Constraint::ApplyPost()
+{
+ GetImplementation(*this).ApplyPost();
+}
+
void Constraint::Remove()
{
GetImplementation(*this).Remove();
void AddSource(ConstraintSource source);
/**
- * @brief Applies this constraint.
+ * @brief Applies this constraint to be computed before transform.
*
* @SINCE_1_0.0
* @pre The constraint must be initialized.
* @pre The target object must still be alive.
* @pre The source inputs should not have been destroyed.
+ *
+ * @note This method cannot be called with ApplyPost at the same time.
*/
void Apply();
/**
+ * @brief Applies this constraint to be computed after transform.
+ *
+ * @SINCE_2_2.23
+ * @pre The constraint must be initialized.
+ * @pre The target object must still be alive.
+ * @pre The source inputs should not have been destroyed.
+ *
+ * @note This method cannot be called with Apply at the same time.
+ */
+ void ApplyPost();
+
+ /**
* @brief Removes this constraint.
* @SINCE_1_0.0
*/
{
const uint32_t CORE_MAJOR_VERSION = 2;
const uint32_t CORE_MINOR_VERSION = 2;
-const uint32_t CORE_MICRO_VERSION = 22;
+const uint32_t CORE_MICRO_VERSION = 23;
const char* const CORE_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
return GetImplementation(*this).GetSize();
}
+void VertexBuffer::SetDivisor(uint32_t divisor)
+{
+ GetImplementation(*this).SetDivisor(divisor);
+}
+
+uint32_t VertexBuffer::GetDivisor() const
+{
+ return GetImplementation(*this).GetDivisor();
+}
+
VertexBuffer::VertexBuffer(Internal::VertexBuffer* pointer)
: BaseHandle(pointer)
{
#define DALI_VERTEX_BUFFER_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
*/
std::size_t GetSize() const;
+ /**
+ * @brief Sets vertex divisor for all attributes
+ *
+ * If instancing isn't supported, the function has no effect.
+ * It's responsibility of developer to make sure the feature is supported.
+ * A divisor of 0 will turn off instanced drawing.
+ * Currently, a divisor > 1 will turn on instanced draw, but will have an
+ * actual rate of 1.
+ *
+ * @param[in] divisor Sets vertex buffer divisor for an instanced draw
+ */
+ void SetDivisor(uint32_t divisor);
+
+ /**
+ * @brief Get the divisor for the given attribute. A return value of 0 means that
+ * instancing is turned off.
+ *
+ * @return either 0 (not instanced), or > 0 (instanced)
+ */
+ uint32_t GetDivisor() const;
+
public:
/**
* @brief The constructor.
Name: dali2
Summary: DALi 3D Engine
-Version: 2.2.22
+Version: 2.2.23
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT