From: Richard Huang Date: Fri, 28 May 2021 09:52:06 +0000 (+0100) Subject: [dali_2.0.28] Merge branch 'devel/master' X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=383021a5eeff5ade0a8e7d50d3fdbe5a7549f0da;hp=e2640d747fd9fce8c06a1c5e1ddcbc39838d3916 [dali_2.0.28] Merge branch 'devel/master' Change-Id: Idfa1e34c419ee1b94edf28d6482ea1bdb42a4e5c --- diff --git a/automated-tests/resources/papermill_E_diffuse-64.ktx b/automated-tests/resources/papermill_E_diffuse-64.ktx new file mode 100644 index 0000000..c000b61 Binary files /dev/null and b/automated-tests/resources/papermill_E_diffuse-64.ktx differ diff --git a/automated-tests/src/dali-scene-loader-internal/CMakeLists.txt b/automated-tests/src/dali-scene-loader-internal/CMakeLists.txt index 16f96f0..0270d3d 100755 --- a/automated-tests/src/dali-scene-loader-internal/CMakeLists.txt +++ b/automated-tests/src/dali-scene-loader-internal/CMakeLists.txt @@ -42,10 +42,12 @@ SET(TEST_HARNESS_SOURCES ${TEST_HARNESS_DIR}/test-harness.cpp ${TEST_HARNESS_DIR}/test-gesture-generator.cpp ${TEST_HARNESS_DIR}/test-gl-abstraction.cpp - ${TEST_HARNESS_DIR}/test-gl-sync-abstraction.cpp + ${TEST_HARNESS_DIR}/test-graphics-sync-impl.cpp + ${TEST_HARNESS_DIR}/test-graphics-sync-object.cpp ${TEST_HARNESS_DIR}/test-graphics-buffer.cpp ${TEST_HARNESS_DIR}/test-graphics-command-buffer.cpp ${TEST_HARNESS_DIR}/test-graphics-controller.cpp + ${TEST_HARNESS_DIR}/test-graphics-framebuffer.cpp ${TEST_HARNESS_DIR}/test-graphics-texture.cpp ${TEST_HARNESS_DIR}/test-graphics-sampler.cpp ${TEST_HARNESS_DIR}/test-graphics-pipeline.cpp diff --git a/automated-tests/src/dali-scene-loader/CMakeLists.txt b/automated-tests/src/dali-scene-loader/CMakeLists.txt index 693db47..60c1b22 100755 --- a/automated-tests/src/dali-scene-loader/CMakeLists.txt +++ b/automated-tests/src/dali-scene-loader/CMakeLists.txt @@ -57,9 +57,11 @@ SET(TEST_HARNESS_SOURCES ${TEST_HARNESS_DIR}/test-harness.cpp ${TEST_HARNESS_DIR}/test-gesture-generator.cpp ${TEST_HARNESS_DIR}/test-gl-abstraction.cpp - ${TEST_HARNESS_DIR}/test-gl-sync-abstraction.cpp + ${TEST_HARNESS_DIR}/test-graphics-sync-impl.cpp + ${TEST_HARNESS_DIR}/test-graphics-sync-object.cpp ${TEST_HARNESS_DIR}/test-graphics-buffer.cpp ${TEST_HARNESS_DIR}/test-graphics-command-buffer.cpp + ${TEST_HARNESS_DIR}/test-graphics-framebuffer.cpp ${TEST_HARNESS_DIR}/test-graphics-controller.cpp ${TEST_HARNESS_DIR}/test-graphics-texture.cpp ${TEST_HARNESS_DIR}/test-graphics-sampler.cpp diff --git a/automated-tests/src/dali-scene-loader/utc-Dali-KtxLoader.cpp b/automated-tests/src/dali-scene-loader/utc-Dali-KtxLoader.cpp index 15d6b58..783745d 100644 --- a/automated-tests/src/dali-scene-loader/utc-Dali-KtxLoader.cpp +++ b/automated-tests/src/dali-scene-loader/utc-Dali-KtxLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -146,3 +146,20 @@ int UtcDaliKtxLoaderCubeDataCreateTexture2(void) END_TEST; } + +int UtcDaliKtxLoaderCubeDataCreateTexture3(void) +{ + CubeData cubeData; + auto path = TEST_RESOURCE_DIR "/papermill_E_diffuse-64.ktx"; + DALI_TEST_CHECK(LoadCubeMapData(path, cubeData)); + + TestApplication app; + auto texture = cubeData.CreateTexture(); + + DALI_TEST_CHECK(texture); + DALI_TEST_EQUAL(64u, texture.GetWidth()); + DALI_TEST_EQUAL(64u, texture.GetHeight()); + + END_TEST; + +} diff --git a/automated-tests/src/dali-shader-generator/CMakeLists.txt b/automated-tests/src/dali-shader-generator/CMakeLists.txt index 9a30ca7..517b7d3 100644 --- a/automated-tests/src/dali-shader-generator/CMakeLists.txt +++ b/automated-tests/src/dali-shader-generator/CMakeLists.txt @@ -44,10 +44,12 @@ SET(TEST_HARNESS_SOURCES ${TEST_HARNESS_DIR}/test-harness.cpp ${TEST_HARNESS_DIR}/test-gesture-generator.cpp ${TEST_HARNESS_DIR}/test-gl-abstraction.cpp - ${TEST_HARNESS_DIR}/test-gl-sync-abstraction.cpp + ${TEST_HARNESS_DIR}/test-graphics-sync-impl.cpp + ${TEST_HARNESS_DIR}/test-graphics-sync-object.cpp ${TEST_HARNESS_DIR}/test-graphics-buffer.cpp ${TEST_HARNESS_DIR}/test-graphics-command-buffer.cpp ${TEST_HARNESS_DIR}/test-graphics-controller.cpp + ${TEST_HARNESS_DIR}/test-graphics-framebuffer.cpp ${TEST_HARNESS_DIR}/test-graphics-texture.cpp ${TEST_HARNESS_DIR}/test-graphics-sampler.cpp ${TEST_HARNESS_DIR}/test-graphics-program.cpp @@ -129,4 +131,3 @@ ADD_CUSTOM_TARGET( ALL COMMAND ${SHADER_GENERATOR} ${SHADER_FOLDER} ${GENERATED_FOLDER} | grep "SHADER_SHADER_DEFINE_DEF" | grep "shader-define-def.h" > /dev/null 2>&1 && echo "test_def_correct Succeeded" VERBATIM) - diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index f20e494..0a65397 100755 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -81,10 +81,12 @@ SET(TEST_HARNESS_SOURCES ../dali-toolkit/dali-toolkit-test-utils/test-button.cpp ../dali-toolkit/dali-toolkit-test-utils/test-harness.cpp ../dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp - ../dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-program.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-pipeline.cpp diff --git a/automated-tests/src/dali-toolkit-styling/CMakeLists.txt b/automated-tests/src/dali-toolkit-styling/CMakeLists.txt index cc1488e..4c211d1 100644 --- a/automated-tests/src/dali-toolkit-styling/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-styling/CMakeLists.txt @@ -45,10 +45,12 @@ SET(TEST_HARNESS_SOURCES ../dali-toolkit/dali-toolkit-test-utils/test-application.cpp ../dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp ../dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp - ../dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-pipeline.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-program.cpp diff --git a/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt b/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt index 820a4a5..e30acba 100644 --- a/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-third-party/CMakeLists.txt @@ -31,10 +31,12 @@ SET(TEST_HARNESS_SOURCES ../dali-toolkit/dali-toolkit-test-utils/test-button.cpp ../dali-toolkit/dali-toolkit-test-utils/test-harness.cpp ../dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp - ../dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp + ../dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-sampler.cpp ../dali-toolkit/dali-toolkit-test-utils/test-graphics-pipeline.cpp diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index c3ab255..2983fd7 100755 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -112,10 +112,12 @@ SET(TEST_HARNESS_SOURCES dali-toolkit-test-utils/test-harness.cpp dali-toolkit-test-utils/test-gesture-generator.cpp dali-toolkit-test-utils/test-gl-abstraction.cpp - dali-toolkit-test-utils/test-gl-sync-abstraction.cpp + dali-toolkit-test-utils/test-graphics-sync-impl.cpp + dali-toolkit-test-utils/test-graphics-sync-object.cpp dali-toolkit-test-utils/test-graphics-buffer.cpp dali-toolkit-test-utils/test-graphics-command-buffer.cpp dali-toolkit-test-utils/test-graphics-controller.cpp + dali-toolkit-test-utils/test-graphics-framebuffer.cpp dali-toolkit-test-utils/test-graphics-texture.cpp dali-toolkit-test-utils/test-graphics-pipeline.cpp dali-toolkit-test-utils/test-graphics-program.cpp diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp index 2db4dbc..bf62bb8 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -91,4 +91,44 @@ Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, co return actor; } +Actor CreateRenderableActor2(TextureSet textures, const std::string& vertexShader, const std::string& fragmentShader) +{ + // Create the geometry + Geometry geometry = CreateQuadGeometry(); + + // Create Shader + Shader shader = Shader::New(vertexShader, fragmentShader); + + // Create renderer from geometry and material + Renderer renderer = Renderer::New(geometry, shader); + + // Create actor and set renderer + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + + // If we a texture, then create a texture-set and add to renderer + if(textures) + { + renderer.SetTextures(textures); + + auto texture = textures.GetTexture(0); + + // Set actor to the size of the texture if set + actor.SetProperty(Actor::Property::SIZE, Vector2(texture.GetWidth(), texture.GetHeight())); + } + + return actor; +} + +Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height) +{ + Texture texture = Texture::New(type, format, width, height); + + int bufferSize = width * height * 2; + uint8_t* buffer = reinterpret_cast(malloc(bufferSize)); + PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, format, PixelData::FREE); + texture.Upload(pixelData, 0u, 0u, 0u, 0u, width, height); + return texture; +} + } // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h index be085bf..0dbe07e 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h @@ -2,7 +2,7 @@ #define DALI_TEST_ACTOR_UTILS_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -19,6 +19,8 @@ */ // EXTERNAL INCLUDES +#include +#include #include namespace Dali @@ -49,6 +51,17 @@ Actor CreateRenderableActor(Texture texture); */ Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, const std::string& fragmentShader); +/** + * @brief Creates a renderable-actor with a texture and custom shaders. + * @param[in] textures TextureSet to set. + * @param[in] vertexShader The vertex-shader. + * @param[in] fragmentShader The fragment-shader. + * @return An actor with a renderer. + */ +Actor CreateRenderableActor2(TextureSet textures, const std::string& vertexShader, const std::string& fragmentShader); + +Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height); + } // namespace Dali #endif // DALI_TEST_ACTOR_UTILS_H diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp index a2a1848..5e69c95 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp @@ -76,6 +76,12 @@ void TestApplication::CreateScene() { mScene = Dali::Integration::Scene::New(Size(static_cast(mSurfaceWidth), static_cast(mSurfaceHeight))); mScene.SetDpi(Vector2(static_cast(mDpi.x), static_cast(mDpi.y))); + + // Create render target for the scene + Graphics::RenderTargetCreateInfo rtInfo{}; + rtInfo.SetExtent({mSurfaceWidth, mSurfaceHeight}); + mRenderTarget = mGraphicsController.CreateRenderTarget(rtInfo, nullptr); + mScene.SetSurfaceRenderTarget(mRenderTarget.get()); } void TestApplication::InitializeCore() @@ -149,14 +155,14 @@ TestGlAbstraction& TestApplication::GetGlAbstraction() return static_cast(mGraphicsController.GetGlAbstraction()); } -TestGlSyncAbstraction& TestApplication::GetGlSyncAbstraction() +TestGlContextHelperAbstraction& TestApplication::GetGlContextHelperAbstraction() { - return static_cast(mGraphicsController.GetGlSyncAbstraction()); + return static_cast(mGraphicsController.GetGlContextHelperAbstraction()); } -TestGlContextHelperAbstraction& TestApplication::GetGlContextHelperAbstraction() +TestGraphicsSyncImplementation& TestApplication::GetGraphicsSyncImpl() { - return static_cast(mGraphicsController.GetGlContextHelperAbstraction()); + return static_cast(mGraphicsController.GetGraphicsSyncImpl()); } void TestApplication::ProcessEvent(const Integration::Event& event) diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h index e7d8c76..4f32cd8 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h @@ -65,8 +65,8 @@ public: TestGraphicsController& GetGraphicsController(); TestGlAbstraction& GetGlAbstraction(); - TestGlSyncAbstraction& GetGlSyncAbstraction(); TestGlContextHelperAbstraction& GetGlContextHelperAbstraction(); + TestGraphicsSyncImplementation& GetGraphicsSyncImpl(); void ProcessEvent(const Integration::Event& event); void SendNotification(); @@ -108,6 +108,8 @@ protected: uint32_t mSurfaceHeight; uint32_t mFrame; + Graphics::UniquePtr mRenderTarget; + struct { uint32_t x; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp index f2086d6..b85cf4d 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp @@ -18,21 +18,24 @@ #include "test-gl-abstraction.h" #include "test-trace-call-stack.h" +static const bool TRACE{ + false}; + namespace Dali { TestGlAbstraction::TestGlAbstraction() -: mBufferTrace(true, std::string("gl")), - mCullFaceTrace(true, "gl"), - mEnableDisableTrace(true, "gl"), - mShaderTrace(true, "gl"), - mTextureTrace(true, std::string("gl")), - mTexParameterTrace(true, "gl"), - mDrawTrace(true, "gl"), - mDepthFunctionTrace(true, "gl"), - mStencilFunctionTrace(true, "gl"), - mScissorTrace(true, "gl"), - mSetUniformTrace(true, "Uniform "), - mViewportTrace(true, "gl") +: mBufferTrace(TRACE, std::string("gl")), + mCullFaceTrace(TRACE, "gl"), + mEnableDisableTrace(TRACE, "gl"), + mShaderTrace(TRACE, "gl"), + mTextureTrace(TRACE, std::string("gl")), + mTexParameterTrace(TRACE, "gl"), + mDrawTrace(TRACE, "gl"), + mDepthFunctionTrace(TRACE, "gl"), + mStencilFunctionTrace(TRACE, "gl"), + mScissorTrace(TRACE, "gl"), + mSetUniformTrace(TRACE, "Uniform "), + mViewportTrace(TRACE, "gl") { Initialize(); } @@ -46,7 +49,6 @@ void TestGlAbstraction::Initialize() mCurrentProgram = 0; mCompileStatus = GL_TRUE; mLinkStatus = GL_TRUE; - mNumberOfActiveUniforms = 0; mGetErrorResult = 0; mGetStringResult = NULL; mIsBufferResult = 0; @@ -112,6 +114,31 @@ void TestGlAbstraction::Initialize() { mVertexAttribArrayState[i] = false; } + + mActiveUniforms = std::vector{ + {"uRendererColor", GL_FLOAT, 1}, + {"uCustom", GL_FLOAT_VEC3, 1}, + {"uCustom3", GL_FLOAT_VEC3, 1}, + {"uFadeColor", GL_FLOAT_VEC4, 1}, + {"uUniform1", GL_FLOAT_VEC4, 1}, + {"uUniform2", GL_FLOAT_VEC4, 1}, + {"uUniform3", GL_FLOAT_VEC4, 1}, + {"uFadeProgress", GL_FLOAT, 1}, + {"uANormalMatrix", GL_FLOAT_MAT3, 1}, + {"sEffect", GL_SAMPLER_2D, 1}, + {"sTexture", GL_SAMPLER_2D, 1}, + {"sTextureRect", GL_SAMPLER_2D, 1}, + {"sGloss", GL_SAMPLER_2D, 1}, + {"uColor", GL_FLOAT_VEC4, 1}, + {"uModelMatrix", GL_FLOAT_MAT4, 1}, + {"uModelView", GL_FLOAT_MAT4, 1}, + {"uMvpMatrix", GL_FLOAT_MAT4, 1}, + {"uNormalMatrix", GL_FLOAT_MAT4, 1}, + {"uProjection", GL_FLOAT_MAT4, 1}, + {"uSize", GL_FLOAT_VEC3, 1}, + {"uViewMatrix", GL_FLOAT_MAT4, 1}, + {"uLightCameraProjectionMatrix", GL_FLOAT_MAT4, 1}, + {"uLightCameraViewMatrix", GL_FLOAT_MAT4, 1}}; } void TestGlAbstraction::PreRender() diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h index 9357803..aec9f5d 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h @@ -49,6 +49,13 @@ struct UniformData } }; +struct ActiveUniform +{ + std::string name; + GLenum type; + GLint size; +}; + class DALI_CORE_API TestGlAbstraction : public Dali::Integration::GlAbstraction { public: @@ -621,6 +628,11 @@ public: { mFramebufferStencilAttached = true; } + else if(attachment == GL_DEPTH_STENCIL_ATTACHMENT) + { + mFramebufferStencilAttached = true; + mFramebufferDepthAttached = true; + } } inline void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) override @@ -749,27 +761,18 @@ public: { } + inline void SetActiveUniforms(const std::vector& uniforms) + { + mActiveUniforms = uniforms; + } + inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) override { - switch(index) + if(index < mActiveUniforms.size()) { - case 0: - *length = snprintf(name, bufsize, "sTexture"); - *type = GL_SAMPLER_2D; - *size = 1; - break; - case 1: - *length = snprintf(name, bufsize, "sEffect"); - *type = GL_SAMPLER_2D; - *size = 1; - break; - case 2: - *length = snprintf(name, bufsize, "sGloss"); - *type = GL_SAMPLER_2D; - *size = 1; - break; - default: - break; + *length = snprintf(name, bufsize, "%s", mActiveUniforms[index].name.c_str()); + *type = mActiveUniforms[index].type; + *size = mActiveUniforms[index].size; } } @@ -837,7 +840,7 @@ public: *params = mProgramBinaryLength; break; case GL_ACTIVE_UNIFORMS: - *params = mNumberOfActiveUniforms; + *params = mActiveUniforms.size(); break; case GL_ACTIVE_UNIFORM_MAX_LENGTH: *params = 100; @@ -981,31 +984,10 @@ public: namedParams["program"] << program; mShaderTrace.PushCall("LinkProgram", out.str(), namedParams); - mNumberOfActiveUniforms = 3; - - GetUniformLocation(program, "uRendererColor"); - GetUniformLocation(program, "uCustom"); - GetUniformLocation(program, "uCustom3"); - GetUniformLocation(program, "uFadeColor"); - GetUniformLocation(program, "uUniform1"); - GetUniformLocation(program, "uUniform2"); - GetUniformLocation(program, "uUniform3"); - GetUniformLocation(program, "uFadeProgress"); - GetUniformLocation(program, "uANormalMatrix"); - GetUniformLocation(program, "sEffect"); - GetUniformLocation(program, "sTexture"); - GetUniformLocation(program, "sTextureRect"); - GetUniformLocation(program, "sGloss"); - GetUniformLocation(program, "uColor"); - GetUniformLocation(program, "uModelMatrix"); - GetUniformLocation(program, "uModelView"); - GetUniformLocation(program, "uMvpMatrix"); - GetUniformLocation(program, "uNormalMatrix"); - GetUniformLocation(program, "uProjection"); - GetUniformLocation(program, "uSize"); - GetUniformLocation(program, "uViewMatrix"); - GetUniformLocation(program, "uLightCameraProjectionMatrix"); - GetUniformLocation(program, "uLightCameraViewMatrix"); + for(const auto& uniform : mActiveUniforms) + { + GetUniformLocation(program, uniform.name.c_str()); + } for(const auto& uniform : mCustomUniformData) { @@ -2465,14 +2447,13 @@ public: // TEST FUNCTIONS mBufferSubDataCalls.clear(); } -private: +public: GLuint mCurrentProgram; GLuint mCompileStatus; BufferDataCalls mBufferDataCalls; BufferSubDataCalls mBufferSubDataCalls; GLvoid* mMappedBuffer{nullptr}; GLuint mLinkStatus; - GLint mNumberOfActiveUniforms; GLenum mGetErrorResult; GLubyte* mGetStringResult; GLboolean mIsBufferResult; @@ -2547,8 +2528,8 @@ private: typedef std::map UniformIDMap; typedef std::map ProgramUniformMap; ProgramUniformMap mUniforms; - - std::vector mCustomUniformData{}; + std::vector mActiveUniforms; + std::vector mCustomUniformData{}; template struct ProgramUniformValue : public std::map > diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.cpp index d8a1b1a..21eecf4 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.cpp @@ -80,14 +80,15 @@ GLenum TestGraphicsBuffer::GetTarget() return target; } -void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program) const +void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const { auto* reflection = static_cast(&program->GetReflection()); Graphics::UniformBlockInfo uboInfo{}; reflection->GetUniformBlock(0, uboInfo); - auto* data = memory.data(); + auto offset = uboBinding.offset; + auto* data = memory.data() + offset; for(const auto& member : uboInfo.members) { diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.h index 87c9f87..1dc2715 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-buffer.h @@ -26,6 +26,7 @@ namespace Dali { class TestGraphicsProgram; +class UniformBufferBindingDescriptor; class TestGraphicsBuffer : public Graphics::Buffer { public: @@ -40,7 +41,7 @@ public: return true; } - void BindAsUniformBuffer(const TestGraphicsProgram* program) const; + void BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const; TraceCallStack& mCallStack; TestGlAbstraction& mGl; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.cpp index ed63416..9f86b99 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.cpp @@ -18,6 +18,70 @@ namespace Dali { +std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op) +{ + switch(op) + { + case Graphics::StencilOp::KEEP: + os << "KEEP"; + return os; + case Graphics::StencilOp::ZERO: + os << "ZERO"; + return os; + case Graphics::StencilOp::REPLACE: + os << "REPLACE"; + return os; + case Graphics::StencilOp::INCREMENT_AND_CLAMP: + os << "INCREMENT_AND_CLAMP"; + return os; + case Graphics::StencilOp::DECREMENT_AND_CLAMP: + os << "DECREMENT_AND_CLAMP"; + return os; + case Graphics::StencilOp::INVERT: + os << "INVERT"; + return os; + case Graphics::StencilOp::INCREMENT_AND_WRAP: + os << "INCREMENT_AND_WRAP"; + return os; + case Graphics::StencilOp::DECREMENT_AND_WRAP: + os << "DECREMENT_AND_WRAP"; + return os; + } + return os; +}; + +std::ostream& operator<<(std::ostream& os, Graphics::CompareOp op) +{ + switch(op) + { + case Graphics::CompareOp::NEVER: + os << "NEVER"; + return os; + case Graphics::CompareOp::LESS: + os << "LESS"; + return os; + case Graphics::CompareOp::EQUAL: + os << "EQUAL"; + return os; + case Graphics::CompareOp::LESS_OR_EQUAL: + os << "LESS_OR_EQUAL"; + return os; + case Graphics::CompareOp::GREATER: + os << "GREATER"; + return os; + case Graphics::CompareOp::NOT_EQUAL: + os << "NOT_EQUAL"; + return os; + case Graphics::CompareOp::GREATER_OR_EQUAL: + os << "GREATER_OR_EQUAL"; + return os; + case Graphics::CompareOp::ALWAYS: + os << "ALWAYS"; + return os; + } + return os; +}; + TestGraphicsCommandBuffer::TestGraphicsCommandBuffer(TraceCallStack& callstack, TestGlAbstraction& glAbstraction) : mCallStack(callstack), mGlAbstraction(glAbstraction) @@ -60,9 +124,9 @@ void TestGraphicsCommandBuffer::GetStateForDrawCall(int drawCallIndex) } } -std::vector TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMask mask) +std::vector TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMask mask) const { - std::vector mCommandStack{}; + std::vector mCommandStack{}; for(auto& cmd : mCommands) { if(uint32_t(cmd.type) == (mask & uint32_t(cmd.type))) @@ -73,4 +137,27 @@ std::vector TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMa return mCommandStack; } +std::vector TestGraphicsCommandBuffer::GetChildCommandsByType(CommandTypeMask mask) const +{ + std::vector mCommandStack{}; + for(auto& cmd : mCommands) + { + if(uint32_t(cmd.type) == (mask & uint32_t(cmd.type))) + { + mCommandStack.emplace_back(&cmd); + } + if(cmd.type == CommandType::EXECUTE_COMMAND_BUFFERS) + { + for(auto secondaryCB : cmd.data.executeCommandBuffers.buffers) + { + for(auto command : secondaryCB->GetChildCommandsByType(mask)) + { + mCommandStack.push_back(command); + } + } + } + } + return mCommandStack; +} + } // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.h index c10c3f1..3df3219 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-command-buffer.h @@ -32,27 +32,45 @@ namespace Dali { class TestGraphicsTexture; class TestGraphicsBuffer; +class TestGraphicsCommandBuffer; class TestGraphicsSampler; class TestGraphicsPipeline; enum class CommandType { - FLUSH = 1 << 0, - BIND_TEXTURES = 1 << 1, - BIND_SAMPLERS = 1 << 2, - BIND_VERTEX_BUFFERS = 1 << 3, - BIND_INDEX_BUFFER = 1 << 4, - BIND_UNIFORM_BUFFER = 1 << 5, - BIND_PIPELINE = 1 << 6, - DRAW = 1 << 7, - DRAW_INDEXED = 1 << 8, - DRAW_INDEXED_INDIRECT = 1 << 9, - SET_SCISSOR = 1 << 10, - SET_SCISSOR_TEST = 1 << 11, - SET_VIEWPORT = 1 << 12, - SET_VIEWPORT_TEST = 1 << 13 + FLUSH = 1 << 0, + BIND_TEXTURES = 1 << 1, + BIND_SAMPLERS = 1 << 2, + BIND_VERTEX_BUFFERS = 1 << 3, + BIND_INDEX_BUFFER = 1 << 4, + BIND_UNIFORM_BUFFER = 1 << 5, + BIND_PIPELINE = 1 << 6, + DRAW = 1 << 7, + DRAW_INDEXED = 1 << 8, + DRAW_INDEXED_INDIRECT = 1 << 9, + SET_SCISSOR = 1 << 10, + SET_SCISSOR_TEST = 1 << 11, + SET_VIEWPORT = 1 << 12, + SET_VIEWPORT_TEST = 1 << 13, + BEGIN_RENDER_PASS = 1 << 14, + END_RENDER_PASS = 1 << 15, + EXECUTE_COMMAND_BUFFERS = 1 << 16, + SET_COLOR_MASK = 1 << 17, + CLEAR_STENCIL_BUFFER = 1 << 18, + CLEAR_DEPTH_BUFFER = 1 << 19, + SET_STENCIL_TEST_ENABLE = 1 << 20, + SET_STENCIL_WRITE_MASK = 1 << 21, + SET_STENCIL_OP = 1 << 22, + SET_STENCIL_FUNC = 1 << 23, + SET_DEPTH_COMPARE_OP = 1 << 24, + SET_DEPTH_TEST_ENABLE = 1 << 25, + SET_DEPTH_WRITE_ENABLE = 1 << 26, }; +std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op); + +std::ostream& operator<<(std::ostream& os, Graphics::CompareOp op); + using CommandTypeMask = uint32_t; template inline CommandTypeMask operator|(T flags, CommandType bit) @@ -160,8 +178,37 @@ struct Command { } + Command(CommandType type) + : type(type) + { + // do non-trivial initialization + switch(type) + { + case CommandType::BEGIN_RENDER_PASS: + { + new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor(); + break; + } + default: + { + } + } + } + ~Command() { + switch(type) + { + case CommandType::BEGIN_RENDER_PASS: + { + data.beginRenderPass.~BeginRenderPassDescriptor(); + break; + } + default: + { + break; + } + } } /** @@ -172,6 +219,22 @@ struct Command { switch(rhs.type) { + case CommandType::BEGIN_RENDER_PASS: + { + new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor(rhs.data.beginRenderPass); + break; + } + case CommandType::END_RENDER_PASS: + { + data.endRenderPass = rhs.data.endRenderPass; + break; + } + case CommandType::EXECUTE_COMMAND_BUFFERS: + { + data.executeCommandBuffers = rhs.data.executeCommandBuffers; + break; + } + case CommandType::BIND_VERTEX_BUFFERS: { data.bindVertexBuffers = rhs.data.bindVertexBuffers; @@ -245,6 +308,59 @@ struct Command data.viewportTest.enable = rhs.data.viewportTest.enable; break; } + case CommandType::SET_COLOR_MASK: + { + data.colorMask.enabled = rhs.data.colorMask.enabled; + break; + } + case CommandType::CLEAR_STENCIL_BUFFER: + { + break; + } + case CommandType::CLEAR_DEPTH_BUFFER: + { + break; + } + case CommandType::SET_STENCIL_TEST_ENABLE: + { + data.stencilTest.enabled = rhs.data.stencilTest.enabled; + break; + } + case CommandType::SET_STENCIL_FUNC: + { + data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask; + data.stencilFunc.compareOp = rhs.data.stencilFunc.compareOp; + data.stencilFunc.reference = rhs.data.stencilFunc.reference; + break; + } + case CommandType::SET_STENCIL_WRITE_MASK: + { + data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask; + break; + } + case CommandType::SET_STENCIL_OP: + { + data.stencilOp.failOp = rhs.data.stencilOp.failOp; + data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp; + data.stencilOp.passOp = rhs.data.stencilOp.passOp; + break; + } + + case CommandType::SET_DEPTH_COMPARE_OP: + { + data.depth.compareOp = rhs.data.depth.compareOp; + break; + } + case CommandType::SET_DEPTH_TEST_ENABLE: + { + data.depth.testEnabled = rhs.data.depth.testEnabled; + break; + } + case CommandType::SET_DEPTH_WRITE_ENABLE: + { + data.depth.writeEnabled = rhs.data.depth.writeEnabled; + break; + } } type = rhs.type; } @@ -257,6 +373,21 @@ struct Command { switch(rhs.type) { + case CommandType::BEGIN_RENDER_PASS: + { + new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor(std::move(rhs.data.beginRenderPass)); + break; + } + case CommandType::END_RENDER_PASS: + { + data.endRenderPass = std::move(rhs.data.endRenderPass); + break; + } + case CommandType::EXECUTE_COMMAND_BUFFERS: + { + data.executeCommandBuffers = std::move(rhs.data.executeCommandBuffers); + break; + } case CommandType::BIND_VERTEX_BUFFERS: { data.bindVertexBuffers = std::move(rhs.data.bindVertexBuffers); @@ -330,6 +461,59 @@ struct Command data.viewportTest.enable = rhs.data.viewportTest.enable; break; } + + case CommandType::SET_COLOR_MASK: + { + data.colorMask.enabled = rhs.data.colorMask.enabled; + break; + } + case CommandType::CLEAR_STENCIL_BUFFER: + { + break; + } + case CommandType::CLEAR_DEPTH_BUFFER: + { + break; + } + case CommandType::SET_STENCIL_TEST_ENABLE: + { + data.stencilTest.enabled = rhs.data.stencilTest.enabled; + break; + } + case CommandType::SET_STENCIL_WRITE_MASK: + { + data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask; + break; + } + case CommandType::SET_STENCIL_OP: + { + data.stencilOp.failOp = rhs.data.stencilOp.failOp; + data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp; + data.stencilOp.passOp = rhs.data.stencilOp.passOp; + break; + } + case CommandType::SET_STENCIL_FUNC: + { + data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask; + data.stencilFunc.compareOp = rhs.data.stencilFunc.compareOp; + data.stencilFunc.reference = rhs.data.stencilFunc.reference; + break; + } + case CommandType::SET_DEPTH_COMPARE_OP: + { + data.depth.compareOp = rhs.data.depth.compareOp; + break; + } + case CommandType::SET_DEPTH_TEST_ENABLE: + { + data.depth.testEnabled = rhs.data.depth.testEnabled; + break; + } + case CommandType::SET_DEPTH_WRITE_ENABLE: + { + data.depth.writeEnabled = rhs.data.depth.writeEnabled; + break; + } } type = rhs.type; } @@ -398,6 +582,60 @@ struct Command { bool enable; } viewportTest; + + struct BeginRenderPassDescriptor + { + Graphics::RenderPass* renderPass; + Graphics::RenderTarget* renderTarget; + Graphics::Rect2D renderArea; + std::vector clearValues; + } beginRenderPass; + + struct + { + Graphics::SyncObject* syncObject; + } endRenderPass; + + struct + { + std::vector buffers; + } executeCommandBuffers; + + struct + { + Graphics::CompareOp compareOp; + bool testEnabled; + bool writeEnabled; + } depth; + + struct + { + Graphics::StencilOp failOp; + Graphics::StencilOp passOp; + Graphics::StencilOp depthFailOp; + } stencilOp; + + struct + { + uint32_t mask; + } stencilWriteMask; + + struct + { + uint32_t compareMask; + Graphics::CompareOp compareOp; + uint32_t reference; + } stencilFunc; + + struct + { + bool enabled; + } stencilTest; + + struct + { + bool enabled; + } colorMask; } data; }; @@ -509,12 +747,23 @@ public: } void BeginRenderPass( - Graphics::RenderPass& renderPass, - Graphics::RenderTarget& renderTarget, - Graphics::Extent2D renderArea, + Graphics::RenderPass* renderPass, + Graphics::RenderTarget* renderTarget, + Graphics::Rect2D renderArea, std::vector clearValues) override { - mCallStack.PushCall("BeginRenderPass", ""); + mCommands.emplace_back(CommandType::BEGIN_RENDER_PASS); + auto& cmd = mCommands.back(); + cmd.data.beginRenderPass.renderPass = renderPass; + cmd.data.beginRenderPass.renderTarget = renderTarget; + cmd.data.beginRenderPass.renderArea = renderArea; + cmd.data.beginRenderPass.clearValues = clearValues; + + TraceCallStack::NamedParams namedParams; + namedParams["renderPass"] << std::hex << renderPass; + namedParams["renderTarget"] << std::hex << renderTarget; + namedParams["renderArea"] << renderArea.width << ", " << renderArea.height; + mCallStack.PushCall("BeginRenderPass", namedParams.str(), namedParams); } /** @@ -526,9 +775,29 @@ public: * dependencies (for example, to know when target texture is ready * before passing it to another render pass). */ - void EndRenderPass() override + void EndRenderPass(Graphics::SyncObject* syncObject) override { - mCallStack.PushCall("EndRenderPass", ""); + mCommands.emplace_back(CommandType::END_RENDER_PASS); + auto& cmd = mCommands.back(); + + cmd.data.endRenderPass.syncObject = syncObject; + + TraceCallStack::NamedParams namedParams; + namedParams["syncObject"] << std::hex << syncObject; + mCallStack.PushCall("EndRenderPass", namedParams.str(), namedParams); + } + + void ExecuteCommandBuffers(std::vector&& commandBuffers) override + { + mCommands.emplace_back(); + auto& cmd = mCommands.back(); + cmd.type = CommandType::EXECUTE_COMMAND_BUFFERS; + cmd.data.executeCommandBuffers.buffers.reserve(commandBuffers.size()); + for(auto&& item : commandBuffers) + { + cmd.data.executeCommandBuffers.buffers.emplace_back(static_cast(item)); + } + mCallStack.PushCall("ExecuteCommandBuffers", ""); } void Draw( @@ -642,6 +911,112 @@ public: mCommands.back().data.viewportTest.enable = value; } + void SetColorMask(bool enabled) override + { + TraceCallStack::NamedParams params; + params["enabled"] << (enabled ? "T" : "F"); + mCallStack.PushCall("SetColorMask", params.str(), params); + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_COLOR_MASK; + mCommands.back().data.colorMask.enabled = enabled; + } + + void ClearStencilBuffer() override + { + mCallStack.PushCall("SetStencilMask", ""); + mCommands.emplace_back(); + mCommands.back().type = CommandType::CLEAR_STENCIL_BUFFER; + } + + void SetStencilTestEnable(bool stencilEnable) override + { + TraceCallStack::NamedParams params; + params["enabled"] << (stencilEnable ? "T" : "F"); + mCallStack.PushCall("SetStencilTestEnable", params.str(), params); + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_STENCIL_TEST_ENABLE; + mCommands.back().data.stencilTest.enabled = stencilEnable; + } + + void SetStencilWriteMask(uint32_t writeMask) override + { + TraceCallStack::NamedParams params; + params["writeMask"] << std::hex << writeMask; + mCallStack.PushCall("SetStencilWriteMask", params.str(), params); + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_STENCIL_WRITE_MASK; + mCommands.back().data.stencilWriteMask.mask = writeMask; + } + + void SetStencilOp(Graphics::StencilOp failOp, + Graphics::StencilOp passOp, + Graphics::StencilOp depthFailOp) override + { + TraceCallStack::NamedParams params; + params["failOp"] << failOp; + params["passOp"] << passOp; + params["depthFailOp"] << depthFailOp; + mCallStack.PushCall("SetStencilOp", params.str(), params); + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_STENCIL_OP; + mCommands.back().data.stencilOp.failOp = failOp; + mCommands.back().data.stencilOp.passOp = passOp; + mCommands.back().data.stencilOp.depthFailOp = depthFailOp; + } + + void SetStencilFunc(Graphics::CompareOp compareOp, + uint32_t reference, + uint32_t compareMask) override + { + TraceCallStack::NamedParams params; + params["compareOp"] << compareOp; + params["compareMask"] << std::hex << compareMask; + params["reference"] << std::hex << reference; + mCallStack.PushCall("SetStencilFunc", params.str(), params); + + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_STENCIL_FUNC; + + mCommands.back().data.stencilFunc.compareOp = compareOp; + mCommands.back().data.stencilFunc.compareMask = compareMask; + mCommands.back().data.stencilFunc.reference = reference; + } + + void SetDepthCompareOp(Graphics::CompareOp compareOp) override + { + TraceCallStack::NamedParams params; + params["compareOp"] << compareOp; + mCallStack.PushCall("SetDepthCompareOp", params.str(), params); + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_DEPTH_COMPARE_OP; + mCommands.back().data.depth.compareOp = compareOp; + } + + void SetDepthTestEnable(bool depthTestEnable) override + { + TraceCallStack::NamedParams params; + params["enabled"] << (depthTestEnable ? "T" : "F"); + mCallStack.PushCall("SetDepthTestEnable", params.str(), params); + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_DEPTH_TEST_ENABLE; + mCommands.back().data.depth.testEnabled = depthTestEnable; + } + void SetDepthWriteEnable(bool depthWriteEnable) override + { + TraceCallStack::NamedParams params; + params["enabled"] << (depthWriteEnable ? "T" : "F"); + mCallStack.PushCall("SetDepthWriteEnable", params.str(), params); + mCommands.emplace_back(); + mCommands.back().type = CommandType::SET_DEPTH_WRITE_ENABLE; + mCommands.back().data.depth.writeEnabled = depthWriteEnable; + } + void ClearDepthBuffer() override + { + mCallStack.PushCall("ClearDepthBuffer", ""); + mCommands.emplace_back(); + mCommands.back().type = CommandType::CLEAR_DEPTH_BUFFER; + } + [[nodiscard]] const std::vector& GetCommands() const { return mCommands; @@ -662,7 +1037,9 @@ public: /** * Retrieves commands of specified type */ - std::vector GetCommandsByType(CommandTypeMask mask); + std::vector GetCommandsByType(CommandTypeMask mask) const; + + std::vector GetChildCommandsByType(CommandTypeMask mask) const; private: TraceCallStack& mCallStack; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp index 51f0721..0886719 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.cpp @@ -18,9 +18,13 @@ #include "test-graphics-buffer.h" #include "test-graphics-command-buffer.h" +#include "test-graphics-framebuffer.h" #include "test-graphics-reflection.h" +#include "test-graphics-render-pass.h" +#include "test-graphics-render-target.h" #include "test-graphics-sampler.h" #include "test-graphics-shader.h" +#include "test-graphics-sync-object.h" #include "test-graphics-texture.h" #include @@ -30,36 +34,6 @@ namespace Dali { -template -T* Uncast(const Graphics::CommandBuffer* object) -{ - return const_cast(static_cast(object)); -} - -template -T* Uncast(const Graphics::Texture* object) -{ - return const_cast(static_cast(object)); -} - -template -T* Uncast(const Graphics::Sampler* object) -{ - return const_cast(static_cast(object)); -} - -template -T* Uncast(const Graphics::Buffer* object) -{ - return const_cast(static_cast(object)); -} - -template -T* Uncast(const Graphics::Shader* object) -{ - return const_cast(static_cast(object)); -} - std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo) { return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size; @@ -173,70 +147,34 @@ std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& cre return o; } -class TestGraphicsMemory : public Graphics::Memory +std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment) { -public: - TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize) - : mCallStack(callStack), - mBuffer(buffer), - mMappedOffset(mappedOffset), - mMappedSize(mappedSize), - mLockedOffset(0u), - mLockedSize(0u) - { - } - - void* LockRegion(uint32_t offset, uint32_t size) override - { - std::ostringstream o; - o << offset << ", " << size; - mCallStack.PushCall("Memory::LockRegion", o.str()); - - if(offset > mMappedOffset + mMappedSize || - size + offset > mMappedOffset + mMappedSize) - { - fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds"); - mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing - } - mLockedOffset = offset; - mLockedSize = size; - return &mBuffer.memory[mMappedOffset + offset]; - } + o << "attachmentId:" << colorAttachment.attachmentId + << " layerId:" << colorAttachment.layerId + << " levelId:" << colorAttachment.levelId + << " texture:" << colorAttachment.texture; + return o; +} - void Unlock(bool flush) override - { - mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush")); - if(flush) - { - Flush(); - } - } +std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment) +{ + o << "depthTexture:" << depthStencilAttachment.depthTexture + << "depthLevel:" << depthStencilAttachment.depthLevel + << "stencilTexture:" << depthStencilAttachment.stencilTexture + << "stencilLevel:" << depthStencilAttachment.stencilLevel; + return o; +} - void Flush() override +std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo) +{ + o << "colorAttachments:"; + for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i) { - mCallStack.PushCall("Memory::Flush", ""); - mBuffer.Bind(); - mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize); - mBuffer.Unbind(); + o << "[" << i << "]=" << createInfo.colorAttachments[i] << " "; } - - TraceCallStack& mCallStack; - TestGraphicsBuffer& mBuffer; - uint32_t mMappedOffset; - uint32_t mMappedSize; - uint32_t mLockedOffset; - uint32_t mLockedSize; -}; - -TestGraphicsController::TestGraphicsController() -: mCallStack(true, "TestGraphicsController."), - mCommandBufferCallStack(true, "TestCommandBuffer.") -{ - mCallStack.Enable(true); - mCommandBufferCallStack.Enable(true); - auto& trace = mGl.GetTextureTrace(); - trace.Enable(true); - trace.EnableLogging(true); + o << "depthStencilAttachment:" << createInfo.depthStencilAttachment; + o << "size: " << createInfo.size; + return o; } int GetNumComponents(Graphics::VertexInputFormat vertexFormat) @@ -447,6 +385,143 @@ GLenum GetBlendOp(Graphics::BlendOp blendOp) return op; } +struct GLCompareOp +{ + constexpr explicit GLCompareOp(Graphics::CompareOp compareOp) + { + switch(compareOp) + { + case Graphics::CompareOp::NEVER: + op = GL_NEVER; + break; + case Graphics::CompareOp::LESS: + op = GL_LESS; + break; + case Graphics::CompareOp::EQUAL: + op = GL_EQUAL; + break; + case Graphics::CompareOp::LESS_OR_EQUAL: + op = GL_LEQUAL; + break; + case Graphics::CompareOp::GREATER: + op = GL_GREATER; + break; + case Graphics::CompareOp::NOT_EQUAL: + op = GL_NOTEQUAL; + break; + case Graphics::CompareOp::GREATER_OR_EQUAL: + op = GL_GEQUAL; + break; + case Graphics::CompareOp::ALWAYS: + op = GL_ALWAYS; + break; + } + } + GLenum op{GL_LESS}; +}; + +struct GLStencilOp +{ + constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp) + { + switch(stencilOp) + { + case Graphics::StencilOp::KEEP: + op = GL_KEEP; + break; + case Graphics::StencilOp::ZERO: + op = GL_ZERO; + break; + case Graphics::StencilOp::REPLACE: + op = GL_REPLACE; + break; + case Graphics::StencilOp::INCREMENT_AND_CLAMP: + op = GL_INCR; + break; + case Graphics::StencilOp::DECREMENT_AND_CLAMP: + op = GL_DECR; + break; + case Graphics::StencilOp::INVERT: + op = GL_INVERT; + break; + case Graphics::StencilOp::INCREMENT_AND_WRAP: + op = GL_INCR_WRAP; + break; + case Graphics::StencilOp::DECREMENT_AND_WRAP: + op = GL_DECR_WRAP; + break; + } + } + GLenum op{GL_KEEP}; +}; + +class TestGraphicsMemory : public Graphics::Memory +{ +public: + TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize) + : mCallStack(callStack), + mBuffer(buffer), + mMappedOffset(mappedOffset), + mMappedSize(mappedSize), + mLockedOffset(0u), + mLockedSize(0u) + { + } + + void* LockRegion(uint32_t offset, uint32_t size) override + { + std::ostringstream o; + o << offset << ", " << size; + mCallStack.PushCall("Memory::LockRegion", o.str()); + + if(offset > mMappedOffset + mMappedSize || + size + offset > mMappedOffset + mMappedSize) + { + fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds"); + mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing + } + mLockedOffset = offset; + mLockedSize = size; + return &mBuffer.memory[mMappedOffset + offset]; + } + + void Unlock(bool flush) override + { + mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush")); + if(flush) + { + Flush(); + } + } + + void Flush() override + { + mCallStack.PushCall("Memory::Flush", ""); + mBuffer.Bind(); + mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize); + mBuffer.Unbind(); + } + + TraceCallStack& mCallStack; + TestGraphicsBuffer& mBuffer; + uint32_t mMappedOffset; + uint32_t mMappedSize; + uint32_t mLockedOffset; + uint32_t mLockedSize; +}; + +TestGraphicsController::TestGraphicsController() +: mCallStack(true, "TestGraphicsController."), + mCommandBufferCallStack(true, "TestCommandBuffer."), + mFrameBufferCallStack(true, "TestFrameBuffer.") +{ + mCallStack.Enable(true); + mCommandBufferCallStack.Enable(true); + auto& trace = mGl.GetTextureTrace(); + trace.Enable(true); + trace.EnableLogging(true); +} + void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo) { TraceCallStack::NamedParams namedParams; @@ -460,193 +535,420 @@ void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& su for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer) { auto commandBuffer = Uncast(graphicsCommandBuffer); + ProcessCommandBuffer(*commandBuffer); + } +} + +void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer) +{ + bool scissorEnabled = false; + TestGraphicsFramebuffer* currentFramebuffer{nullptr}; + TestGraphicsPipeline* currentPipeline{nullptr}; - auto value = commandBuffer->GetCommandsByType(0 | CommandType::BIND_TEXTURES); - if(!value.empty()) + for(auto& cmd : commandBuffer.GetCommands()) + { + // process command + switch(cmd.type) { - // must be fixed - for(auto& binding : value[0]->data.bindTextures.textureBindings) + case CommandType::FLUSH: { - if(binding.texture) + // Nothing to do here + break; + } + case CommandType::BIND_TEXTURES: + { + for(auto& binding : cmd.data.bindTextures.textureBindings) { - auto texture = Uncast(binding.texture); - - texture->Bind(binding.binding); - - if(binding.sampler) + if(binding.texture) { - auto sampler = Uncast(binding.sampler); - if(sampler) + auto texture = Uncast(binding.texture); + texture->Bind(binding.binding); + + if(binding.sampler) { - sampler->Apply(texture->GetTarget()); + auto sampler = Uncast(binding.sampler); + if(sampler) + { + sampler->Apply(texture->GetTarget()); + } } - } - texture->Prepare(); // Ensure native texture is ready + texture->Prepare(); // Ensure native texture is ready + } } + break; } - } - - // IndexBuffer binding, - auto bindIndexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_INDEX_BUFFER); - if(!bindIndexBufferCmds.empty()) - { - auto& indexBufferBinding = bindIndexBufferCmds[0]->data.bindIndexBuffer; - if(indexBufferBinding.buffer) + case CommandType::BIND_VERTEX_BUFFERS: { - auto buffer = Uncast(indexBufferBinding.buffer); - buffer->Bind(); + for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings) + { + auto graphicsBuffer = binding.buffer; + auto vertexBuffer = Uncast(graphicsBuffer); + vertexBuffer->Bind(); + } + break; } - } - - // VertexBuffer binding, - auto bindVertexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_VERTEX_BUFFERS); - if(!bindVertexBufferCmds.empty()) - { - for(auto& binding : bindVertexBufferCmds[0]->data.bindVertexBuffers.vertexBufferBindings) + case CommandType::BIND_INDEX_BUFFER: { - auto graphicsBuffer = binding.buffer; - auto vertexBuffer = Uncast(graphicsBuffer); - vertexBuffer->Bind(); + auto& indexBufferBinding = cmd.data.bindIndexBuffer; + if(indexBufferBinding.buffer) + { + auto buffer = Uncast(indexBufferBinding.buffer); + buffer->Bind(); + } + break; } - } - - bool scissorEnabled = false; + case CommandType::BIND_UNIFORM_BUFFER: + { + if(currentPipeline) + { + auto& bindings = cmd.data.bindUniformBuffers; + auto buffer = bindings.standaloneUniformsBufferBinding; - auto scissorTestList = commandBuffer->GetCommandsByType(0 | CommandType::SET_SCISSOR_TEST); - if(!scissorTestList.empty()) - { - if(scissorTestList[0]->data.scissorTest.enable) + // based on reflection, issue gl calls + buffer.buffer->BindAsUniformBuffer(static_cast(currentPipeline->programState.program), bindings.standaloneUniformsBufferBinding); + } + break; + } + case CommandType::BIND_SAMPLERS: { - mGl.Enable(GL_SCISSOR_TEST); - scissorEnabled = true; + break; } - else + case CommandType::BIND_PIPELINE: { - mGl.Disable(GL_SCISSOR_TEST); + currentPipeline = Uncast(cmd.data.bindPipeline.pipeline); + BindPipeline(currentPipeline); + break; + } + case CommandType::DRAW: + { + if(currentPipeline) + { + mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology), + 0, + cmd.data.draw.draw.vertexCount); + } + break; + } + case CommandType::DRAW_INDEXED: + { + if(currentPipeline) + { + mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology), + static_cast(cmd.data.draw.drawIndexed.indexCount), + GL_UNSIGNED_SHORT, + reinterpret_cast(cmd.data.draw.drawIndexed.firstIndex)); + } + break; + } + case CommandType::DRAW_INDEXED_INDIRECT: + { + if(currentPipeline) + { + mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology), + static_cast(cmd.data.draw.drawIndexed.indexCount), + GL_UNSIGNED_SHORT, + reinterpret_cast(cmd.data.draw.drawIndexed.firstIndex)); + } + break; + } + case CommandType::SET_SCISSOR: + { + if(scissorEnabled) + { + auto& rect = cmd.data.scissor.region; + mGl.Scissor(rect.x, rect.y, rect.width, rect.height); + } + break; + } + case CommandType::SET_SCISSOR_TEST: + { + if(cmd.data.scissorTest.enable) + { + mGl.Enable(GL_SCISSOR_TEST); + scissorEnabled = true; + } + else + { + mGl.Disable(GL_SCISSOR_TEST); + scissorEnabled = false; + } + break; + } + case CommandType::SET_VIEWPORT_TEST: + { + break; + } + case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here? + { + auto& rect = cmd.data.viewport.region; + mGl.Viewport(rect.x, rect.y, rect.width, rect.height); + break; } - } - - auto scissorList = commandBuffer->GetCommandsByType(0 | CommandType::SET_SCISSOR); - if(!scissorList.empty() && scissorEnabled) - { - auto& rect = scissorList[0]->data.scissor.region; - mGl.Scissor(rect.x, rect.y, rect.width, rect.height); - } - auto viewportList = commandBuffer->GetCommandsByType(0 | CommandType::SET_VIEWPORT); - if(!viewportList.empty()) - { - mGl.Viewport(viewportList[0]->data.viewport.region.x, viewportList[0]->data.viewport.region.y, viewportList[0]->data.viewport.region.width, viewportList[0]->data.viewport.region.height); - } + case CommandType::SET_COLOR_MASK: + { + // Set all channels to the same mask + const bool mask = cmd.data.colorMask.enabled; + mGl.ColorMask(mask, mask, mask, mask); + break; + } + case CommandType::CLEAR_STENCIL_BUFFER: + { + mGl.Clear(GL_STENCIL_BUFFER_BIT); + break; + } + case CommandType::CLEAR_DEPTH_BUFFER: + { + mGl.Clear(GL_DEPTH_BUFFER_BIT); + break; + } - // ignore viewport enable + case CommandType::SET_STENCIL_TEST_ENABLE: + { + if(cmd.data.stencilTest.enabled) + { + mGl.Enable(GL_STENCIL_TEST); + } + else + { + mGl.Disable(GL_STENCIL_TEST); + } + break; + } - // Pipeline attribute setup - auto bindPipelineCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_PIPELINE); - if(!bindPipelineCmds.empty()) - { - auto pipeline = bindPipelineCmds[0]->data.bindPipeline.pipeline; - auto& vi = pipeline->vertexInputState; - for(auto& attribute : vi.attributes) + case CommandType::SET_STENCIL_FUNC: { - mGl.EnableVertexAttribArray(attribute.location); - uint32_t attributeOffset = attribute.offset; - GLsizei stride = vi.bufferBindings[attribute.binding].stride; - - mGl.VertexAttribPointer(attribute.location, - GetNumComponents(attribute.format), - GetGlType(attribute.format), - GL_FALSE, // Not normalized - stride, - reinterpret_cast(attributeOffset)); + mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op, + cmd.data.stencilFunc.reference, + cmd.data.stencilFunc.compareMask); + break; } - // Cull face setup - auto& rasterizationState = pipeline->rasterizationState; - if(rasterizationState.cullMode == Graphics::CullMode::NONE) + case CommandType::SET_STENCIL_WRITE_MASK: { - mGl.Disable(GL_CULL_FACE); + mGl.StencilMask(cmd.data.stencilWriteMask.mask); + break; } - else + case CommandType::SET_STENCIL_OP: { - mGl.Enable(GL_CULL_FACE); - mGl.CullFace(GetCullFace(rasterizationState.cullMode)); + mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op, + GLStencilOp(cmd.data.stencilOp.depthFailOp).op, + GLStencilOp(cmd.data.stencilOp.passOp).op); + break; } - mGl.FrontFace(GetFrontFace(rasterizationState.frontFace)); - // We don't modify glPolygonMode in our context/abstraction from GL_FILL (the GL default), - // so it isn't present in the API (and won't have any tests!) - - // Blending setup - auto& colorBlendState = pipeline->colorBlendState; - if(colorBlendState.blendEnable) + case CommandType::SET_DEPTH_COMPARE_OP: { - mGl.Enable(GL_BLEND); - - mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor), - GetBlendFactor(colorBlendState.dstColorBlendFactor), - GetBlendFactor(colorBlendState.srcAlphaBlendFactor), - GetBlendFactor(colorBlendState.dstAlphaBlendFactor)); - if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp) + mGl.DepthFunc(GLCompareOp(cmd.data.depth.compareOp).op); + break; + } + case CommandType::SET_DEPTH_TEST_ENABLE: + { + if(cmd.data.depth.testEnabled) { - mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp)); + mGl.Enable(GL_DEPTH_TEST); } else { - mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp)); + mGl.Disable(GL_DEPTH_TEST); } - mGl.BlendColor(colorBlendState.blendConstants[0], - colorBlendState.blendConstants[1], - colorBlendState.blendConstants[2], - colorBlendState.blendConstants[3]); + break; } - else + case CommandType::SET_DEPTH_WRITE_ENABLE: { - mGl.Disable(GL_BLEND); + mGl.DepthMask(cmd.data.depth.writeEnabled); + break; } - // draw call - auto topology = pipeline->inputAssemblyState.topology; - - // UniformBuffer binding (once we know pipeline) - auto bindUniformBuffersCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_UNIFORM_BUFFER); - if(!bindUniformBuffersCmds.empty()) + case CommandType::EXECUTE_COMMAND_BUFFERS: { - auto buffer = bindUniformBuffersCmds[0]->data.bindUniformBuffers.standaloneUniformsBufferBinding; - - // based on reflection, issue gl calls - buffer.buffer->BindAsUniformBuffer(static_cast(pipeline->programState.program)); + // Process secondary command buffers + for(auto& buf : cmd.data.executeCommandBuffers.buffers) + { + ProcessCommandBuffer(*Uncast(buf)); + } + break; } - - auto drawCmds = commandBuffer->GetCommandsByType(0 | - CommandType::DRAW | - CommandType::DRAW_INDEXED_INDIRECT | - CommandType::DRAW_INDEXED); - - if(!drawCmds.empty()) + case CommandType::BEGIN_RENDER_PASS: { - if(drawCmds[0]->data.draw.type == DrawCallDescriptor::Type::DRAW_INDEXED) + auto renderTarget = Uncast(cmd.data.beginRenderPass.renderTarget); + + if(renderTarget) { - mGl.DrawElements(GetTopology(topology), - static_cast(drawCmds[0]->data.draw.drawIndexed.indexCount), - GL_UNSIGNED_SHORT, - reinterpret_cast(drawCmds[0]->data.draw.drawIndexed.firstIndex)); + auto fb = renderTarget->mCreateInfo.framebuffer; + if(fb) + { + if(currentFramebuffer != fb) + { + currentFramebuffer = Uncast(fb); + currentFramebuffer->Bind(); + } + } + else + { + mGl.BindFramebuffer(GL_FRAMEBUFFER, 0); + } } else { - mGl.DrawArrays(GetTopology(topology), 0, drawCmds[0]->data.draw.draw.vertexCount); + mGl.BindFramebuffer(GL_FRAMEBUFFER, 0); } + + auto& clearValues = cmd.data.beginRenderPass.clearValues; + if(clearValues.size() > 0) + { + const auto renderPass = static_cast(cmd.data.beginRenderPass.renderPass); + if(renderPass) + { + const auto& color0 = renderPass->attachments[0]; + GLuint mask = 0; + if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR) + { + mask |= GL_COLOR_BUFFER_BIT; + + // Set clear color (todo: cache it!) + // Something goes wrong here if Alpha mask is GL_TRUE + mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + mGl.ClearColor(clearValues[0].color.r, + clearValues[0].color.g, + clearValues[0].color.b, + clearValues[0].color.a); + } + + // check for depth stencil + if(renderPass->attachments.size() > 1) + { + const auto& depthStencil = renderPass->attachments.back(); + if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR) + { + mGl.DepthMask(true); + uint32_t depthClearColor = 0u; + if(clearValues.size() == renderPass->attachments.size()) + { + depthClearColor = clearValues.back().depthStencil.depth; + } + mGl.ClearDepthf(depthClearColor); + mask |= GL_DEPTH_BUFFER_BIT; + } + if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR) + { + uint32_t stencilClearColor = 0u; + if(clearValues.size() == renderPass->attachments.size()) + { + stencilClearColor = clearValues.back().depthStencil.stencil; + } + mGl.ClearStencil(stencilClearColor); + mGl.StencilMask(0xFF); // Clear all the bitplanes (assume 8) + mask |= GL_STENCIL_BUFFER_BIT; + } + } + + if(mask != 0) + { + // Test scissor area and RT size + const auto& area = cmd.data.beginRenderPass.renderArea; + if(area.x == 0 && + area.y == 0 && + renderTarget && + area.width == renderTarget->mCreateInfo.extent.width && + area.height == renderTarget->mCreateInfo.extent.height) + { + mGl.Disable(GL_SCISSOR_TEST); + mGl.Clear(mask); + } + else + { + mGl.Enable(GL_SCISSOR_TEST); + mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height); + mGl.Clear(mask); + mGl.Disable(GL_SCISSOR_TEST); + } + } + } + else + { + DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass"); + } + } + break; } - // attribute clear - for(auto& attribute : vi.attributes) + case CommandType::END_RENDER_PASS: { - mGl.DisableVertexAttribArray(attribute.location); + if(cmd.data.endRenderPass.syncObject != nullptr) + { + auto syncObject = Uncast(cmd.data.endRenderPass.syncObject); + syncObject->InitializeResource(); // create the sync object. + } + break; } } } } +void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline) +{ + auto& vi = pipeline->vertexInputState; + for(auto& attribute : vi.attributes) + { + mGl.EnableVertexAttribArray(attribute.location); + uint32_t attributeOffset = attribute.offset; + GLsizei stride = vi.bufferBindings[attribute.binding].stride; + + mGl.VertexAttribPointer(attribute.location, + GetNumComponents(attribute.format), + GetGlType(attribute.format), + GL_FALSE, // Not normalized + stride, + reinterpret_cast(attributeOffset)); + } + + // Cull face setup + auto& rasterizationState = pipeline->rasterizationState; + if(rasterizationState.cullMode == Graphics::CullMode::NONE) + { + mGl.Disable(GL_CULL_FACE); + } + else + { + mGl.Enable(GL_CULL_FACE); + mGl.CullFace(GetCullFace(rasterizationState.cullMode)); + } + + mGl.FrontFace(GetFrontFace(rasterizationState.frontFace)); + + // Blending setup + auto& colorBlendState = pipeline->colorBlendState; + if(colorBlendState.blendEnable) + { + mGl.Enable(GL_BLEND); + + mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor), + GetBlendFactor(colorBlendState.dstColorBlendFactor), + GetBlendFactor(colorBlendState.srcAlphaBlendFactor), + GetBlendFactor(colorBlendState.dstAlphaBlendFactor)); + if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp) + { + mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp)); + } + else + { + mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp)); + } + mGl.BlendColor(colorBlendState.blendConstants[0], + colorBlendState.blendConstants[1], + colorBlendState.blendConstants[2], + colorBlendState.blendConstants[3]); + } + else + { + mGl.Disable(GL_BLEND); + } + + auto* program = static_cast(pipeline->programState.program); + mGl.UseProgram(program->mImpl->mId); +} + /** * @brief Presents render target * @param renderTarget render target to present @@ -713,6 +1015,15 @@ void TestGraphicsController::UpdateTextures(const std::vector(&texture); + mGl.BindTexture(gfxTexture->GetTarget(), 0); + mGl.GenerateMipmap(gfxTexture->GetTarget()); +} + bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) { TraceCallStack::NamedParams namedParams; @@ -770,7 +1081,7 @@ Graphics::UniquePtr TestGraphicsController::CreateComma Graphics::UniquePtr TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr&& oldRenderPass) { mCallStack.PushCall("CreateRenderPass", ""); - return nullptr; + return Graphics::MakeUnique(mGl, renderPassCreateInfo); } Graphics::UniquePtr TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr&& oldTexture) @@ -782,10 +1093,15 @@ Graphics::UniquePtr TestGraphicsController::CreateTexture(con return Graphics::MakeUnique(mGl, textureCreateInfo); } -Graphics::UniquePtr TestGraphicsController::CreateFramebuffer(const Graphics::FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr&& oldFramebuffer) +Graphics::UniquePtr TestGraphicsController::CreateFramebuffer( + const Graphics::FramebufferCreateInfo& createInfo, + Graphics::UniquePtr&& oldFramebuffer) { - mCallStack.PushCall("CreateFramebuffer", ""); - return nullptr; + TraceCallStack::NamedParams namedParams; + namedParams["framebufferCreateInfo"] << createInfo; + mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams); + + return Graphics::MakeUnique(mFrameBufferCallStack, mGl, createInfo); } Graphics::UniquePtr TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr&& oldPipeline) @@ -849,7 +1165,15 @@ Graphics::UniquePtr TestGraphicsController::CreateSampler(con Graphics::UniquePtr TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr&& oldRenderTarget) { mCallStack.PushCall("CreateRenderTarget", ""); - return nullptr; + return Graphics::MakeUnique(mGl, renderTargetCreateInfo); +} + +Graphics::UniquePtr TestGraphicsController::CreateSyncObject( + const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo, + Graphics::UniquePtr&& oldSyncObject) +{ + mCallStack.PushCall("CreateSyncObject", ""); + return Graphics::MakeUnique(mGraphicsSyncImpl, syncObjectCreateInfo); } Graphics::UniquePtr TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo) diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.h index 803678e..cabc414 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-controller.h @@ -20,9 +20,10 @@ #include #include "test-gl-abstraction.h" #include "test-gl-context-helper-abstraction.h" -#include "test-gl-sync-abstraction.h" +#include "test-graphics-command-buffer.h" #include "test-graphics-program.h" #include "test-graphics-reflection.h" +#include "test-graphics-sync-impl.h" namespace Dali { @@ -36,6 +37,60 @@ std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode); std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode); std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo); +template +T* Uncast(const Graphics::CommandBuffer* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::Texture* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::Sampler* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::Buffer* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::Shader* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::Framebuffer* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::Pipeline* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::RenderTarget* object) +{ + return const_cast(static_cast(object)); +} + +template +T* Uncast(const Graphics::SyncObject* object) +{ + return const_cast(static_cast(object)); +} + class TestGraphicsController : public Dali::Graphics::Controller { public: @@ -53,14 +108,14 @@ public: return mGl; } - Integration::GlSyncAbstraction& GetGlSyncAbstraction() override + Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override { - return mGlSyncAbstraction; + return mGlContextHelperAbstraction; } - Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override + TestGraphicsSyncImplementation& GetGraphicsSyncImpl() { - return mGlContextHelperAbstraction; + return mGraphicsSyncImpl; } void SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo) override; @@ -113,6 +168,12 @@ public: const std::vector& sourceList) override; /** + * Auto generates mipmaps for the texture + * @param[in] texture The texture + */ + void GenerateTextureMipmaps(const Graphics::Texture& texture) override; + + /** * TBD: do we need those functions in the new implementation? */ bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override; @@ -219,11 +280,20 @@ public: Graphics::UniquePtr CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr&& oldRenderTarget) override; /** + * @brief Creates new sync object + * Could add timeout etc to createinfo... but nah. + * + * @return pointer to the SyncObject + */ + Graphics::UniquePtr CreateSyncObject(const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo, + Graphics::UniquePtr&& oldSyncObject) override; + + /** * @brief Maps memory associated with Buffer object * * @param[in] mapInfo Filled details of mapped resource * - * @return Returns pointer to Memory object or Graphicsnullptr on error + * @return Returns pointer to Memory object or nullptr on error */ Graphics::UniquePtr MapBufferRange(const Graphics::MapBufferInfo& mapInfo) override; @@ -331,13 +401,18 @@ public: // Test Functions */ bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) override; + void ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer); + + void BindPipeline(TestGraphicsPipeline* pipeline); + public: mutable TraceCallStack mCallStack; mutable TraceCallStack mCommandBufferCallStack; + mutable TraceCallStack mFrameBufferCallStack; mutable std::vector mSubmitStack; TestGlAbstraction mGl; - TestGlSyncAbstraction mGlSyncAbstraction; + TestGraphicsSyncImplementation mGraphicsSyncImpl; TestGlContextHelperAbstraction mGlContextHelperAbstraction; bool isDiscardQueueEmptyResult{true}; @@ -352,6 +427,10 @@ public: }; std::vector mProgramCache; + struct PipelineCache + { + }; + std::vector mCustomUniforms; }; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.cpp new file mode 100644 index 0000000..74f1e29 --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test-graphics-framebuffer.h" +#include +#include "test-graphics-controller.h" +#include "test-graphics-texture.h" + +namespace +{ +const GLenum COLOR_ATTACHMENTS[] = + { + GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3, + GL_COLOR_ATTACHMENT4, + GL_COLOR_ATTACHMENT5, + GL_COLOR_ATTACHMENT6, + GL_COLOR_ATTACHMENT7, +}; + +struct DEPTH_STENCIL_ATTACHMENT_TYPE +{ + constexpr explicit DEPTH_STENCIL_ATTACHMENT_TYPE(Graphics::Format textureFormat) + { + switch(textureFormat) + { + case Graphics::Format::D16_UNORM: + case Graphics::Format::D32_SFLOAT: + case Graphics::Format::X8_D24_UNORM_PACK32: + { + attachment = GL_DEPTH_ATTACHMENT; + break; + } + + case Graphics::Format::S8_UINT: + { + attachment = GL_STENCIL_ATTACHMENT; + break; + } + + case Graphics::Format::D16_UNORM_S8_UINT: + case Graphics::Format::D24_UNORM_S8_UINT: + case Graphics::Format::D32_SFLOAT_S8_UINT: + { + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + break; + } + default: + { + attachment = GL_NONE; + break; + } + } + } + GLenum attachment{GL_NONE}; +}; + +} // namespace +//namespace + +namespace Dali +{ +TestGraphicsFramebuffer::TestGraphicsFramebuffer( + TraceCallStack& callStack, + TestGlAbstraction& glAbstraction, + const Graphics::FramebufferCreateInfo& createInfo) +: mGl(glAbstraction), + mCallStack(callStack) +{ + mCreateInfo.colorAttachments = std::move(createInfo.colorAttachments); + mCreateInfo.depthStencilAttachment = createInfo.depthStencilAttachment; + mCreateInfo.size = createInfo.size; +} + +TestGraphicsFramebuffer::~TestGraphicsFramebuffer() +{ + if(mId) + { + mGl.DeleteFramebuffers(1, &mId); + } +} + +void TestGraphicsFramebuffer::Initialize() +{ + mCallStack.PushCall("Initialize", ""); + + mGl.GenFramebuffers(1, &mId); + mGl.BindFramebuffer(GL_FRAMEBUFFER, mId); + + for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments) + { + AttachTexture(attachment.texture, COLOR_ATTACHMENTS[attachment.attachmentId], attachment.layerId, attachment.levelId); + } + mGl.DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS); + + if(mCreateInfo.depthStencilAttachment.depthTexture) + { + // Create a depth or depth/stencil render target. + auto depthTexture = Uncast(mCreateInfo.depthStencilAttachment.depthTexture); + auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(depthTexture->GetFormat()).attachment; + + mGl.GenRenderbuffers(1, &mDepthBuffer); + mGl.BindRenderbuffer(GL_RENDERBUFFER, mDepthBuffer); + mGl.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mCreateInfo.size.width, mCreateInfo.size.height); + mGl.FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mDepthBuffer); + + AttachTexture(depthTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.depthLevel); + } + + if(mCreateInfo.depthStencilAttachment.stencilTexture) + { + auto stencilTexture = Uncast(mCreateInfo.depthStencilAttachment.stencilTexture); + auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(stencilTexture->GetFormat()).attachment; + + // Create a stencil render target. + mGl.GenRenderbuffers(1, &mStencilBuffer); + mGl.BindRenderbuffer(GL_RENDERBUFFER, mStencilBuffer); + mGl.RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mCreateInfo.size.width, mCreateInfo.size.height); + mGl.FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mStencilBuffer); + + AttachTexture(stencilTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.stencilLevel); + } + mGl.BindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void TestGraphicsFramebuffer::AttachTexture(Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId) +{ + auto graphicsTexture = Uncast(texture); + if(graphicsTexture->GetType() == Graphics::TextureType::TEXTURE_2D) + { + mGl.FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, graphicsTexture->GetTarget(), graphicsTexture->mId, levelId); + } + else + { + mGl.FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layerId, graphicsTexture->mId, levelId); + } +} + +void TestGraphicsFramebuffer::Bind() +{ + mCallStack.PushCall("Bind", ""); + + if(!mId) + { + Initialize(); + } + mGl.BindFramebuffer(GL_FRAMEBUFFER, mId); +} + +} // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.h new file mode 100644 index 0000000..97efe39 --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-framebuffer.h @@ -0,0 +1,49 @@ +#ifndef TEST_GRAPHICS_FRAMEBUFFER_H +#define TEST_GRAPHICS_FRAMEBUFFER_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "test-gl-abstraction.h" +#include "test-trace-call-stack.h" + +namespace Dali +{ +class TestGraphicsFramebuffer : public Graphics::Framebuffer +{ +public: + TestGraphicsFramebuffer(TraceCallStack& callStack, TestGlAbstraction& glAbstraction, const Graphics::FramebufferCreateInfo& createInfo); + ~TestGraphicsFramebuffer(); + + void Initialize(); + void AttachTexture(Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId); + void Bind(); + + TestGlAbstraction& mGl; + Graphics::FramebufferCreateInfo mCreateInfo; + TraceCallStack& mCallStack; + + GLuint mId{0}; + GLuint mDepthBuffer{0}; + GLuint mStencilBuffer{0}; +}; + +} // namespace Dali + +#endif //TEST_GRAPHICS_FRAMEBUFFER_H diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-pipeline.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-pipeline.cpp index d303d56..9e80f8f 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-pipeline.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-pipeline.cpp @@ -21,7 +21,7 @@ namespace Dali TestGraphicsPipeline::TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics::PipelineCreateInfo& createInfo) : mGl(gl) { - // Need to deep copy, otherwise pointed at memory will go out of scope. Probably should do something about this. + // Need to deep copy, otherwise pointed at memory will go out of scope. @todo Probably should do something about this. if(createInfo.colorBlendState) colorBlendState = *createInfo.colorBlendState; @@ -32,9 +32,6 @@ TestGraphicsPipeline::TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics if(createInfo.viewportState) viewportState = *createInfo.viewportState; - if(createInfo.framebufferState) - framebufferState = *createInfo.framebufferState; - if(createInfo.depthStencilState) depthStencilState = *createInfo.depthStencilState; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-render-pass.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-render-pass.h new file mode 100644 index 0000000..b52dd2d --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-render-pass.h @@ -0,0 +1,41 @@ +#ifndef DALI_TEST_GRAPHICS_RENDER_PASS_H +#define DALI_TEST_GRAPHICS_RENDER_PASS_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace Dali +{ +class TestGraphicsRenderPass : public Graphics::RenderPass +{ +public: + TestGraphicsRenderPass(TestGlAbstraction& gl, Graphics::RenderPassCreateInfo createInfo) + : mGl(gl) + { + attachments = *createInfo.attachments; // Deep copy the vector's contents... @todo FIXME! + } + ~TestGraphicsRenderPass() = default; + + TestGlAbstraction& mGl; + std::vector attachments; +}; + +} // namespace Dali + +#endif //DALI_TEST_GRAPHICS_RENDER_PASS_H diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-render-target.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-render-target.h new file mode 100644 index 0000000..1ad7a5a --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-render-target.h @@ -0,0 +1,44 @@ +#ifndef DALI_TEST_GRAPHICS_RENDER_TARGET_H +#define DALI_TEST_GRAPHICS_RENDER_TARGET_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace Dali +{ +class TestGraphicsRenderTarget : public Graphics::RenderTarget +{ +public: + TestGraphicsRenderTarget(TestGlAbstraction& gl, Graphics::RenderTargetCreateInfo createInfo) + : mGl(gl) + { + mCreateInfo.surface = createInfo.surface; + mCreateInfo.framebuffer = createInfo.framebuffer; + mCreateInfo.extent = createInfo.extent; + mCreateInfo.preTransform = createInfo.preTransform; + } + ~TestGraphicsRenderTarget() = default; + + TestGlAbstraction& mGl; + Graphics::RenderTargetCreateInfo mCreateInfo; +}; + +} // namespace Dali + +#endif //DALI_TEST_GRAPHICS_RENDER_TARGET_H diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.cpp similarity index 66% rename from automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp rename to automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.cpp index f404f32..17f53a7 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.cpp @@ -15,18 +15,21 @@ * */ -#include "test-gl-sync-abstraction.h" +#include "test-graphics-sync-impl.h" namespace Dali { -TestSyncObject::TestSyncObject(TraceCallStack& trace) +TestSyncObject::TestSyncObject(Dali::TraceCallStack& trace) + : synced(false), mTrace(trace) { + mTrace.PushCall("TestSyncObject cons", ""); // Trace the method } TestSyncObject::~TestSyncObject() { + mTrace.PushCall("TestSyncObject dstr", ""); // Trace the method } bool TestSyncObject::IsSynced() @@ -35,7 +38,7 @@ bool TestSyncObject::IsSynced() return synced; } -TestGlSyncAbstraction::TestGlSyncAbstraction() +TestGraphicsSyncImplementation::TestGraphicsSyncImplementation() { Initialize(); } @@ -43,7 +46,7 @@ TestGlSyncAbstraction::TestGlSyncAbstraction() /** * Destructor */ -TestGlSyncAbstraction::~TestGlSyncAbstraction() +TestGraphicsSyncImplementation::~TestGraphicsSyncImplementation() { for(SyncIter iter = mSyncObjects.begin(), end = mSyncObjects.end(); iter != end; ++iter) { @@ -52,18 +55,14 @@ TestGlSyncAbstraction::~TestGlSyncAbstraction() } /** - * Initialize the sync objects - clear down the map + * Initialize the sync objects */ -void TestGlSyncAbstraction::Initialize() +void TestGraphicsSyncImplementation::Initialize() { mSyncObjects.clear(); } -/** - * Create a sync object - * @return the sync object - */ -Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::CreateSyncObject() +Integration::GraphicsSyncAbstraction::SyncObject* TestGraphicsSyncImplementation::CreateSyncObject() { mTrace.PushCall("CreateSyncObject", ""); // Trace the method @@ -76,7 +75,7 @@ Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::CreateSyncObj * Destroy a sync object * @param[in] syncObject The object to destroy */ -void TestGlSyncAbstraction::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject) +void TestGraphicsSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject) { std::stringstream out; out << syncObject; @@ -93,7 +92,7 @@ void TestGlSyncAbstraction::DestroySyncObject(Integration::GlSyncAbstraction::Sy } } -Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::GetLastSyncObject() +Integration::GraphicsSyncAbstraction::SyncObject* TestGraphicsSyncImplementation::GetLastSyncObject() { if(!mSyncObjects.empty()) { @@ -107,7 +106,7 @@ Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::GetLastSyncOb * @param[in] * @param[in] sync The sync value to set */ -void TestGlSyncAbstraction::SetObjectSynced(Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync) +void TestGraphicsSyncImplementation::SetObjectSynced(Integration::GraphicsSyncAbstraction::SyncObject* syncObject, bool sync) { TestSyncObject* testSyncObject = static_cast(syncObject); testSyncObject->synced = sync; @@ -116,7 +115,7 @@ void TestGlSyncAbstraction::SetObjectSynced(Integration::GlSyncAbstraction::Sync /** * Turn trace on */ -void TestGlSyncAbstraction::EnableTrace(bool enable) +void TestGraphicsSyncImplementation::EnableTrace(bool enable) { mTrace.Enable(enable); } @@ -124,7 +123,7 @@ void TestGlSyncAbstraction::EnableTrace(bool enable) /** * Reset the trace callstack */ -void TestGlSyncAbstraction::ResetTrace() +void TestGraphicsSyncImplementation::ResetTrace() { mTrace.Reset(); } @@ -132,12 +131,12 @@ void TestGlSyncAbstraction::ResetTrace() /** * Get the trace object (allows test case to find methods on it) */ -TraceCallStack& TestGlSyncAbstraction::GetTrace() +TraceCallStack& TestGraphicsSyncImplementation::GetTrace() { return mTrace; } -int32_t TestGlSyncAbstraction::GetNumberOfSyncObjects() +int32_t TestGraphicsSyncImplementation::GetNumberOfSyncObjects() { return static_cast(mSyncObjects.size()); } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.h similarity index 64% rename from automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.h rename to automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.h index 73be9ee..cbc5331 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-impl.h @@ -1,5 +1,5 @@ -#ifndef TEST_GL_SYNC_ABSTRACTION_H -#define TEST_GL_SYNC_ABSTRACTION_H +#ifndef TEST_SYNC_IMPLEMENTATION_H +#define TEST_SYNC_IMPLEMENTATION_H /* * Copyright (c) 2021 Samsung Electronics Co., Ltd. @@ -24,14 +24,18 @@ #include // INTERNAL INCLUDES +#include +#include #include -#include +#include #include "test-trace-call-stack.h" namespace Dali { -class DALI_CORE_API TestSyncObject : public Integration::GlSyncAbstraction::SyncObject +class TestGraphicsSyncImplementation; + +class TestSyncObject : public Integration::GraphicsSyncAbstraction::SyncObject { public: TestSyncObject(TraceCallStack& trace); @@ -42,47 +46,45 @@ public: }; /** - * Class to emulate the GL sync functions with tracing + * Class to emulate the gpu sync functions with tracing */ -class DALI_CORE_API TestGlSyncAbstraction : public Integration::GlSyncAbstraction +class TestGraphicsSyncImplementation : public Integration::GraphicsSyncAbstraction { public: /** * Constructor */ - TestGlSyncAbstraction(); + TestGraphicsSyncImplementation(); /** * Destructor */ - ~TestGlSyncAbstraction() override; + virtual ~TestGraphicsSyncImplementation(); /** - * Initialize the sync objects - clear down the map + * Initialize the sync objects */ void Initialize(); /** - * Create a sync object - * @return the sync object + * Create a sync object that can be polled */ - Integration::GlSyncAbstraction::SyncObject* CreateSyncObject() override; + GraphicsSyncAbstraction::SyncObject* CreateSyncObject() override; /** * Destroy a sync object - * @param[in] syncObject The object to destroy */ - void DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject) override; + void DestroySyncObject(GraphicsSyncAbstraction::SyncObject* syncObject) override; public: // TEST FUNCTIONS - Integration::GlSyncAbstraction::SyncObject* GetLastSyncObject(); + GraphicsSyncAbstraction::SyncObject* GetLastSyncObject(); /** * Test method to trigger the object sync behaviour. * @param[in] * @param[in] sync The sync value to set */ - void SetObjectSynced(Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync); + void SetObjectSynced(GraphicsSyncAbstraction::SyncObject* syncObject, bool sync); /** * Turn trace on @@ -106,10 +108,10 @@ public: // TEST FUNCTIONS */ int32_t GetNumberOfSyncObjects(); -private: - TestGlSyncAbstraction(const TestGlSyncAbstraction&); ///< Undefined - TestGlSyncAbstraction& operator=(const TestGlSyncAbstraction&); ///< Undefined + TestGraphicsSyncImplementation(const TestGraphicsSyncImplementation&) = delete; + TestGraphicsSyncImplementation& operator=(const TestGraphicsSyncImplementation&) = delete; +private: typedef std::vector SyncContainer; typedef SyncContainer::iterator SyncIter; SyncContainer mSyncObjects; ///< The sync objects diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.cpp new file mode 100644 index 0000000..cf9b3c9 --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test-graphics-sync-object.h" + +namespace Dali +{ +TestGraphicsSyncObject::TestGraphicsSyncObject(TestGraphicsSyncImplementation& syncImpl, const Graphics::SyncObjectCreateInfo& createInfo) +: mSyncImplementation(syncImpl), + mSyncObject(nullptr), + mCreateInfo(createInfo) +{ +} + +TestGraphicsSyncObject::~TestGraphicsSyncObject() +{ + mSyncImplementation.DestroySyncObject(mSyncObject); +} + +void TestGraphicsSyncObject::InitializeResource() +{ + mSyncObject = static_cast(mSyncImplementation.CreateSyncObject()); +} + +bool TestGraphicsSyncObject::IsSynced() +{ + bool synced = false; + if(mSyncObject) + { + synced = mSyncObject->IsSynced(); + } + return synced; +} + +} // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.h new file mode 100644 index 0000000..c33de6c --- /dev/null +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-sync-object.h @@ -0,0 +1,43 @@ +#ifndef DALI_TEST_GRAPHICS_SYNC_OBJECT_H_ +#define DALI_TEST_GRAPHICS_SYNC_OBJECT_H_ + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +namespace Dali +{ +class TestGraphicsSyncObject : public Graphics::SyncObject +{ +public: + TestGraphicsSyncObject(TestGraphicsSyncImplementation& syncImpl, const Graphics::SyncObjectCreateInfo& createInfo); + ~TestGraphicsSyncObject() override; + void InitializeResource(); + bool IsSynced() override; + +public: + TestGraphicsSyncImplementation& mSyncImplementation; + TestSyncObject* mSyncObject; + Graphics::SyncObjectCreateInfo mCreateInfo; +}; + +} // namespace Dali + +#endif //DALI_TEST_GRAPHICS_SYNC_OBJECT_H diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.cpp index adeeeca..9e1ad3e 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.cpp @@ -183,6 +183,7 @@ bool IsCompressedFormat(Graphics::Format pixelFormat) case Graphics::Format::R64G64B64A64_SINT: case Graphics::Format::R64G64B64A64_SFLOAT: case Graphics::Format::B10G11R11_UFLOAT_PACK32: + case Graphics::Format::R11G11B10_UFLOAT_PACK32: case Graphics::Format::E5B9G9R9_UFLOAT_PACK32: case Graphics::Format::D16_UNORM: case Graphics::Format::X8_D24_UNORM_PACK32: @@ -618,6 +619,12 @@ void PixelFormatToGl(Graphics::Format pixelFormat, GLenum& glFormat, GLint& glIn glFormat = 0; break; } + case Graphics::Format::R11G11B10_UFLOAT_PACK32: + { + glFormat = GL_RGB; + pixelDataType = GL_FLOAT; + break; + } case Graphics::Format::R4G4_UNORM_PACK8: case Graphics::Format::A1R5G5B5_UNORM_PACK16: @@ -768,6 +775,7 @@ void PixelFormatToGl(Graphics::Format pixelFormat, GLenum& glFormat, GLint& glIn { case Graphics::Format::R16G16B16A16_SFLOAT: case Graphics::Format::R32G32B32A32_SFLOAT: + case Graphics::Format::R11G11B10_UFLOAT_PACK32: { glInternalFormat = GL_R11F_G11F_B10F; break; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.h index 3eb54d3..58f7738 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-texture.h @@ -49,6 +49,22 @@ public: GLuint GetTarget(); /** + * Get the texture type + */ + Graphics::TextureType GetType() + { + return mCreateInfo.textureType; + } + + /** + * Get the texture format + */ + Graphics::Format GetFormat() + { + return mCreateInfo.format; + } + + /** * Bind this texture, ensure Native image is initialized if necessary. */ void Bind(uint32_t textureUnit); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder-impl.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder-impl.h index 86b3bd9..0cfdcc0 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder-impl.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-scene-holder-impl.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_SCENE_HOLDER_IMPL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -51,7 +51,11 @@ public: bool PreRender( bool resizingSurface, const std::vector>& damagedRects, Rect& clippingRect ) override { return false; }; - void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) override {}; + void PostRender() + { + } + + //void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector>& damagedRects ) override {}; void StopRender() override {}; diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp index 48173fd..e309bfe 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.cpp @@ -45,6 +45,12 @@ ToolkitTestApplication::ToolkitTestApplication( size_t surfaceWidth, size_t surf mScene = AdaptorImpl::GetScene( *mMainWindow ); mScene.SetDpi( Vector2( horizontalDpi, verticalDpi ) ); + // Create render target for the scene + Graphics::RenderTargetCreateInfo rtInfo{}; + rtInfo.SetExtent( {mSurfaceWidth, mSurfaceHeight }); + mRenderTarget = mGraphicsController.CreateRenderTarget( rtInfo, nullptr ); + mScene.SetSurfaceRenderTarget( mRenderTarget.get() ); + // Core needs to be initialized next before we start the adaptor InitializeCore(); Accessibility::Accessible::SetObjectRegistry(mCore->GetObjectRegistry()); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index 396bab4..221bac0 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -525,22 +525,9 @@ int UtcDaliControlBackgroundColorRendererCount(void) ToolkitTestApplication application; Control control = Control::New(); + control[Actor::Property::SIZE] = Vector2(100.0f, 100.0f); application.GetScene().Add( control ); - tet_infoline( "Set transparent, no renderers should be created" ); - control.SetBackgroundColor( Color::TRANSPARENT ); - application.SendNotification(); - application.Render(); - DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); - - tet_infoline( "Set transparent alpha with positive RGB values, no renderers should be created, but returned color should reflect what we set" ); - const Vector4 alphaZero( 1.0f, 0.5f, 0.25f, 0.0f ); - control.SetBackgroundColor( alphaZero ); - application.SendNotification(); - application.Render(); - DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( GetControlBackgroundColor( control ), alphaZero, TEST_LOCATION ); - tet_infoline( "Set semi transparent alpha with positive RGB values, 1 renderer should be created, but returned color should reflect what we set" ); const Vector4 semiTransparent( 1.0f, 0.75f, 0.5f, 0.5f ); control.SetBackgroundColor( semiTransparent ); @@ -561,19 +548,29 @@ int UtcDaliControlBackgroundColorRendererCount(void) DALI_TEST_EQUALS( GetControlBackgroundColor( control ), newColor, TEST_LOCATION ); DALI_TEST_EQUALS( renderer, control.GetRendererAt( 0 ), TEST_LOCATION ); - tet_infoline( "Set transparent, ensure no renderers are created" ); + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& drawTrace = gl.GetDrawTrace(); + drawTrace.Enable(true); + + tet_infoline( "Set transparent, 1 renderer should be created, but ensure nothing is drawn" ); control.SetBackgroundColor( Color::TRANSPARENT ); application.SendNotification(); application.Render(); - DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); + + DALI_TEST_EQUALS( control.GetRendererCount(), 1u, TEST_LOCATION ); DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); + DALI_TEST_EQUALS(drawTrace.FindMethod("DrawArrays"), false, TEST_LOCATION); + + drawTrace.Reset(); tet_infoline( "Set control to clip its children, a renderer should be created which will be transparent" ); control.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN ); application.SendNotification(); application.Render(); + DALI_TEST_EQUALS( control.GetRendererCount(), 1u, TEST_LOCATION ); DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); + DALI_TEST_EQUALS(drawTrace.FindMethod("DrawArrays"), true, TEST_LOCATION); tet_infoline( "Set a color, only 1 renderer should exist" ); control.SetBackgroundColor( Color::RED ); @@ -595,12 +592,15 @@ int UtcDaliControlBackgroundColorRendererCount(void) DALI_TEST_EQUALS( control.GetRendererCount(), 1u, TEST_LOCATION ); DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); - tet_infoline( "Disable clipping, no renderers" ); + drawTrace.Reset(); + + tet_infoline( "Disable clipping, render nothing" ); control.SetProperty( Actor::Property::CLIPPING_MODE, ClippingMode::DISABLED ); application.SendNotification(); application.Render(); - DALI_TEST_EQUALS( control.GetRendererCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( GetControlBackgroundColor( control ), Color::TRANSPARENT, TEST_LOCATION ); + DALI_TEST_EQUALS(drawTrace.FindMethod("DrawArrays"), false, TEST_LOCATION); END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp b/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp index 720f596..be3cf44 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-KeyboardFocusManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -1616,4 +1616,172 @@ int UtcDaliKeyboardFocusManagerFocusPerWindow(void) END_TEST; } +int UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus(void) +{ + ToolkitTestApplication application; + + tet_infoline(" UtcDaliKeyboardFocusManagerWithoutFocusablePropertiesMoveFocus"); + + // Register Type + TypeInfo type; + type = TypeRegistry::Get().GetTypeInfo( "KeyboardFocusManager" ); + DALI_TEST_CHECK( type ); + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + + KeyboardFocusManager manager = KeyboardFocusManager::Get(); + DALI_TEST_CHECK(manager); + + bool focusChangedSignalVerified = false; + FocusChangedCallback focusChangedCallback(focusChangedSignalVerified); + manager.FocusChangedSignal().Connect( &focusChangedCallback, &FocusChangedCallback::Callback ); + + PushButton button1 = PushButton::New(); + PushButton button2 = PushButton::New(); + PushButton button3 = PushButton::New(); + PushButton button4 = PushButton::New(); + PushButton button5 = PushButton::New(); + + button1.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) ); + button2.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) ); + button3.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) ); + button4.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) ); + button5.SetProperty( Actor::Property::SIZE, Vector2( 50, 50 ) ); + + button1.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true); + button2.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true); + button3.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true); + button4.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true); + button5.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true); + + application.GetScene().Add(button1); + application.GetScene().Add(button2); + application.GetScene().Add(button3); + application.GetScene().Add(button4); + application.GetScene().Add(button5); + + // set position + // button1 -- button2 + // | | + // | button5| + // button3 -- button4 + button1.SetProperty( Actor::Property::POSITION, Vector2(0.0f, 0.0f)); + button2.SetProperty( Actor::Property::POSITION, Vector2(100.0f, 0.0f)); + button3.SetProperty( Actor::Property::POSITION, Vector2(0.0f, 100.0f)); + button4.SetProperty( Actor::Property::POSITION, Vector2(100.0f, 100.0f)); + button5.SetProperty( Actor::Property::POSITION, Vector2(60.0f, 60.0f)); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + // Set the focus to the button1 + // [button1] -- button2 + // | | + // | button5| + // button3 -- button4 + DALI_TEST_CHECK(manager.SetCurrentFocusActor(button1) == true); + DALI_TEST_CHECK(manager.GetCurrentFocusActor() == button1); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == Actor()); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1); + focusChangedCallback.Reset(); + + // without set the navigation properties, but we can focus move + + // Move the focus towards right + // button1 -- [button2] + // | | + // | button5| + // button3 -- button4 + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true); + + // Confirm whether focus is moved to button2 + DALI_TEST_EQUALS(button2.GetProperty(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION ); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button1); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button2); + focusChangedCallback.Reset(); + + // Move the focus towards down + // button1 -- button2 + // | | + // | [button5]| + // button3 -- button4 + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::DOWN) == true); + + // Confirm whether focus is moved to button5 + DALI_TEST_EQUALS(button5.GetProperty(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION ); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button2); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5); + focusChangedCallback.Reset(); + + // Move the focus towards right + // button1 -- button2 + // | | + // | button5| + // button3 -- [button4] + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::RIGHT) == true); + + // Confirm whether focus is moved to button4 + DALI_TEST_EQUALS(button4.GetProperty(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION ); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button4); + focusChangedCallback.Reset(); + + // Move the focus towards left + // button1 -- button2 + // | | + // | [button5]| + // button3 -- button4 + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true); + + // Confirm whether focus is moved to button5 + DALI_TEST_EQUALS(button5.GetProperty(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION ); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button4); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button5); + focusChangedCallback.Reset(); + + // Move the focus towards left + // button1 -- button2 + // | | + // | button5| + //[button3] -- button4 + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == true); + + // Confirm whether focus is moved to button3 + DALI_TEST_EQUALS(button3.GetProperty(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION ); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button5); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button3); + focusChangedCallback.Reset(); + + // Move the focus towards up + //[button1]-- button2 + // | | + // | button5| + // button3 -- button4 + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::UP) == true); + + // Confirm whether focus is moved to button1 + DALI_TEST_EQUALS(button1.GetProperty(DevelControl::Property::STATE), (int)DevelControl::FOCUSED, TEST_LOCATION ); + DALI_TEST_CHECK(focusChangedCallback.mSignalVerified); + DALI_TEST_CHECK(focusChangedCallback.mOriginalFocusedActor == button3); + DALI_TEST_CHECK(focusChangedCallback.mCurrentFocusedActor == button1); + focusChangedCallback.Reset(); + + + // Move the focus towards left. The focus move will fail as no way to move it upwards + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::LEFT) == false); + + // Move the focus toward page up/down. The focus move will fail as invalid direction. + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::PAGE_UP) == false); + DALI_TEST_CHECK(manager.MoveFocus(Control::KeyboardFocus::PAGE_DOWN) == false); + focusChangedCallback.Reset(); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index 127a611..a0f5334 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -3559,56 +3559,6 @@ int UtcDaliRegisterVisualWithDepthIndex(void) END_TEST; } -int UtcDaliColorVisualRenderIfTransparentProperty(void) -{ - ToolkitTestApplication application; - tet_infoline( "Test the renderIfTransparent property of ColorVisual" ); - - VisualFactory factory = VisualFactory::Get(); - Property::Map propertyMap; - propertyMap.Insert( Visual::Property::TYPE, Visual::COLOR ); - propertyMap.Insert( ColorVisual::Property::MIX_COLOR, Color::BLUE ); - - tet_infoline( "Check default value" ); - { - Visual::Base testVisual = factory.CreateVisual( propertyMap ); - Property::Map returnedMap; - testVisual.CreatePropertyMap( returnedMap ); - - Property::Value* renderIfTransparentProperty = returnedMap.Find( DevelColorVisual::Property::RENDER_IF_TRANSPARENT ); - DALI_TEST_CHECK( renderIfTransparentProperty ); - DALI_TEST_EQUALS( renderIfTransparentProperty->Get< bool >(), false, TEST_LOCATION ); - } - - propertyMap.Insert( DevelColorVisual::Property::RENDER_IF_TRANSPARENT, true ); - - tet_infoline( "Ensure set to value required" ); - { - Visual::Base testVisual = factory.CreateVisual( propertyMap ); - Property::Map returnedMap; - testVisual.CreatePropertyMap( returnedMap ); - - Property::Value* renderIfTransparentProperty = returnedMap.Find( DevelColorVisual::Property::RENDER_IF_TRANSPARENT ); - DALI_TEST_CHECK( renderIfTransparentProperty ); - DALI_TEST_EQUALS( renderIfTransparentProperty->Get< bool >(), true, TEST_LOCATION ); - } - - propertyMap[ DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = Color::BLUE; - - tet_infoline( "Ensure it returns default value if set to wrong type" ); - { - Visual::Base testVisual = factory.CreateVisual( propertyMap ); - Property::Map returnedMap; - testVisual.CreatePropertyMap( returnedMap ); - - Property::Value* renderIfTransparentProperty = returnedMap.Find( DevelColorVisual::Property::RENDER_IF_TRANSPARENT ); - DALI_TEST_CHECK( renderIfTransparentProperty ); - DALI_TEST_EQUALS( renderIfTransparentProperty->Get< bool >(), false, TEST_LOCATION ); - } - - END_TEST; -} - int UtcDaliSvgVisualCustomShader(void) { ToolkitTestApplication application; @@ -4234,11 +4184,6 @@ int UtcDaliVisualGetVisualProperty01(void) DALI_TEST_CHECK(!property1.object); DALI_TEST_CHECK(property1.propertyIndex == Property::INVALID_INDEX); - // Test not-supported property - Property property2 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelColorVisual::Property::RENDER_IF_TRANSPARENT); - DALI_TEST_CHECK(!property2.object); - DALI_TEST_CHECK(property2.propertyIndex == Property::INVALID_INDEX); - // Test unregistered visual Property property3 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL2, Visual::Property::MIX_COLOR); DALI_TEST_CHECK(!property3.object); diff --git a/dali-scene-loader/public-api/ktx-loader.cpp b/dali-scene-loader/public-api/ktx-loader.cpp index 147b3fd..857163d 100644 --- a/dali-scene-loader/public-api/ktx-loader.cpp +++ b/dali-scene-loader/public-api/ktx-loader.cpp @@ -161,7 +161,7 @@ bool ConvertPixelFormat(const uint32_t ktxPixelFormat, Pixel::Format& format) } case 0x8C3A: // GL_R11F_G11F_B10F { - format = Pixel::RGB32F; + format = Pixel::R11G11B10F; break; } case 0x8D7C: // GL_RGBA8UI diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index f583d3c..e94f60b 100755 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -46,6 +46,7 @@ SET( devel_api_src_files ${devel_api_src_dir}/controls/web-view/web-view.cpp ${devel_api_src_dir}/focus-manager/keyinput-focus-manager.cpp ${devel_api_src_dir}/focus-manager/keyboard-focus-manager-devel.cpp + ${devel_api_src_dir}/focus-manager/focus-finder.cpp ${devel_api_src_dir}/image-loader/async-image-loader-devel.cpp ${devel_api_src_dir}/image-loader/atlas-upload-observer.cpp ${devel_api_src_dir}/image-loader/image-atlas.cpp @@ -188,6 +189,7 @@ SET( devel_api_shadow_view_header_files SET( devel_api_focus_manager_header_files ${devel_api_src_dir}/focus-manager/keyinput-focus-manager.h ${devel_api_src_dir}/focus-manager/keyboard-focus-manager-devel.h + ${devel_api_src_dir}/focus-manager/focus-finder.h ) SET( devel_api_image_loader_header_files diff --git a/dali-toolkit/devel-api/focus-manager/focus-finder.cpp b/dali-toolkit/devel-api/focus-manager/focus-finder.cpp new file mode 100644 index 0000000..d12ed11 --- /dev/null +++ b/dali-toolkit/devel-api/focus-manager/focus-finder.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include "focus-finder.h" + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +FocusFinder::FocusFinder() +{ +} + +FocusFinder::~FocusFinder() +{ +} + +FocusFinder FocusFinder::Get() +{ + FocusFinder finder; + + // Check whether the focus finder is already created + SingletonService singletonService(SingletonService::Get()); + if(singletonService) + { + Dali::BaseHandle handle = singletonService.GetSingleton(typeid(FocusFinder)); + if(handle) + { + // If so, downcast the handle of singleton to focus finder + finder = FocusFinder(dynamic_cast(handle.GetObjectPtr())); + } + + if(!finder) + { + // If not, create the focus finder and register it as a singleton + finder = FocusFinder(new Internal::FocusFinder()); + singletonService.Register(typeid(finder), finder); + } + } + + return finder; +} + +FocusFinder::FocusFinder(Internal::FocusFinder* impl) +: BaseHandle(impl) +{ +} + +Actor FocusFinder::GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction) +{ + return GetImpl(*this).GetNearestFocusableActor(focusedActor, direction); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/devel-api/focus-manager/focus-finder.h b/dali-toolkit/devel-api/focus-manager/focus-finder.h new file mode 100644 index 0000000..8012675 --- /dev/null +++ b/dali-toolkit/devel-api/focus-manager/focus-finder.h @@ -0,0 +1,77 @@ +#ifndef DALI_TOOLKIT_FOCUS_FINDER_H +#define DALI_TOOLKIT_FOCUS_FINDER_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal DALI_INTERNAL +{ +class FocusFinder; +} + +/** + * FocusFinder + * This class used for finding the next focusable actor in a given direction + * from a actor that currently has focus. + */ +class DALI_TOOLKIT_API FocusFinder : public BaseHandle +{ +public: + /** + * Create a FocusFinder handle; this can be initialised with FocusFinder::Get() + * Calling member functions with an uninitialised handle is not allowed. + */ + FocusFinder(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~FocusFinder(); + + /** + * @brief Get the singleton of FocusFinder object. + * @return A handle to the FocusFinder control. + */ + static FocusFinder Get(); + + /** + * Get the nearest focusable actor. + * @param [in] focusedActor The current focused actor. + * @param [in] direction The direction. + * @return The nearest focusable actor, or null if none exists. + */ + Actor GetNearestFocusableActor(Actor focusedActor, Toolkit::Control::KeyboardFocus::Direction direction); + +private: + explicit DALI_INTERNAL FocusFinder(Internal::FocusFinder* impl); + +}; // class FocusFinder + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_FOCUS_FINDER_H diff --git a/dali-toolkit/devel-api/utility/npatch-utilities.cpp b/dali-toolkit/devel-api/utility/npatch-utilities.cpp index 7f462f6..78a6268 100644 --- a/dali-toolkit/devel-api/utility/npatch-utilities.cpp +++ b/dali-toolkit/devel-api/utility/npatch-utilities.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2020 Samsung Electronics Co., Ltd. +* Copyright (c) 2021 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. @@ -175,6 +175,7 @@ void GetRedOffsetAndMask(Dali::Pixel::Format pixelFormat, int32_t& byteOffset, i case Dali::Pixel::DEPTH_UNSIGNED_INT: case Dali::Pixel::DEPTH_FLOAT: case Dali::Pixel::DEPTH_STENCIL: + case Dali::Pixel::R11G11B10F: { DALI_LOG_ERROR("Pixel format not compatible.\n"); byteOffset = 0; diff --git a/dali-toolkit/devel-api/visuals/color-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/color-visual-properties-devel.h index 448bf88..bae7111 100644 --- a/dali-toolkit/devel-api/visuals/color-visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/color-visual-properties-devel.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_COLOR_VISUAL_PROPERTIES_DEVEL_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 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. @@ -40,14 +40,6 @@ enum MIX_COLOR = Toolkit::ColorVisual::Property::MIX_COLOR, /** - * @brief Whether to render if the MIX_COLOR is transparent. - * @details Name "renderIfTransparent", type Property::BOOLEAN. - * @note Optional. - * @note By default it's false, i.e. ColorVisual will not render if the MIX_COLOR is transparent. - */ - RENDER_IF_TRANSPARENT = MIX_COLOR + 1, - - /** * @brief The blur radius of the visual. * @details Name "blurRadius", type Property::FLOAT, animatable. * If the value is 0, the edge is sharp. Otherwise, the larger the value, the more the edge is blurred. diff --git a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp index 509426e..181a47e 100644 --- a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp +++ b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp @@ -21,13 +21,13 @@ // EXTERNAL INCLUDES #include #include +#include #include #include #include #include #include #include -#include #include // INTERNAL INCLUDES @@ -123,6 +123,9 @@ void VideoView::OnInitialize() new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::VIDEO)); }); + //Enable highightability + Self().SetProperty(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, true); + //update self property self.RegisterProperty(IS_VIDEO_VIEW_PROPERTY_NAME, true, Property::READ_WRITE); } diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 395dfc8..fc8edaf 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -114,6 +114,7 @@ SET( toolkit_src_files ${toolkit_src_dir}/focus-manager/keyboard-focus-manager-impl.cpp ${toolkit_src_dir}/focus-manager/keyinput-focus-manager-impl.cpp + ${toolkit_src_dir}/focus-manager/focus-finder-impl.cpp ${toolkit_src_dir}/helpers/color-conversion.cpp ${toolkit_src_dir}/helpers/property-helper.cpp ${toolkit_src_dir}/filters/blur-two-pass-filter.cpp diff --git a/dali-toolkit/internal/focus-manager/focus-finder-impl.cpp b/dali-toolkit/internal/focus-manager/focus-finder-impl.cpp new file mode 100644 index 0000000..93f1d65 --- /dev/null +++ b/dali-toolkit/internal/focus-manager/focus-finder-impl.cpp @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Modified by joogab yun(joogab.yun@samsung.com) + */ + +// CLASS HEADER +#include "focus-finder-impl.h" + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace +{ +static int MajorAxisDistanceRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect source, Dali::Rect dest) +{ + switch(direction) + { + case Dali::Toolkit::Control::KeyboardFocus::LEFT: + { + return source.left - dest.right; + } + case Dali::Toolkit::Control::KeyboardFocus::RIGHT: + { + return dest.left - source.right; + } + case Dali::Toolkit::Control::KeyboardFocus::UP: + { + return source.top - dest.bottom; + } + case Dali::Toolkit::Control::KeyboardFocus::DOWN: + { + return dest.top - source.bottom; + } + default: + { + return 0; + } + } +} + +/** + * @return The distance from the edge furthest in the given direction + * of source to the edge nearest in the given direction of dest. + * If the dest is not in the direction from source, return 0. + */ +static int MajorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect source, Dali::Rect dest) +{ + return std::max(0, MajorAxisDistanceRaw(direction, source, dest)); +} + +static int MajorAxisDistanceToFarEdgeRaw(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect source, Dali::Rect dest) +{ + switch(direction) + { + case Dali::Toolkit::Control::KeyboardFocus::LEFT: + { + return source.left - dest.left; + } + case Dali::Toolkit::Control::KeyboardFocus::RIGHT: + { + return dest.right - source.right; + } + case Dali::Toolkit::Control::KeyboardFocus::UP: + { + return source.top - dest.top; + } + case Dali::Toolkit::Control::KeyboardFocus::DOWN: + { + return dest.bottom - source.bottom; + } + default: + { + return 0; + } + } +} + +/** + * @return The distance along the major axis w.r.t the direction from the + * edge of source to the far edge of dest. + * If the dest is not in the direction from source, return 1 + */ +static int MajorAxisDistanceToFarEdge(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect source, Dali::Rect dest) +{ + return std::max(1, MajorAxisDistanceToFarEdgeRaw(direction, source, dest)); +} + +/** + * Find the distance on the minor axis w.r.t the direction to the nearest + * edge of the destination rectangle. + * @param direction the direction (up, down, left, right) + * @param source The source rect. + * @param dest The destination rect. + * @return The distance. + */ +static int MinorAxisDistance(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect source, Dali::Rect dest) +{ + switch(direction) + { + case Dali::Toolkit::Control::KeyboardFocus::LEFT: + case Dali::Toolkit::Control::KeyboardFocus::RIGHT: + { + // the distance between the center verticals + return std::abs( + (((source.top + source.bottom) * 0.5f) - + (((dest.top + dest.bottom) * 0.5f)))); + } + case Dali::Toolkit::Control::KeyboardFocus::UP: + case Dali::Toolkit::Control::KeyboardFocus::DOWN: + { + // the distance between the center horizontals + return std::abs( + (((source.left + source.right) * 0.5f) - + (((dest.left + dest.right) * 0.5f)))); + } + default: + { + return 0; + } + } +} + +/** + * Calculate distance given major and minor axis distances. + * @param majorAxisDistance The majorAxisDistance + * @param minorAxisDistance The minorAxisDistance + * @return The distance + */ +static int GetWeightedDistanceFor(int majorAxisDistance, int minorAxisDistance) +{ + return 13 * majorAxisDistance * majorAxisDistance + minorAxisDistance * minorAxisDistance; +} + +/** + * Convert x,y,width,height coordinates into left, right, bottom, top coordinates. + * @param[in,out] rect The rect + */ +static void ConvertCoordinate(Dali::Rect& rect) +{ + // convert x, y, width, height -> left, right, bottom, top + float left = rect.x; + float right = rect.x + rect.width; + float bottom = rect.y + rect.height; + float top = rect.y; + + rect.left = left; + rect.right = right; + rect.bottom = bottom; + rect.top = top; +} + +/** + * Is destRect a candidate for the next focus given the direction? + * @param srcRect The source rect. + * @param destRect The dest rect. + * @param direction The direction (up, down, left, right) + * @return Whether destRect is a candidate. + */ +static bool IsCandidate(Dali::Rect srcRect, Dali::Rect destRect, Dali::Toolkit::Control::KeyboardFocus::Direction direction) +{ + switch(direction) + { + case Dali::Toolkit::Control::KeyboardFocus::LEFT: + { + return (srcRect.right > destRect.right || srcRect.left >= destRect.right) && srcRect.left > destRect.left; + } + case Dali::Toolkit::Control::KeyboardFocus::RIGHT: + { + return (srcRect.left < destRect.left || srcRect.right <= destRect.left) && srcRect.right < destRect.right; + } + case Dali::Toolkit::Control::KeyboardFocus::UP: + { + return (srcRect.bottom > destRect.bottom || srcRect.top >= destRect.bottom) && srcRect.top > destRect.top; + } + case Dali::Toolkit::Control::KeyboardFocus::DOWN: + { + return (srcRect.top < destRect.top || srcRect.bottom <= destRect.top) && srcRect.bottom < destRect.bottom; + } + default: + { + return false; + } + } + return false; +} + +/** + * Is dest in a given direction from src? + * @param direction the direction (up, down, left, right) + * @param src The source rect + * @param dest The dest rect + */ +static bool IsToDirectionOf(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect src, Dali::Rect dest) +{ + switch(direction) + { + case Dali::Toolkit::Control::KeyboardFocus::LEFT: + { + return src.left >= dest.right; + } + case Dali::Toolkit::Control::KeyboardFocus::RIGHT: + { + return src.right <= dest.left; + } + case Dali::Toolkit::Control::KeyboardFocus::UP: + { + return src.top >= dest.bottom; + } + case Dali::Toolkit::Control::KeyboardFocus::DOWN: + { + return src.bottom <= dest.top; + } + default: + { + return false; + } + } +} + +/** + * Do the given direction's axis of rect1 and rect2 overlap? + * @param direction the direction (up, down, left, right) + * @param rect1 The first rect + * @param rect2 The second rect + * @return whether the beams overlap + */ +static bool BeamsOverlap(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect rect1, Dali::Rect rect2) +{ + switch(direction) + { + case Dali::Toolkit::Control::KeyboardFocus::LEFT: + case Dali::Toolkit::Control::KeyboardFocus::RIGHT: + { + return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom); + } + case Dali::Toolkit::Control::KeyboardFocus::UP: + case Dali::Toolkit::Control::KeyboardFocus::DOWN: + { + return (rect2.right >= rect1.left) && (rect2.left <= rect1.right); + } + default: + { + return false; + } + } +} + +/** + * One rectangle may be another candidate than another by virtue of being exclusively in the beam of the source rect. + * @param direction The direction (up, down, left, right) + * @param source The source rect + * @param rect1 The first rect + * @param rect2 The second rect + * @return Whether rect1 is a better candidate than rect2 by virtue of it being in src's beam + */ +static bool BeamBeats(Dali::Toolkit::Control::KeyboardFocus::Direction direction, Dali::Rect source, Dali::Rect rect1, Dali::Rect rect2) +{ + const bool rect1InSrcBeam = BeamsOverlap(direction, source, rect1); + const bool rect2InSrcBeam = BeamsOverlap(direction, source, rect2); + // if rect1 isn't exclusively in the src beam, it doesn't win + if(rect2InSrcBeam || !rect1InSrcBeam) + { + return false; + } + // we know rect1 is in the beam, and rect2 is not + // if rect1 is to the direction of, and rect2 is not, rect1 wins. + // for example, for direction left, if rect1 is to the left of the source + // and rect2 is below, then we always prefer the in beam rect1, since rect2 + // could be reached by going down. + if(!IsToDirectionOf(direction, source, rect2)) + { + return true; + } + // for horizontal directions, being exclusively in beam always wins + if((direction == Dali::Toolkit::Control::KeyboardFocus::LEFT || direction == Dali::Toolkit::Control::KeyboardFocus::RIGHT)) + { + return true; + } + // for vertical directions, beams only beat up to a point: + // now, as long as rect2 isn't completely closer, rect1 wins + // e.g for direction down, completely closer means for rect2's top + // edge to be closer to the source's top edge than rect1's bottom edge. + return (MajorAxisDistance(direction, source, rect1) < MajorAxisDistanceToFarEdge(direction, source, rect2)); +} + +} // unnamed namespace + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +FocusFinder::FocusFinder() +{ +} + +FocusFinder::~FocusFinder() +{ +} + +Actor FocusFinder::GetNearestFocusableActor(Actor& focusedActor, Toolkit::Control::KeyboardFocus::Direction direction) +{ + Actor nearestActor; + if(!focusedActor) + { + return nearestActor; + } + + Rect focusedRect = DevelActor::CalculateScreenExtents(focusedActor); + + // initialize the best candidate to something impossible + // (so the first plausible actor will become the best choice) + Rect bestCandidateRect = focusedRect; + switch(direction) + { + case Toolkit::Control::KeyboardFocus::LEFT: + { + bestCandidateRect.x += 1; + break; + } + case Toolkit::Control::KeyboardFocus::RIGHT: + { + bestCandidateRect.x -= 1; + break; + } + case Toolkit::Control::KeyboardFocus::UP: + { + bestCandidateRect.y += 1; + break; + } + case Toolkit::Control::KeyboardFocus::DOWN: + { + bestCandidateRect.y -= 1; + break; + } + default: + { + break; + } + } + + ConvertCoordinate(bestCandidateRect); + + ConvertCoordinate(focusedRect); + + Integration::SceneHolder window = Integration::SceneHolder::Get(focusedActor); + if(window) + { + Actor rootActor = window.GetRootLayer(); + nearestActor = FindNextFocus(rootActor, focusedActor, focusedRect, bestCandidateRect, direction); + } + return nearestActor; +} + +Actor FocusFinder::FindNextFocus(Actor& actor, Actor& focusedActor, Rect& focusedRect, Rect& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction) +{ + Actor nearestActor; + if(actor) + { + // Recursively children + const auto childCount = actor.GetChildCount(); + for(auto i = 0u; i < childCount; ++i) + { + Dali::Actor child = actor.GetChildAt(i); + if(child && child != focusedActor && child.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE)) + { + Rect candidateRect = DevelActor::CalculateScreenExtents(child); + + // convert x, y, width, height -> left, right, bottom, top + ConvertCoordinate(candidateRect); + + if(IsBetterCandidate(direction, focusedRect, candidateRect, bestCandidateRect)) + { + bestCandidateRect = candidateRect; + nearestActor = child; + } + } + Actor nextActor = FindNextFocus(child, focusedActor, focusedRect, bestCandidateRect, direction); + if(nextActor) + { + nearestActor = nextActor; + } + } + } + return nearestActor; +} + +bool FocusFinder::IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect& focusedRect, Rect& candidateRect, Rect& bestCandidateRect) const +{ + // to be a better candidate, need to at least be a candidate in the first place + if(!IsCandidate(focusedRect, candidateRect, direction)) + { + return false; + } + // we know that candidateRect is a candidate.. if bestCandidateRect is not a candidate, + // candidateRect is better + if(!IsCandidate(focusedRect, bestCandidateRect, direction)) + { + return true; + } + // if candidateRect is better by beam, it wins + if(BeamBeats(direction, focusedRect, candidateRect, bestCandidateRect)) + { + return true; + } + // if bestCandidateRect is better, then candidateRect cant' be :) + if(BeamBeats(direction, focusedRect, bestCandidateRect, candidateRect)) + { + return false; + } + + // otherwise, do fudge-tastic comparison of the major and minor axis + return (GetWeightedDistanceFor( + MajorAxisDistance(direction, focusedRect, candidateRect), + MinorAxisDistance(direction, focusedRect, candidateRect)) < GetWeightedDistanceFor(MajorAxisDistance(direction, focusedRect, bestCandidateRect), + MinorAxisDistance(direction, focusedRect, bestCandidateRect))); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/focus-manager/focus-finder-impl.h b/dali-toolkit/internal/focus-manager/focus-finder-impl.h new file mode 100644 index 0000000..012b1aa --- /dev/null +++ b/dali-toolkit/internal/focus-manager/focus-finder-impl.h @@ -0,0 +1,117 @@ +#ifndef DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H +#define DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Integration +{ +class SceneHolder; + +} // namespace Integration + +namespace Toolkit +{ +namespace Internal +{ +class FocusFinder; + +/** + * @copydoc Toolkit::FocusFinder + */ +class FocusFinder : public Dali::BaseObject +{ +public: + /** + * Construct a new FocusFinder. + */ + FocusFinder(); + + /** + * @copydoc Toolkit::GetNearestFocusableActor + */ + Actor GetNearestFocusableActor(Actor& focusedActor, Toolkit::Control::KeyboardFocus::Direction direction); + +protected: + /** + * Destructor + */ + virtual ~FocusFinder(); + +private: + /** + * Find the next actor to take focus in root's descendants, starting from the actor. + * @param[in] actor The root actor. + * @param[in] focusedActor The current focused actor. + * @param[in] focusedRect The rect of current focused actor. + * @param[in] bestCandidateRect The current best candidate. + * @param[in] direction The direction. + * @return nearest Actor. + */ + Actor FindNextFocus(Actor& actor, Actor& focusedActor, Rect& focusedRect, Rect& bestCandidateRect, Toolkit::Control::KeyboardFocus::Direction direction); + + /** + * Is rect1 a better candidate than rect2 for a focus search in a particular + * direction from a source rect? This is the core routine that determines + * the order of focus searching. + * @param direction The direction (up, down, left, right) + * @param candidateRect The candidate rectangle + * @param bestCandidateRect The current best candidate. + * @return Whether the candidate is the new best. + */ + bool IsBetterCandidate(Toolkit::Control::KeyboardFocus::Direction direction, Rect& focusedRect, Rect& candidateRect, Rect& bestCandidateRect) const; + +private: + // Undefined + FocusFinder(const FocusFinder&); + + FocusFinder& operator=(const FocusFinder& rhs); +}; + +} // namespace Internal + +inline Internal::FocusFinder& GetImpl(Dali::Toolkit::FocusFinder& obj) +{ + DALI_ASSERT_ALWAYS(obj); + + Dali::BaseObject& handle = obj.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::FocusFinder& GetImpl(const Dali::Toolkit::FocusFinder& obj) +{ + DALI_ASSERT_ALWAYS(obj); + + const Dali::BaseObject& handle = obj.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_INTERNAL_FOCUS_FINDER_H diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp index 0d7bbfd..b06edea 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp @@ -36,6 +36,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -495,6 +496,11 @@ bool KeyboardFocusManager::MoveFocus(Toolkit::Control::KeyboardFocus::Direction nextFocusableActor = mPreFocusChangeSignal.Emit(currentFocusActor, Actor(), direction); mIsWaitingKeyboardFocusChangeCommit = false; } + else + { + // We should find it among the actors nearby. + nextFocusableActor = Toolkit::FocusFinder::Get().GetNearestFocusableActor(currentFocusActor, direction); + } } if(nextFocusableActor && nextFocusableActor.GetProperty(Actor::Property::KEYBOARD_FOCUSABLE)) diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index 9ce3a29..cf6abd3 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -51,7 +51,6 @@ ColorVisual::ColorVisual(VisualFactoryCache& factoryCache) : Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR), mBlurRadius(0.0f), mBlurRadiusIndex(Property::INVALID_INDEX), - mRenderIfTransparent(false), mNeedBlurRadius(false) { } @@ -87,15 +86,6 @@ void ColorVisual::DoSetProperties(const Property::Map& propertyMap) } } - Property::Value* renderIfTransparentValue = propertyMap.Find(Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, RENDER_IF_TRANSPARENT_NAME); - if(renderIfTransparentValue) - { - if(!renderIfTransparentValue->Get(mRenderIfTransparent)) - { - DALI_LOG_ERROR("ColorVisual: renderIfTransparent property has incorrect type: %d\n", renderIfTransparentValue->GetType()); - } - } - Property::Value* blurRadiusValue = propertyMap.Find(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME); if(blurRadiusValue) { @@ -108,12 +98,7 @@ void ColorVisual::DoSetProperties(const Property::Map& propertyMap) void ColorVisual::DoSetOnScene(Actor& actor) { - // Only add the renderer if it's not fully transparent - // We cannot avoid creating a renderer as it's used in the base class - if(mRenderIfTransparent || mImpl->mMixColor.a > 0.0f) - { - actor.AddRenderer(mImpl->mRenderer); - } + actor.AddRenderer(mImpl->mRenderer); // Color Visual generated and ready to display ResourceReady(Toolkit::Visual::ResourceStatus::READY); @@ -129,7 +114,6 @@ void ColorVisual::DoCreatePropertyMap(Property::Map& map) const map.Clear(); map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR); map.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor); - map.Insert(Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, mRenderIfTransparent); if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX) { diff --git a/dali-toolkit/internal/visuals/color/color-visual.h b/dali-toolkit/internal/visuals/color/color-visual.h index ba9a590..6fe1f43 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.h +++ b/dali-toolkit/internal/visuals/color/color-visual.h @@ -133,10 +133,9 @@ private: ColorVisual& operator=(const ColorVisual& colorRenderer); private: - float mBlurRadius; ///< The blur radius - Property::Index mBlurRadiusIndex; ///< The blur radius property index - bool mRenderIfTransparent; ///< Whether we should render even if the mix-color is transparent. - bool mNeedBlurRadius; ///< Whether we need the blur radius in shader. + float mBlurRadius; ///< The blur radius + Property::Index mBlurRadiusIndex; ///< The blur radius property index + bool mNeedBlurRadius; ///< Whether we need the blur radius in shader. }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 9f1ad0a..9c9ca4b 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -80,7 +80,6 @@ const char* const CORNER_RADIUS("cornerRadius"); const char* const CORNER_RADIUS_POLICY("cornerRadiusPolicy"); // Color visual -const char* const RENDER_IF_TRANSPARENT_NAME("renderIfTransparent"); const char* const BLUR_RADIUS_NAME("blurRadius"); // Image visual diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index 5f7f336..966e51f 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -64,7 +64,6 @@ extern const char* const CORNER_RADIUS; extern const char* const CORNER_RADIUS_POLICY; // Color visual -extern const char* const RENDER_IF_TRANSPARENT_NAME; extern const char* const BLUR_RADIUS_NAME; // Image visual diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index 781b531..61e67eb 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -64,27 +64,6 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_CON #endif /** - * @brief Replace the background visual if it's a color visual with the renderIfTransparent property set as required. - * @param[in] controlImpl The control implementation - * @param[in] renderIfTransaparent Whether we should render if the color is transparent - */ -void ChangeBackgroundColorVisual(Control& controlImpl, bool renderIfTransparent) -{ - Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlImpl); - - Toolkit::Visual::Base backgroundVisual = controlDataImpl.GetVisual(Toolkit::Control::Property::BACKGROUND); - if(backgroundVisual && backgroundVisual.GetType() == Toolkit::Visual::COLOR) - { - Property::Map map; - backgroundVisual.CreatePropertyMap(map); - - // Only change it if it's a color visual - map[Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT] = renderIfTransparent; - controlImpl.SetBackground(map); - } -} - -/** * @brief Creates a clipping renderer if required. * (EG. If no renders exist and clipping is enabled). * @param[in] controlImpl The control implementation. @@ -96,34 +75,11 @@ void CreateClippingRenderer(Control& controlImpl) int clippingMode = ClippingMode::DISABLED; if(self.GetProperty(Actor::Property::CLIPPING_MODE).Get(clippingMode)) { - switch(clippingMode) - { - case ClippingMode::CLIP_CHILDREN: - { - if(self.GetRendererCount() == 0u) - { - Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlImpl); - if(controlDataImpl.mVisuals.Empty()) - { - controlImpl.SetBackgroundColor(Color::TRANSPARENT); - } - else - { - // We have visuals, check if we've set the background and re-create it to - // render even if transparent (only if it's a color visual) - ChangeBackgroundColorVisual(controlImpl, true); - } - } - break; - } + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(controlImpl); - case ClippingMode::DISABLED: - case ClippingMode::CLIP_TO_BOUNDING_BOX: - { - // If we have a background visual, check if it's a color visual and remove the render if transparent flag - ChangeBackgroundColorVisual(controlImpl, false); - break; - } + if(clippingMode == ClippingMode::CLIP_CHILDREN && controlDataImpl.mVisuals.Empty() && self.GetRendererCount() == 0u) + { + controlImpl.SetBackgroundColor(Color::TRANSPARENT); } } } @@ -173,33 +129,12 @@ void Control::SetBackgroundColor(const Vector4& color) map[Toolkit::Visual::Property::TYPE] = Toolkit::Visual::COLOR; map[Toolkit::ColorVisual::Property::MIX_COLOR] = color; - bool renderIfTransparent = false; - int clippingMode = ClippingMode::DISABLED; - if((Self().GetProperty(Actor::Property::CLIPPING_MODE).Get(clippingMode)) && - (clippingMode == ClippingMode::CLIP_CHILDREN)) - { - // If clipping-mode is set to CLIP_CHILDREN, then force visual to add the render even if transparent - map[Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT] = true; - renderIfTransparent = true; - } - Toolkit::Visual::Base visual = mImpl->GetVisual(Toolkit::Control::Property::BACKGROUND); if(visual && visual.GetType() == Toolkit::Visual::COLOR) { - Property::Map visualMap; - visual.CreatePropertyMap(visualMap); - - Property::Value* renderValue = visualMap.Find(Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT); - Property::Value* colorValue = visualMap.Find(Toolkit::ColorVisual::Property::MIX_COLOR); - if(renderValue && colorValue) - { - if((renderValue->Get() == true || colorValue->Get().a > 0.0f) && (renderIfTransparent || color.a > 0.0f)) - { - // Update background color only - mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelColorVisual::Action::UPDATE_PROPERTY, map); - return; - } - } + // Update background color only + mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelColorVisual::Action::UPDATE_PROPERTY, map); + return; } SetBackground(map); diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 6d52641..f31d0a0 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -29,7 +29,7 @@ namespace Toolkit { const unsigned int TOOLKIT_MAJOR_VERSION = 2; const unsigned int TOOLKIT_MINOR_VERSION = 0; -const unsigned int TOOLKIT_MICRO_VERSION = 27; +const unsigned int TOOLKIT_MICRO_VERSION = 28; const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 391ddf9..70ea699 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali2-toolkit Summary: Dali 3D engine Toolkit -Version: 2.0.27 +Version: 2.0.28 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT