LCOV - code coverage report
Current view: top level - xenolith/scene/director - XLView.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 164 164 100.0 %
Date: 2024-05-12 00:16:13 Functions: 33 34 97.1 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "XLView.h"
      24             : #include "XLInputDispatcher.h"
      25             : 
      26             : namespace STAPPLER_VERSIONIZED stappler::xenolith {
      27             : 
      28             : XL_DECLARE_EVENT_CLASS(View, onFrameRate);
      29             : XL_DECLARE_EVENT_CLASS(View, onBackground);
      30             : XL_DECLARE_EVENT_CLASS(View, onFocus);
      31             : 
      32          21 : View::View() { }
      33             : 
      34          21 : View::~View() {
      35          21 :         log::debug("xenolith::View", "~View");
      36          21 : }
      37             : 
      38          21 : bool View::init(Application &loop, ViewInfo &&info) {
      39          21 :         _mainLoop = &loop;
      40          21 :         _glLoop = _mainLoop->getGlLoop();
      41          21 :         _constraints.extent = Extent2(info.rect.width, info.rect.height);
      42          21 :         _constraints.density = 1.0f;
      43          21 :         if (info.density != 0.0f) {
      44          21 :                 _constraints.density = info.density;
      45             :         }
      46          21 :         _constraints.contentPadding = info.decoration;
      47          21 :         _frameEmitter = Rc<FrameEmitter>::create(_glLoop, info.frameInterval);
      48          21 :         _info = move(info);
      49             : 
      50          21 :         log::debug("View", "init");
      51             : 
      52          21 :         return true;
      53             : }
      54             : 
      55          21 : void View::end() {
      56          21 :         _running = false;
      57          21 :         _frameEmitter->invalidate();
      58          21 :         _mainLoop->performOnMainThread([this, cb = move(_info.onClosed)] () {
      59          21 :                 if (_director) {
      60          21 :                         _director->end();
      61             :                 }
      62          21 :                 cb(*this);
      63          21 :         }, this);
      64          21 : }
      65             : 
      66      428776 : void View::update(bool displayLink) {
      67      428776 :         Vector<Pair<Function<void()>, Rc<Ref>>> callback;
      68             : 
      69      428776 :         _mutex.lock();
      70      428776 :         callback = move(_callbacks);
      71      428776 :         _callbacks.clear();
      72      428776 :         _mutex.unlock();
      73             : 
      74      469645 :         for (auto &it : callback) {
      75       40869 :                 it.first();
      76             :         }
      77      428776 : }
      78             : 
      79          21 : void View::close() {
      80          21 :         _shouldQuit.clear();
      81          21 : }
      82             : 
      83       51748 : void View::performOnThread(Function<void()> &&func, Ref *target, bool immediate) {
      84       51748 :         if (immediate && std::this_thread::get_id() == _threadId) {
      85       10791 :                 func();
      86             :         } else {
      87       40957 :                 std::unique_lock<Mutex> lock(_mutex);
      88       40957 :                 if (_running) {
      89       40723 :                         _callbacks.emplace_back(move(func), target);
      90       40723 :                         wakeup(lock);
      91         234 :                 } else if (!_init) {
      92         147 :                         _callbacks.emplace_back(move(func), target);
      93             :                 }
      94       40957 :         }
      95       51748 : }
      96             : 
      97          21 : const Rc<Director> &View::getDirector() const {
      98          21 :         return _director;
      99             : }
     100             : 
     101         363 : void View::handleInputEvent(const InputEventData &event) {
     102         363 :         _mainLoop->performOnMainThread([this, event = event] () mutable {
     103         363 :                 if (event.isPointEvent()) {
     104         300 :                         event.point.density = _constraints.density;
     105             :                 }
     106             : 
     107         363 :                 switch (event.event) {
     108          21 :                 case InputEventName::Background:
     109          21 :                         _inBackground = event.getValue();
     110          21 :                         onBackground(this, _inBackground);
     111          21 :                         break;
     112          21 :                 case InputEventName::PointerEnter:
     113          21 :                         _pointerInWindow = event.getValue();
     114          21 :                         break;
     115          21 :                 case InputEventName::FocusGain:
     116          21 :                         _hasFocus = event.getValue();
     117          21 :                         onFocus(this, _hasFocus);
     118          21 :                         break;
     119         300 :                 default:
     120         300 :                         break;
     121             :                 }
     122         363 :                 _director->getInputDispatcher()->handleInputEvent(event);
     123         363 :         }, this);
     124         363 :         setReadyForNextFrame();
     125         363 : }
     126             : 
     127        2708 : void View::handleInputEvents(Vector<InputEventData> &&events) {
     128        2708 :         _mainLoop->performOnMainThread([this, events = move(events)] () mutable {
     129        7006 :                 for (auto &event : events) {
     130        4298 :                         if (event.isPointEvent()) {
     131        2850 :                                 event.point.density = _constraints.density;
     132             :                         }
     133             : 
     134        4298 :                         switch (event.event) {
     135          21 :                         case InputEventName::Background:
     136          21 :                                 _inBackground = event.getValue();
     137          21 :                                 onBackground(this, _inBackground);
     138          21 :                                 break;
     139          37 :                         case InputEventName::PointerEnter:
     140          37 :                                 _pointerInWindow = event.getValue();
     141          37 :                                 break;
     142          46 :                         case InputEventName::FocusGain:
     143          46 :                                 _hasFocus = event.getValue();
     144          46 :                                 onFocus(this, _hasFocus);
     145          46 :                                 break;
     146        4194 :                         default:
     147        4194 :                                 break;
     148             :                         }
     149        4298 :                         _director->getInputDispatcher()->handleInputEvent(event);
     150             :                 }
     151        2708 :         }, this, true);
     152        2708 :         setReadyForNextFrame();
     153        2708 : }
     154             : 
     155          21 : core::ImageInfo View::getSwapchainImageInfo() const {
     156          21 :         return getSwapchainImageInfo(_config);
     157             : }
     158             : 
     159          63 : core::ImageInfo View::getSwapchainImageInfo(const core::SwapchainConfig &cfg) const {
     160          63 :         core::ImageInfo swapchainImageInfo;
     161          63 :         swapchainImageInfo.format = cfg.imageFormat;
     162          63 :         swapchainImageInfo.flags = core::ImageFlags::None;
     163          63 :         swapchainImageInfo.imageType = core::ImageType::Image2D;
     164          63 :         swapchainImageInfo.extent = Extent3(cfg.extent.width, cfg.extent.height, 1);
     165          63 :         swapchainImageInfo.arrayLayers = core::ArrayLayers( 1 );
     166          63 :         swapchainImageInfo.usage = core::ImageUsage::ColorAttachment;
     167          63 :         if (cfg.transfer) {
     168          63 :                 swapchainImageInfo.usage |= core::ImageUsage::TransferDst;
     169             :         }
     170          63 :         return swapchainImageInfo;
     171             : }
     172             : 
     173          63 : core::ImageViewInfo View::getSwapchainImageViewInfo(const core::ImageInfo &image) const {
     174          63 :         core::ImageViewInfo info;
     175          63 :         switch (image.imageType) {
     176          21 :         case core::ImageType::Image1D:
     177          21 :                 info.type = core::ImageViewType::ImageView1D;
     178          21 :                 break;
     179          21 :         case core::ImageType::Image2D:
     180          21 :                 info.type = core::ImageViewType::ImageView2D;
     181          21 :                 break;
     182          21 :         case core::ImageType::Image3D:
     183          21 :                 info.type = core::ImageViewType::ImageView3D;
     184          21 :                 break;
     185             :         }
     186             : 
     187         126 :         return image.getViewInfo(info);
     188             : }
     189             : 
     190          42 : uint64_t View::getLastFrameInterval() const {
     191          42 :         return _lastFrameInterval;
     192             : }
     193        9559 : uint64_t View::getAvgFrameInterval() const {
     194        9559 :         return _avgFrameIntervalValue;
     195             : }
     196             : 
     197        9538 : uint64_t View::getLastFrameTime() const {
     198        9538 :         return _frameEmitter->getLastFrameTime();
     199             : }
     200          21 : uint64_t View::getAvgFrameTime() const {
     201          21 :         return _frameEmitter->getAvgFrameTime();
     202             : }
     203             : 
     204        9538 : uint64_t View::getAvgFenceTime() const {
     205        9538 :         return _frameEmitter->getAvgFenceTime();
     206             : }
     207             : 
     208             : SP_COVERAGE_TRIVIAL
     209             : Extent2 View::getExtent() const {
     210             :         return Extent2(_constraints.extent.width, _constraints.extent.height);
     211             : }
     212             : 
     213          21 : uint64_t View::getFrameInterval() const {
     214          21 :         std::unique_lock<Mutex> lock(_frameIntervalMutex);
     215          21 :         return _info.frameInterval;
     216          21 : }
     217             : 
     218          21 : void View::setFrameInterval(uint64_t value) {
     219          21 :         performOnThread([this, value] {
     220          21 :                 std::unique_lock<Mutex> lock(_frameIntervalMutex);
     221          21 :                 _info.frameInterval = value;
     222          21 :                 _frameEmitter->setFrameInterval(value);
     223          21 :                 onFrameRate(this, int64_t(_info.frameInterval));
     224          21 :         }, this, true);
     225          21 : }
     226             : 
     227             : SP_COVERAGE_TRIVIAL
     228             : void View::setReadyForNextFrame() {
     229             : 
     230             : }
     231             : 
     232             : SP_COVERAGE_TRIVIAL
     233             : void View::setRenderOnDemand(bool value) {
     234             : 
     235             : }
     236             : 
     237             : SP_COVERAGE_TRIVIAL
     238             : bool View::isRenderOnDemand() const {
     239             :         return true;
     240             : }
     241             : 
     242          42 : void View::retainBackButton() {
     243          42 :         performOnThread([this] {
     244          42 :                 ++ _backButtonCounter;
     245          42 :         }, this, true);
     246          42 : }
     247             : 
     248          42 : void View::releaseBackButton() {
     249          42 :         performOnThread([this] {
     250          21 :                 -- _backButtonCounter;
     251          21 :         }, this, true);
     252          42 : }
     253             : 
     254          21 : uint64_t View::getBackButtonCounter() const {
     255          21 :         return _backButtonCounter;
     256             : }
     257             : 
     258         969 : void View::setDecorationTone(float) {
     259             : 
     260         969 : }
     261             : 
     262         105 : void View::setDecorationVisible(bool) {
     263             : 
     264         105 : }
     265             : 
     266          21 : uint64_t View::retainView() {
     267          21 :         return retain();
     268             : }
     269             : 
     270          21 : void View::releaseView(uint64_t id) {
     271          21 :         release(id);
     272          21 : }
     273             : 
     274             : SP_COVERAGE_TRIVIAL
     275             : void View::setContentPadding(const Padding &padding) {
     276             :         _constraints.contentPadding = padding;
     277             :         setReadyForNextFrame();
     278             : }
     279             : 
     280             : }

Generated by: LCOV version 1.14