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 : #ifndef XENOLITH_SCENE_DIRECTOR_XLVIEW_H_ 24 : #define XENOLITH_SCENE_DIRECTOR_XLVIEW_H_ 25 : 26 : #include "XLEventHeader.h" 27 : #include "XLCoreFrameEmitter.h" 28 : #include "XLCoreLoop.h" 29 : #include "XLPlatformViewInterface.h" 30 : #include "XLInput.h" 31 : #include "XLDirector.h" 32 : #include "SPThread.h" 33 : 34 : namespace STAPPLER_VERSIONIZED stappler::xenolith { 35 : 36 : class View; 37 : class Director; 38 : 39 : struct ViewInfo { 40 : String name; 41 : String bundleId; 42 : URect rect = URect(0, 0, 1024, 768); 43 : Padding decoration; 44 : uint64_t frameInterval = 0; // in microseconds ( 1'000'000 / 60 for 60 fps) 45 : float density = 0.0f; 46 : Function<core::SwapchainConfig (View &, const core::SurfaceInfo &)> selectConfig; 47 : Function<void(View &, const core::FrameContraints &)> onCreated; 48 : Function<void(View &)> onClosed; 49 : }; 50 : 51 : class View : public thread::ThreadInterface<Interface>, public TextInputViewInterface, public platform::ViewInterface { 52 : public: 53 : static constexpr size_t FrameAverageCount = 20; 54 : 55 : using AttachmentLayout = core::AttachmentLayout; 56 : using ImageStorage = core::ImageStorage; 57 : using FrameEmitter = core::FrameEmitter; 58 : using FrameRequest = core::FrameRequest; 59 : using RenderQueue = core::Queue; 60 : 61 : static EventHeader onFrameRate; 62 : static EventHeader onBackground; 63 : static EventHeader onFocus; 64 : 65 : View(); 66 : virtual ~View(); 67 : 68 : virtual bool init(Application &, ViewInfo &&); 69 : 70 : virtual void run() = 0; 71 : virtual void runWithQueue(const Rc<core::Queue> &) = 0; 72 : virtual void end() override; 73 : 74 : virtual void update(bool displayLink) override; 75 : virtual void close(); 76 : 77 : void performOnThread(Function<void()> &&func, Ref *target = nullptr, bool immediate = false); 78 : 79 : // true - if presentation request accepted, false otherwise, 80 : // frame should not mark image as detached if false is returned 81 : virtual bool present(Rc<ImageStorage> &&) = 0; 82 : 83 : // present image in place instead of scheduling presentation 84 : // should be called in view's thread 85 : virtual bool presentImmediate(Rc<ImageStorage> &&, Function<void(bool)> &&) = 0; 86 : 87 : // invalidate swapchain image target, if drawing process was not successful 88 : virtual void invalidateTarget(Rc<ImageStorage> &&) = 0; 89 : 90 : virtual Rc<Ref> getSwapchainHandle() const = 0; 91 : 92 : virtual void captureImage(StringView, const Rc<core::ImageObject> &image, AttachmentLayout l) const = 0; 93 : virtual void captureImage(Function<void(const core::ImageInfoData &info, BytesView view)> &&, 94 : const Rc<core::ImageObject> &image, AttachmentLayout l) const = 0; 95 : 96 : const Rc<Director> &getDirector() const; 97 : const Rc<Application> &getMainLoop() const { return _mainLoop; } 98 : const Rc<core::Loop> &getGlLoop() const { return _glLoop; } 99 : 100 : // update screen extent, non thread-safe 101 : // only updates field, view is not resized 102 : 103 : // handle and propagate input event 104 : virtual void handleInputEvent(const InputEventData &) override; 105 : virtual void handleInputEvents(Vector<InputEventData> &&) override; 106 : 107 : virtual core::ImageInfo getSwapchainImageInfo() const; 108 : virtual core::ImageInfo getSwapchainImageInfo(const core::SwapchainConfig &cfg) const; 109 : virtual core::ImageViewInfo getSwapchainImageViewInfo(const core::ImageInfo &image) const; 110 : 111 : // interval between two frame presented 112 : uint64_t getLastFrameInterval() const; 113 : uint64_t getAvgFrameInterval() const; 114 : 115 : // time between frame stared and last queue submission completed 116 : uint64_t getLastFrameTime() const; 117 : uint64_t getAvgFrameTime() const; 118 : 119 : uint64_t getAvgFenceTime() const; 120 : 121 : const core::FrameContraints & getFrameContraints() const { return _constraints; } 122 0 : virtual Extent2 getExtent() const override { return Extent2(_constraints.extent.width, _constraints.extent.height); } 123 : 124 : bool hasFocus() const { return _hasFocus; } 125 : bool isInBackground() const { return _inBackground; } 126 : bool isPointerWithinWindow() const { return _pointerInWindow; } 127 : 128 : uint64_t getFrameInterval() const; 129 : void setFrameInterval(uint64_t); 130 : 131 : virtual void setReadyForNextFrame() override; 132 : 133 : virtual void setRenderOnDemand(bool value); 134 : virtual bool isRenderOnDemand() const; 135 : 136 : virtual void retainBackButton(); 137 : virtual void releaseBackButton(); 138 0 : virtual uint64_t getBackButtonCounter() const override { return _backButtonCounter; } 139 : 140 : virtual void setDecorationTone(float); // 0.0 - 1.0 141 : virtual void setDecorationVisible(bool); 142 : 143 : virtual uint64_t retainView() override; 144 : virtual void releaseView(uint64_t) override; 145 : 146 : virtual void setContentPadding(const Padding &) override; 147 : 148 : protected: 149 : virtual void wakeup(std::unique_lock<Mutex> &) = 0; 150 : 151 : core::FrameContraints _constraints; 152 : 153 : bool _inBackground = false; 154 : bool _hasFocus = true; 155 : bool _pointerInWindow = false; 156 : bool _threadStarted = false; 157 : bool _navigationEmpty = true; 158 : 159 : std::atomic<bool> _init = false; 160 : std::atomic<bool> _running = false; 161 : 162 : Rc<Director> _director; 163 : Rc<Application> _mainLoop; 164 : Rc<core::Loop> _glLoop; 165 : Rc<core::FrameEmitter> _frameEmitter; 166 : 167 : ViewInfo _info; 168 : 169 : uint64_t _gen = 1; 170 : core::SwapchainConfig _config; 171 : 172 : std::thread _thread; 173 : std::thread::id _threadId; 174 : std::atomic_flag _shouldQuit; 175 : Mutex _mutex; 176 : Vector<Pair<Function<void()>, Rc<Ref>>> _callbacks; 177 : 178 : mutable Mutex _frameIntervalMutex; 179 : uint64_t _lastFrameStart = 0; 180 : std::atomic<uint64_t> _lastFrameInterval = 0; 181 : math::MovingAverage<FrameAverageCount, uint64_t> _avgFrameInterval; 182 : std::atomic<uint64_t> _avgFrameIntervalValue = 0; 183 : uint64_t _backButtonCounter = 0; 184 : }; 185 : 186 : } 187 : 188 : #endif /* XENOLITH_SCENE_DIRECTOR_XLVIEW_H_ */