From: SooChan Lim Date: Fri, 3 Jul 2020 06:13:25 +0000 (+0900) Subject: DSDisplayDevice: implement HWC functions. X-Git-Tag: accepted/tizen/unified/20200820.213435~302 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F73%2F241573%2F1;p=platform%2Fcore%2Fuifw%2Flibds.git DSDisplayDevice: implement HWC functions. Change-Id: I664b763358926f1575f42c122072035e7ca8c366 --- diff --git a/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.cpp b/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.cpp index d8b17c7..f7b1cce 100644 --- a/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.cpp +++ b/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.cpp @@ -2,71 +2,149 @@ #include "DSDisplayDeviceHWCTDMImpl.h" #include "DSDisplayDeviceHWCWindowTDMImpl.h" #include "DSDebugLog.h" +#include namespace display_server { + DSDisplayDeviceHWCTDMImpl::DSDisplayDeviceHWCTDMImpl(tdm_hwc *thwc) - : __thwc(thwc) + : __thwc(thwc), + __bufferQueue(nullptr) +{} + +DSDisplayDeviceHWCTDMImpl::~DSDisplayDeviceHWCTDMImpl() +{ + clearVisibleHWCWindows(); +} + +std::shared_ptr DSDisplayDeviceHWCTDMImpl::getTargetBufferQueue() { + tdm_error terror; + tbm_surface_queue_h tqueue; + + if (__bufferQueue) { + DSLOG_INF("TDM_HWC", "return the existed IDSBufferQueue."); + return __bufferQueue; + } + + tqueue = tdm_hwc_get_client_target_buffer_queue(__thwc, &terror); + if (terror != TDM_ERROR_NONE) { + DSLOG_ERR("HWCTDM", "tdm_hwc_get_client_target_buffer_queue fails.\n"); + } + __bufferQueue = std::make_shared(tqueue); + + return __bufferQueue; } -DSDisplayDeviceHWCTDMImpl::~DSDisplayDeviceHWCTDMImpl() + +bool DSDisplayDeviceHWCTDMImpl::setTargetBuffer(std::shared_ptr buffer) { + tdm_error terror; + tdm_region fb_damage; + std::memset(&fb_damage, 0, sizeof (tdm_region)); + + terror = tdm_hwc_set_client_target_buffer(__thwc, (tbm_surface_h)buffer->getNativeBuffer(), fb_damage); + if (terror != TDM_ERROR_NONE) { + DSLOG_ERR("TDM_HWC", "tdm_hwc_set_client_target_buffer fails."); + return false; + } + return true; } -IDSDisplayDeviceHWCWindow *DSDisplayDeviceHWCTDMImpl::createHWCWindow() +std::shared_ptr DSDisplayDeviceHWCTDMImpl::makeHWCWindow() { + std::shared_ptr deviceHWCWindow; tdm_error terror; tdm_hwc_window *twindow; - IDSDisplayDeviceHWCWindow *deviceHWCWindow; twindow = tdm_hwc_create_window(__thwc, &terror); if (!twindow) { - DSLOG_ERR("TDM HWCWindow", "tdm_hwc_create_window fails.\n"); + DSLOG_ERR("HWCTDM", "tdm_hwc_create_window fails.\n"); return nullptr; } - deviceHWCWindow = new DSDisplayDeviceHWCWindowTDMImpl(twindow); + deviceHWCWindow = std::make_shared(twindow); if (!deviceHWCWindow) { - DSLOG_ERR("TDM HWCWindow", "new DSDisplayDeviceHWCWindowTDMImpl fails.\n"); + DSLOG_ERR("HWCTDM", "new DSDisplayDeviceHWCWindowTDMImpl fails.\n"); return nullptr; } - __deviceHWCWindowList.push_back(deviceHWCWindow); - return deviceHWCWindow; } -void DSDisplayDeviceHWCTDMImpl::destroyHWCWindow(IDSDisplayDeviceHWCWindow *deviceHWCWindow) +bool DSDisplayDeviceHWCTDMImpl::addVisibleHWCWindow(std::shared_ptr deviceHWCWindow) +{ + __visibleDeviceHWCWindowList.push_back(deviceHWCWindow); + + return true; +} + +bool DSDisplayDeviceHWCTDMImpl::removeVisibleHWCWindow(std::shared_ptr deviceHWCWindow) +{ + __visibleDeviceHWCWindowList.remove(deviceHWCWindow); + + return true; +} + +void DSDisplayDeviceHWCTDMImpl::clearVisibleHWCWindows() { - delete deviceHWCWindow; - __deviceHWCWindowList.remove(deviceHWCWindow); + __visibleDeviceHWCWindowList.clear(); } bool DSDisplayDeviceHWCTDMImpl::commit() { tdm_error terror; - int numVisibleHWCWins = __deviceHWCWindowList.size(); //TODO: need to fix. change it to visible windows list. __deviceHWCWindowList is not the visible window list. - DSDisplayDeviceHWCWindowTDMImpl *hwcWinsImpl; - uint32_t numTypes; + uint32_t numChanges; - // get the thwc_windows to request validate. + if (!__validate(numChanges)) { + DSLOG_ERR("HWCTDM", "__validate fails.\n"); + return false; + } + + if (numChanges > 0) { + if (!__updateChanges(numChanges)) { + DSLOG_ERR("HWCTDM", "__updateChanges fails.\n"); + return false; + } + } + + if (!__acceptValidation()) { + DSLOG_ERR("HWCTDM", "__acceptValidation fails.\n"); + return false; + } + + //TODO: tdm_hwc_commit + terror = tdm_hwc_commit(__thwc, 0, NULL, NULL); + if (terror != TDM_ERROR_NONE) { + DSLOG_ERR("HWCTDM", "tdm_hwc_commit fails."); + return false; + } + + return true; +} + +bool DSDisplayDeviceHWCTDMImpl::__validate(uint32_t &numChanges) +{ + int numVisibleHWCWins = __visibleDeviceHWCWindowList.size(); + tdm_error terror; tdm_hwc_window **thwc_windows; + int i = 0; + + // get the thwc_windows to request validate. thwc_windows = (tdm_hwc_window **)calloc(numVisibleHWCWins, sizeof(tdm_hwc_window *)); if (thwc_windows == nullptr) { DSLOG_ERR("TDM_HWC", "calloc thwc_windows fails."); return false; } - int i = 0; - for (auto *hwcwins : __deviceHWCWindowList) { - hwcWinsImpl = (DSDisplayDeviceHWCWindowTDMImpl *)hwcwins; - thwc_windows[i++] = hwcWinsImpl->getTDMHWCWindow(); + for (auto &&deviceHWCWindow : __visibleDeviceHWCWindowList) { + auto deviceHWCWindowTDM = std::dynamic_pointer_cast(deviceHWCWindow); + thwc_windows[i++] = deviceHWCWindowTDM->getNativeHWCWindow(); } // validate thwc_windows - terror = tdm_hwc_validate(__thwc, thwc_windows, numVisibleHWCWins, &numTypes); + terror = tdm_hwc_validate(__thwc, thwc_windows, numVisibleHWCWins, &numChanges); if (terror != TDM_ERROR_NONE) { DSLOG_ERR("TDM_HWC", "tdm_hwc_validate fails."); free(thwc_windows); @@ -75,56 +153,60 @@ bool DSDisplayDeviceHWCTDMImpl::commit() free(thwc_windows); - // get changed_types + return true; +} + +bool DSDisplayDeviceHWCTDMImpl::__updateChanges(uint32_t numChanges) +{ + tdm_error terror; tdm_hwc_window **changed_thwc_window = NULL; tdm_hwc_window_composition *tcomposition_types = NULL; - uint32_t numChanges = 0; - if (numTypes > 0) { - changed_thwc_window = (tdm_hwc_window **)calloc(numTypes, sizeof(tdm_hwc_window *)); - if (changed_thwc_window == nullptr) { - DSLOG_ERR("TDM_HWC", "calloc changed_thwc_window fails."); - return false; - } - - tcomposition_types = (tdm_hwc_window_composition *)calloc(numTypes, sizeof(tdm_hwc_window_composition)); - if (tcomposition_types == nullptr) { - DSLOG_ERR("TDM_HWC", "calloc changed_thwc_window fails."); - free(changed_thwc_window); - return false; - } - - terror = tdm_hwc_get_changed_composition_types(__thwc, &numChanges, changed_thwc_window, tcomposition_types); - if (terror != TDM_ERROR_NONE) { - DSLOG_ERR("TDM_HWC", "tdm_hwc_get_changed_composition_types fails."); - free(tcomposition_types); - free(changed_thwc_window); - return false; - } + int i; - for (i = 0; i < (int)numChanges; ++i) { - //TODO: change the TYPES of HWCWindows - } + changed_thwc_window = (tdm_hwc_window **)calloc(numChanges, sizeof(tdm_hwc_window *)); + if (changed_thwc_window == nullptr) { + DSLOG_ERR("TDM_HWC", "calloc changed_thwc_window fails."); + return false; + } - // TODO: accept_validation is depending on the transitions. - terror = tdm_hwc_accept_validation(__thwc); - if (terror != TDM_ERROR_NONE) { - DSLOG_ERR("TDM_HWC", "tdm_hwc_accept_validation fails."); - free(tcomposition_types); - free(changed_thwc_window); - return false; - } + // get changed_types + tcomposition_types = (tdm_hwc_window_composition *)calloc(numChanges, sizeof(tdm_hwc_window_composition)); + if (tcomposition_types == nullptr) { + DSLOG_ERR("TDM_HWC", "calloc changed_thwc_window fails."); + free(changed_thwc_window); + return false; + } + terror = tdm_hwc_get_changed_composition_types(__thwc, &numChanges, changed_thwc_window, tcomposition_types); + if (terror != TDM_ERROR_NONE) { + DSLOG_ERR("TDM_HWC", "tdm_hwc_get_changed_composition_types fails."); free(tcomposition_types); free(changed_thwc_window); + return false; } - //TODO: tdm_hwc_commit - terror = tdm_hwc_commit(__thwc, 0, NULL, NULL); + for (i = 0; i < (int)numChanges; ++i) { + //TODO: change the TYPES of HWCWindows + } + + free(tcomposition_types); + free(changed_thwc_window); + + return true; +} + +bool DSDisplayDeviceHWCTDMImpl::__acceptValidation() +{ + tdm_error terror; + + // TODO: accept_validation is depending on the transitions. + terror = tdm_hwc_accept_validation(__thwc); if (terror != TDM_ERROR_NONE) { - DSLOG_ERR("TDM_HWC", "tdm_hwc_commit fails."); + DSLOG_ERR("TDM_HWC", "tdm_hwc_accept_validation fails.\n"); return false; } return true; } -} \ No newline at end of file + +} diff --git a/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.h b/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.h index cd266e7..ba1daaf 100644 --- a/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.h +++ b/src/DSDisplayDevice/DSDisplayDeviceHWCTDMImpl.h @@ -2,6 +2,7 @@ #define _DS_DISPLAY_DEVICE_HWC_TDM_IMPL_H_ #include "IDSDisplayDeviceHWC.h" +#include "DSBufferQueueTBMImpl.h" #include #include @@ -13,13 +14,22 @@ public: DSDisplayDeviceHWCTDMImpl(tdm_hwc *thwc); ~DSDisplayDeviceHWCTDMImpl(); - IDSDisplayDeviceHWCWindow *createHWCWindow() override; - void destroyHWCWindow(IDSDisplayDeviceHWCWindow *deviceHWCWindow) override; - bool commit() override; + std::shared_ptr getTargetBufferQueue() override; + bool setTargetBuffer(std::shared_ptr buffer) override; + std::shared_ptr makeHWCWindow() override; + bool addVisibleHWCWindow(std::shared_ptr deviceHWCWindow) override; + bool removeVisibleHWCWindow(std::shared_ptr deviceHWCWindow) override; + void clearVisibleHWCWindows() override; + bool commit() override; private: tdm_hwc *__thwc; - std::list __deviceHWCWindowList; + std::shared_ptr __bufferQueue; + std::list> __visibleDeviceHWCWindowList; + + bool __validate(uint32_t &numChanges); + bool __updateChanges(uint32_t numChanges); + bool __acceptValidation(); }; } diff --git a/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.cpp b/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.cpp index 7fcf260..3fde0ef 100644 --- a/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.cpp +++ b/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.cpp @@ -8,8 +8,10 @@ DSDisplayDeviceHWCWindowTDMImpl::DSDisplayDeviceHWCWindowTDMImpl(tdm_hwc_window : __twindow(twindow) {} DSDisplayDeviceHWCWindowTDMImpl::~DSDisplayDeviceHWCWindowTDMImpl() -{} -tdm_hwc_window *DSDisplayDeviceHWCWindowTDMImpl::getTDMHWCWindow() +{ + tdm_hwc_window_destroy(__twindow); +} +tdm_hwc_window *DSDisplayDeviceHWCWindowTDMImpl::getNativeHWCWindow() { return __twindow; } diff --git a/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.h b/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.h index 43facd9..d4d9bbf 100644 --- a/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.h +++ b/src/DSDisplayDevice/DSDisplayDeviceHWCWindowTDMImpl.h @@ -11,10 +11,11 @@ class DSDisplayDeviceHWCWindowTDMImpl : public IDSDisplayDeviceHWCWindow public: DSDisplayDeviceHWCWindowTDMImpl(tdm_hwc_window *twindow); ~DSDisplayDeviceHWCWindowTDMImpl(); - tdm_hwc_window *getTDMHWCWindow(); + tdm_hwc_window *getNativeHWCWindow(); private: tdm_hwc_window* __twindow; }; + } #endif diff --git a/src/DSDisplayDevice/DSDisplayDeviceOutputTDMImpl.cpp b/src/DSDisplayDevice/DSDisplayDeviceOutputTDMImpl.cpp index bfdb287..ed1e9c9 100644 --- a/src/DSDisplayDevice/DSDisplayDeviceOutputTDMImpl.cpp +++ b/src/DSDisplayDevice/DSDisplayDeviceOutputTDMImpl.cpp @@ -45,7 +45,7 @@ DSDisplayDeviceOutputTDMImpl::DSDisplayDeviceOutputTDMImpl(tdm_output *toutput) __displayDeviceHWC = std::make_shared(thwc); } else { //TODO: need fallback for HWC - DSLOG_WRN("TDM OUTPUT", "tdm_output_get_hwc fails.\n"); + DSLOG_WRN("TDM OUTPUT", "tdm_output_get_hwc fails."); } } diff --git a/src/DSDisplayDevice/DSDisplayDeviceTDMImpl.cpp b/src/DSDisplayDevice/DSDisplayDeviceTDMImpl.cpp index 7dccce7..c950704 100644 --- a/src/DSDisplayDevice/DSDisplayDeviceTDMImpl.cpp +++ b/src/DSDisplayDevice/DSDisplayDeviceTDMImpl.cpp @@ -1,5 +1,6 @@ #include "DSDisplayDeviceTDMImpl.h" #include "DSDisplayDeviceOutputTDMImpl.h" +#include "DSDisplayDeviceHWCTDMImpl.h" #include "DSDebugLog.h" namespace display_server @@ -35,6 +36,17 @@ DSDisplayDeviceTDMImpl::DSDisplayDeviceTDMImpl() DSDisplayDeviceTDMImpl::~DSDisplayDeviceTDMImpl() { + // Clear the visible hwc windows before tdm_display_deinit. + // Otherwise, the process will block inside libtdm + // when it calls tdm_hwc_window_destroy() function at ~DSDisplayDeviceHWCWindowTDMImpl() + // because the mutex_lock(private_display->lock) is destroyed at tdm_display_deinit(). + for (auto displayDeviceOutput: __outputList) { + std::shared_ptr displayDeviceHWC = displayDeviceOutput->getHWC(); + if (displayDeviceHWC) { + displayDeviceHWC->clearVisibleHWCWindows(); + } + } + tdm_display_deinit(__tdisplay); } diff --git a/src/DSDisplayDevice/IDSDisplayDeviceHWC.h b/src/DSDisplayDevice/IDSDisplayDeviceHWC.h index 995ee57..154b4d7 100644 --- a/src/DSDisplayDevice/IDSDisplayDeviceHWC.h +++ b/src/DSDisplayDevice/IDSDisplayDeviceHWC.h @@ -2,18 +2,26 @@ #define _I_DS_DISPLAY_DEVICE_HWC_H_ #include "IDSDisplayDeviceHWCWindow.h" +#include "IDSBufferQueue.h" +#include namespace display_server { + class IDSDisplayDeviceHWC { public: virtual ~IDSDisplayDeviceHWC() = default; - virtual IDSDisplayDeviceHWCWindow *createHWCWindow() = 0; - virtual void destroyHWCWindow(IDSDisplayDeviceHWCWindow *deviceHWCWindow) = 0; - virtual bool commit() = 0; + virtual std::shared_ptr getTargetBufferQueue() = 0; + virtual bool setTargetBuffer(std::shared_ptr buffer) = 0; + virtual std::shared_ptr makeHWCWindow() = 0; + virtual bool addVisibleHWCWindow(std::shared_ptr deviceHWCWindow) = 0; + virtual bool removeVisibleHWCWindow(std::shared_ptr deviceHWCWindow) = 0; + virtual void clearVisibleHWCWindows() = 0; + virtual bool commit() = 0; }; + } #endif diff --git a/tests/DSDisplayDeviceTDMImpl-test.cpp b/tests/DSDisplayDeviceTDMImpl-test.cpp index eb6875c..b8cf18e 100644 --- a/tests/DSDisplayDeviceTDMImpl-test.cpp +++ b/tests/DSDisplayDeviceTDMImpl-test.cpp @@ -223,7 +223,7 @@ TEST_F(DSDisplayDeviceTDMImplTest, DeviceOutput_registerCallbackOutputResolution // DSDisplayDeviceTDMHWC -TEST_F(DSDisplayDeviceTDMImplTest, DeviceOutput_createHWCWindow) +TEST_F(DSDisplayDeviceTDMImplTest, DeviceOutput_makeHWCWindow) { std::unique_ptr displayDevice = std::make_unique(); std::list> outputList = displayDevice->getOutputList(); @@ -232,7 +232,7 @@ TEST_F(DSDisplayDeviceTDMImplTest, DeviceOutput_createHWCWindow) IDSDisplayDeviceOutput::ConnectorType connType; IDSDisplayDeviceOutput::ConnectState connState; std::shared_ptr deviceHWC; - IDSDisplayDeviceHWCWindow *deviceHWCWindow; + std::shared_ptr deviceHWCWindow; for (std::shared_ptr output : outputList) { connType = output->getConnectType(); @@ -244,10 +244,8 @@ TEST_F(DSDisplayDeviceTDMImplTest, DeviceOutput_createHWCWindow) deviceHWC = output->getHWC(); EXPECT_TRUE(deviceHWC != nullptr); - deviceHWCWindow = deviceHWC->createHWCWindow(); + deviceHWCWindow = deviceHWC->makeHWCWindow(); EXPECT_TRUE(deviceHWC != nullptr); - - deviceHWC->destroyHWCWindow(deviceHWCWindow); } } @@ -260,7 +258,7 @@ TEST_F(DSDisplayDeviceTDMImplTest, DeviceHWC_commit) IDSDisplayDeviceOutput::ConnectorType connType; IDSDisplayDeviceOutput::ConnectState connState; std::shared_ptr deviceHWC; - IDSDisplayDeviceHWCWindow *deviceHWCWindow; + std::shared_ptr deviceHWCWindow; for (std::shared_ptr output : outputList) { connType = output->getConnectType(); @@ -269,15 +267,38 @@ TEST_F(DSDisplayDeviceTDMImplTest, DeviceHWC_commit) EXPECT_TRUE(connState <= IDSDisplayDeviceOutput::STATE_MODESET); if (connState == IDSDisplayDeviceOutput::STATE_DISCONNECTED) continue; + DSDisplayDeviceOutputMode *bestMode = nullptr; + for (DSDisplayDeviceOutputMode *mode : output->getAvailableModes()) { + if (bestMode == nullptr) { + bestMode = mode; + continue; + } + + int resSize = mode->hdisplay * mode->vdisplay; + int resSizeBest = bestMode->hdisplay *bestMode->vdisplay; + if (resSize > resSizeBest) { + bestMode = mode; + } + } + EXPECT_TRUE(output->setMode(bestMode) == true); + EXPECT_TRUE(output->getMode() == bestMode); + deviceHWC = output->getHWC(); EXPECT_TRUE(deviceHWC != nullptr); - deviceHWCWindow = deviceHWC->createHWCWindow(); + auto bufferQueue = deviceHWC->getTargetBufferQueue(); EXPECT_TRUE(deviceHWC != nullptr); - // commit - deviceHWC->commit(); + deviceHWCWindow = deviceHWC->makeHWCWindow(); + EXPECT_TRUE(deviceHWC != nullptr); + EXPECT_TRUE(deviceHWC->addVisibleHWCWindow(deviceHWCWindow)); + + auto buffer = bufferQueue->dequeueBuffer(); + EXPECT_TRUE(buffer != nullptr); - deviceHWC->destroyHWCWindow(deviceHWCWindow); + EXPECT_TRUE(deviceHWC->setTargetBuffer(buffer)); + + // commit + EXPECT_TRUE(deviceHWC->commit()); } } \ No newline at end of file