LCOV - code coverage report
Current view: top level - xenolith/scene/director - XLDirector.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 150 162 92.6 %
Date: 2024-05-12 00:16:13 Functions: 27 28 96.4 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2020-2022 Roman Katuntsev <sbkarr@stappler.org>
       3             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       6             :  of this software and associated documentation files (the "Software"), to deal
       7             :  in the Software without restriction, including without limitation the rights
       8             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             :  copies of the Software, and to permit persons to whom the Software is
      10             :  furnished to do so, subject to the following conditions:
      11             : 
      12             :  The above copyright notice and this permission notice shall be included in
      13             :  all copies or substantial portions of the Software.
      14             : 
      15             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             :  THE SOFTWARE.
      22             :  **/
      23             : 
      24             : #include "XLDirector.h"
      25             : 
      26             : #include "XLResourceCache.h"
      27             : #include "XLScheduler.h"
      28             : #include "XLScene.h"
      29             : #include "XLInputDispatcher.h"
      30             : #include "XLTextInputManager.h"
      31             : #include "XLActionManager.h"
      32             : #include "XLCoreLoop.h"
      33             : #include "XLCoreFrameRequest.h"
      34             : #include "XLView.h"
      35             : 
      36             : namespace STAPPLER_VERSIONIZED stappler::xenolith {
      37             : 
      38          21 : Director::Director() {
      39          21 :         memset(&_drawStat, 0, sizeof(DrawStat));
      40          21 : }
      41             : 
      42          42 : Director::~Director() { }
      43             : 
      44          21 : bool Director::init(Application *main, const core::FrameContraints &constraints, View *view) {
      45          21 :         _mainLoop = main;
      46          21 :         _view = view;
      47          21 :         _pool = Rc<PoolRef>::alloc();
      48          21 :         _pool->perform([&, this] {
      49          21 :                 _scheduler = Rc<Scheduler>::create();
      50          21 :                 _actionManager = Rc<ActionManager>::create();
      51          21 :                 _inputDispatcher = Rc<InputDispatcher>::create(_pool, view);
      52          21 :         });
      53          21 :         _startTime = _mainLoop->getClock();
      54          21 :         _time.global = 0;
      55          21 :         _time.app = 0;
      56          21 :         _time.delta = 0;
      57             : 
      58          21 :         _constraints = constraints;
      59             : 
      60          21 :         updateGeneralTransform();
      61             : 
      62          21 :         return true;
      63             : }
      64             : 
      65         105 : TextInputManager *Director::getTextInputManager() const {
      66         105 :         return _inputDispatcher->getTextInputManager();
      67             : }
      68             : 
      69       47023 : const Rc<ResourceCache> &Director::getResourceCache() const {
      70       47023 :         return _mainLoop->getResourceCache();
      71             : }
      72             : 
      73        9538 : bool Director::acquireFrame(const Rc<FrameRequest> &req) {
      74        9538 :         if (!_scene) {
      75           0 :                 return false;
      76             :         }
      77             : 
      78        9538 :         auto t = _mainLoop->getClock();
      79             : 
      80        9538 :         setFrameConstraints(req->getFrameConstraints());
      81             : 
      82        9538 :         update(t);
      83        9538 :         if (_scene) {
      84        9538 :                 req->setQueue(_scene->getQueue());
      85             :         }
      86             : 
      87        9538 :         _mainLoop->performOnMainThread([this, req] {
      88        9538 :                 if (!_scene) {
      89           0 :                         return;
      90             :                 }
      91             : 
      92        9538 :                 req->getPool()->perform([&, this] {
      93        9538 :                         _scene->renderRequest(req);
      94             : 
      95        9538 :                         if (hasActiveInteractions()) {
      96        9538 :                                 _view->setReadyForNextFrame();
      97             :                         }
      98        9538 :                 });
      99             :         }, this, true);
     100             : 
     101        9538 :         _avgFrameTime.addValue(_mainLoop->getClock() - t);
     102        9538 :         _avgFrameTimeValue = _avgFrameTime.getAverage();
     103        9538 :         return true;
     104             : }
     105             : 
     106        9538 : void Director::update(uint64_t t) {
     107        9538 :         if (_time.global) {
     108        9517 :                 _time.delta = t - _time.global;
     109             :         } else {
     110          21 :                 _time.delta = 0;
     111             :         }
     112             : 
     113        9538 :         _time.global = t;
     114        9538 :         _time.app = t - _startTime;
     115             : 
     116             :     // If we are debugging our code, prevent big delta time
     117        9538 :     if (_time.delta && _time.delta > config::MaxDirectorDeltaTime) {
     118           0 :         _time.delta = config::MaxDirectorDeltaTime;
     119             :     }
     120             : 
     121        9538 :     _time.dt = float(_time.delta) / 1'000'000;
     122             : 
     123        9538 :         if (_nextScene) {
     124           0 :                 if (_scene) {
     125           0 :                         _scene->onFinished(this);
     126             :                 }
     127           0 :                 _scene = _nextScene;
     128             : 
     129           0 :                 _scene->setFrameConstraints(_constraints);
     130           0 :                 _scene->onPresented(this);
     131           0 :                 _nextScene = nullptr;
     132             :         }
     133             : 
     134        9538 :         _inputDispatcher->update(_time);
     135        9538 :         _scheduler->update(_time);
     136        9538 :         _actionManager->update(_time);
     137             : 
     138        9538 :         _mainLoop->getResourceCache()->update(_time);
     139             : 
     140        9538 :         _autorelease.clear();
     141        9538 : }
     142             : 
     143          21 : void Director::end() {
     144             : #if SP_REF_DEBUG
     145             :         if (_scene) {
     146             :                 _scene->onFinished(this);
     147             :         }
     148             :         _autorelease.clear();
     149             : 
     150             :         if (_scene) {
     151             :                 if (_scene->getReferenceCount() > 1) {
     152             :                         auto scene = _scene.get();
     153             :                         _scene = nullptr;
     154             : 
     155             :                         scene->foreachBacktrace([] (uint64_t id, Time time, const std::vector<std::string> &vec) {
     156             :                                 StringStream stream;
     157             :                                 stream << "[" << id << ":" << time.toHttp<Interface>() << "]:\n";
     158             :                                 for (auto &it : vec) {
     159             :                                         stream << "\t" << it << "\n";
     160             :                                 }
     161             :                                 log::debug("Director", stream.str());
     162             :                         });
     163             :                 } else {
     164             :                         _scene = nullptr;
     165             :                 }
     166             :         }
     167             : 
     168             :         if (core::FrameHandle::GetActiveFramesCount()) {
     169             :                 core::FrameHandle::DescribeActiveFrames();
     170             :         }
     171             : #else
     172          21 :         if (_scene) {
     173          21 :                 _scene->onFinished(this);
     174          21 :                 _scene = nullptr;
     175             :         }
     176             : 
     177          21 :         if (!_scheduler->empty()) {
     178          21 :                 _scheduler->unscheduleAll();
     179             :         }
     180             : 
     181          21 :         _nextScene = nullptr;
     182          21 :         _autorelease.clear();
     183             : #endif
     184          21 : }
     185             : 
     186       19245 : core::Loop *Director::getGlLoop() const {
     187       19245 :         return _mainLoop->getGlLoop();
     188             : }
     189             : 
     190        9706 : void Director::setFrameConstraints(const core::FrameContraints &c) {
     191        9706 :         if (_constraints != c) {
     192         168 :                 _constraints = c;
     193         168 :                 if (_scene) {
     194         168 :                         _scene->setFrameConstraints(_constraints);
     195             :                 }
     196             : 
     197         168 :                 updateGeneralTransform();
     198             :         }
     199        9706 : }
     200             : 
     201          21 : void Director::runScene(Rc<Scene> &&scene) {
     202          21 :         if (!scene) {
     203           0 :                 return;
     204             :         }
     205             : 
     206          21 :         log::debug("Director", "runScene");
     207             : 
     208          21 :         auto linkId = retain();
     209          21 :         auto &queue = scene->getQueue();
     210          21 :         getGlLoop()->compileQueue(queue, [this, scene = move(scene), linkId, view = Rc<View>(_view)] (bool success) mutable {
     211          21 :                 if (success) {
     212          21 :                         _mainLoop->performOnMainThread([this, scene = move(scene), view] {
     213          21 :                                 _nextScene = scene;
     214          21 :                                 if (!_scene) {
     215          21 :                                         _scene = _nextScene;
     216          21 :                                         _nextScene = nullptr;
     217          21 :                                         _scene->setFrameConstraints(_constraints);
     218          21 :                                         updateGeneralTransform();
     219          21 :                                         _scene->onPresented(this);
     220          21 :                                         getGlLoop()->performOnGlThread([view, scene = _scene] {
     221          21 :                                                 auto &q = scene->getQueue();
     222          21 :                                                 view->runWithQueue(q);
     223          21 :                                         }, this);
     224             :                                 }
     225          21 :                         }, this);
     226             :                 }
     227          21 :                 release(linkId);
     228          21 :         });
     229             : }
     230             : 
     231        9518 : void Director::pushDrawStat(const DrawStat &stat) {
     232        9518 :         _mainLoop->performOnMainThread([this, stat] {
     233        9518 :                 _drawStat = stat;
     234        9518 :         }, this);
     235        9518 : }
     236             : 
     237          42 : float Director::getFps() const {
     238          42 :         return 1.0f / (_view->getLastFrameInterval() / 1000000.0f);
     239             : }
     240             : 
     241        9538 : float Director::getAvgFps() const {
     242        9538 :         return 1.0f / (_view->getAvgFrameInterval() / 1000000.0f);
     243             : }
     244             : 
     245        9538 : float Director::getSpf() const {
     246        9538 :         return _view->getLastFrameTime() / 1000.0f;
     247             : }
     248             : 
     249        9538 : float Director::getLocalFrameTime() const {
     250        9538 :         return _view->getAvgFenceTime() / 1000.0f;
     251             : }
     252             : 
     253       86279 : void Director::autorelease(Ref *ref) {
     254       86279 :         _autorelease.emplace_back(ref);
     255       86279 : }
     256             : 
     257           0 : void Director::invalidate() {
     258             : 
     259           0 : }
     260             : 
     261         210 : void Director::updateGeneralTransform() {
     262         210 :         auto transform = core::getPureTransform(_constraints.transform);
     263             : 
     264         210 :         Mat4 proj;
     265         210 :         switch (transform) {
     266          21 :         case core::SurfaceTransformFlags::Rotate90: proj = Mat4::ROTATION_Z_90; break;
     267          21 :         case core::SurfaceTransformFlags::Rotate180: proj = Mat4::ROTATION_Z_180; break;
     268          21 :         case core::SurfaceTransformFlags::Rotate270: proj = Mat4::ROTATION_Z_270; break;
     269          21 :         case core::SurfaceTransformFlags::Mirror: break;
     270          21 :         case core::SurfaceTransformFlags::MirrorRotate90: break;
     271          21 :         case core::SurfaceTransformFlags::MirrorRotate180: break;
     272          21 :         case core::SurfaceTransformFlags::MirrorRotate270: break;
     273          63 :         default: proj = Mat4::IDENTITY; break;
     274             :         }
     275             : 
     276         210 :         if ((_constraints.transform & core::SurfaceTransformFlags::PreRotated) != core::SurfaceTransformFlags::None) {
     277         147 :                 switch (transform) {
     278          84 :                 case core::SurfaceTransformFlags::Rotate90:
     279             :                 case core::SurfaceTransformFlags::Rotate270:
     280             :                 case core::SurfaceTransformFlags::MirrorRotate90:
     281             :                 case core::SurfaceTransformFlags::MirrorRotate270:
     282          84 :                         proj.scale(2.0f / _constraints.extent.height, -2.0f / _constraints.extent.width, -1.0);
     283          84 :                         break;
     284          63 :                 default:
     285          63 :                         proj.scale(2.0f / _constraints.extent.width, -2.0f / _constraints.extent.height, -1.0);
     286          63 :                         break;
     287             :                 }
     288             :         } else {
     289          63 :                 proj.scale(2.0f / _constraints.extent.width, -2.0f / _constraints.extent.height, -1.0);
     290             :         }
     291         210 :         proj.m[12] = -1.0;
     292         210 :         proj.m[13] = 1.0f;
     293         210 :         proj.m[14] = 0.0f;
     294         210 :         proj.m[15] = 1.0f;
     295             : 
     296         210 :         switch (transform) {
     297          21 :         case core::SurfaceTransformFlags::Rotate90: proj.m[13] = -1.0f; break;
     298          21 :         case core::SurfaceTransformFlags::Rotate180: proj.m[12] = 1.0f; proj.m[13] = -1.0f; break;
     299          21 :         case core::SurfaceTransformFlags::Rotate270: proj.m[12] = 1.0f; break;
     300          21 :         case core::SurfaceTransformFlags::Mirror: break;
     301          21 :         case core::SurfaceTransformFlags::MirrorRotate90: break;
     302          21 :         case core::SurfaceTransformFlags::MirrorRotate180: break;
     303          21 :         case core::SurfaceTransformFlags::MirrorRotate270: break;
     304          63 :         default: break;
     305             :         }
     306             : 
     307         210 :         _generalProjection = proj;
     308         210 : }
     309             : 
     310        9538 : bool Director::hasActiveInteractions() {
     311        9538 :         return !_actionManager->empty() || _inputDispatcher->hasActiveInput();
     312             : }
     313             : 
     314             : }

Generated by: LCOV version 1.14