CHECK_MODULE_AND_SET( LIBDRM libdrm [] )
CHECK_MODULE_AND_SET( LIBCURL libcurl [] )
CHECK_MODULE_AND_SET( HARFBUZZ harfbuzz [] )
+CHECK_MODULE_AND_SET( HYPHEN libhyphen [] )
CHECK_MODULE_AND_SET( FRIBIDI fribidi [] )
CHECK_MODULE_AND_SET( CAIRO cairo [] )
CHECK_MODULE_AND_SET( EVAS evas [] )
-lturbojpeg
-ljpeg
)
+
+if( NOT ANDROID_PROFILE )
+ SET( DALI_LDFLAGS ${DALI_LDFLAGS}
+ -lhyphen
+ )
+ENDIF()
+
ENDIF()
# Android includes pthread with android lib
)
ENDIF()
+# Set the linker flags
+SET(REQUIRED_LIBS
+ -lhyphen
+)
+
+FIND_LIBRARY( HYPHEN_LIBRARY NAMES hyphen )
+IF (${HYPHEN_LIBRARY} MATCHES "HYPHEN_LIBRARY-NOTFOUND")
+ UNSET (HYPHEN_LIBRARY_AVAILABLE)
+ELSE()
+ SET (HYPHEN_LIBRARY_AVAILABLE "HYPHEN_LIBRARY_AVAILABLE")
+ ADD_DEFINITIONS(-DHYPHEN_LIBRARY_AVAILABLE="${HYPHEN_LIBRARY_AVAILABLE}")
+
+ #The path of hyphen library dictionary
+ IF (NOT "${HYPHEN_DIC}")
+ FIND_PATH(HYPHEN_DIC hyph_en_US.dic HINTS "/usr/local/share/hyphen" "/usr/share/hyphen" )
+ IF ( NOT HYPHEN_DIC MATCHES "HYPHEN_DIC-NOTFOUND")
+ ADD_DEFINITIONS(-DHYPHEN_DIC="${HYPHEN_DIC}")
+ ENDIF()
+ ENDIF()
+ MESSAGE (HYPHEN_DIC: "${HYPHEN_DIC}")
+
+ENDIF()
+
)
ENDIF()
+# Set the linker flags
+SET(REQUIRED_LIBS
+ -lhyphen
+)
+
+FIND_LIBRARY( HYPHEN_LIBRARY NAMES hyphen )
+IF (${HYPHEN_LIBRARY} MATCHES "HYPHEN_LIBRARY-NOTFOUND")
+ UNSET (HYPHEN_LIBRARY_AVAILABLE)
+ELSE()
+ SET (HYPHEN_LIBRARY_AVAILABLE "HYPHEN_LIBRARY_AVAILABLE")
+ ADD_DEFINITIONS(-DHYPHEN_LIBRARY_AVAILABLE="${HYPHEN_LIBRARY_AVAILABLE}")
+
+ #The path of hyphen library dictionary
+ IF (NOT "${HYPHEN_DIC}")
+ FIND_PATH(HYPHEN_DIC hyph_en_US.dic HINTS "/usr/local/share/hyphen" "/usr/share/hyphen" )
+ IF ( NOT HYPHEN_DIC MATCHES "HYPHEN_DIC-NOTFOUND")
+ ADD_DEFINITIONS(-DHYPHEN_DIC="${HYPHEN_DIC}")
+ ENDIF()
+ ENDIF()
+ MESSAGE (HYPHEN_DIC: "${HYPHEN_DIC}")
+
+ENDIF()
)
ENDIF()
+# Set the linker flags
+SET(REQUIRED_LIBS
+ -lhyphen
+)
+
+FIND_LIBRARY( HYPHEN_LIBRARY NAMES hyphen )
+IF (${HYPHEN_LIBRARY} MATCHES "HYPHEN_LIBRARY-NOTFOUND")
+ UNSET (HYPHEN_LIBRARY_AVAILABLE)
+ELSE()
+ SET (HYPHEN_LIBRARY_AVAILABLE "HYPHEN_LIBRARY_AVAILABLE")
+ ADD_DEFINITIONS(-DHYPHEN_LIBRARY_AVAILABLE="${HYPHEN_LIBRARY_AVAILABLE}")
+
+ #The path of hyphen library dictionary
+ IF (NOT "${HYPHEN_DIC}")
+ FIND_PATH(HYPHEN_DIC hyph_en_US.dic HINTS "/usr/local/share/hyphen" "/usr/share/hyphen" )
+ IF ( NOT HYPHEN_DIC MATCHES "HYPHEN_DIC-NOTFOUND")
+ ADD_DEFINITIONS(-DHYPHEN_DIC="${HYPHEN_DIC}")
+ ENDIF()
+ ENDIF()
+ MESSAGE (HYPHEN_DIC: "${HYPHEN_DIC}")
+
+ENDIF()
+
-lpthread
-lturbojpeg
-ljpeg
+ -lhyphen
)
+
+
+FIND_LIBRARY( HYPHEN_LIBRARY NAMES hyphen )
+IF (${HYPHEN_LIBRARY} MATCHES "HYPHEN_LIBRARY-NOTFOUND")
+ UNSET (HYPHEN_LIBRARY_AVAILABLE)
+ELSE()
+ SET (HYPHEN_LIBRARY_AVAILABLE "HYPHEN_LIBRARY_AVAILABLE")
+ ADD_DEFINITIONS(-DHYPHEN_LIBRARY_AVAILABLE="${HYPHEN_LIBRARY_AVAILABLE}")
+
+ #The path of hyphen library dictionary
+ IF (NOT "${HYPHEN_DIC}")
+ FIND_PATH(HYPHEN_DIC hyph_en_US.dic HINTS "/usr/local/share/hyphen" "/usr/share/hyphen" )
+ IF ( NOT HYPHEN_DIC MATCHES "HYPHEN_DIC-NOTFOUND")
+ ADD_DEFINITIONS(-DHYPHEN_DIC="${HYPHEN_DIC}")
+ ENDIF()
+ ENDIF()
+ MESSAGE (HYPHEN_DIC: "${HYPHEN_DIC}")
+
+ENDIF()
+
Dali::TypeInfo type;
Self().GetTypeInfo(type);
return {
- {"t", type.GetName()},
+ {"class", type.GetName()},
};
}
/**
* @brief Re-enables auto-initialization of AT-SPI bridge
*
- * @param topLevelWindow Accessible object for Scene::GetRootLayer()
- * @param applicationName Application name
- *
* Normal applications do not have to call this function. GetCurrentBridge() tries to
* initialize the AT-SPI bridge when it is called for the first time.
*
* @see Dali::Accessibility::Bridge::AddTopLevelWindow
* @see Dali::Accessibility::Bridge::SetApplicationName
*/
- static void EnableAutoInit(Accessible* topLevelWindow, const std::string& applicationName);
+ static void EnableAutoInit();
protected:
struct Data
/*
- * 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.
return Internal::GetImplementation(*this).GetDpi();
}
-OffscreenWindow::PostRenderSignalType& OffscreenWindow::PostRenderSignal()
+void OffscreenWindow::SetPostRenderCallback(CallbackBase* callback)
{
- return Internal::GetImplementation(*this).PostRenderSignal();
+ Internal::GetImplementation(*this).SetPostRenderCallback(callback);
}
OffscreenWindow::OffscreenWindow(Internal::OffscreenWindow* window)
#define DALI_OFFSCREEN_WINDOW_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.
#include <dali/public-api/actors/actor.h>
#include <dali/public-api/math/uint-16-pair.h>
#include <dali/public-api/object/any.h>
-#include <dali/public-api/signals/dali-signal.h>
// INTERNAL INCLUDES
#include <dali/public-api/dali-adaptor-common.h>
class DALI_ADAPTOR_API OffscreenWindow : public Dali::BaseHandle
{
public:
- using WindowSize = Uint16Pair;
- using PostRenderSignalType = Signal<void(OffscreenWindow, Any)>;
+ using WindowSize = Uint16Pair;
public:
/**
*/
Uint16Pair GetDpi() const;
-public: // Signals
/**
- * @brief This signal is emitted when the OffscreenWindow is rendered.
+ * @brief Sets the PostRenderCallback of the OffscreenWindow.
+ *
+ * @param[in] callback The PostRenderCallback function
+ * @code
+ * void MyFunction( OffscreenWindow window, Any nativeSurface );
+ * @endcode
+ *
+ * @note Ownership of the callback is passed onto this class.
*
- * @return The signal
*/
- PostRenderSignalType& PostRenderSignal();
+ void SetPostRenderCallback(CallbackBase* callback);
public: // Not intended for application developers
/**
using WebEngineFrameRenderedSignalType = Signal<void(void)>;
/**
- * @brief WebView signal type related with policy would be decided.
+ * @brief WebView signal type related with response policy would be decided.
*/
- using WebEnginePolicyDecisionSignalType = Signal<void(std::shared_ptr<Dali::WebEnginePolicyDecision>)>;
+ using WebEngineResponsePolicyDecisionSignalType = Signal<void(std::shared_ptr<Dali::WebEnginePolicyDecision>)>;
/**
* @brief Hit test callback called after hit test is created asynchronously.
virtual WebEngineConsoleMessageSignalType& ConsoleMessageSignal() = 0;
/**
- * @brief Connect to this signal to be notified when new policy would be decided.
+ * @brief Connect to this signal to be notified when response policy would be decided.
*
* @return A signal object to connect with.
*/
- virtual WebEnginePolicyDecisionSignalType& PolicyDecisionSignal() = 0;
+ virtual WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal() = 0;
/**
* @brief Connect to this signal to be notified when certificate need be confirmed.
return GetImplementation(*this).ConsoleMessageSignal();
}
-Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& WebEngine::PolicyDecisionSignal()
+Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& WebEngine::ResponsePolicyDecisionSignal()
{
- return GetImplementation(*this).PolicyDecisionSignal();
+ return GetImplementation(*this).ResponsePolicyDecisionSignal();
}
Dali::WebEnginePlugin::WebEngineCertificateSignalType& WebEngine::CertificateConfirmSignal()
Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType& ConsoleMessageSignal();
/**
- * @brief Connect to this signal to be notified when new policy would be decided.
+ * @brief Connect to this signal to be notified when response policy would be decided.
*
* @return A signal object to connect with.
*/
- Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& PolicyDecisionSignal();
+ Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal();
/**
* @brief Connect to this signal to be notified when certificate need be confirmed.
${adaptor_devel_api_dir}/text-abstraction/shaping.cpp
${adaptor_devel_api_dir}/text-abstraction/text-renderer.cpp
${adaptor_devel_api_dir}/text-abstraction/text-renderer-layout-helper.cpp
+ ${adaptor_devel_api_dir}/text-abstraction/hyphenation.cpp
)
${adaptor_devel_api_dir}/text-abstraction/text-abstraction-definitions.h
${adaptor_devel_api_dir}/text-abstraction/text-renderer.h
${adaptor_devel_api_dir}/text-abstraction/text-renderer-layout-helper.h
+ ${adaptor_devel_api_dir}/text-abstraction/hyphenation.h
)
--- /dev/null
+/*
+ * 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 <dali/devel-api/text-abstraction/hyphenation.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/text/text-abstraction/hyphenation-impl.h>
+
+namespace Dali
+{
+namespace TextAbstraction
+{
+Hyphenation::Hyphenation()
+{
+}
+
+Hyphenation::~Hyphenation()
+{
+}
+
+Hyphenation::Hyphenation(Internal::Hyphenation* impl)
+: BaseHandle(impl)
+{
+}
+
+Hyphenation Hyphenation::Get()
+{
+ return Internal::Hyphenation::Get();
+}
+
+const char* Hyphenation::GetDictionaryEncoding(const char* lang)
+{
+ return GetImplementation(*this).GetDictionaryEncoding(lang);
+}
+
+Vector<bool> Hyphenation::GetWordHyphens(const char* word,
+ Length wordSize,
+ const char* lang)
+{
+ return GetImplementation(*this).GetWordHyphens(word,
+ wordSize,
+ lang);
+}
+
+} // namespace TextAbstraction
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_PLATFORM_TEXT_ABSTRACTION_HYPHENATION_H
+#define DALI_PLATFORM_TEXT_ABSTRACTION_HYPHENATION_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 <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+#include <dali/public-api/dali-adaptor-common.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+
+namespace Dali
+{
+namespace TextAbstraction
+{
+namespace Internal DALI_INTERNAL
+{
+class Hyphenation;
+
+} // namespace DALI_INTERNAL
+
+/**
+ * @brief Hyphenation provides an interface to retrieve possible hyphenation of the text.
+ *
+ * This module get the hyphen positions for a word.
+ * To get the hyphen positions it needs to load the dictionary for the word language.
+ * also it need the word to be send using the correct encoding which can be known using
+ *
+ * @code
+ * Hyphenation hyphenation = Hyphenation::Get();
+ *
+ * Character* text = "Hyphenation";
+ *
+ * // get a vector of booleans that indicates possible hyphen locations.
+ * Vector<bool> *hyphens = hyphenation.GetWordHyphens(text, 11, "en_US");
+ *
+ * @endcode
+ */
+class DALI_ADAPTOR_API Hyphenation : public BaseHandle
+{
+public:
+ /**
+ * @brief Create an uninitialized Hyphenation handle.
+ *
+ */
+ Hyphenation();
+
+ /**
+ * @brief Destructor
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ */
+ ~Hyphenation();
+
+ /**
+ * @brief This constructor is used by Hyphenation::Get().
+ *
+ * @param[in] implementation A pointer to the internal hyphenation object.
+ */
+ explicit DALI_INTERNAL Hyphenation(Internal::Hyphenation* implementation);
+
+ /**
+ * @brief Retrieve a handle to the Hyphenation instance.
+ *
+ * @return A handle to the Hyphenation.
+ */
+ static Hyphenation Get();
+
+ /**
+ *
+ * Gets the encoding of the dictionary for the given language
+ *
+ * @param[in] lang language to get encoding for (en_US).
+ *
+ * @return The encoding of the language (UTF-32).
+ */
+ const char* GetDictionaryEncoding(const char* lang);
+
+ /**
+ * Gets a vector booleans that indicates possible hyphen locations.
+ *
+ * @param[in] word the word to get possible hyphens for.
+ * @param[in] wordSize the word size in bytes.
+ * @param[in] lang the language for the word
+ *
+ * @return vector of boolean, true if possible to hyphenate at this character position.
+ */
+ Vector<bool> GetWordHyphens(const char* word,
+ Length wordSize,
+ const char* lang);
+};
+
+} // namespace TextAbstraction
+
+} // namespace Dali
+
+#endif // DALI_PLATFORM_TEXT_ABSTRACTION_HYPHENATION_H
#define DALI_TEXT_ABSTRACTION_DEFINITIONS_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.
*/
enum
{
- LINE_MUST_BREAK = 0u, ///< Text must be broken into a new line.
- LINE_ALLOW_BREAK = 1u, ///< Is possible to break the text into a new line.
- LINE_NO_BREAK = 2u ///< Text can't be broken into a new line.
+ LINE_MUST_BREAK = 0u, ///< Text must be broken into a new line.
+ LINE_ALLOW_BREAK = 1u, ///< Is possible to break the text into a new line.
+ LINE_NO_BREAK = 2u, ///< Text can't be broken into a new line.
+ LINE_INSIDEACHAR = 3u, ///< A UTF-8/16 sequence is unfinished.
+ LINE_INDETERMINATE = 4u, ///< End of input on a non-EOL char.
+ LINE_HYPHENATION_BREAK = 5u ///< Text can be broken with adding hyphen.
};
/**
#include <dali/devel-api/text-abstraction/script.h>
#include <dali/devel-api/text-abstraction/segmentation.h>
#include <dali/devel-api/text-abstraction/shaping.h>
+#include <dali/devel-api/text-abstraction/hyphenation.h>
#endif // DALI_TEXT_ABSTRACTION_H
public: // API
/**
- * @brief Get the render surface the adaptor is using to render to.
- * @return reference to current render surface
- */
- virtual Any GetDrawable() = 0;
-
- /**
* @brief Sets the render notification trigger to call when render thread is completed a frame
* @param renderNotification to use
*/
*/
virtual void CreateNativeRenderable() = 0;
- /**
- * @brief Release a drawable
- */
- virtual void ReleaseDrawable() = 0;
-
protected:
// Undefined
NativeRenderSurface(const NativeRenderSurface&) = delete;
#define A11yDbusPath "/org/a11y/bus"
#define A11yDbusStatusInterface "org.a11y.Status"
#define AtspiDbusNameRegistry "org.a11y.atspi.Registry"
+#define AtspiDbusPathRegistry "/org/a11y/atspi/registry"
+#define AtspiDbusInterfaceRegistry "org.a11y.atspi.Registry"
#define AtspiDbusPathRoot "/org/a11y/atspi/accessible/root"
#define AtspiDbusInterfaceSocket "org.a11y.atspi.Socket"
#define AtspiPath "/org/a11y/atspi/accessible"
return !filteredEvents.empty();
}
+void BridgeBase::RegisteredEventsUpdate()
+{
+ using ReturnType = std::vector<std::tuple<std::string, std::string>>;
+ registry.method<DBus::ValueOrError<ReturnType>()>( "GetRegisteredEvents" ).asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
+ if(!msg)
+ {
+ LOG() << "Get registered events failed";
+ return;
+ }
+
+ allowObjectBoundsChangedEvent = false;
+
+ ReturnType values = std::get<ReturnType>(msg.getValues());
+ for(long unsigned int i = 0; i < values.size(); i++)
+ {
+ if (!std::get<1>(values[i]).compare("Object:BoundsChanged"))
+ {
+ allowObjectBoundsChangedEvent = true;
+ }
+ }
+ });
+}
+
BridgeBase::ForceUpResult BridgeBase::ForceUp()
{
if(Bridge::ForceUp() == ForceUpResult::ALREADY_UP)
dbusServer.addInterface(AtspiPath, desc);
}
+ registry = {AtspiDbusNameRegistry, AtspiDbusPathRegistry, AtspiDbusInterfaceRegistry, con};
+
+ RegisteredEventsUpdate();
+
+ registry.addSignal<void(void)>("EventListenerRegistered", [this](void) {
+ RegisteredEventsUpdate();
+ });
+
+ registry.addSignal<void(void)>("EventListenerDeregistered", [this](void) {
+ RegisteredEventsUpdate();
+ });
+
return ForceUpResult::JUST_STARTED;
}
void BridgeBase::ForceDown()
{
Bridge::ForceDown();
+ registry = {};
dbusServer = {};
con = {};
}
private:
void IdSet(int id);
int IdGet();
+ void RegisteredEventsUpdate();
using CacheElementType = std::tuple<
Dali::Accessibility::Address,
DBus::DBusServer dbusServer;
DBusWrapper::ConnectionPtr con;
int id = 0;
+ DBus::DBusClient registry;
+ bool allowObjectBoundsChangedEvent{false};
};
#endif // DALI_INTERNAL_ACCESSIBILITY_BRIDGE_BASE_H
// CLASS HEADER
// EXTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+#include <dali/devel-api/common/stage.h>
#include <dali/integration-api/debug.h>
#include <iostream>
#include <unordered_map>
#include <dali/internal/accessibility/bridge/bridge-text.h>
#include <dali/internal/accessibility/bridge/bridge-value.h>
#include <dali/internal/accessibility/bridge/dummy-atspi.h>
+#include <dali/internal/adaptor/common/adaptor-impl.h>
#include <dali/internal/system/common/environment-variables.h>
#include <dali/devel-api/adaptor-framework/environment-variable.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
using namespace Dali::Accessibility;
else if (autoInitState == AutoInitState::ENABLED)
{
bridge = CreateBridge();
+
+ /* check environment variable for suppressing screen-reader */
+ const char *envSuppressScreenReader = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SUPPRESS_SCREEN_READER);
+ if (envSuppressScreenReader && std::atoi(envSuppressScreenReader) != 0)
+ {
+ bridge->SuppressScreenReader(true);
+ }
+
return bridge;
}
autoInitState = AutoInitState::DISABLED;
}
-void Bridge::EnableAutoInit(Accessible* topLevelWindow, const std::string& applicationName)
+void Bridge::EnableAutoInit()
{
autoInitState = AutoInitState::ENABLED;
return;
}
+ auto rootLayer = Dali::Stage::GetCurrent().GetRootLayer();
+ auto window = Dali::DevelWindow::Get(rootLayer);
+ auto applicationName = Dali::Internal::Adaptor::Adaptor::GetApplicationPackageName();
+
auto* bridge = Bridge::GetCurrentBridge();
- bridge->AddTopLevelWindow(topLevelWindow);
+ bridge->AddTopLevelWindow(Dali::Accessibility::Accessible::Get(rootLayer, true));
bridge->SetApplicationName(applicationName);
bridge->Initialize();
+
+ if(window && window.IsVisible())
+ {
+ bridge->ApplicationShown();
+ }
}
void BridgeObject::EmitBoundsChanged(Accessible* obj, Dali::Rect<> rect)
{
+ if(!allowObjectBoundsChangedEvent) return;
+
auto addr = obj->GetAddress();
const auto prefixPath = "/org/a11y/atspi/accessible/";
const auto nullPath = "/org/a11y/atspi/null";
{
}
-void Accessibility::Bridge::EnableAutoInit(Accessible*, const std::string&)
+void Accessibility::Bridge::EnableAutoInit()
{
}
return static_cast<T0*>(apiObject);
}
+// Maximum size of texture upload buffer.
+const uint32_t TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB = 1;
+
} // namespace
EglGraphicsController::~EglGraphicsController() = default;
reinterpret_cast<char*>(source.memorySource.memory) + info.srcSize,
stagingBuffer);
+ mTextureUploadTotalCPUMemoryUsed += info.srcSize;
+
// store staging buffer
source.memorySource.memory = stagingBuffer;
break;
}
}
}
+
+ // If upload buffer exceeds maximum size, flush.
+ if( mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB*1024 )
+ {
+ Flush();
+ mTextureUploadTotalCPUMemoryUsed = 0;
+ }
}
Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
std::unique_ptr<GLES::PipelineCache> mPipelineCache{nullptr}; ///< Internal pipeline cache
+ uint32_t mTextureUploadTotalCPUMemoryUsed {0u};
+
bool mIsShuttingDown{false}; ///< Indicates whether the controller is shutting down
};
bool ProgramImpl::Create()
{
// Create and link new program
- auto& gl = *mImpl->controller.GetGL();
- auto program = gl.CreateProgram();
+ auto gl = mImpl->controller.GetGL();
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return false;
+ }
+
+ auto program = gl->CreateProgram();
const auto& info = mImpl->createInfo;
for(const auto& state : *info.shaderState)
// Compile shader first (ignored when compiled)
if(shader->Compile())
{
- gl.AttachShader(program, shader->GetGLShader());
+ gl->AttachShader(program, shader->GetGLShader());
}
}
- gl.LinkProgram(program);
+ gl->LinkProgram(program);
GLint status{0};
- gl.GetProgramiv(program, GL_LINK_STATUS, &status);
+ gl->GetProgramiv(program, GL_LINK_STATUS, &status);
if(status != GL_TRUE)
{
char output[4096];
GLsizei size{0u};
- gl.GetProgramInfoLog(program, 4096, &size, output);
+ gl->GetProgramInfoLog(program, 4096, &size, output);
// log on error
// TODO: un-printf-it
printf("Log: %s\n", output);
- gl.DeleteProgram(program);
+ gl->DeleteProgram(program);
return false;
}
*/
#include "gles-graphics-reflection.h"
+
+#include <dali/integration-api/debug.h>
#include <dali/integration-api/gl-abstraction.h>
#include <dali/integration-api/gl-defines.h>
char* name;
auto gl = mController.GetGL();
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return;
+ }
gl->GetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
gl->GetProgramiv(glProgram, GL_ACTIVE_ATTRIBUTES, &nAttribs);
int numUniforms = 0;
auto gl = mController.GetGL();
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return;
+ }
gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
auto gl = mController.GetGL();
auto glProgram = mProgram.GetGlProgram();
int numUniformBlocks = 0;
+
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return;
+ }
+
gl->GetProgramiv(glProgram, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
mUniformBlocks.clear();
Graphics::ShaderLanguage Reflection::GetLanguage() const
{
+ auto version = Graphics::ShaderLanguage::GLSL_3_2;
+
auto gl = mController.GetGL();
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return version;
+ }
int majorVersion, minorVersion;
gl->GetIntegerv(GL_MAJOR_VERSION, &majorVersion);
gl->GetIntegerv(GL_MINOR_VERSION, &minorVersion);
- printf("GL Version (integer) : %d.%d\n", majorVersion, minorVersion);
- printf("GLSL Version : %s\n", gl->GetString(GL_SHADING_LANGUAGE_VERSION));
+ DALI_LOG_RELEASE_INFO("GL Version (integer) : %d.%d\n", majorVersion, minorVersion);
+ DALI_LOG_RELEASE_INFO("GLSL Version : %s\n", gl->GetString(GL_SHADING_LANGUAGE_VERSION));
// TODO: the language version is hardcoded for now, but we may use what we get
// from GL_SHADING_LANGUAGE_VERSION?
- return Graphics::ShaderLanguage::GLSL_3_2;
+ return version;
}
} // namespace Dali::Graphics::GLES
#include "gles-graphics-shader.h"
// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
#include "egl-graphics-controller.h"
namespace Dali::Graphics::GLES
bool Shader::Compile() const
{
- auto& gl = *GetController().GetGL();
+ auto gl = GetController().GetGL();
+
+ if(!gl)
+ {
+ return false;
+ }
+
if(!mImpl->glShader)
{
GLenum pipelineStage{0u};
if(pipelineStage)
{
- auto shader = gl.CreateShader(pipelineStage);
+ auto shader = gl->CreateShader(pipelineStage);
const auto src = reinterpret_cast<const char*>(GetCreateInfo().sourceData);
GLint size = GetCreateInfo().sourceSize;
- gl.ShaderSource(shader, 1, const_cast<const char**>(&src), &size);
- gl.CompileShader(shader);
+ gl->ShaderSource(shader, 1, const_cast<const char**>(&src), &size);
+ gl->CompileShader(shader);
GLint status{0};
- gl.GetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status != GL_TRUE)
{
char output[4096];
GLsizei size{0u};
- gl.GetShaderInfoLog(shader, 4096, &size, output);
- printf("Code: %s\n", reinterpret_cast<const char*>(GetCreateInfo().sourceData));
- printf("Log: %s\n", output);
- gl.DeleteShader(shader);
+ gl->GetShaderInfoLog(shader, 4096, &size, output);
+ DALI_LOG_RELEASE_INFO("Code: %s\n", reinterpret_cast<const char*>(GetCreateInfo().sourceData));
+ DALI_LOG_RELEASE_INFO("Log: %s\n", output);
+ gl->DeleteShader(shader);
return false;
}
GetController().DiscardResource(this);
}
-} // namespace Dali::Graphics::GLES
\ No newline at end of file
+} // namespace Dali::Graphics::GLES
auto gl = mController.GetGL();
GLuint texture{0};
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return false;
+ }
+
NativeImageInterfacePtr nativeImage = mCreateInfo.nativeImagePtr;
bool created = nativeImage->CreateResource();
mGlTarget = nativeImage->GetTextureTarget();
bool Texture::InitializeTexture()
{
auto gl = mController.GetGL();
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return false;
+ }
GLuint texture{0};
void Texture::Bind(const TextureBinding& binding) const
{
auto gl = mController.GetGL();
+ if(!gl)
+ {
+ // Do nothing during shutdown
+ return;
+ }
gl->ActiveTexture(GL_TEXTURE0 + binding.binding);
gl->BindTexture(mGlTarget, mTextureId);
return mGLES->GetShadingLanguageVersion();
}
+ const char* GetEglImageExtensionString()
+ {
+ return mGLES->GetEglImageExtensionString();
+ }
+
void CacheConfigurations(ConfigurationManager& configurationManager) override;
private:
{
namespace
{
-const int32_t INITIAL_GLES_VERSION = 30;
-const int32_t GLES_VERSION_SUPPORT_BLEND_EQUATION_ADVANCED = 32;
-const char* KHR_BLEND_EQUATION_ADVANCED = "GL_KHR_blend_equation_advanced";
+static constexpr int32_t INITIAL_GLES_VERSION = 30;
+static constexpr int32_t GLES_VERSION_SUPPORT_BLEND_EQUATION_ADVANCED = 32;
+static constexpr const char* KHR_BLEND_EQUATION_ADVANCED = "GL_KHR_blend_equation_advanced";
-const char* FRAGMENT_SHADER_ADVANCED_BLEND_EQUATION_PREFIX =
+static constexpr const char* FRAGMENT_SHADER_ADVANCED_BLEND_EQUATION_PREFIX =
"#extension GL_KHR_blend_equation_advanced : enable\n"
"#if GL_KHR_blend_equation_advanced==1 || __VERSION__>=320\n"
" layout(blend_support_all_equations) out;\n"
"#endif\n";
-const char* FRAGMENT_SHADER_OUTPUT_COLOR_STRING =
+static constexpr const char* FRAGMENT_SHADER_OUTPUT_COLOR_STRING =
"out mediump vec4 fragColor;\n";
+
+static constexpr const char* OES_EGL_IMAGE_EXTERNAL_STRING = "#extension GL_OES_EGL_image_external:require\n";
+
+static constexpr const char* OES_EGL_IMAGE_EXTERNAL_STRING_ESSL3 = "#extension GL_OES_EGL_image_external_essl3:require\n";
} // namespace
/**
{
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
- GLint majorVersion, minorVersion;
- glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
- glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
- mGlesVersion = majorVersion * 10 + minorVersion;
+ // Only change gles version for the device that support above gles 3.0.
+ if(mGlesVersion >= INITIAL_GLES_VERSION)
+ {
+ GLint majorVersion, minorVersion;
+ glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
+ glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
+ mGlesVersion = majorVersion * 10 + minorVersion;
+ }
if(mGlesVersion >= GLES_VERSION_SUPPORT_BLEND_EQUATION_ADVANCED)
{
return mShadingLanguageVersion;
}
+ const char* GetEglImageExtensionString()
+ {
+ ConditionalWait::ScopedLock lock(mContextCreatedWaitCondition);
+ if(!mIsContextCreated)
+ {
+ mContextCreatedWaitCondition.Wait(lock);
+ }
+ if(mShadingLanguageVersion < 300)
+ {
+ return OES_EGL_IMAGE_EXTERNAL_STRING;
+ }
+ else
+ {
+ return OES_EGL_IMAGE_EXTERNAL_STRING_ESSL3;
+ }
+ }
+
/* OpenGL ES 2.0 */
void ActiveTexture(GLenum texture) override
#include <dali/internal/graphics/common/egl-image-extensions.h>
#include <dali/internal/graphics/gles/egl-graphics.h>
-namespace
-{
-const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
-const char* SAMPLER_TYPE = "samplerExternalOES";
-} // namespace
-
namespace Dali
{
namespace Internal
#include <dali/internal/imaging/common/loader-astc.h>
#include <dali/internal/imaging/common/loader-bmp.h>
#include <dali/internal/imaging/common/loader-gif.h>
+#include <dali/internal/imaging/common/loader-webp.h>
#include <dali/internal/imaging/common/loader-ico.h>
#include <dali/internal/imaging/common/loader-jpeg.h>
#include <dali/internal/imaging/common/loader-ktx.h>
FORMAT_JPEG,
FORMAT_BMP,
FORMAT_GIF,
+ FORMAT_WEBP,
FORMAT_KTX,
FORMAT_ASTC,
FORMAT_ICO,
{Jpeg::MAGIC_BYTE_1, Jpeg::MAGIC_BYTE_2, LoadBitmapFromJpeg, LoadJpegHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{Bmp::MAGIC_BYTE_1, Bmp::MAGIC_BYTE_2, LoadBitmapFromBmp, LoadBmpHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{Gif::MAGIC_BYTE_1, Gif::MAGIC_BYTE_2, LoadBitmapFromGif, LoadGifHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
+ {Webp::MAGIC_BYTE_1, Webp::MAGIC_BYTE_2, LoadBitmapFromWebp, LoadWebpHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{Ktx::MAGIC_BYTE_1, Ktx::MAGIC_BYTE_2, LoadBitmapFromKtx, LoadKtxHeader, Bitmap::BITMAP_COMPRESSED },
{Astc::MAGIC_BYTE_1, Astc::MAGIC_BYTE_2, LoadBitmapFromAstc, LoadAstcHeader, Bitmap::BITMAP_COMPRESSED },
{Ico::MAGIC_BYTE_1, Ico::MAGIC_BYTE_2, LoadBitmapFromIco, LoadIcoHeader, Bitmap::BITMAP_2D_PACKED_PIXELS},
{".jpg", FORMAT_JPEG},
{".bmp", FORMAT_BMP },
{".gif", FORMAT_GIF },
+ {".webp", FORMAT_WEBP },
{".ktx", FORMAT_KTX },
{".astc", FORMAT_ASTC},
{".ico", FORMAT_ICO },
--- /dev/null
+/*
+ * 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 <dali/internal/imaging/common/loader-webp.h>
+
+// EXTERNAL INCLUDES
+#ifdef DALI_WEBP_AVAILABLE
+#include <webp/decode.h>
+#include <webp/demux.h>
+
+#if WEBP_DEMUX_ABI_VERSION > 0x0101
+#define DALI_ANIMATED_WEBP_ENABLED 1
+#endif
+#endif
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/integration-api/debug.h>
+#include <cstring>
+#include <memory>
+
+typedef unsigned char WebPByteType;
+
+namespace Dali
+{
+namespace TizenPlatform
+{
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+bool ReadWebPInformation(FILE* const fp, WebPData& webPData)
+{
+ if(fp == NULL)
+ {
+ return false;
+ }
+
+ if(fseek(fp, 0, SEEK_END) <= -1)
+ {
+ return false;
+ }
+ WebPDataInit(&webPData);
+ webPData.size = ftell(fp);
+
+ if((!fseek(fp, 0, SEEK_SET)))
+ {
+ unsigned char* WebPDataBuffer;
+ WebPDataBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * webPData.size));
+ webPData.size = fread(WebPDataBuffer, sizeof(WebPByteType), webPData.size, fp);
+ webPData.bytes = WebPDataBuffer;
+ }
+ else
+ {
+ return false;
+ }
+ return true;
+}
+
+void ReleaseResource(WebPData& webPData, WebPAnimDecoder* webPAnimDecoder)
+{
+ free((void*)webPData.bytes);
+ webPData.bytes = nullptr;
+ WebPDataInit(&webPData);
+ if(webPAnimDecoder)
+ {
+ WebPAnimDecoderDelete(webPAnimDecoder);
+ }
+}
+
+#endif
+
+bool LoadWebpHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height)
+{
+ FILE* const fp = input.file;
+ if(fp == NULL)
+ {
+ return false;
+ }
+
+ if(fseek(fp, 0, SEEK_END) <= -1)
+ {
+ return false;
+ }
+
+ // If the image is non-animated webp
+#ifdef DALI_WEBP_AVAILABLE
+ size_t webPSize = ftell(fp);
+ if((!fseek(fp, 0, SEEK_SET)))
+ {
+ std::vector<uint8_t> encodedImage;
+ encodedImage.resize(webPSize, 0);
+ size_t readCount = fread(&encodedImage[0], sizeof(uint8_t), encodedImage.size(), fp);
+ if(readCount != encodedImage.size())
+ {
+ return false;
+ }
+ int32_t imageWidth, imageHeight;
+ if(WebPGetInfo(&encodedImage[0], encodedImage.size(), &imageWidth, &imageHeight))
+ {
+ width = static_cast<uint32_t>(imageWidth);
+ height = static_cast<uint32_t>(imageHeight);
+ return true;
+ }
+ }
+#endif
+
+ // If the image is animated webp
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+ WebPData webPData;
+ WebPAnimDecoder* webPAnimDecoder;
+ WebPAnimInfo webPAnimInfo;
+ if(ReadWebPInformation(fp, webPData))
+ {
+ WebPAnimDecoderOptions webPAnimDecoderOptions;
+ WebPAnimDecoderOptionsInit(&webPAnimDecoderOptions);
+ webPAnimDecoderOptions.color_mode = MODE_RGBA;
+ webPAnimDecoder = WebPAnimDecoderNew(&webPData, &webPAnimDecoderOptions);
+ if(webPAnimDecoder != nullptr)
+ {
+ WebPAnimDecoderGetInfo(webPAnimDecoder, &webPAnimInfo);
+ width = webPAnimInfo.canvas_width;
+ height = webPAnimInfo.canvas_height;
+ return true;
+ }
+ }
+ ReleaseResource(webPData, webPAnimDecoder);
+#endif
+ DALI_LOG_ERROR("WebP file open failed.\n");
+ return false;
+}
+
+bool LoadBitmapFromWebp(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap)
+{
+ FILE* const fp = input.file;
+ if(fp == NULL)
+ {
+ return false;
+ }
+
+ if(fseek(fp, 0, SEEK_END) <= -1)
+ {
+ return false;
+ }
+
+ // If the image is non-animated webp
+#ifdef DALI_WEBP_AVAILABLE
+ size_t webPSize = ftell(fp);
+ if((!fseek(fp, 0, SEEK_SET)))
+ {
+ std::vector<uint8_t> encodedImage;
+ encodedImage.resize(webPSize, 0);
+ size_t readCount = fread(&encodedImage[0], sizeof(uint8_t), encodedImage.size(), fp);
+ if(readCount != encodedImage.size())
+ {
+ DALI_LOG_ERROR("WebP image loading failed.\n");
+ return false;
+ }
+
+ int32_t width, height;
+ if(!WebPGetInfo(&encodedImage[0], encodedImage.size(), &width, &height))
+ {
+ DALI_LOG_ERROR("Cannot retrieve WebP image size information.\n");
+ return false;
+ }
+
+ WebPBitstreamFeatures features;
+ if(VP8_STATUS_NOT_ENOUGH_DATA == WebPGetFeatures(&encodedImage[0], encodedImage.size(), &features))
+ {
+ DALI_LOG_ERROR("Cannot retrieve WebP image features.\n");
+ return false;
+ }
+
+ uint32_t channelNumber = (features.has_alpha) ? 4 : 3;
+ Pixel::Format pixelFormat = (channelNumber == 4) ? Pixel::RGBA8888 : Pixel::RGB888;
+ bitmap = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
+ uint8_t* frameBuffer = nullptr;
+ if(channelNumber == 4)
+ {
+ frameBuffer = WebPDecodeRGBA(&encodedImage[0], encodedImage.size(), &width, &height);
+ }
+ else
+ {
+ frameBuffer = WebPDecodeRGB(&encodedImage[0], encodedImage.size(), &width, &height);
+ }
+
+ if(frameBuffer != nullptr)
+ {
+ const int32_t bufferSize = width * height * sizeof(uint8_t) * channelNumber;
+ memcpy(bitmap.GetBuffer(), frameBuffer, bufferSize);
+ free((void*)frameBuffer);
+ return true;
+ }
+ }
+#endif
+
+ // If the image is animated webp
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+ WebPData webPData;
+ WebPAnimDecoder* webPAnimDecoder;
+ WebPAnimInfo webPAnimInfo;
+ if(ReadWebPInformation(fp, webPData))
+ {
+ WebPAnimDecoderOptions webPAnimDecoderOptions;
+ WebPAnimDecoderOptionsInit(&webPAnimDecoderOptions);
+ webPAnimDecoderOptions.color_mode = MODE_RGBA;
+ webPAnimDecoder = WebPAnimDecoderNew(&webPData, &webPAnimDecoderOptions);
+ if(webPAnimDecoder != nullptr)
+ {
+ uint8_t* frameBuffer;
+ int timestamp;
+ WebPAnimDecoderGetInfo(webPAnimDecoder, &webPAnimInfo);
+ WebPAnimDecoderReset(webPAnimDecoder);
+ WebPAnimDecoderGetNext(webPAnimDecoder, &frameBuffer, ×tamp);
+
+ bitmap = Dali::Devel::PixelBuffer::New(webPAnimInfo.canvas_width, webPAnimInfo.canvas_height, Dali::Pixel::RGBA8888);
+ const int32_t bufferSize = webPAnimInfo.canvas_width * webPAnimInfo.canvas_height * sizeof(uint32_t);
+ memcpy(bitmap.GetBuffer(), frameBuffer, bufferSize);
+ return true;
+ }
+ }
+ ReleaseResource(webPData, webPAnimDecoder);
+#endif
+
+ DALI_LOG_ERROR("WebP image loading failed.\n");
+ return false;
+}
+
+} // namespace TizenPlatform
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TIZEN_PLATFORM_LOADER_WEBP_H
+#define DALI_TIZEN_PLATFORM_LOADER_WEBP_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 <dali/devel-api/adaptor-framework/image-loader-input.h>
+#include <cstdio>
+
+namespace Dali
+{
+namespace Devel
+{
+class PixelBuffer;
+}
+
+namespace TizenPlatform
+{
+class ResourceLoadingClient;
+
+namespace Webp
+{
+const unsigned char MAGIC_BYTE_1 = 0x52;
+const unsigned char MAGIC_BYTE_2 = 0x49;
+} // namespace Webp
+
+/**
+ * Loads the header of a Webp file and fills in the width and height appropriately.
+ * @param[in] input Information about the input image (including file pointer)
+ * @param[out] width Is set with the width of the image
+ * @param[out] height Is set with the height of the image
+ * @return true if the file's header was read successully, false otherwise
+ */
+bool LoadWebpHeader(const Dali::ImageLoader::Input& input, unsigned int& width, unsigned int& height);
+
+/**
+ * Loads the bitmap from a Webp file. This function checks the header first
+ * and if it is not a Webp file, then it returns straight away.
+ * @note For animated Webps, only the first image is displayed
+ * @param[in] input Information about the input image (including file pointer)
+ * @param[out] bitmap The bitmap class where the decoded image will be stored
+ * @return true if file decoded successfully, false otherwise
+ */
+bool LoadBitmapFromWebp(const Dali::ImageLoader::Input& input, Dali::Devel::PixelBuffer& bitmap);
+
+} // namespace TizenPlatform
+
+} // namespace Dali
+
+#endif // DALI_TIZEN_PLATFORM_LOADER_WEBP_H
#include <webp/demux.h>
#if WEBP_DEMUX_ABI_VERSION > 0x0101
-#define DALI_WEBP_ENABLED 1
+#define DALI_ANIMATED_WEBP_ENABLED 1
#endif
#endif
#include <unistd.h>
#include <cstring>
+// INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+
typedef unsigned char WebPByteType;
namespace Dali
public:
Impl(const std::string& url, bool isLocalResource)
: mUrl(url),
- mLoadSucceeded(true),
- mMutex()
+ mFrameCount(1u),
+ mMutex(),
+ mBuffer(nullptr),
+ mBufferSize(0u),
+ mImageSize(),
+ mLoadSucceeded(true)
{
-#ifdef DALI_WEBP_ENABLED
+ // mFrameCount will be 1 if the input image is non-animated image or animated image with single frame.
if(ReadWebPInformation(isLocalResource))
{
+#ifdef DALI_ANIMATED_WEBP_ENABLED
+ WebPDataInit(&mWebPData);
+ mWebPData.size = mBufferSize;
+ mWebPData.bytes = mBuffer;
WebPAnimDecoderOptions webPAnimDecoderOptions;
WebPAnimDecoderOptionsInit(&webPAnimDecoderOptions);
webPAnimDecoderOptions.color_mode = MODE_RGBA;
mWebPAnimDecoder = WebPAnimDecoderNew(&mWebPData, &webPAnimDecoderOptions);
WebPAnimDecoderGetInfo(mWebPAnimDecoder, &mWebPAnimInfo);
mTimeStamp.assign(mWebPAnimInfo.frame_count, 0);
+ mFrameCount = mWebPAnimInfo.frame_count;
+ mImageSize = ImageDimensions(mWebPAnimInfo.canvas_width, mWebPAnimInfo.canvas_height);
+#elif DALI_WEBP_AVAILABLE
+ int32_t imageWidth, imageHeight;
+ if(WebPGetInfo(mBuffer, mBufferSize, &imageWidth, &imageHeight))
+ {
+ mImageSize = ImageDimensions(imageWidth, imageHeight);
+ }
+#endif
+#ifndef DALI_WEBP_AVAILABLE
+ // If the system doesn't support webp, loading will be failed.
+ mFrameCount = 0u;
+ mLoadSucceeded = false;
+#endif
}
else
{
+ mFrameCount = 0u;
mLoadSucceeded = false;
+ DALI_LOG_ERROR("Image loading failed for: \"%s\".\n", mUrl.c_str());
}
-#endif
}
bool ReadWebPInformation(bool isLocalResource)
{
-#ifdef DALI_WEBP_ENABLED
- WebPDataInit(&mWebPData);
+ FILE* fp = nullptr;
if(isLocalResource)
{
Internal::Platform::FileReader fileReader(mUrl);
- FILE* fp = fileReader.GetFile();
+ fp = fileReader.GetFile();
if(fp == NULL)
{
return false;
return false;
}
- mWebPData.size = ftell(fp);
- if((!fseek(fp, 0, SEEK_SET)))
- {
- unsigned char* WebPDataBuffer;
- WebPDataBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * mWebPData.size));
- mWebPData.size = fread(WebPDataBuffer, sizeof(WebPByteType), mWebPData.size, fp);
- mWebPData.bytes = WebPDataBuffer;
- }
- else
+ mBufferSize = ftell(fp);
+ if(!fseek(fp, 0, SEEK_SET))
{
- return false;
+ mBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * mBufferSize));
+ mBufferSize = fread(mBuffer, sizeof(WebPByteType), mBufferSize, fp);
+ return true;
}
}
else
succeeded = TizenPlatform::Network::DownloadRemoteFileIntoMemory(mUrl, dataBuffer, dataSize, MAXIMUM_DOWNLOAD_IMAGE_SIZE);
if(succeeded)
{
- size_t blobSize = dataBuffer.Size();
- if(blobSize > 0U)
+ mBufferSize = dataBuffer.Size();
+ if(mBufferSize > 0U)
{
// Open a file handle on the memory buffer:
- Dali::Internal::Platform::FileReader fileReader(dataBuffer, blobSize);
- FILE* const fp = fileReader.GetFile();
- if(NULL != fp)
+ Internal::Platform::FileReader fileReader(dataBuffer, mBufferSize);
+ fp = fileReader.GetFile();
+ if(fp != nullptr)
{
- if((!fseek(fp, 0, SEEK_SET)))
+ if(!fseek(fp, 0, SEEK_SET))
{
- unsigned char* WebPDataBuffer;
- WebPDataBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * blobSize));
- mWebPData.size = fread(WebPDataBuffer, sizeof(WebPByteType), mWebPData.size, fp);
- mWebPData.bytes = WebPDataBuffer;
+ mBuffer = reinterpret_cast<WebPByteType*>(malloc(sizeof(WebPByteType) * mBufferSize));
+ mBufferSize = fread(mBuffer, sizeof(WebPByteType), mBufferSize, fp);
+ return true;
}
- else
- {
- DALI_LOG_ERROR("Error seeking within file\n");
- }
- }
- else
- {
- DALI_LOG_ERROR("Error reading file\n");
}
}
}
}
- return true;
-#else
return false;
-#endif
}
// Moveable but not copyable
~Impl()
{
-#ifdef DALI_WEBP_ENABLED
+#ifdef DALI_ANIMATED_WEBP_ENABLED
if(&mWebPData != NULL)
{
- free((void*)mWebPData.bytes);
mWebPData.bytes = nullptr;
WebPDataInit(&mWebPData);
}
WebPAnimDecoderDelete(mWebPAnimDecoder);
}
#endif
+ free((void*)mBuffer);
+ mBuffer = nullptr;
}
std::string mUrl;
std::vector<uint32_t> mTimeStamp;
uint32_t mLoadingFrame{0};
- bool mLoadSucceeded;
+ uint32_t mFrameCount;
Mutex mMutex;
+ // For the case the system doesn't support DALI_ANIMATED_WEBP_ENABLED
+ unsigned char* mBuffer;
+ uint32_t mBufferSize;
+ ImageDimensions mImageSize;
+ bool mLoadSucceeded;
-#ifdef DALI_WEBP_ENABLED
+#ifdef DALI_ANIMATED_WEBP_ENABLED
WebPData mWebPData{0};
WebPAnimDecoder* mWebPAnimDecoder{nullptr};
WebPAnimInfo mWebPAnimInfo{0};
AnimatedImageLoadingPtr WebPLoading::New(const std::string& url, bool isLocalResource)
{
-#ifndef DALI_WEBP_ENABLED
+#ifndef DALI_ANIMATED_WEBP_ENABLED
DALI_LOG_ERROR("The system does not support Animated WebP format.\n");
#endif
return AnimatedImageLoadingPtr(new WebPLoading(url, isLocalResource));
bool WebPLoading::LoadNextNFrames(uint32_t frameStartIndex, int count, std::vector<Dali::PixelData>& pixelData)
{
-#ifdef DALI_WEBP_ENABLED
- Mutex::ScopedLock lock(mImpl->mMutex);
- if(frameStartIndex >= mImpl->mWebPAnimInfo.frame_count || !mImpl->mLoadSucceeded)
+ for(int i = 0; i < count; ++i)
{
- return false;
+ Dali::Devel::PixelBuffer pixelBuffer = LoadFrame((frameStartIndex + i) % mImpl->mFrameCount);
+ Dali::PixelData imageData = Devel::PixelBuffer::Convert(pixelBuffer);
+ pixelData.push_back(imageData);
}
-
- DALI_LOG_INFO(gWebPLoadingLogFilter, Debug::Concise, "LoadNextNFrames( frameStartIndex:%d, count:%d )\n", frameStartIndex, count);
-
- if(mImpl->mLoadingFrame > frameStartIndex)
+ if(pixelData.size() != static_cast<uint32_t>(count))
{
- mImpl->mLoadingFrame = 0;
- WebPAnimDecoderReset(mImpl->mWebPAnimDecoder);
+ return false;
}
+ return true;
+}
- for(; mImpl->mLoadingFrame < frameStartIndex; ++mImpl->mLoadingFrame)
- {
- uint8_t* frameBuffer;
- int timestamp;
- WebPAnimDecoderGetNext(mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp);
- mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp;
- }
+Dali::Devel::PixelBuffer WebPLoading::LoadFrame(uint32_t frameIndex)
+{
+ Dali::Devel::PixelBuffer pixelBuffer;
- for(int i = 0; i < count; ++i)
+ // WebPDecodeRGBA is faster than to use demux API for loading non-animated image.
+ // If frame count is 1, use WebPDecodeRGBA api.
+#ifdef DALI_WEBP_AVAILABLE
+ if(mImpl->mFrameCount == 1)
{
- const int bufferSize = mImpl->mWebPAnimInfo.canvas_width * mImpl->mWebPAnimInfo.canvas_height * sizeof(uint32_t);
- uint8_t* frameBuffer;
- int timestamp;
- WebPAnimDecoderGetNext(mImpl->mWebPAnimDecoder, &frameBuffer, ×tamp);
+ int32_t width, height;
+ if(!WebPGetInfo(mImpl->mBuffer, mImpl->mBufferSize, &width, &height))
+ {
+ return pixelBuffer;
+ }
- auto pixelBuffer = new uint8_t[bufferSize];
- memcpy(pixelBuffer, frameBuffer, bufferSize);
- mImpl->mTimeStamp[mImpl->mLoadingFrame] = timestamp;
+ WebPBitstreamFeatures features;
+ if(VP8_STATUS_NOT_ENOUGH_DATA == WebPGetFeatures(mImpl->mBuffer, mImpl->mBufferSize, &features))
+ {
+ return pixelBuffer;
+ }
- if(pixelBuffer)
+ uint32_t channelNumber = (features.has_alpha) ? 4 : 3;
+ Pixel::Format pixelFormat = (channelNumber == 4) ? Pixel::RGBA8888 : Pixel::RGB888;
+ pixelBuffer = Dali::Devel::PixelBuffer::New(width, height, pixelFormat);
+ uint8_t* frameBuffer = nullptr;
+ if(channelNumber == 4)
+ {
+ frameBuffer = WebPDecodeRGBA(mImpl->mBuffer, mImpl->mBufferSize, &width, &height);
+ }
+ else
{
- pixelData.push_back(Dali::PixelData::New(pixelBuffer, bufferSize, mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height, Dali::Pixel::RGBA8888, Dali::PixelData::DELETE_ARRAY));
+ frameBuffer = WebPDecodeRGB(mImpl->mBuffer, mImpl->mBufferSize, &width, &height);
}
- mImpl->mLoadingFrame++;
- if(mImpl->mLoadingFrame >= mImpl->mWebPAnimInfo.frame_count)
+ if(frameBuffer != nullptr)
{
- mImpl->mLoadingFrame = 0;
- WebPAnimDecoderReset(mImpl->mWebPAnimDecoder);
+ const int32_t imageBufferSize = width * height * sizeof(uint8_t) * channelNumber;
+ memcpy(pixelBuffer.GetBuffer(), frameBuffer, imageBufferSize);
+ free((void*)frameBuffer);
+ return pixelBuffer;
}
}
-
- return true;
-#else
- return false;
#endif
-}
-Dali::Devel::PixelBuffer WebPLoading::LoadFrame(uint32_t frameIndex)
-{
- Dali::Devel::PixelBuffer pixelBuffer;
-
-#ifdef DALI_WEBP_ENABLED
+#ifdef DALI_ANIMATED_WEBP_ENABLED
Mutex::ScopedLock lock(mImpl->mMutex);
if(frameIndex >= mImpl->mWebPAnimInfo.frame_count || !mImpl->mLoadSucceeded)
{
ImageDimensions WebPLoading::GetImageSize() const
{
-#ifdef DALI_WEBP_ENABLED
- return ImageDimensions(mImpl->mWebPAnimInfo.canvas_width, mImpl->mWebPAnimInfo.canvas_height);
-#else
- return ImageDimensions();
-#endif
+ return mImpl->mImageSize;
}
uint32_t WebPLoading::GetImageCount() const
{
-#ifdef DALI_WEBP_ENABLED
- return mImpl->mWebPAnimInfo.frame_count;
-#else
- return 0u;
-#endif
+ return mImpl->mFrameCount;
}
uint32_t WebPLoading::GetFrameInterval(uint32_t frameIndex) const
${adaptor_imaging_dir}/common/loader-ktx.cpp
${adaptor_imaging_dir}/common/loader-png.cpp
${adaptor_imaging_dir}/common/loader-wbmp.cpp
+ ${adaptor_imaging_dir}/common/loader-webp.cpp
${adaptor_imaging_dir}/common/pixel-manipulation.cpp
${adaptor_imaging_dir}/common/gif-loading.cpp
${adaptor_imaging_dir}/common/webp-loading.cpp
{
namespace
{
-const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
const char* SAMPLER_TYPE = "samplerExternalOES";
// clang-format off
}
NativeImageSourceTizen::NativeImageSourceTizen(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
-: mWidth(width),
+: mCustomFragmentPrefix(),
+ mWidth(width),
mHeight(height),
mOwnTbmSurface(false),
mTbmSurface(NULL),
GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
mEglGraphics = static_cast<EglGraphics*>(graphics);
+ mCustomFragmentPrefix = mEglGraphics->GetEglImageExtensionString();
+
mTbmSurface = GetSurfaceFromAny(nativeImageSource);
if(mTbmSurface != NULL)
const char* NativeImageSourceTizen::GetCustomFragmentPrefix() const
{
- return FRAGMENT_PREFIX;
+ return mCustomFragmentPrefix;
}
const char* NativeImageSourceTizen::GetCustomSamplerTypename() const
void DestroySurface();
private:
- uint32_t mWidth; ///< image width
- uint32_t mHeight; ///< image height
- bool mOwnTbmSurface; ///< Whether we created pixmap or not
+ const char* mCustomFragmentPrefix; ///< Prefix for CustomFragment
+ uint32_t mWidth; ///< image width
+ uint32_t mHeight; ///< image height
+ bool mOwnTbmSurface; ///< Whether we created pixmap or not
tbm_surface_h mTbmSurface;
tbm_format mTbmFormat;
bool mBlendingRequired; ///< Whether blending is required
{
#define TBM_SURFACE_QUEUE_SIZE 3
-const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
const char* SAMPLER_TYPE = "samplerExternalOES";
// clang-format off
}
NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue)
-: mMutex(),
+: mCustomFragmentPrefix(),
+ mMutex(),
mWidth(width),
mHeight(height),
mTbmQueue(NULL),
GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
mEglGraphics = static_cast<EglGraphics*>(graphics);
+ mCustomFragmentPrefix = mEglGraphics->GetEglImageExtensionString();
+
mTbmQueue = GetSurfaceFromAny(nativeImageSourceQueue);
if(mTbmQueue != NULL)
const char* NativeImageSourceQueueTizen::GetCustomFragmentPrefix() const
{
- return FRAGMENT_PREFIX;
+ return mCustomFragmentPrefix;
}
const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
private:
typedef std::pair<tbm_surface_h, void*> EglImagePair;
- Dali::Mutex mMutex; ///< Mutex
- uint32_t mWidth; ///< image width
- uint32_t mHeight; ///< image height
- tbm_surface_queue_h mTbmQueue; ///< Tbm surface queue handle
- tbm_surface_h mConsumeSurface; ///< The current tbm surface
- std::vector<EglImagePair> mEglImages; ///< EGL Image vector
- EglGraphics* mEglGraphics; ///< EGL Graphics
- EglImageExtensions* mEglImageExtensions; ///< The EGL Image Extensions
- bool mOwnTbmQueue; ///< Whether we created tbm queue
- bool mBlendingRequired; ///< Whether blending is required
+ const char* mCustomFragmentPrefix; ///< Prefix for CustomFragment
+ Dali::Mutex mMutex; ///< Mutex
+ uint32_t mWidth; ///< image width
+ uint32_t mHeight; ///< image height
+ tbm_surface_queue_h mTbmQueue; ///< Tbm surface queue handle
+ tbm_surface_h mConsumeSurface; ///< The current tbm surface
+ std::vector<EglImagePair> mEglImages; ///< EGL Image vector
+ EglGraphics* mEglGraphics; ///< EGL Graphics
+ EglImageExtensions* mEglImageExtensions; ///< The EGL Image Extensions
+ bool mOwnTbmQueue; ///< Whether we created tbm queue
+ bool mBlendingRequired; ///< Whether blending is required
};
} // namespace Adaptor
#include <dali/integration-api/adaptor-framework/native-render-surface-factory.h>
#include <dali/integration-api/adaptor-framework/native-render-surface.h>
#include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
+#include <dali/integration-api/debug.h>
#include <dali/internal/offscreen/common/offscreen-application-impl.h>
namespace Dali
{
if(isDefaultWindow)
{
- Initialize();
return;
}
Dali::Integration::SceneHolder sceneHolderHandler = Dali::Integration::SceneHolder(this);
Dali::Adaptor::Get().AddWindow(sceneHolderHandler);
-
- Initialize();
-}
-
-void OffscreenWindow::Initialize()
-{
- // Connect callback to be notified when the surface is rendered
- TriggerEventFactory triggerEventFactory;
-
- mRenderNotification = std::unique_ptr<TriggerEventInterface>(triggerEventFactory.CreateTriggerEvent(MakeCallback(this, &OffscreenWindow::OnPostRender), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
-
- NativeRenderSurface* surface = GetNativeRenderSurface();
-
- if(!surface)
- {
- return;
- }
-
- surface->SetRenderNotification(mRenderNotification.get());
}
OffscreenWindow::~OffscreenWindow()
return surface->GetNativeRenderable();
}
+void OffscreenWindow::SetPostRenderCallback(CallbackBase* callback)
+{
+ // Connect callback to be notified when the surface is rendered
+ mPostRenderCallback = std::unique_ptr<CallbackBase>(callback);
+ TriggerEventFactory triggerEventFactory;
+
+ if(!mRenderNotification)
+ {
+ mRenderNotification = std::unique_ptr<TriggerEventInterface>(triggerEventFactory.CreateTriggerEvent(MakeCallback(this, &OffscreenWindow::OnPostRender), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+ }
+
+ NativeRenderSurface* surface = GetNativeRenderSurface();
+
+ if(!surface)
+ {
+ DALI_LOG_ERROR("NativeRenderSurface is null.");
+ return;
+ }
+
+ surface->SetRenderNotification(mRenderNotification.get());
+}
+
NativeRenderSurface* OffscreenWindow::GetNativeRenderSurface() const
{
return dynamic_cast<NativeRenderSurface*>(mSurface.get());
void OffscreenWindow::OnPostRender()
{
+ NativeRenderSurface* surface = GetNativeRenderSurface();
+
+ if(!surface)
+ {
+ DALI_LOG_ERROR("NativeRenderSurface is null.");
+ return;
+ }
+
Dali::OffscreenWindow handle(this);
- mPostRenderSignal.Emit(handle, GetNativeHandle());
-}
+ CallbackBase::Execute(*mPostRenderCallback, handle, surface->GetNativeRenderable());
-OffscreenWindow::PostRenderSignalType& OffscreenWindow::PostRenderSignal()
-{
- return mPostRenderSignal;
+ surface->ReleaseLock();
}
} // namespace Internal
// EXTERNAL INCLUDES
#include <dali/public-api/common/intrusive-ptr.h>
-#include <dali/public-api/signals/connection-tracker.h>
#include <memory>
// INTERNAL INCLUDES
/**
* Implementation of the OffscreenWindow class.
*/
-class OffscreenWindow : public Dali::Internal::Adaptor::SceneHolder,
- public ConnectionTracker
+class OffscreenWindow : public Dali::Internal::Adaptor::SceneHolder
{
public:
- using WindowSize = Dali::OffscreenWindow::WindowSize;
- using PostRenderSignalType = Dali::OffscreenWindow::PostRenderSignalType;
+ using WindowSize = Dali::OffscreenWindow::WindowSize;
/**
* @brief Create a new OffscreenWindow
*/
Any GetNativeHandle() const override;
+ /**
+ * @copydoc Dali::OffscreenWindow::SetPostRenderCallback
+ */
+ void SetPostRenderCallback(CallbackBase* callback);
+
/*
* @brief Initialize the OffscreenWindow
* @param[in] isDefaultWindow Whether the OffscreenWindow is a default one or not
*/
void Initialize(bool isDefaultWindow);
-public: // Signals
- /**
- * @copydoc Dali::OffscreenWindow::PostRenderSignal
- */
- PostRenderSignalType& PostRenderSignal();
-
private:
/**
* This function is called after drawing by dali.
OffscreenWindow(const OffscreenWindow&);
OffscreenWindow& operator=(OffscreenWindow&);
- /*
- * @brief Initialize the OffscreenWindow (for internal use)
- */
- void Initialize();
-
private:
std::unique_ptr<TriggerEventInterface> mRenderNotification;
- PostRenderSignalType mPostRenderSignal;
+ std::unique_ptr<CallbackBase> mPostRenderCallback;
};
inline OffscreenWindow& GetImplementation(Dali::OffscreenWindow& offscreenWindow)
#define DALI_ENV_DISABLE_ATSPI "DALI_DISABLE_ATSPI"
+#define DALI_ENV_SUPPRESS_SCREEN_READER "DALI_SUPPRESS_SCREEN_READER"
+
} // namespace Adaptor
} // namespace Internal
# module: text, backend: common
-SET( adaptor_text_common_src_files
- ${adaptor_text_dir}/text-abstraction/bidirectional-support-impl.cpp
- ${adaptor_text_dir}/text-abstraction/cairo-renderer.cpp
- ${adaptor_text_dir}/text-abstraction/font-client-helper.cpp
- ${adaptor_text_dir}/text-abstraction/font-client-impl.cpp
- ${adaptor_text_dir}/text-abstraction/font-client-plugin-impl.cpp
- ${adaptor_text_dir}/text-abstraction/segmentation-impl.cpp
- ${adaptor_text_dir}/text-abstraction/shaping-impl.cpp
+SET( adaptor_text_common_src_files
+ ${adaptor_text_dir}/text-abstraction/bidirectional-support-impl.cpp
+ ${adaptor_text_dir}/text-abstraction/cairo-renderer.cpp
+ ${adaptor_text_dir}/text-abstraction/font-client-helper.cpp
+ ${adaptor_text_dir}/text-abstraction/font-client-impl.cpp
+ ${adaptor_text_dir}/text-abstraction/font-client-plugin-impl.cpp
+ ${adaptor_text_dir}/text-abstraction/segmentation-impl.cpp
+ ${adaptor_text_dir}/text-abstraction/shaping-impl.cpp
${adaptor_text_dir}/text-abstraction/text-renderer-impl.cpp
+ ${adaptor_text_dir}/text-abstraction/hyphenation-impl.cpp
)
--- /dev/null
+/*
+ * 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 <dali/internal/text/text-abstraction/hyphenation-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+#include <dali/devel-api/common/singleton-service.h>
+
+// EXTERNAL INCLUDES
+#ifdef HYPHEN_LIBRARY_AVAILABLE
+#include <hyphen.h>
+#else
+#define HyphenDict void
+#endif
+
+#ifndef HYPHEN_DIC
+#define HYPHEN_DIC "abc"
+#endif
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Dali::Integration::Log::Filter* gLogFilter = Dali::Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_HYPHENATION");
+#endif
+
+} // namespace
+
+namespace Dali
+{
+namespace TextAbstraction
+{
+namespace Internal
+{
+const char* const DEFAULT_LANGUAGE = "en_US";
+const unsigned int DEFAULT_LANGUAGE_LENGTH = 5u;
+
+struct Hyphenation::HyphenDictionary
+{
+ HyphenDictionary(std::string lang, HyphenDict* dict)
+ {
+ mLanguage = lang;
+ mDictionary = dict;
+ }
+
+ ~HyphenDictionary()
+ {
+ }
+
+ std::string mLanguage;
+ HyphenDict* mDictionary;
+};
+
+struct Hyphenation::Plugin
+{
+ Plugin()
+ : mHyphenDictionary()
+ {
+ }
+
+ ~Plugin()
+ {
+#ifdef HYPHEN_LIBRARY_AVAILABLE
+ for(auto&& it : mHyphenDictionary)
+ {
+ hnj_hyphen_free(it.mDictionary);
+ }
+#endif
+ }
+
+ std::string GetPathForLanguage(const char* lang)
+ {
+ std::string path = HYPHEN_DIC;
+ std::string filName = "/hyph_";
+ filName.append(lang);
+ filName.append(".dic");
+ path.append(filName);
+
+ return path; // must be ..../hyph_en_US.dic
+ }
+
+ HyphenDict* LoadDictionary(const char* language)
+ {
+#ifdef HYPHEN_LIBRARY_AVAILABLE
+ const char* lang = (language ? language : DEFAULT_LANGUAGE);
+
+ for(auto&& it : mHyphenDictionary)
+ {
+ if(!it.mLanguage.compare(lang))
+ {
+ return it.mDictionary;
+ }
+ }
+
+ std::string path = GetPathForLanguage(lang);
+ HyphenDict* dict = hnj_hyphen_load(path.c_str());
+ if(!dict)
+ {
+ DALI_LOG_ERROR("Couldn't load hyphen dictionary:%s\n", lang);
+ }
+ else
+ {
+ mHyphenDictionary.push_back(HyphenDictionary(lang, dict));
+ }
+
+ return dict;
+#else
+ return nullptr;
+#endif
+ }
+
+ const char* GetDictionaryEncoding(const char* lang)
+ {
+#ifdef HYPHEN_LIBRARY_AVAILABLE
+ HyphenDict* dict = LoadDictionary(lang);
+ if(!dict)
+ {
+ return nullptr;
+ }
+
+ return dict->cset;
+#else
+ return "UTF_32";
+#endif
+ }
+
+ Vector<bool> GetWordHyphens(const char* word,
+ Length wordLength,
+ const char* lang)
+ {
+ Vector<bool> hyphensList;
+
+#ifdef HYPHEN_LIBRARY_AVAILABLE
+ char* hyphens = nullptr;
+ char** rep = nullptr;
+ int* pos = nullptr;
+ int* cut = nullptr;
+ HyphenDict* dict;
+
+ if((!word) || (wordLength < 1))
+ {
+ return hyphensList;
+ }
+
+ dict = LoadDictionary(lang);
+ if(!dict)
+ {
+ return hyphensList;
+ }
+
+ hyphens = (char*)malloc(wordLength + 5);
+ if(hyphens)
+ {
+ hnj_hyphen_hyphenate2(dict, (char*)(word), wordLength, hyphens, NULL, &rep, &pos, &cut);
+
+ hyphensList.PushBack(false);
+
+ for(Length i = 0; i < wordLength - 1; i++)
+ {
+ hyphensList.PushBack((bool)(hyphens[i + 1] & 1));
+ }
+
+ free(hyphens);
+ }
+#endif
+
+ return hyphensList;
+ }
+
+ std::vector<HyphenDictionary> mHyphenDictionary;
+};
+
+Hyphenation::Hyphenation()
+: mPlugin(nullptr)
+{
+}
+
+Hyphenation::~Hyphenation()
+{
+}
+
+TextAbstraction::Hyphenation Hyphenation::Get()
+{
+ TextAbstraction::Hyphenation hyphenationHandle;
+
+ SingletonService service(SingletonService::Get());
+ if(service)
+ {
+ // Check whether the singleton is already created
+ Dali::BaseHandle handle = service.GetSingleton(typeid(TextAbstraction::Hyphenation));
+ if(handle)
+ {
+ // If so, downcast the handle
+ Hyphenation* impl = dynamic_cast<Internal::Hyphenation*>(handle.GetObjectPtr());
+ hyphenationHandle = TextAbstraction::Hyphenation(impl);
+ }
+ else // create and register the object
+ {
+ hyphenationHandle = TextAbstraction::Hyphenation(new Hyphenation);
+ service.Register(typeid(hyphenationHandle), hyphenationHandle);
+ }
+ }
+
+ return hyphenationHandle;
+}
+
+const char* Hyphenation::GetDictionaryEncoding(const char* lang)
+{
+ CreatePlugin();
+
+ return mPlugin->GetDictionaryEncoding(lang);
+}
+
+Vector<bool> Hyphenation::GetWordHyphens(const char* word,
+ Length wordLength,
+ const char* lang)
+{
+ CreatePlugin();
+
+ return mPlugin->GetWordHyphens(word, wordLength, lang);
+}
+
+void Hyphenation::CreatePlugin()
+{
+ if(!mPlugin)
+ {
+ mPlugin = std::make_unique<Plugin>();
+ }
+}
+
+} // namespace Internal
+
+} // namespace TextAbstraction
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_INTERNAL_TEXT_ABSTRACTION_HYPHENATION_IMPL_H
+#define DALI_INTERNAL_TEXT_ABSTRACTION_HYPHENATION_IMPL_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 <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/hyphenation.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+namespace TextAbstraction
+{
+namespace Internal
+{
+/**
+ * Implementation of the Hyphenation
+ */
+class Hyphenation : public BaseObject
+{
+public:
+ /**
+ * Constructor
+ */
+ Hyphenation();
+
+ /**
+ * Destructor
+ */
+ ~Hyphenation();
+
+ /**
+ * @copydoc Dali::Hyphenation::Get()
+ */
+ static TextAbstraction::Hyphenation Get();
+
+ /**
+ * @copydoc Dali::Hyphenation::GetDictionaryEncoding()
+ */
+ const char* GetDictionaryEncoding(const char* lang);
+
+ /**
+ * @copydoc Dali::Hyphenation::GetWordHyphens()
+ */
+ Vector<bool> GetWordHyphens(const char* word,
+ Length wordLength,
+ const char* lang);
+
+private:
+ /**
+ * Helper for lazy initialization.
+ */
+ void CreatePlugin();
+
+private:
+ // Undefined copy constructor.
+ Hyphenation(const Hyphenation&);
+
+ // Undefined assignment constructor.
+ Hyphenation& operator=(const Hyphenation&);
+
+ struct HyphenDictionary;
+ struct Plugin;
+ std::unique_ptr<Plugin> mPlugin;
+
+}; // class Hyphenation
+
+} // namespace Internal
+
+} // namespace TextAbstraction
+
+inline static TextAbstraction::Internal::Hyphenation& GetImplementation(TextAbstraction::Hyphenation& hyphenation)
+{
+ DALI_ASSERT_ALWAYS(hyphenation && "hyphenation handle is empty");
+ BaseObject& handle = hyphenation.GetBaseObject();
+ return static_cast<TextAbstraction::Internal::Hyphenation&>(handle);
+}
+
+inline static const TextAbstraction::Internal::Hyphenation& GetImplementation(const TextAbstraction::Hyphenation& hyphenation)
+{
+ DALI_ASSERT_ALWAYS(hyphenation && "hyphenation handle is empty");
+ const BaseObject& handle = hyphenation.GetBaseObject();
+ return static_cast<const TextAbstraction::Internal::Hyphenation&>(handle);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_TEXT_ABSTRACTION_HYPHENATION_IMPL_H
return mPlugin->ConsoleMessageSignal();
}
-Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& WebEngine::PolicyDecisionSignal()
+Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& WebEngine::ResponsePolicyDecisionSignal()
{
- return mPlugin->PolicyDecisionSignal();
+ return mPlugin->ResponsePolicyDecisionSignal();
}
Dali::WebEnginePlugin::WebEngineCertificateSignalType& WebEngine::CertificateConfirmSignal()
Dali::WebEnginePlugin::WebEngineConsoleMessageSignalType& ConsoleMessageSignal();
/**
- @copydoc Dali::WebEngine::PolicyDecisionSignal()
+ @copydoc Dali::WebEngine::ResponsePolicyDecisionSignal()
*/
- Dali::WebEnginePlugin::WebEnginePolicyDecisionSignalType& PolicyDecisionSignal();
+ Dali::WebEnginePlugin::WebEngineResponsePolicyDecisionSignalType& ResponsePolicyDecisionSignal();
/**
* @copydoc Dali::WebEngine::CertificateConfirmSignal()
{
}
-bool WindowBaseAndroid::SetNotificationLevel(Dali::WindowNotificationLevel level)
+Dali::WindowOperationResult WindowBaseAndroid::SetNotificationLevel(Dali::WindowNotificationLevel level)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
Dali::WindowNotificationLevel WindowBaseAndroid::GetNotificationLevel() const
{
}
-bool WindowBaseAndroid::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+Dali::WindowOperationResult WindowBaseAndroid::SetScreenOffMode(WindowScreenOffMode screenOffMode)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
WindowScreenOffMode WindowBaseAndroid::GetScreenOffMode() const
return WindowScreenOffMode::TIMEOUT;
}
-bool WindowBaseAndroid::SetBrightness(int brightness)
+Dali::WindowOperationResult WindowBaseAndroid::SetBrightness(int brightness)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
int WindowBaseAndroid::GetBrightness() const
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetNotificationLevel()
*/
- bool SetNotificationLevel(Dali::WindowNotificationLevel level) override;
+ Dali::WindowOperationResult SetNotificationLevel(Dali::WindowNotificationLevel level) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetNotificationLevel()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetScreenOffMode()
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
+ Dali::WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenOffMode()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetBrightness()
*/
- bool SetBrightness(int brightness) override;
+ Dali::WindowOperationResult SetBrightness(int brightness) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetBrightness()
mOpaqueState(false),
mResizeEnabled(false),
mVisible(false),
- mIsRotated(false),
- mIsWindowRotated(false),
mIsTouched(false),
mIsEGLInitialized(false),
mDepth(false),
mWindowBase = windowFactory->CreateWindowBase(mPositionSize, surface, (mIsTransparent ? true : false));
mWindowBase->IconifyChangedSignal().Connect(this, &GlWindow::OnIconifyChanged);
mWindowBase->FocusChangedSignal().Connect(this, &GlWindow::OnFocusChanged);
+ mWindowBase->OutputTransformedSignal().Connect(this, &GlWindow::OnOutputTransformed);
if(Dali::Adaptor::IsAvailable())
{
}
// If window's size or position is changed, the signal will be emitted to user.
- if((needToMove) || (needToResize))
+ if(needToMove || needToResize)
{
Uint16Pair newSize(mPositionSize.width, mPositionSize.height);
Dali::GlWindow handle(this);
mResizeSignal.Emit(newSize);
+
+ if(mGlWindowRenderThread)
+ {
+ mGlWindowRenderThread->RequestWindowResize(mPositionSize.width, mPositionSize.height);
+ }
}
}
void GlWindow::OnOutputTransformed()
{
- int screenRotationAngle = mWindowBase->GetScreenRotationAngle();
- if(screenRotationAngle != mScreenRotationAngle)
- {
- mScreenRotationAngle = screenRotationAngle;
- mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
-
- if(mTotalRotationAngle == 90 || mTotalRotationAngle == 270)
- {
- mWindowWidth = mPositionSize.height;
- mWindowHeight = mPositionSize.width;
- }
- else
- {
- mWindowWidth = mPositionSize.width;
- mWindowHeight = mPositionSize.height;
- }
+ int newScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
+ DALI_LOG_RELEASE_INFO("GlWindow::OnOutputTransformed(), screen rotation occurs, old[%d], new[%d\n", mScreenRotationAngle, newScreenRotationAngle);
- // Emit Resize signal
- Dali::GlWindow handle(this);
- mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
+ if(newScreenRotationAngle != mScreenRotationAngle)
+ {
+ UpdateScreenRotation(newScreenRotationAngle);
}
}
mWindowHeight = mPositionSize.height;
}
- mIsRotated = true;
- mIsWindowRotated = true;
DALI_LOG_RELEASE_INFO("Window (%p), WinId (%d), OnRotation(): resize signal emit [%d x %d]\n", this, mNativeWindowId, mWindowWidth, mWindowHeight);
// Emit Resize signal
Dali::GlWindow handle(this);
mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
+
+ if(mGlWindowRenderThread)
+ {
+ mGlWindowRenderThread->RequestWindowRotate(mWindowRotationAngle);
+ }
}
void GlWindow::RecalculateTouchPosition(Integration::Point& point)
mGlWindowRenderThread->SetOnDemandRenderMode(onDemand);
mIsEGLInitialized = true;
+
+ // Check screen rotation
+ int newScreenRotationAngle = mWindowBase->GetScreenRotationAngle();
+ DALI_LOG_RELEASE_INFO("GlWindow::InitializeGraphics(), GetScreenRotationAngle(): %d\n", mScreenRotationAngle);
+ if(newScreenRotationAngle != 0)
+ {
+ UpdateScreenRotation(newScreenRotationAngle);
+ }
}
}
{
}
+void GlWindow::UpdateScreenRotation(int newAngle)
+{
+ mScreenRotationAngle = newAngle;
+ mTotalRotationAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
+
+ if(mTotalRotationAngle == 90 || mTotalRotationAngle == 270)
+ {
+ mWindowWidth = mPositionSize.height;
+ mWindowHeight = mPositionSize.width;
+ }
+ else
+ {
+ mWindowWidth = mPositionSize.width;
+ mWindowHeight = mPositionSize.height;
+ }
+
+ // Emit Resize signal
+ Dali::GlWindow handle(this);
+ mResizeSignal.Emit(Dali::Uint16Pair(mWindowWidth, mWindowHeight));
+
+ if(mGlWindowRenderThread)
+ {
+ DALI_LOG_RELEASE_INFO("GlWindow::UpdateScreenRotation(), RequestScreenRotatem(), mScreenRotationAngle: %d\n", mScreenRotationAngle);
+ mGlWindowRenderThread->RequestScreenRotate(mScreenRotationAngle);
+ }
+}
+
} // namespace Adaptor
} // namespace Internal
*/
void OnDamaged(const DamageArea& area);
+ /**
+ * @brief Updates screen rotation value and screen rotation works.
+ *
+ * @param[in] newAngle new screen rotation angle
+ */
+ void UpdateScreenRotation(int newAngle);
+
public: // Signals
/**
* @copydoc Dali::GlWindow::FocusChangeSignal()
bool mOpaqueState : 1;
bool mResizeEnabled : 1;
bool mVisible : 1;
- bool mIsRotated : 1;
bool mIsWindowRotated : 1;
bool mIsTouched : 1;
bool mIsEGLInitialized : 1;
/*
- * 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.
*
*/
+// EXTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/thread-settings.h>
+// INTERNAL INCLUDES
#include <dali/internal/adaptor/common/adaptor-impl.h>
#include <dali/internal/system/common/time-service.h>
#include <dali/internal/window-system/common/gl-window-render-thread.h>
{
namespace
{
-const unsigned int NANOSECONDS_PER_SECOND(1e+9);
+constexpr unsigned int NANOSECONDS_PER_SECOND(1e+9);
// The following values will get calculated at compile time
-const float DEFAULT_FRAME_DURATION_IN_SECONDS(1.0f / 60.0f);
-const uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* NANOSECONDS_PER_SECOND);
+constexpr float DEFAULT_FRAME_DURATION_IN_SECONDS(1.0f / 60.0f);
+constexpr uint64_t DEFAULT_FRAME_DURATION_IN_NANOSECONDS(DEFAULT_FRAME_DURATION_IN_SECONDS* NANOSECONDS_PER_SECOND);
+constexpr uint64_t REFRESH_RATE(1u);
+constexpr int MINIMUM_DIMENSION_CHANGE(1);
} // namespace
GlWindowRenderThread::GlWindowRenderThread(PositionSize positionSize, ColorDepth colorDepth)
: mGraphics(nullptr),
mWindowBase(nullptr),
+ mWindowRotationTrigger(),
mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
mPositionSize(positionSize),
mColorDepth(colorDepth),
mIsEGLInitialize(false),
mGLESVersion(30), //Default GLES version 30
mMSAA(0),
+ mWindowRotationAngle(0),
+ mScreenRotationAngle(0),
mRenderThreadWaitCondition(),
mDestroyRenderThread(0),
mPauseRenderThread(0),
mRenderingMode(0),
- mRequestRenderOnce(0)
+ mRequestRenderOnce(0),
+ mSurfaceStatus(0),
+ mPostRendering(0),
+ mDefaultFrameDurationNanoseconds(REFRESH_RATE * DEFAULT_FRAME_DURATION_IN_NANOSECONDS)
{
- unsigned int refrashRate = 1u;
- mDefaultFrameDurationNanoseconds = uint64_t(refrashRate) * DEFAULT_FRAME_DURATION_IN_NANOSECONDS;
}
GlWindowRenderThread::~GlWindowRenderThread()
mRenderThreadWaitCondition.Notify(lock);
}
+void GlWindowRenderThread::RequestWindowResize(int width, int height)
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ // Check resizing
+ if((fabs(width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
+ (fabs(height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE))
+ {
+ mSurfaceStatus |= static_cast<unsigned int>(SurfaceStatus::RESIZED); // Set bit for window resized
+ mPositionSize.width = width;
+ mPositionSize.height = height;
+
+ DALI_LOG_RELEASE_INFO("GlWindowRenderThread::RequestWindowResize(), width:%d, height:%d\n", width, height);
+ mRenderThreadWaitCondition.Notify(lock);
+ }
+}
+
+void GlWindowRenderThread::RequestWindowRotate(int windowAngle)
+{
+ if(!mWindowRotationTrigger)
+ {
+ mWindowRotationTrigger = std::unique_ptr<TriggerEventInterface>(TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &GlWindowRenderThread::WindowRotationCompleted),
+ TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+ }
+
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ if(mWindowRotationAngle != windowAngle)
+ {
+ mSurfaceStatus |= static_cast<unsigned int>(SurfaceStatus::WINDOW_ROTATED); // Set bit for window rotation
+ mWindowRotationAngle = windowAngle;
+ DALI_LOG_RELEASE_INFO("GlWindowRenderThread::RequestWindowRotate(): %d\n", windowAngle);
+ mRenderThreadWaitCondition.Notify(lock);
+ }
+}
+
+void GlWindowRenderThread::RequestScreenRotate(int screenAngle)
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ if(mScreenRotationAngle != screenAngle)
+ {
+ mSurfaceStatus |= static_cast<unsigned int>(SurfaceStatus::SCREEN_ROTATED); // Set bit for screen rotation
+ mScreenRotationAngle = screenAngle;
+ DALI_LOG_RELEASE_INFO("GlWindowRenderThread::RequestScreenRotate(): %d\n", screenAngle);
+ mRenderThreadWaitCondition.Notify(lock);
+ }
+}
+
+void GlWindowRenderThread::WindowRotationCompleted()
+{
+ mWindowBase->WindowRotationCompleted(mWindowRotationAngle, mPositionSize.width, mPositionSize.height);
+
+ PostRenderFinish();
+}
+
+unsigned int GlWindowRenderThread::GetSurfaceStatus(int& windowRotationAngle, int& screenRotationAngle)
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+
+ // Get the surface status and reset that.
+ unsigned int status = mSurfaceStatus;
+ mSurfaceStatus = static_cast<unsigned int>(SurfaceStatus::NO_CHANGED);
+
+ windowRotationAngle = mWindowRotationAngle;
+ screenRotationAngle = mScreenRotationAngle;
+
+ return status;
+}
+
void GlWindowRenderThread::Run()
{
Dali::SetThreadName("GlWindowRenderThread");
mLogFactory.InstallLogFunction();
int renderFrameResult = 0;
- EglGraphics* eglGraphics = static_cast<EglGraphics*>(mGraphics);
+ unsigned int isSurfaceChanged = 0;
+ bool isWindowResized = false, isWindowRotated = false, isScreenRotated = false;
+ int windowRotationAngle = 0, screenRotationAngle = 0, totalAngle = 0;
+ EglGraphics* eglGraphics = static_cast<EglGraphics*>(mGraphics);
Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
if(mGLRenderFrameCallback)
{
+ // PreRender
+ isSurfaceChanged = GetSurfaceStatus(windowRotationAngle, screenRotationAngle);
+ if(DALI_UNLIKELY(isSurfaceChanged))
+ {
+ isWindowResized = (isSurfaceChanged & static_cast<unsigned int>(SurfaceStatus::RESIZED)) ? true : false;
+ isWindowRotated = (isSurfaceChanged & static_cast<unsigned int>(SurfaceStatus::WINDOW_ROTATED)) ? true : false;
+ isScreenRotated = (isSurfaceChanged & static_cast<unsigned int>(SurfaceStatus::SCREEN_ROTATED)) ? true : false;
+ totalAngle = (windowRotationAngle + screenRotationAngle) % 360;
+
+ if(isWindowRotated || isScreenRotated)
+ {
+ mWindowBase->SetEglWindowBufferTransform(totalAngle);
+ if(isWindowRotated)
+ {
+ mWindowBase->SetEglWindowTransform(windowRotationAngle);
+ }
+ }
+
+ if(isWindowResized)
+ {
+ Dali::PositionSize positionSize;
+ positionSize.x = mPositionSize.x;
+ positionSize.y = mPositionSize.y;
+ if(totalAngle == 0 || totalAngle == 180)
+ {
+ positionSize.width = mPositionSize.width;
+ positionSize.height = mPositionSize.height;
+ }
+ else
+ {
+ positionSize.width = mPositionSize.height;
+ positionSize.height = mPositionSize.width;
+ }
+ mWindowBase->ResizeEglWindow(positionSize);
+ }
+ }
+
+ // Render
renderFrameResult = CallbackBase::ExecuteReturn<int>(*mGLRenderFrameCallback);
+ // PostRender
+ if(DALI_UNLIKELY(isWindowRotated))
+ {
+ PostRenderStart();
+
+ mWindowRotationTrigger->Trigger();
+
+ PostRenderWaitForFinished();
+ isWindowRotated = false;
+ }
+
+ // buffer commit
if(renderFrameResult)
{
eglImpl.SwapBuffers(mEGLSurface);
bool GlWindowRenderThread::RenderReady(uint64_t& timeToSleepUntil)
{
ConditionalWait::ScopedLock updateLock(mRenderThreadWaitCondition);
- while((!mDestroyRenderThread && mRenderingMode && !mRequestRenderOnce) || mPauseRenderThread)
+ while((!mDestroyRenderThread && mRenderingMode && !mRequestRenderOnce && !mSurfaceStatus) || mPauseRenderThread)
{
timeToSleepUntil = 0;
mRenderThreadWaitCondition.Wait(updateLock);
return !mDestroyRenderThread;
}
+void GlWindowRenderThread::PostRenderStart()
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ mPostRendering = false;
+}
+
+void GlWindowRenderThread::PostRenderFinish()
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ mPostRendering = true;
+ mRenderThreadWaitCondition.Notify(lock);
+}
+
+void GlWindowRenderThread::PostRenderWaitForFinished()
+{
+ ConditionalWait::ScopedLock lock(mRenderThreadWaitCondition);
+ while(!mPostRendering && !mDestroyRenderThread)
+ {
+ mRenderThreadWaitCondition.Wait(lock);
+ }
+}
+
} // namespace Adaptor
} // namespace Internal
namespace Dali
{
class Adaptor;
+class TriggerEventInterface;
namespace Internal
{
{
public:
/**
+ * @brief Enumeration for GlWindow Surface status type
+ * It has the status as resized, window is rotated and screen is rotated.
+ *
+ */
+ enum class SurfaceStatus
+ {
+ NO_CHANGED = 0x00, ///< no changed,
+ RESIZED = 0x01, ///< When surface is resized,
+ WINDOW_ROTATED = 0x02, ///< When window is rotated,
+ SCREEN_ROTATED = 0x04 ///< When screen is rotated,
+ };
+
+ /**
* Constructor
*
* @param[in] positionSize The position and size of the physical window
*/
void RenderOnce();
+ /**
+ * Requests the window resize to GlWindow's render thread.
+ *
+ * @param[in] width new width.
+ * @param[in] height new height.
+ */
+ void RequestWindowResize(int width, int height);
+
+ /**
+ * Requests the window rotation to GlWindow's render thread.
+ *
+ * @param[in] windowAngle the window rotation's angle as 0, 90, 180 and 270.
+ */
+ void RequestWindowRotate(int windowAngle);
+
+ /**
+ * Requests the screen rotation to GlWindow's render thread.
+ *
+ * @param[in] screenAngle the screen rotation's angle as 0, 90, 180 and 270.
+ */
+ void RequestScreenRotate(int screenAngle);
+
protected:
/**
* The Render thread loop. This thread will be destroyed on exit from this function.
*/
bool RenderReady(uint64_t& timeToSleepUntil);
+ /**
+ * In the Tizen world, when GlWindow rotation is finished in client side,
+ * the completed message should be sent to display server.
+ * This function should be called in the event thread after buffer is committed.
+ */
+ void WindowRotationCompleted();
+
+ /**
+ * Gets window's current surface status
+ *
+ * @brief This function return window's current surface status.
+ * The status has the the information of window resized, window rotated and screen rotated.
+ * After called, the status value is reset
+ *
+ * @[output] windowRotationAngle return current window rotation angle.
+ * @[output] screenRotationAngle return current screen rotation angle.
+ * @return the window's current surface status.
+ */
+ unsigned int GetSurfaceStatus(int& windowRotationAngle, int& screenRotationAngle);
+
+ /**
+ * Starts post rendering process
+ *
+ * @brief Starts post rendering process for window rotation
+ * It is to pause the render thread until maint thread finishes the window rotation work.
+ */
+ void PostRenderStart();
+
+ /**
+ * Finishs post rendering process
+ *
+ * @brief Finishes post rendering process for window rotation
+ * It set the resume flag for resume the render thread.
+ */
+ void PostRenderFinish();
+
+ /**
+ * Pauses the render thread unitil post rendering process
+ *
+ * @brief Pauses the render thread until main thread works window rotation.
+ */
+ void PostRenderWaitForFinished();
+
private:
- GraphicsInterface* mGraphics; ///< Graphics interface
- WindowBase* mWindowBase;
+ GraphicsInterface* mGraphics; ///< Graphics interface
+ WindowBase* mWindowBase;
+ std::unique_ptr<TriggerEventInterface> mWindowRotationTrigger;
const Dali::LogFactoryInterface& mLogFactory;
bool mIsEGLInitialize : 1;
int mGLESVersion;
int mMSAA;
+ int mWindowRotationAngle; ///< The angle of window rotation angle
+ int mScreenRotationAngle; ///< The angle of screen rotation angle
// To manage the render/main thread
- ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
- volatile unsigned int mDestroyRenderThread; ///< Stop render thread. It means this rendter thread will be destoried.
- volatile unsigned int mPauseRenderThread; ///< Sleep render thread by pause.
- volatile unsigned int mRenderingMode; ///< Rendering Mode, 0: continuous, 1:OnDemad
- volatile unsigned int mRequestRenderOnce; ///< Request rendering once
+ ConditionalWait mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
+ volatile unsigned int mDestroyRenderThread; ///< Stop render thread. It means this rendter thread will be destoried.
+ volatile unsigned int mPauseRenderThread; ///< Sleep render thread by pause.
+ volatile unsigned int mRenderingMode; ///< Rendering Mode, 0: continuous, 1:OnDemad
+ volatile unsigned int mRequestRenderOnce; ///< Request rendering once
+ volatile unsigned int mSurfaceStatus; ///< When surface is changed as resized or rotated, this flag is set. 0: No changed, 1:resized, 2:window rotation, 4:screen rotation
+ volatile unsigned int mPostRendering; ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
uint64_t mDefaultFrameDurationNanoseconds; ///< Default duration of a frame (used for sleeping if not enough time elapsed). Not protected by lock, but written to rarely so not worth adding a lock when reading.
mStyleChangedSignal(),
mAccessibilitySignal(),
mTransitionEffectEventSignal(),
- mKeyboardRepeatSettingsChangedSignal()
+ mKeyboardRepeatSettingsChangedSignal(),
+ mUpdatePositionSizeSignal()
{
}
return mWindowRedrawRequestSignal;
}
+WindowBase::UpdatePositionSizeType& WindowBase::UpdatePositionSizeSignal()
+{
+ return mUpdatePositionSizeSignal;
+}
+
+
} // namespace Adaptor
} // namespace Internal
typedef Signal<void(WindowEffectState, WindowEffectType)> TransitionEffectEventSignalType;
typedef Signal<void()> KeyboardRepeatSettingsChangedSignalType;
typedef Signal<void()> WindowRedrawRequestSignalType;
+ typedef Signal<void(Dali::PositionSize&)> UpdatePositionSizeType;
// Input events
typedef Signal<void(Integration::Point&, uint32_t)> TouchEventSignalType;
/**
* @copydoc Dali::Window::SetNotificationLevel()
*/
- virtual bool SetNotificationLevel(Dali::WindowNotificationLevel level) = 0;
+ virtual Dali::WindowOperationResult SetNotificationLevel(Dali::WindowNotificationLevel level) = 0;
/**
* @copydoc Dali::Window::GetNotificationLevel()
/**
* @copydoc Dali::Window::SetScreenOffMode()
*/
- virtual bool SetScreenOffMode(WindowScreenOffMode screenOffMode) = 0;
+ virtual Dali::WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode) = 0;
/**
* @copydoc Dali::Window::GetScreenOffMode()
/**
* @copydoc Dali::Window::SetBrightness()
*/
- virtual bool SetBrightness(int brightness) = 0;
+ virtual Dali::WindowOperationResult SetBrightness(int brightness) = 0;
/**
* @copydoc Dali::Window::GetBrightness()
*/
WindowRedrawRequestSignalType& WindowRedrawRequestSignal();
+ /**
+ * @brief This signal is emitted when the window is resized or moved by display server.
+ */
+ UpdatePositionSizeType& UpdatePositionSizeSignal();
+
protected:
// Undefined
WindowBase(const WindowBase&) = delete;
TransitionEffectEventSignalType mTransitionEffectEventSignal;
KeyboardRepeatSettingsChangedSignalType mKeyboardRepeatSettingsChangedSignal;
WindowRedrawRequestSignalType mWindowRedrawRequestSignal;
+ UpdatePositionSizeType mUpdatePositionSizeSignal;
+
};
} // namespace Adaptor
mIsFocusAcceptable(true),
mIconified(false),
mOpaqueState(false),
- mResizeEnabled(false),
mType(WindowType::NORMAL),
mParentWindow(NULL),
mPreferredAngle(static_cast<int>(WindowOrientation::NO_ORIENTATION_PREFERENCE)),
mWindowBase->TransitionEffectEventSignal().Connect(this, &Window::OnTransitionEffectEvent);
mWindowBase->KeyboardRepeatSettingsChangedSignal().Connect(this, &Window::OnKeyboardRepeatSettingsChanged);
mWindowBase->WindowRedrawRequestSignal().Connect(this, &Window::OnWindowRedrawRequest);
+ mWindowBase->UpdatePositionSizeSignal().Connect(this, &Window::OnUpdatePositionSize);
mWindowSurface->OutputTransformedSignal().Connect(this, &Window::OnOutputTransformed);
- if(!positionSize.IsEmpty())
- {
- AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
- mResizeEnabled = true;
- }
+ AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
SetClass(name, className);
return mType;
}
-bool Window::SetNotificationLevel(WindowNotificationLevel level)
+WindowOperationResult Window::SetNotificationLevel(WindowNotificationLevel level)
{
if(mType != WindowType::NOTIFICATION)
{
DALI_LOG_INFO(gWindowLogFilter, Debug::Verbose, "Window::SetNotificationLevel: Not supported window type [%d]\n", mType);
- return false;
+ return WindowOperationResult::INVALID_OPERATION;
}
return mWindowBase->SetNotificationLevel(level);
return mOpaqueState;
}
-bool Window::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+WindowOperationResult Window::SetScreenOffMode(WindowScreenOffMode screenOffMode)
{
return mWindowBase->SetScreenOffMode(screenOffMode);
}
return mWindowBase->GetScreenOffMode();
}
-bool Window::SetBrightness(int brightness)
+WindowOperationResult Window::SetBrightness(int brightness)
{
if(brightness < 0 || brightness > 100)
{
DALI_LOG_INFO(gWindowLogFilter, Debug::Verbose, "Window::SetBrightness: Invalid brightness value [%d]\n", brightness);
- return false;
+ return WindowOperationResult::INVALID_OPERATION;
}
return mWindowBase->SetBrightness(brightness);
void Window::SetSize(Dali::Window::WindowSize size)
{
- if(!mResizeEnabled)
- {
- AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
- mResizeEnabled = true;
- }
-
PositionSize oldRect = mSurface->GetPositionSize();
mWindowSurface->MoveResize(PositionSize(oldRect.x, oldRect.y, size.GetWidth(), size.GetHeight()));
void Window::SetPosition(Dali::Window::WindowPosition position)
{
- if(!mResizeEnabled)
- {
- AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
- mResizeEnabled = true;
- }
-
PositionSize oldRect = mSurface->GetPositionSize();
mWindowSurface->MoveResize(PositionSize(position.GetX(), position.GetY(), oldRect.width, oldRect.height));
void Window::SetPositionSize(PositionSize positionSize)
{
- if(!mResizeEnabled)
- {
- AddAuxiliaryHint("wm.policy.win.user.geometry", "1");
- mResizeEnabled = true;
- }
-
PositionSize oldRect = mSurface->GetPositionSize();
mWindowSurface->MoveResize(positionSize);
mAdaptor->RenderOnce();
}
+void Window::OnUpdatePositionSize(Dali::PositionSize& positionSize)
+{
+ SetPositionSize(positionSize);
+}
+
void Window::OnTouchPoint(Dali::Integration::Point& point, int timeStamp)
{
FeedTouchPoint(point, timeStamp);
/**
* @copydoc Dali::Window::SetNotificationLevel()
*/
- bool SetNotificationLevel(WindowNotificationLevel level);
+ WindowOperationResult SetNotificationLevel(WindowNotificationLevel level);
/**
* @copydoc Dali::Window::GetNotificationLevel()
/**
* @copydoc Dali::Window::SetScreenOffMode()
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode);
+ WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode);
/**
* @copydoc Dali::Window::GetScreenOffMode()
/**
* @copydoc Dali::Window::SetBrightness()
*/
- bool SetBrightness(int brightness);
+ WindowOperationResult SetBrightness(int brightness);
/**
* @copydoc Dali::Window::GetBrightness()
void OnWindowRedrawRequest();
/**
+ * @brief Called when the window is resized or moved by display server.
+ *
+ * @param positionSize the updated window's position and size.
+ */
+ void OnUpdatePositionSize(Dali::PositionSize& positionSize);
+
+ /**
* @brief Set available orientation to window base.
*/
void SetAvailableAnlges(const std::vector<int>& angles);
bool mIsFocusAcceptable : 1;
bool mIconified : 1;
bool mOpaqueState : 1;
- bool mResizeEnabled : 1;
WindowType mType;
Dali::Window mParentWindow;
}
}
+Rect<int32_t> RecalculateRect0(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+ return rect;
+}
+
+Rect<int32_t> RecalculateRect90(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+ Rect<int32_t> newRect;
+ newRect.x = surfaceSize.height - (rect.y + rect.height);
+ newRect.y = rect.x;
+ newRect.width = rect.height;
+ newRect.height = rect.width;
+ return newRect;
+}
+
+Rect<int32_t> RecalculateRect180(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+ Rect<int32_t> newRect;
+ newRect.x = surfaceSize.width - (rect.x + rect.width);
+ newRect.y = surfaceSize.height - (rect.y + rect.height);
+ newRect.width = rect.width;
+ newRect.height = rect.height;
+ return newRect;
+}
+
+Rect<int32_t> RecalculateRect270(Rect<int32_t>& rect, const Rect<int32_t>& surfaceSize)
+{
+ Rect<int32_t> newRect;
+ newRect.x = rect.y;
+ newRect.y = surfaceSize.width - (rect.x + rect.width);
+ newRect.width = rect.height;
+ newRect.height = rect.width;
+ return newRect;
+}
+
+using RecalculateRectFunction = Rect<int32_t> (*)(Rect<int32_t>&, const Rect<int32_t>&);
+
+RecalculateRectFunction RecalculateRect[4] = {RecalculateRect0, RecalculateRect90, RecalculateRect180, RecalculateRect270};
+
} // unnamed namespace
WindowRenderSurface::WindowRenderSurface(Dali::PositionSize positionSize, Any surface, bool isTransparent)
bool needToResize = false;
// Check moving
- if((fabs(positionSize.x - mPositionSize.x) > MINIMUM_DIMENSION_CHANGE) ||
- (fabs(positionSize.y - mPositionSize.y) > MINIMUM_DIMENSION_CHANGE))
+ if((fabs(positionSize.x - mPositionSize.x) >= MINIMUM_DIMENSION_CHANGE) ||
+ (fabs(positionSize.y - mPositionSize.y) >= MINIMUM_DIMENSION_CHANGE))
{
needToMove = true;
}
// Check resizing
- if((fabs(positionSize.width - mPositionSize.width) > MINIMUM_DIMENSION_CHANGE) ||
- (fabs(positionSize.height - mPositionSize.height) > MINIMUM_DIMENSION_CHANGE))
+ if((fabs(positionSize.width - mPositionSize.width) >= MINIMUM_DIMENSION_CHANGE) ||
+ (fabs(positionSize.height - mPositionSize.height) >= MINIMUM_DIMENSION_CHANGE))
{
needToResize = true;
}
return;
}
- std::vector<Rect<int>> damagedRegion;
- damagedRegion.push_back(clippingRect);
+ std::vector<Rect<int>> damagedRegion;
+ Dali::Integration::Scene scene = mScene.GetHandle();
+ if(scene)
+ {
+ damagedRegion.push_back(RecalculateRect[std::min(scene.GetCurrentSurfaceOrientation() / 90, 3)](clippingRect, scene.GetCurrentSurfaceRect()));
+ }
+ else
+ {
+ damagedRegion.push_back(clippingRect);
+ }
eglImpl.SetDamageRegion(mEGLSurface, damagedRegion);
}
auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
if(eglGraphics)
{
- Rect<int> surfaceRect(0, 0, mPositionSize.width, mPositionSize.height);
+ Rect<int32_t> surfaceRect;
+ int32_t orientation = 0;
+
+ Dali::Integration::Scene scene = mScene.GetHandle();
+ if(scene)
+ {
+ surfaceRect = scene.GetCurrentSurfaceRect();
+ orientation = std::min(scene.GetCurrentSurfaceOrientation() / 90, 3);
+ }
Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
{
if(!mergedRects[i].IsEmpty())
{
- mergedRects[j++] = mergedRects[i];
+ mergedRects[j++] = RecalculateRect[orientation](mergedRects[i], surfaceRect);
}
}
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetNotificationLevel()
*/
- bool SetNotificationLevel(WindowNotificationLevel level) override;
+ WindowOperationResult SetNotificationLevel(WindowNotificationLevel level) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetNotificationLevel()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetScreenOffMode()
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
+ WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenOffMode()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetBrightness()
*/
- bool SetBrightness(int brightness) override;
+ WindowOperationResult SetBrightness(int brightness) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetBrightness()
/*
- * 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.
{
}
-bool WindowBaseCocoa::SetNotificationLevel( WindowNotificationLevel level )
+WindowOperationResult WindowBaseCocoa::SetNotificationLevel( WindowNotificationLevel level )
{
- return false;
+ return WindowOperationResult::NOT_SUPPORTED;
}
WindowNotificationLevel WindowBaseCocoa::GetNotificationLevel() const
{
}
-bool WindowBaseCocoa::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+WindowOperationResult WindowBaseCocoa::SetScreenOffMode(WindowScreenOffMode screenOffMode)
{
- return false;
+ return WindowOperationResult::NOT_SUPPORTED;
}
WindowScreenOffMode WindowBaseCocoa::GetScreenOffMode() const
return WindowScreenOffMode::TIMEOUT;
}
-bool WindowBaseCocoa::SetBrightness( int brightness )
+WindowOperationResult WindowBaseCocoa::SetBrightness( int brightness )
{
- return false;
+ return WindowOperationResult::NOT_SUPPORTED;
}
int WindowBaseCocoa::GetBrightness() const
ecore_wl_window_type_set(mEcoreWindow, windowType);
}
-bool WindowBaseEcoreWl::SetNotificationLevel(Dali::WindowNotificationLevel level)
+Dali::WindowOperationResult WindowBaseEcoreWl::SetNotificationLevel(Dali::WindowNotificationLevel level)
{
while(!mTizenPolicy)
{
if(!mNotificationLevelChangeDone)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetNotificationLevel: Level change is failed [%d, %d]\n", level, mNotificationChangeState);
- return false;
+ return Dali::WindowOperationResult::UNKNOWN_ERROR;
}
else if(mNotificationChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetNotificationLevel: Permission denied! [%d]\n", level);
- return false;
+ return Dali::WindowOperationResult::PERMISSION_DENIED;
}
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetNotificationLevel: Level is changed [%d]\n", mNotificationLevel);
- return true;
+ return Dali::WindowOperationResult::SUCCEED;
}
Dali::WindowNotificationLevel WindowBaseEcoreWl::GetNotificationLevel() const
tizen_policy_set_opaque_state(mTizenPolicy, ecore_wl_window_surface_get(mEcoreWindow), (opaque ? 1 : 0));
}
-bool WindowBaseEcoreWl::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+Dali::WindowOperationResult WindowBaseEcoreWl::SetScreenOffMode(WindowScreenOffMode screenOffMode)
{
while(!mTizenPolicy)
{
if(!mScreenOffModeChangeDone)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetScreenOffMode: Screen mode change is failed [%d, %d]\n", screenOffMode, mScreenOffModeChangeState);
- return false;
+ return Dali::WindowOperationResult::UNKNOWN_ERROR;
}
else if(mScreenOffModeChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetScreenOffMode: Permission denied! [%d]\n", screenOffMode);
- return false;
+ return Dali::WindowOperationResult::PERMISSION_DENIED;
}
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetScreenOffMode: Screen mode is changed [%d]\n", mScreenOffMode);
- return true;
+ return Dali::WindowOperationResult::SUCCEED;
}
WindowScreenOffMode WindowBaseEcoreWl::GetScreenOffMode() const
return screenMode;
}
-bool WindowBaseEcoreWl::SetBrightness(int brightness)
+Dali::WindowOperationResult WindowBaseEcoreWl::SetBrightness(int brightness)
{
while(!mTizenDisplayPolicy)
{
if(!mBrightnessChangeDone)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetBrightness: Brightness change is failed [%d, %d]\n", brightness, mBrightnessChangeState);
- return false;
+ return Dali::WindowOperationResult::UNKNOWN_ERROR;
}
else if(mBrightnessChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetBrightness: Permission denied! [%d]\n", brightness);
- return false;
+ return Dali::WindowOperationResult::PERMISSION_DENIED;
}
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl::SetBrightness: Brightness is changed [%d]\n", mBrightness);
- return true;
+ return Dali::WindowOperationResult::SUCCEED;
}
int WindowBaseEcoreWl::GetBrightness() const
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetNotificationLevel()
*/
- bool SetNotificationLevel(Dali::WindowNotificationLevel level) override;
+ Dali::WindowOperationResult SetNotificationLevel(Dali::WindowNotificationLevel level) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetNotificationLevel()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetScreenOffMode()
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
+ Dali::WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenOffMode()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetBrightness()
*/
- bool SetBrightness(int brightness) override;
+ Dali::WindowOperationResult SetBrightness(int brightness) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetBrightness()
{
Ecore_Wl2_Event_Window_Configure* ev(static_cast<Ecore_Wl2_Event_Window_Configure*>(event));
- if(ev->win == static_cast<unsigned int>(ecore_wl2_window_id_get(mEcoreWindow)))
+ if(ev && ev->win == static_cast<unsigned int>(ecore_wl2_window_id_get(mEcoreWindow)))
{
// Note: To comply with the wayland protocol, Dali should make an ack_configure
// by calling ecore_wl2_window_commit
+
+ int tempWidth = static_cast<int>(ev->w);
+ int tempHeight = static_cast<int>(ev->h);
+
+ // Initialize with previous size for skip resize when new size is 0.
+ // When window is just moved or window is resized by client application,
+ // The configure notification event's size will be 0.
+ // If new size is 0, the resized work should be skip.
+ int newWidth = mWindowPositionSize.width;
+ int newHeight = mWindowPositionSize.height;
+ bool windowMoved = false, windowResized = false;
+
+ if(ev->x != mWindowPositionSize.x || ev->y != mWindowPositionSize.y)
+ {
+ windowMoved = true;
+ }
+
+ if(tempWidth != 0 && tempHeight != 0 && (tempWidth != mWindowPositionSize.width || tempHeight != mWindowPositionSize.height))
+ {
+ windowResized = true;
+ newWidth = tempWidth;
+ newHeight = tempHeight;
+ }
+
+ if(windowMoved || windowResized)
+ {
+ Dali::PositionSize newPositionSize(ev->x, ev->y, newWidth, newHeight);
+ mUpdatePositionSizeSignal.Emit(newPositionSize);
+ }
+
ecore_wl2_window_commit(mEcoreWindow, EINA_FALSE);
}
}
ecore_wl2_window_type_set(mEcoreWindow, windowType);
}
-bool WindowBaseEcoreWl2::SetNotificationLevel(Dali::WindowNotificationLevel level)
+Dali::WindowOperationResult WindowBaseEcoreWl2::SetNotificationLevel(Dali::WindowNotificationLevel level)
{
while(!mTizenPolicy)
{
if(!mNotificationLevelChangeDone)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetNotificationLevel: Level change is failed [%d, %d]\n", level, mNotificationChangeState);
- return false;
+ Dali::WindowOperationResult::UNKNOWN_ERROR;
}
else if(mNotificationChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetNotificationLevel: Permission denied! [%d]\n", level);
- return false;
+ return Dali::WindowOperationResult::PERMISSION_DENIED;
}
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetNotificationLevel: Level is changed [%d]\n", mNotificationLevel);
- return true;
+ return Dali::WindowOperationResult::SUCCEED;
}
Dali::WindowNotificationLevel WindowBaseEcoreWl2::GetNotificationLevel() const
tizen_policy_set_opaque_state(mTizenPolicy, ecore_wl2_window_surface_get(mEcoreWindow), (opaque ? 1 : 0));
}
-bool WindowBaseEcoreWl2::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+Dali::WindowOperationResult WindowBaseEcoreWl2::SetScreenOffMode(WindowScreenOffMode screenOffMode)
{
while(!mTizenPolicy)
{
if(!mScreenOffModeChangeDone)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetScreenOffMode: Screen mode change is failed [%d, %d]\n", screenOffMode, mScreenOffModeChangeState);
- return false;
+ return Dali::WindowOperationResult::UNKNOWN_ERROR;
}
else if(mScreenOffModeChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetScreenOffMode: Permission denied! [%d]\n", screenOffMode);
- return false;
+ return Dali::WindowOperationResult::PERMISSION_DENIED;
}
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetScreenOffMode: Screen mode is changed [%d]\n", mScreenOffMode);
- return true;
+ return Dali::WindowOperationResult::SUCCEED;
}
WindowScreenOffMode WindowBaseEcoreWl2::GetScreenOffMode() const
return screenMode;
}
-bool WindowBaseEcoreWl2::SetBrightness(int brightness)
+Dali::WindowOperationResult WindowBaseEcoreWl2::SetBrightness(int brightness)
{
while(!mTizenDisplayPolicy)
{
if(!mBrightnessChangeDone)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetBrightness: Brightness change is failed [%d, %d]\n", brightness, mBrightnessChangeState);
- return false;
+ return Dali::WindowOperationResult::UNKNOWN_ERROR;
}
else if(mBrightnessChangeState == TIZEN_POLICY_ERROR_STATE_PERMISSION_DENIED)
{
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetBrightness: Permission denied! [%d]\n", brightness);
- return false;
+ return Dali::WindowOperationResult::PERMISSION_DENIED;
}
DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Verbose, "WindowBaseEcoreWl2::SetBrightness: Brightness is changed [%d]\n", mBrightness);
- return true;
+ return Dali::WindowOperationResult::SUCCEED;
}
int WindowBaseEcoreWl2::GetBrightness() const
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetNotificationLevel()
*/
- bool SetNotificationLevel(Dali::WindowNotificationLevel level) override;
+ Dali::WindowOperationResult SetNotificationLevel(Dali::WindowNotificationLevel level) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetNotificationLevel()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetScreenOffMode()
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
+ Dali::WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenOffMode()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetBrightness()
*/
- bool SetBrightness(int brightness) override;
+ Dali::WindowOperationResult SetBrightness(int brightness) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetBrightness()
mEGLContext(nullptr),
mOwnSurface(false),
mTbmQueue(NULL),
- mConsumeSurface(NULL),
mThreadSynchronization(NULL)
{
Dali::Internal::Adaptor::WindowSystem::Initialize();
// release the surface if we own one
if(mOwnSurface)
{
- ReleaseDrawable();
-
if(mTbmQueue)
{
tbm_surface_queue_destroy(mTbmQueue);
Dali::Internal::Adaptor::WindowSystem::Shutdown();
}
-Any NativeRenderSurfaceEcoreWl::GetDrawable()
-{
- return mConsumeSurface;
-}
-
void NativeRenderSurfaceEcoreWl::SetRenderNotification(TriggerEventInterface* renderNotification)
{
mRenderNotification = renderNotification;
eglImpl.SwapBuffers(mEGLSurface, damagedRects);
}
- //TODO: Move calling tbm_surface_queue_acruie to OffscreenWindow and Scene in EvasPlugin
- if(mOwnSurface)
+ if(mRenderNotification)
{
if(mThreadSynchronization)
{
mThreadSynchronization->PostRenderStarted();
}
- if(tbm_surface_queue_can_acquire(mTbmQueue, 1))
- {
- if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
- {
- DALI_LOG_ERROR("Failed to acquire a tbm_surface\n");
- return;
- }
- }
-
- if(mConsumeSurface)
- {
- tbm_surface_internal_ref(mConsumeSurface);
- }
-
- // create damage for client applications which wish to know the update timing
- if(mRenderNotification)
- {
- // use notification trigger
- // Tell the event-thread to render the tbm_surface
- mRenderNotification->Trigger();
- }
+ // Tell the event-thread to render the tbm_surface
+ mRenderNotification->Trigger();
if(mThreadSynchronization)
{
// wait until the event-thread completed to use the tbm_surface
mThreadSynchronization->PostRenderWaitForCompletion();
}
-
- // release the consumed surface after post render was completed
- ReleaseDrawable();
- }
- else
- {
- // create damage for client applications which wish to know the update timing
- if(mRenderNotification)
- {
- // use notification trigger
- // Tell the event-thread to render the tbm_surface
- mRenderNotification->Trigger();
- }
}
}
}
}
-void NativeRenderSurfaceEcoreWl::ReleaseDrawable()
-{
- if(mConsumeSurface)
- {
- tbm_surface_internal_unref(mConsumeSurface);
-
- if(tbm_surface_internal_is_valid(mConsumeSurface))
- {
- tbm_surface_queue_release(mTbmQueue, mConsumeSurface);
- }
- mConsumeSurface = NULL;
- }
-}
-
} // namespace Dali
public: // from WindowRenderSurface
/**
- * @copydoc Dali::NativeRenderSurface::GetSurface()
- */
- Any GetDrawable() override;
-
- /**
* @copydoc Dali::NativeRenderSurface::SetRenderNotification()
*/
void SetRenderNotification(TriggerEventInterface* renderNotification) override;
*/
void CreateNativeRenderable() override;
- /**
- * @copydoc Dali::NativeRenderSurface::ReleaseDrawable()
- */
- void ReleaseDrawable() override;
-
private: // Data
SurfaceSize mSurfaceSize;
TriggerEventInterface* mRenderNotification;
bool mOwnSurface;
tbm_surface_queue_h mTbmQueue;
- tbm_surface_h mConsumeSurface;
ThreadSynchronizationInterface* mThreadSynchronization; ///< A pointer to the thread-synchronization
};
{
}
-bool WindowBaseEcoreX::SetNotificationLevel(Dali::WindowNotificationLevel level)
+Dali::WindowOperationResult WindowBaseEcoreX::SetNotificationLevel(Dali::WindowNotificationLevel level)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
Dali::WindowNotificationLevel WindowBaseEcoreX::GetNotificationLevel() const
{
}
-bool WindowBaseEcoreX::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+Dali::WindowOperationResult WindowBaseEcoreX::SetScreenOffMode(WindowScreenOffMode screenOffMode)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
WindowScreenOffMode WindowBaseEcoreX::GetScreenOffMode() const
return WindowScreenOffMode::TIMEOUT;
}
-bool WindowBaseEcoreX::SetBrightness(int brightness)
+Dali::WindowOperationResult WindowBaseEcoreX::SetBrightness(int brightness)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
int WindowBaseEcoreX::GetBrightness() const
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetNotificationLevel()
*/
- bool SetNotificationLevel(Dali::WindowNotificationLevel level) override;
+ Dali::WindowOperationResult SetNotificationLevel(Dali::WindowNotificationLevel level) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetNotificationLevel()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetScreenOffMode()
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
+ Dali::WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenOffMode()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetBrightness()
*/
- bool SetBrightness(int brightness) override;
+ Dali::WindowOperationResult SetBrightness(int brightness) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetBrightness()
{
}
-bool WindowBaseWin::SetNotificationLevel(Dali::WindowNotificationLevel level)
+Dali::WindowOperationResult WindowBaseWin::SetNotificationLevel(Dali::WindowNotificationLevel level)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
Dali::WindowNotificationLevel WindowBaseWin::GetNotificationLevel() const
{
}
-bool WindowBaseWin::SetScreenOffMode(WindowScreenOffMode screenOffMode)
+Dali::WindowOperationResult WindowBaseWin::SetScreenOffMode(WindowScreenOffMode screenOffMode)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
WindowScreenOffMode WindowBaseWin::GetScreenOffMode() const
return WindowScreenOffMode::TIMEOUT;
}
-bool WindowBaseWin::SetBrightness(int brightness)
+Dali::WindowOperationResult WindowBaseWin::SetBrightness(int brightness)
{
- return false;
+ return Dali::WindowOperationResult::NOT_SUPPORTED;
}
int WindowBaseWin::GetBrightness() const
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetNotificationLevel()
*/
- bool SetNotificationLevel(Dali::WindowNotificationLevel level) override;
+ Dali::WindowOperationResult SetNotificationLevel(Dali::WindowNotificationLevel level) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetNotificationLevel()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetScreenOffMode()
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
+ Dali::WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetScreenOffMode()
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::SetBrightness()
*/
- bool SetBrightness(int brightness) override;
+ Dali::WindowOperationResult SetBrightness(int brightness) override;
/**
* @copydoc Dali::Internal::Adaptor::WindowBase::GetBrightness()
HIDE, ///< Window hide effect. @SINCE_2_0.0
};
+/**
+ * @brief An enum of window operation result.
+ */
+enum class WindowOperationResult
+{
+ UNKNOWN_ERROR = 0, ///< Failed for unknown reason.
+ SUCCEED, ///< Succeed.
+ PERMISSION_DENIED, ///< Permission denied.
+ NOT_SUPPORTED, ///< The operation is not supported.
+ INVALID_OPERATION, ///< The operation is invalid. (e.g. Try to operate to the wrong window)
+};
+
} // namespace Dali
#endif // DALI_WINDOW_ENUMERATIONS_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.
return GetImplementation(*this).GetType();
}
-bool Window::SetNotificationLevel(WindowNotificationLevel level)
+WindowOperationResult Window::SetNotificationLevel(WindowNotificationLevel level)
{
return GetImplementation(*this).SetNotificationLevel(level);
}
return GetImplementation(*this).IsOpaqueState();
}
-bool Window::SetScreenOffMode(WindowScreenOffMode screenMode)
+WindowOperationResult Window::SetScreenOffMode(WindowScreenOffMode screenMode)
{
return GetImplementation(*this).SetScreenOffMode(screenMode);
}
return GetImplementation(*this).GetScreenOffMode();
}
-bool Window::SetBrightness(int brightness)
+WindowOperationResult Window::SetBrightness(int brightness)
{
return GetImplementation(*this).SetBrightness(brightness);
}
* @brief Sets a priority level for the specified notification window.
* @@SINCE_2_0.0
* @param[in] level The notification window level.
- * @return True if no error occurred, false otherwise.
+ * @return The result of the window operation.
* @PRIVLEVEL_PUBLIC
* @PRIVILEGE_WINDOW_PRIORITY
* @remarks This can be used for a notification type window only. The default level is NotificationLevel::NONE.
*/
- bool SetNotificationLevel(WindowNotificationLevel level);
+ WindowOperationResult SetNotificationLevel(WindowNotificationLevel level);
/**
* @brief Gets a priority level for the specified notification window.
* If the window is no longer shown, then the window manager requests the display system to go back to normal operation.
* @@SINCE_2_0.0
* @param[in] screenOffMode The screen mode.
- * @return True if no error occurred, false otherwise.
+ * @return The result of the window operation.
* @PRIVLEVEL_PUBLIC
* @PRIVILEGE_DISPLAY
*/
- bool SetScreenOffMode(WindowScreenOffMode screenOffMode);
+ WindowOperationResult SetScreenOffMode(WindowScreenOffMode screenOffMode);
/**
* @brief Gets a screen off mode of the window.
* A value less than 0 results in default brightness and a value greater than 100 results in maximum brightness.
* @SINCE_1_2.60
* @param[in] brightness The preferred brightness (0 to 100).
- * @return True if no error occurred, false otherwise.
+ * @return The result of the window operation.
* @PRIVLEVEL_PUBLIC
* @PRIVILEGE_DISPLAY
*/
- bool SetBrightness(int brightness);
+ WindowOperationResult SetBrightness(int brightness);
/**
* @brief Gets preferred brightness of the window.
{
const unsigned int ADAPTOR_MAJOR_VERSION = 2;
const unsigned int ADAPTOR_MINOR_VERSION = 0;
-const unsigned int ADAPTOR_MICRO_VERSION = 24;
+const unsigned int ADAPTOR_MICRO_VERSION = 27;
const char* const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali2-adaptor
Summary: The DALi Tizen Adaptor
-Version: 2.0.24
+Version: 2.0.27
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT
BuildRequires: pkgconfig(egl)
BuildRequires: libcurl-devel
BuildRequires: pkgconfig(harfbuzz)
+BuildRequires: hyphen-devel
BuildRequires: fribidi-devel
BuildRequires: pkgconfig(capi-system-info)