From 9b8ca1b98063f3bd5c3d00e322ce50cd62021ece Mon Sep 17 00:00:00 2001 From: Robert Borzecki Date: Fri, 7 Jun 2019 08:17:44 +0200 Subject: [PATCH] WIP rendering worker. --- .../application-clock/ApplicationClock.cpp | 6 +- module-services/service-gui/CMakeLists.txt | 4 +- module-services/service-gui/GUIWorker.cpp | 24 ------ module-services/service-gui/ServiceGUI.cpp | 85 ++++++++++++++----- module-services/service-gui/ServiceGUI.hpp | 20 +++-- module-services/service-gui/WorkerGUI.cpp | 65 ++++++++++++++ .../{GUIWorker.hpp => WorkerGUI.hpp} | 25 +++--- rebuild.sh | 10 ++- 8 files changed, 171 insertions(+), 68 deletions(-) delete mode 100644 module-services/service-gui/GUIWorker.cpp create mode 100644 module-services/service-gui/WorkerGUI.cpp rename module-services/service-gui/{GUIWorker.hpp => WorkerGUI.hpp} (54%) diff --git a/module-apps/application-clock/ApplicationClock.cpp b/module-apps/application-clock/ApplicationClock.cpp index 29f5090ad..0ad0f0c74 100644 --- a/module-apps/application-clock/ApplicationClock.cpp +++ b/module-apps/application-clock/ApplicationClock.cpp @@ -128,8 +128,8 @@ void ApplicationClock::createUserInterface() { minuteLabel->setText("05"); minuteLabel->setAlignement( gui::Alignment(gui::Alignment::ALIGN_HORIZONTAL_CENTER, gui::Alignment::ALIGN_VERTICAL_CENTER)); - progressBar = new gui::Progress(clockWin, 480/2-30, 300-4, 60, 8 ); - progressBar->setTotalProgress(59); + progressBar = new gui::Progress(clockWin, 480/2-60, 300-4, 120, 8 ); + progressBar->setTotalProgress(120); progressBar->setCurrentProgress(0); /* gui::Rect* rect = new gui::Rect( clockWin, 480/2-30, 300-4, 60, 8 ); rect->setFillColor( gui::ColorFullBlack ); @@ -169,7 +169,7 @@ bool ApplicationClock::incrementSecond(){ seconds = 0; ret = true; } - progressBar->setCurrentProgress(seconds); + progressBar->setCurrentProgress(seconds*2); return ret; } diff --git a/module-services/service-gui/CMakeLists.txt b/module-services/service-gui/CMakeLists.txt index f1042481a..b26a32d5c 100644 --- a/module-services/service-gui/CMakeLists.txt +++ b/module-services/service-gui/CMakeLists.txt @@ -19,11 +19,11 @@ target_sources( ${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/ServiceGUI.cpp" - "${CMAKE_CURRENT_LIST_DIR}/GUIWorker.cpp" + "${CMAKE_CURRENT_LIST_DIR}/WorkerGUI.cpp" "${CMAKE_CURRENT_LIST_DIR}/messages/DrawMessage.cpp" PUBLIC "${CMAKE_CURRENT_LIST_DIR}/ServiceGUI.hpp" - "${CMAKE_CURRENT_LIST_DIR}/GUIWorker.hpp" + "${CMAKE_CURRENT_LIST_DIR}/WorkerGUI.hpp" "${CMAKE_CURRENT_LIST_DIR}/messages/DrawMessage.hpp" "${CMAKE_CURRENT_LIST_DIR}/messages/GUIMessage.hpp" ) diff --git a/module-services/service-gui/GUIWorker.cpp b/module-services/service-gui/GUIWorker.cpp deleted file mode 100644 index 7a64f5eea..000000000 --- a/module-services/service-gui/GUIWorker.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * @file GUIWorker.cpp - * @author Robert Borzecki (robert.borzecki@mudita.com) - * @date 31 maj 2019 - * @brief - * @copyright Copyright (C) 2019 mudita.com - * @details - */ -#include "GUIWorker.hpp" - -namespace sgui { - -GUIWorker::GUIWorker( ServiceGUI* service ) : Worker( service ) { - -} - -GUIWorker::~GUIWorker() { -} - -bool GUIWorker::handleMessage( uint32_t queueID ) { - return true; -} - -} /* namespace sgui */ diff --git a/module-services/service-gui/ServiceGUI.cpp b/module-services/service-gui/ServiceGUI.cpp index 54cc6c77d..0121f74b3 100644 --- a/module-services/service-gui/ServiceGUI.cpp +++ b/module-services/service-gui/ServiceGUI.cpp @@ -21,10 +21,10 @@ #include "ServiceGUI.hpp" #include "..//gui/core/ImageManager.hpp" -#include "GUIWorker.hpp" #include "log/log.hpp" #include "SystemManager/SystemManager.hpp" +#include "WorkerGUI.hpp" namespace sgui { @@ -35,7 +35,8 @@ ServiceGUI::ServiceGUI(const std::string& name, uint32_t screenWidth, uint32_t s renderFrameCounter{ 1 }, transferedFrameCounter{ 0 }, screenWidth{ screenWidth }, - screenHeight{ screenHeight } { + screenHeight{ screenHeight }, + worker{nullptr} { LOG_INFO("[ServiceGUI] Initializing"); @@ -75,6 +76,25 @@ void ServiceGUI::sendBuffer() { einkReady = false; } +void ServiceGUI::sendToRender() { + if( rendering ) + return; + + WorkerGUIBufferData* wgc = new WorkerGUIBufferData(); + wgc->commandsCount = latestCommands.size(); +// for (uint32_t i = 0; i != latestCommands.size(); ++i){ +// wgc->commands.push_back( std::move(latestCommands[i])); +// } +// +// latestCommands.clear(); + wgc->context = renderContext; + worker->send(static_cast(WorkerGUICommands::Render), nullptr); + + + rendering = true; +} + + // Invoked upon receiving data message sys::Message_t ServiceGUI::DataReceivedHandler(sys::DataMessage* msgl) { @@ -90,31 +110,50 @@ sys::Message_t ServiceGUI::DataReceivedHandler(sys::DataMessage* msgl) { LOG_INFO("[ServiceGUI] Received %d draw commands", dmsg->commands.size()); //create temporary vector of pointers to draw commands to avoid polluting renderer with smart pointers. - std::vector commands; +// std::vector commands; +// for (auto i = dmsg->commands.begin(); i != dmsg->commands.end(); ++i) +// commands.push_back( (*i).get() ); + + if( !latestCommands.empty()) + latestCommands.clear(); + + //store commands in the latestCommands container for (auto i = dmsg->commands.begin(); i != dmsg->commands.end(); ++i) - commands.push_back( (*i).get() ); - uint32_t start_tick = xTaskGetTickCount(); - renderer.render( renderContext, commands ); - uint32_t end_tick = xTaskGetTickCount(); - LOG_INFO("[ServiceGUI] RenderingTime: %d", end_tick - start_tick); + latestCommands.push_back( std::move(*i)); - //increment counter holding number of drawn frames - renderFrameCounter++; - - if( einkReady ) { + if( (renderFrameCounter != transferedFrameCounter) && + (!rendering) && + einkReady) { + LOG_INFO("[ServiceGUI]Sending buffer"); sendBuffer(); } - else if( !requestSent ){ - requestSent = true; - //request eink state - auto msg = std::make_shared(MessageType::EinkStateRequest); - sys::Bus::SendUnicast(msg, "ServiceEink", this); + + //if worker is not rendering send him new set of commands + if( !rendering ) { + sendToRender(); } + +// uint32_t start_tick = xTaskGetTickCount(); +// renderer.render( renderContext, commands ); +// uint32_t end_tick = xTaskGetTickCount(); +// LOG_INFO("[ServiceGUI] RenderingTime: %d", end_tick - start_tick); } } break; - case static_cast( MessageType::GUIRenderingFinished ): { - //TODO implement worker and message handling + case static_cast(MessageType::GUIRenderingFinished): { + LOG_INFO("Rendering finished"); + //increment counter holding number of drawn frames + renderFrameCounter++; + + if( einkReady ) { + sendBuffer(); + } + else if( !requestSent ){ + requestSent = true; + //request eink state + auto msg = std::make_shared(MessageType::EinkStateRequest); + sys::Bus::SendUnicast(msg, "ServiceEink", this); + } }break; case static_cast( MessageType::GUIFocusInfo ): { @@ -127,7 +166,7 @@ sys::Message_t ServiceGUI::DataReceivedHandler(sys::DataMessage* msgl) { requestSent = false; //check if something new was rendered. If so render counter has greater value than //transfer counter. - if( renderFrameCounter != transferedFrameCounter ) { + if( (renderFrameCounter != transferedFrameCounter) && (!rendering) ) { LOG_INFO("[ServiceGUI]Sending buffer"); sendBuffer(); } @@ -153,6 +192,12 @@ void ServiceGUI::TickHandler(uint32_t id) { // Invoked during initialization sys::ReturnCodes ServiceGUI::InitHandler() { + //initialize keyboard worker + worker = new WorkerGUI( this ); + std::list list; + worker->init( list ); + worker->run(); + if( einkReady == false ) { requestSent = true; ReloadTimer( timer_id ); diff --git a/module-services/service-gui/ServiceGUI.hpp b/module-services/service-gui/ServiceGUI.hpp index 095f4e761..3fa15338d 100644 --- a/module-services/service-gui/ServiceGUI.hpp +++ b/module-services/service-gui/ServiceGUI.hpp @@ -8,19 +8,23 @@ #ifndef MODULE_SERVICES_SERVICE_GUI_SERVICEGUI_HPP_ #define MODULE_SERVICES_SERVICE_GUI_SERVICEGUI_HPP_ +#include + //module-gui #include "gui/core/Context.hpp" -#include "gui/core/Renderer.hpp" +//#include "gui/core/Renderer.hpp" +#include "messages/DrawMessage.hpp" #include "Service/Service.hpp" #include "Service/Message.hpp" -#include "GUIWorker.hpp" +#include "WorkerGUI.hpp" -class GUIWorker; +class WorkerGUI; namespace sgui { class ServiceGUI: public sys::Service { + friend WorkerGUI; protected: //this is where every incomming frame is painted. gui::Context* renderContext; @@ -35,16 +39,20 @@ protected: //vertical size of the screen in pixels uint32_t screenHeight; //object responsible for rendering images to context - gui::Renderer renderer; +// gui::Renderer renderer; //flag that defines whether eink is ready for new frame buffer volatile bool einkReady = false; volatile bool requestSent = false; - volatile bool bufferLocked = false; + volatile bool rendering = false; + //set of commands recently received. If this vector is not empty and new set of commands is received + //previous commands are removed. + std::vector> latestCommands; uint32_t timer_id= 0; -// GUIWorker* worker; + WorkerGUI* worker; void sendBuffer(); + void sendToRender(); public: ServiceGUI(const std::string& name, uint32_t screenWidth, uint32_t screenHeight ); diff --git a/module-services/service-gui/WorkerGUI.cpp b/module-services/service-gui/WorkerGUI.cpp new file mode 100644 index 000000000..761e00954 --- /dev/null +++ b/module-services/service-gui/WorkerGUI.cpp @@ -0,0 +1,65 @@ +/* + * @file GUIWorker.cpp + * @author Robert Borzecki (robert.borzecki@mudita.com) + * @date 31 maj 2019 + * @brief + * @copyright Copyright (C) 2019 mudita.com + * @details + */ +#include + +extern "C" { + #include "FreeRTOS.h" + #include "task.h" +} + + +#include "Service/Service.hpp" +#include "Service/Message.hpp" +#include "Service/Worker.hpp" +#include "MessageType.hpp" +#include "WorkerGUI.hpp" +//module-utils +#include "log/log.hpp" + +namespace sgui { + +WorkerGUI::WorkerGUI( ServiceGUI* service ) : Worker( service ) { + +} + +WorkerGUI::~WorkerGUI() { +} + +bool WorkerGUI::handleMessage( uint32_t queueID ) { + QueueHandle_t queue = queues[queueID]; + + //queue for receiving rendering commands + if( queueID == 0 ) + { + LOG_INFO("Received rendering commands"); + + WorkerGUIBufferData* received; + xQueueReceive(queue, &received, 0); + if( received != nullptr); + + //create temporary vector of pointers to draw commands to avoid polluting renderer with smart pointers. + std::vector commands; + for (auto i = service->latestCommands.begin(); i!=service->latestCommands.end(); ++i) + commands.push_back( (*i).get() ); + + uint32_t start_tick = xTaskGetTickCount(); + renderer.render( received->context, commands ); + uint32_t end_tick = xTaskGetTickCount(); + LOG_INFO("[WorkerGUI] RenderingTime: %d", end_tick - start_tick); + + delete received; + + //notify gui service that rendering is complete + auto message = std::make_shared(static_cast(MessageType::GUIRenderingFinished)); + sys::Bus::SendUnicast(message, this->service->GetName(), this->service); + } + return true; +} + +} /* namespace sgui */ diff --git a/module-services/service-gui/GUIWorker.hpp b/module-services/service-gui/WorkerGUI.hpp similarity index 54% rename from module-services/service-gui/GUIWorker.hpp rename to module-services/service-gui/WorkerGUI.hpp index f87d92d24..c32be9608 100644 --- a/module-services/service-gui/GUIWorker.hpp +++ b/module-services/service-gui/WorkerGUI.hpp @@ -6,38 +6,41 @@ * @copyright Copyright (C) 2019 mudita.com * @details */ -#ifndef MODULE_SERVICES_SERVICE_GUI_GUIWORKER_HPP_ -#define MODULE_SERVICES_SERVICE_GUI_GUIWORKER_HPP_ +#ifndef MODULE_SERVICES_SERVICE_GUI_WORKERGUI_HPP_ +#define MODULE_SERVICES_SERVICE_GUI_WORKERGUI_HPP_ #include "core/DrawCommand.hpp" #include "core/Context.hpp" #include "messages/GUIMessage.hpp" #include "ServiceGUI.hpp" #include "Service/Worker.hpp" - - +#include "gui/core/Renderer.hpp" namespace sgui { class ServiceGUI; -enum class GUIWorkerCommands { +enum class WorkerGUICommands { Finish, Render }; -class GUIWorkerBufferData { - std::vector< std::unique_ptr< gui::DrawCommand > > commands; +class WorkerGUIBufferData { +public: + std::vector> commands; + uint32_t commandsCount; gui::Context* context; }; /* * */ -class GUIWorker: public sys::Worker { +class WorkerGUI: public sys::Worker { + //object responsible for rendering images to context + gui::Renderer renderer; public: - GUIWorker( ServiceGUI* service ); - virtual ~GUIWorker(); + WorkerGUI( ServiceGUI* service ); + virtual ~WorkerGUI(); /** * virtual method responsible for finishing the worker and handling rendering commands @@ -47,4 +50,4 @@ public: } /* namespace sgui */ -#endif /* MODULE_SERVICES_SERVICE_GUI_GUIWORKER_HPP_ */ +#endif /* MODULE_SERVICES_SERVICE_GUI_WORKERGUI_HPP_ */ diff --git a/rebuild.sh b/rebuild.sh index 3af521e99..31ae6dd97 100755 --- a/rebuild.sh +++ b/rebuild.sh @@ -26,6 +26,7 @@ fi TARGET="Target_Linux.cmake" TARGET_SET="false" BUILD_TESTS="false" +TYPE="Debug" if [ "$1" != "" ]; then if [ "$1" = "linux" ]; then @@ -37,6 +38,11 @@ if [ "$1" != "" ]; then echo "Building for RT1051." TARGET="Target_RT1051.cmake" fi + if [ "$1" = "release" ]; then + echo "Building for RT1051." + TARGET="Target_RT1051.cmake" + TYPE="RelWithDebInfo" + fi else echo "No platform specified, using target Linux." fi @@ -54,7 +60,7 @@ if [ "$TARGET_SET" = "true" ]; then fi if [ "$BUILD_TESTS" = "true" ]; then - cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_UNIT_TESTS="" -DCMAKE_TOOLCHAIN_FILE=../"$TARGET" ../ + cmake -DCMAKE_BUILD_TYPE="$TYPE" -DBUILD_UNIT_TESTS="" -DCMAKE_TOOLCHAIN_FILE=../"$TARGET" ../ else - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../"$TARGET" ../ + cmake -DCMAKE_BUILD_TYPE="$TYPE" -DCMAKE_TOOLCHAIN_FILE=../"$TARGET" ../ fi