|
| 1 | +diff --git a/src/wpeframework/display.cpp b/src/wpeframework/display.cpp |
| 2 | +index e833bc3..a59e8f4 100644 |
| 3 | +--- a/src/wpeframework/display.cpp |
| 4 | ++++ b/src/wpeframework/display.cpp |
| 5 | +@@ -31,50 +31,6 @@ |
| 6 | + |
| 7 | + namespace WPEFramework { |
| 8 | + |
| 9 | +-// ----------------------------------------------------------------------------------------- |
| 10 | +-// GLIB framework thread, to keep the wayland loop a-live |
| 11 | +-// ----------------------------------------------------------------------------------------- |
| 12 | +-class EventSource { |
| 13 | +-public: |
| 14 | +- static GSourceFuncs sourceFuncs; |
| 15 | +- |
| 16 | +- GSource source; |
| 17 | +- GPollFD pfd; |
| 18 | +- Compositor::IDisplay* display; |
| 19 | +- signed int result; |
| 20 | +-}; |
| 21 | +- |
| 22 | +-GSourceFuncs EventSource::sourceFuncs = { |
| 23 | +- // prepare |
| 24 | +- [](GSource* base, gint* timeout) -> gboolean { |
| 25 | +- *timeout = -1; |
| 26 | +- return FALSE; |
| 27 | +- }, |
| 28 | +- // check |
| 29 | +- [](GSource* base) -> gboolean { |
| 30 | +- EventSource& source(*(reinterpret_cast<EventSource*>(base))); |
| 31 | +- |
| 32 | +- source.result = source.display->Process(source.pfd.revents & G_IO_IN); |
| 33 | +- |
| 34 | +- return (source.result >= 0 ? TRUE : FALSE); |
| 35 | +- }, |
| 36 | +- // dispatch |
| 37 | +- [](GSource* base, GSourceFunc, gpointer) -> gboolean { |
| 38 | +- EventSource& source(*(reinterpret_cast<EventSource*>(base))); |
| 39 | +- |
| 40 | +- if ((source.result == 1) || (source.pfd.revents & (G_IO_ERR | G_IO_HUP))) { |
| 41 | +- fprintf(stderr, "Compositor::Display: error in compositor dispatch\n"); |
| 42 | +- return G_SOURCE_REMOVE; |
| 43 | +- } |
| 44 | +- |
| 45 | +- source.pfd.revents = 0; |
| 46 | +- return G_SOURCE_CONTINUE; |
| 47 | +- }, |
| 48 | +- nullptr, // finalize |
| 49 | +- nullptr, // closure_callback |
| 50 | +- nullptr, // closure_marshall |
| 51 | +-}; |
| 52 | +- |
| 53 | + namespace { |
| 54 | + inline uint32_t TimeNow() |
| 55 | + { |
| 56 | +@@ -224,7 +180,6 @@ void KeyboardHandler::HandleKeyEvent(const uint32_t key, const IKeyboard::state |
| 57 | + // ----------------------------------------------------------------------------------------- |
| 58 | + Display::Display(IPC::Client& ipc, const std::string& name) |
| 59 | + : m_ipc(ipc) |
| 60 | +- , m_eventSource(g_source_new(&EventSource::sourceFuncs, sizeof(EventSource))) |
| 61 | + , m_keyboard(this) |
| 62 | + , m_wheel(this) |
| 63 | + , m_pointer(this) |
| 64 | +@@ -232,21 +187,49 @@ Display::Display(IPC::Client& ipc, const std::string& name) |
| 65 | + , m_backend(nullptr) |
| 66 | + , m_display(Compositor::IDisplay::Instance(name)) |
| 67 | + { |
| 68 | +- int descriptor = m_display->FileDescriptor(); |
| 69 | +- EventSource* source(reinterpret_cast<EventSource*>(m_eventSource)); |
| 70 | +- |
| 71 | +- if (descriptor != -1) { |
| 72 | +- source->display = m_display; |
| 73 | +- source->pfd.fd = descriptor; |
| 74 | +- source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP; |
| 75 | +- source->pfd.revents = 0; |
| 76 | +- |
| 77 | +- g_source_add_poll(m_eventSource, &source->pfd); |
| 78 | +- g_source_set_name(m_eventSource, "[WPE] Display"); |
| 79 | +- g_source_set_priority(m_eventSource, G_PRIORITY_DEFAULT); |
| 80 | +- g_source_set_can_recurse(m_eventSource, TRUE); |
| 81 | +- g_source_attach(m_eventSource, g_main_context_get_thread_default()); |
| 82 | ++} |
| 83 | ++ |
| 84 | ++static constexpr gint FD_TIMEOUT () { |
| 85 | ++ // Milliseconds |
| 86 | ++ // -1, infinite |
| 87 | ++ // 0, immediate |
| 88 | ++ |
| 89 | ++ return 0; |
| 90 | ++} |
| 91 | ++ |
| 92 | ++bool Display::vSyncCallback () { |
| 93 | ++ static_assert (std::is_integral < gint >::value); |
| 94 | ++ static_assert (std::is_integral < decltype (m_display->FileDescriptor ()) >::value); |
| 95 | ++ static_assert (std::numeric_limits < gint >::min () >= std::numeric_limits < decltype (m_display->FileDescriptor ()) >::min ()); |
| 96 | ++ static_assert (std::numeric_limits < gint >::max () <= std::numeric_limits < decltype (m_display->FileDescriptor ()) >::max ()); |
| 97 | ++ |
| 98 | ++ static gint _fd = m_display->FileDescriptor (); |
| 99 | ++ |
| 100 | ++ gushort _flags = 0; |
| 101 | ++ |
| 102 | ++ if (_fd != -1) { |
| 103 | ++ // Watchh for data to read, errors or broken connection |
| 104 | ++ GPollFD _gfd = {_fd, /* events to poll */ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, /* resulting events of poll */ _flags}; |
| 105 | ++ |
| 106 | ++ switch (g_poll (&_gfd, /* number of entries */ 1, /* timeout */ FD_TIMEOUT ())) { |
| 107 | ++ case -1 : // Error |
| 108 | ++ case 0 : // Timed out, always for timeout equal 0 |
| 109 | ++ _flags = 0; |
| 110 | ++ break; |
| 111 | ++ default : // Return value should match g_poll's second field |
| 112 | ++ // Signal there is data to read |
| 113 | ++ _flags = _gfd.revents & (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL); |
| 114 | ++ } |
| 115 | + } |
| 116 | ++ |
| 117 | ++ static_assert (std::is_integral < decltype (_flags) >::value); |
| 118 | ++ static_assert (std::numeric_limits < decltype (_flags) >::min () >= std::numeric_limits < uint32_t >::min ()); |
| 119 | ++ static_assert (std::numeric_limits < decltype (_flags) >::max () <= std::numeric_limits < uint32_t >::max ()); |
| 120 | ++ |
| 121 | ++ // If the loop 'runs' too fast check the implementation of Process |
| 122 | ++ // You may want to add a delay based on the underlying platform just there |
| 123 | ++ |
| 124 | ++ return (m_display != nullptr ? 0 == m_display->Process (_flags) : false); |
| 125 | + } |
| 126 | + |
| 127 | + Display::~Display() |
| 128 | +diff --git a/src/wpeframework/display.h b/src/wpeframework/display.h |
| 129 | +index 8b4fcd0..024bc66 100644 |
| 130 | +--- a/src/wpeframework/display.h |
| 131 | ++++ b/src/wpeframework/display.h |
| 132 | +@@ -225,7 +225,10 @@ public: |
| 133 | + void SendEvent(wpe_input_touch_event& event); |
| 134 | + void SendEvent(wpe_input_touch_event_raw& event); |
| 135 | + |
| 136 | ++ bool vSyncCallback (); |
| 137 | ++ |
| 138 | + private: |
| 139 | ++ |
| 140 | + virtual void Key(const bool pressed, uint32_t keycode, uint32_t unicode, uint32_t modifiers, uint32_t time) override; |
| 141 | + virtual void Key(const uint32_t key, const Compositor::IDisplay::IKeyboard::state action); |
| 142 | + virtual void WheelMotion(const int16_t horizontal, const int16_t vertical) override; |
| 143 | +@@ -235,7 +238,6 @@ private: |
| 144 | + |
| 145 | + private: |
| 146 | + IPC::Client& m_ipc; |
| 147 | +- GSource* m_eventSource; |
| 148 | + KeyboardHandler m_keyboard; |
| 149 | + WheelHandler m_wheel; |
| 150 | + PointerHandler m_pointer; |
| 151 | +diff --git a/src/wpeframework/renderer-backend.cpp b/src/wpeframework/renderer-backend.cpp |
| 152 | +index 88082fc..5570908 100644 |
| 153 | +--- a/src/wpeframework/renderer-backend.cpp |
| 154 | ++++ b/src/wpeframework/renderer-backend.cpp |
| 155 | +@@ -185,6 +185,12 @@ struct wpe_renderer_backend_egl_target_interface wpeframework_renderer_backend_e |
| 156 | + { |
| 157 | + WPEFramework::EGLTarget& target (*static_cast<WPEFramework::EGLTarget*>(data)); |
| 158 | + |
| 159 | ++ /* bool */ target.display.vSyncCallback (); |
| 160 | ++ |
| 161 | ++ // The message has to be sent regardless of the vSyncCallback result. |
| 162 | ++ // Otherwise, the 'frame complete' is never sent, possibly breaking |
| 163 | ++ // the feedback loop. |
| 164 | ++ |
| 165 | + IPC::Message message; |
| 166 | + IPC::BufferCommit::construct(message); |
| 167 | + target.ipcClient.sendMessage(IPC::Message::data(message), IPC::Message::size); |
| 168 | +diff --git a/src/wpeframework/view-backend.cpp b/src/wpeframework/view-backend.cpp |
| 169 | +index 3f50991..7cc6f64 100644 |
| 170 | +--- a/src/wpeframework/view-backend.cpp |
| 171 | ++++ b/src/wpeframework/view-backend.cpp |
| 172 | +@@ -45,16 +45,11 @@ struct ViewBackend : public IPC::Host::Handler { |
| 173 | + void handleFd(int) override { }; |
| 174 | + void handleMessage(char*, size_t) override; |
| 175 | + |
| 176 | +- void ackBufferCommit(); |
| 177 | + void initialize(); |
| 178 | + |
| 179 | +- static gboolean vsyncCallback(gpointer); |
| 180 | +- |
| 181 | + struct wpe_view_backend* backend; |
| 182 | + std::array<struct wpe_input_touch_event_raw, 10> touchpoints; |
| 183 | + IPC::Host ipcHost; |
| 184 | +- GSource* vsyncSource; |
| 185 | +- bool triggered; |
| 186 | + }; |
| 187 | + |
| 188 | + static uint32_t MaxFPS() { |
| 189 | +@@ -72,22 +67,14 @@ static uint32_t MaxFPS() { |
| 190 | + |
| 191 | + ViewBackend::ViewBackend(struct wpe_view_backend* backend) |
| 192 | + : backend(backend) |
| 193 | +- , vsyncSource(g_timeout_source_new(MaxFPS())) |
| 194 | +- , triggered(false) |
| 195 | + { |
| 196 | + ipcHost.initialize(*this); |
| 197 | + |
| 198 | +- g_source_set_callback(vsyncSource, static_cast<GSourceFunc>(vsyncCallback), this, nullptr); |
| 199 | +- g_source_set_priority(vsyncSource, G_PRIORITY_HIGH + 30); |
| 200 | +- g_source_set_can_recurse(vsyncSource, TRUE); |
| 201 | +- g_source_attach(vsyncSource, g_main_context_get_thread_default()); |
| 202 | +- |
| 203 | + touchpoints.fill({ wpe_input_touch_event_type_null, 0, 0, 0, 0 }); |
| 204 | + } |
| 205 | + |
| 206 | + ViewBackend::~ViewBackend() |
| 207 | + { |
| 208 | +- g_source_destroy(vsyncSource); |
| 209 | + ipcHost.deinitialize(); |
| 210 | + } |
| 211 | + |
| 212 | +@@ -141,7 +128,10 @@ void ViewBackend::handleMessage(char* data, size_t size) |
| 213 | + } |
| 214 | + case IPC::BufferCommit::code: |
| 215 | + { |
| 216 | +- triggered = true; |
| 217 | ++ IPC::Message message; |
| 218 | ++ IPC::FrameComplete::construct(message); |
| 219 | ++ ipcHost.sendMessage(IPC::Message::data(message), IPC::Message::size); |
| 220 | ++ |
| 221 | + break; |
| 222 | + } |
| 223 | + case IPC::AdjustedDimensions::code: |
| 224 | +@@ -174,27 +164,6 @@ void ViewBackend::initialize() |
| 225 | + wpe_view_backend_dispatch_set_size( backend, width, height); |
| 226 | + } |
| 227 | + |
| 228 | +-void ViewBackend::ackBufferCommit() |
| 229 | +-{ |
| 230 | +- IPC::Message message; |
| 231 | +- IPC::FrameComplete::construct(message); |
| 232 | +- ipcHost.sendMessage(IPC::Message::data(message), IPC::Message::size); |
| 233 | +- |
| 234 | +- wpe_view_backend_dispatch_frame_displayed(backend); |
| 235 | +-} |
| 236 | +- |
| 237 | +-gboolean ViewBackend::vsyncCallback(gpointer data) |
| 238 | +-{ |
| 239 | +- ViewBackend* impl = static_cast<ViewBackend*>(data); |
| 240 | +- |
| 241 | +- if (impl->triggered) { |
| 242 | +- impl->triggered = false; |
| 243 | +- impl->ackBufferCommit(); |
| 244 | +- } |
| 245 | +- |
| 246 | +- return (G_SOURCE_CONTINUE); |
| 247 | +-} |
| 248 | +- |
| 249 | + } // namespace WPEFramework |
| 250 | + |
| 251 | + extern "C" { |
0 commit comments