fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2021 Amlogic Corporation. |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | #ifndef __WAYLAND_DISPLAY_H__ |
| 17 | #define __WAYLAND_DISPLAY_H__ |
| 18 | #include <stdint.h> |
| 19 | #include <stdlib.h> |
| 20 | #include <pthread.h> |
| 21 | #include <poll.h> |
| 22 | #include <list> |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 23 | #include <unordered_map> |
| 24 | #include <wayland-client-protocol.h> |
| 25 | #include <wayland-client.h> |
| 26 | #include "xdg-shell-client-protocol.h" |
| 27 | #include "fullscreen-shell-unstable-v1-client-protocol.h" |
| 28 | #include "linux-dmabuf-unstable-v1-client-protocol.h" |
| 29 | #include "linux-explicit-synchronization-unstable-v1-client-protocol.h" |
| 30 | #include "viewporter-client-protocol.h" |
| 31 | #include "wayland-cursor.h" |
| 32 | #include "Thread.h" |
fei.deng | b9a1a57 | 2023-09-13 01:33:57 +0000 | [diff] [blame] | 33 | #include "Poll.h" |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 34 | #include "render_plugin.h" |
| 35 | |
| 36 | using namespace std; |
| 37 | |
| 38 | #define DEFAULT_DISPLAY_OUTPUT_NUM 2 |
| 39 | |
| 40 | class WaylandPlugin; |
| 41 | class WaylandShmBuffer; |
| 42 | class WaylandBuffer; |
| 43 | |
| 44 | class WaylandDisplay : public Tls::Thread{ |
| 45 | public: |
fei.deng | b9a1a57 | 2023-09-13 01:33:57 +0000 | [diff] [blame] | 46 | WaylandDisplay(WaylandPlugin *plugin, int logCategory); |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 47 | virtual ~WaylandDisplay(); |
| 48 | /** |
| 49 | * @brief connet client to compositor server |
| 50 | * and acquire a display from compositor |
| 51 | * |
| 52 | * @return int 0 success,other fail |
| 53 | */ |
| 54 | int openDisplay(); |
| 55 | /** |
| 56 | * @brief release display that acquired from compositor |
| 57 | * |
| 58 | */ |
| 59 | void closeDisplay(); |
| 60 | /** |
| 61 | * @brief change RenderVideoFormat to wayland protocol dma buffer format |
| 62 | * and get the matched dmabuffer modifiers |
| 63 | * |
| 64 | */ |
| 65 | int toDmaBufferFormat(RenderVideoFormat format, uint32_t *outDmaformat /*out param*/, uint64_t *outDmaformatModifiers /*out param*/); |
| 66 | /** |
| 67 | * @brief change RenderVideoFormat to wayland protocol shm buffer format |
| 68 | * |
| 69 | * @param format RenderVideoFormat |
| 70 | * @param outformat wayland protocol shm buffer format |
| 71 | * @return int 0 success,other fail |
| 72 | */ |
| 73 | int toShmBufferFormat(RenderVideoFormat format, uint32_t *outformat); |
| 74 | /** |
| 75 | * @brief Set the Video Buffer Format object |
| 76 | * |
| 77 | * @param format RenderVideoFormat it is defined in render_lib.h |
| 78 | */ |
| 79 | void setVideoBufferFormat(RenderVideoFormat format); |
| 80 | RenderVideoFormat getVideoBufferFormat() { |
| 81 | return mBufferFormat; |
| 82 | }; |
| 83 | struct wl_display *getWlDisplay() { |
| 84 | return mWlDisplay; |
| 85 | }; |
| 86 | struct zwp_linux_dmabuf_v1 * getDmaBuf() |
| 87 | { |
| 88 | return mDmabuf; |
| 89 | }; |
| 90 | struct wl_shm *getShm() |
| 91 | { |
| 92 | return mShm; |
| 93 | }; |
| 94 | /** |
| 95 | * @brief Set the Select Display Output index |
| 96 | * |
| 97 | * @param output selected display output index |
| 98 | */ |
| 99 | void setDisplayOutput(int output); |
| 100 | /** |
| 101 | * @brief Get the Select Display Output index |
| 102 | * |
| 103 | * @return int the index of selected output |
| 104 | */ |
| 105 | int getDisplayOutput(); |
| 106 | |
| 107 | /** |
| 108 | * @brief set pip video |
| 109 | * @param pip if set to 1, the video data will display in pip video plane |
| 110 | * otherwise video data will display in main video plane |
| 111 | */ |
| 112 | void setPip(int pip); |
| 113 | |
| 114 | bool isSentPtsToWeston() { |
| 115 | return mIsSendPtsToWeston; |
| 116 | } |
| 117 | |
| 118 | void setRedrawingPending(bool val) { |
| 119 | mRedrawingPending = val; |
| 120 | }; |
| 121 | |
| 122 | bool isRedrawingPending() { |
| 123 | return mRedrawingPending; |
| 124 | }; |
| 125 | |
| 126 | void setRenderRectangle(int x, int y, int w, int h); |
| 127 | void setFrameSize(int w, int h); |
| 128 | void setWindowSize(int x, int y, int w, int h); |
| 129 | int prepareFrameBuffer(RenderBuffer * buf); |
| 130 | void displayFrameBuffer(RenderBuffer * buf, int64_t realDisplayTime); |
| 131 | void setOpaque(); |
| 132 | void flushBuffers(); |
| 133 | void ensureFullscreen(bool fullscreen); |
| 134 | void handleBufferReleaseCallback(WaylandBuffer *buf); |
| 135 | void handleFrameDisplayedCallback(WaylandBuffer *buf); |
| 136 | void handleFrameDropedCallback(WaylandBuffer *buf); |
| 137 | |
| 138 | //thread func |
| 139 | void readyToRun(); |
| 140 | virtual bool threadLoop(); |
| 141 | |
| 142 | /**wayland callback functions**/ |
| 143 | static void dmabuf_modifiers(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, |
| 144 | uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo); |
| 145 | static void dmaBufferFormat (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf, uint32_t format); |
| 146 | static void registryHandleGlobal (void *data, struct wl_registry *registry, |
| 147 | uint32_t id, const char *interface, uint32_t version); |
| 148 | static void registryHandleGlobalRemove (void *data, struct wl_registry *registry, uint32_t name); |
| 149 | static void shmFormat (void *data, struct wl_shm *wl_shm, uint32_t format); |
| 150 | static void outputHandleGeometry( void *data, |
| 151 | struct wl_output *output, |
| 152 | int x, |
| 153 | int y, |
| 154 | int mmWidth, |
| 155 | int mmHeight, |
| 156 | int subPixel, |
| 157 | const char *make, |
| 158 | const char *model, |
| 159 | int transform ); |
| 160 | static void outputHandleMode( void *data, |
| 161 | struct wl_output *output, |
| 162 | uint32_t flags, |
| 163 | int width, |
| 164 | int height, |
| 165 | int refreshRate ); |
| 166 | static void outputHandleDone( void *data, |
| 167 | struct wl_output *output ); |
| 168 | static void outputHandleScale( void *data, |
| 169 | struct wl_output *output, |
| 170 | int32_t scale ); |
| 171 | static void pointerHandleEnter(void *data, struct wl_pointer *pointer, |
| 172 | uint32_t serial, struct wl_surface *surface, |
| 173 | wl_fixed_t sx, wl_fixed_t sy); |
| 174 | static void pointerHandleLeave(void *data, struct wl_pointer *pointer, |
| 175 | uint32_t serial, struct wl_surface *surface); |
| 176 | static void pointerHandleMotion(void *data, struct wl_pointer *pointer, |
| 177 | uint32_t time, wl_fixed_t sx, wl_fixed_t sy); |
| 178 | static void pointerHandleButton(void *data, struct wl_pointer *wl_pointer, |
| 179 | uint32_t serial, uint32_t time, uint32_t button, uint32_t state); |
| 180 | static void pointerHandleAxis(void *data, struct wl_pointer *wl_pointer, |
| 181 | uint32_t time, uint32_t axis, wl_fixed_t value); |
| 182 | static void touchHandleDown(void *data, struct wl_touch *wl_touch, |
| 183 | uint32_t serial, uint32_t time, struct wl_surface *surface, |
| 184 | int32_t id, wl_fixed_t x_w, wl_fixed_t y_w); |
| 185 | static void touchHandleUp(void *data, struct wl_touch *wl_touch, |
| 186 | uint32_t serial, uint32_t time, int32_t id); |
| 187 | static void touchHandleMotion(void *data, struct wl_touch *wl_touch, |
| 188 | uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w); |
| 189 | static void touchHandleFrame(void *data, struct wl_touch *wl_touch); |
| 190 | static void touchHandleCancel(void *data, struct wl_touch *wl_touch); |
| 191 | static void keyboardHandleKeymap(void *data, struct wl_keyboard *keyboard, |
| 192 | uint32_t format, int fd, uint32_t size); |
| 193 | static void keyboardHandleEnter(void *data, struct wl_keyboard *keyboard, |
| 194 | uint32_t serial, struct wl_surface *surface, struct wl_array *keys); |
| 195 | static void keyboardHandleLeave(void *data, struct wl_keyboard *keyboard, |
| 196 | uint32_t serial, struct wl_surface *surface); |
| 197 | static void keyboardHandleKey(void *data, struct wl_keyboard *keyboard, |
| 198 | uint32_t serial, uint32_t time, uint32_t key, uint32_t state); |
| 199 | static void keyboardHandleModifiers(void *data, struct wl_keyboard *keyboard, |
| 200 | uint32_t serial, uint32_t mods_depressed, |
| 201 | uint32_t mods_latched, uint32_t mods_locked, |
| 202 | uint32_t group); |
| 203 | static void seatHandleCapabilities(void *data, struct wl_seat *seat, |
| 204 | uint32_t caps); |
| 205 | static void handleXdgToplevelClose (void *data, struct xdg_toplevel *xdg_toplevel); |
| 206 | static void handleXdgToplevelConfigure (void *data, struct xdg_toplevel *xdg_toplevel, |
| 207 | int32_t width, int32_t height, struct wl_array *states); |
| 208 | static void handleXdgSurfaceConfigure (void *data, struct xdg_surface *xdg_surface, uint32_t serial); |
| 209 | private: |
| 210 | typedef struct DisplayOutput { |
| 211 | struct wl_output *wlOutput; |
| 212 | int offsetX; |
| 213 | int offsetY; |
| 214 | int width; |
| 215 | int height; |
| 216 | int refreshRate; |
| 217 | bool isPrimary; |
fei.deng | af9b07d | 2023-10-10 07:38:40 +0000 | [diff] [blame^] | 218 | uint32_t name; |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 219 | } DisplayOutput; |
| 220 | struct Rectangle { |
| 221 | int x; |
| 222 | int y; |
| 223 | int w; |
| 224 | int h; |
| 225 | }; |
| 226 | char *require_xdg_runtime_dir(); |
| 227 | void createCommonWindowSurface(); |
| 228 | void createXdgShellWindowSurface(); |
| 229 | void destroyWindowSurfaces(); |
| 230 | void resizeVideoSurface(bool commit); |
| 231 | void videoCenterRect(Rectangle src, Rectangle dst, Rectangle *result, bool scaling); |
| 232 | void updateBorders(); |
| 233 | std::size_t calculateDmaBufferHash(RenderDmaBuffer &dmabuf); |
| 234 | void cleanSurface(); |
| 235 | void addWaylandBuffer(RenderBuffer * buf, WaylandBuffer *waylandbuf); |
| 236 | WaylandBuffer* findWaylandBuffer(RenderBuffer * buf); |
| 237 | void cleanAllWaylandBuffer(); |
| 238 | |
| 239 | WaylandPlugin *mWaylandPlugin; |
| 240 | struct wl_display *mWlDisplay; |
| 241 | struct wl_display *mWlDisplayWrapper; |
| 242 | struct wl_event_queue *mWlQueue; |
| 243 | |
| 244 | struct wl_registry *mRegistry; |
| 245 | struct wl_compositor *mCompositor; |
| 246 | struct wl_subcompositor *mSubCompositor; |
| 247 | struct xdg_wm_base *mXdgWmBase; |
| 248 | struct wp_viewporter *mViewporter; |
| 249 | struct zwp_linux_dmabuf_v1 *mDmabuf; |
| 250 | struct wl_shm *mShm; |
| 251 | struct wl_seat *mSeat; |
| 252 | struct wl_pointer *mPointer; |
| 253 | struct wl_touch *mTouch; |
| 254 | struct wl_keyboard *mKeyboard; |
| 255 | |
| 256 | /*primary output will signal first,so 0 index is primary wl_output, 1 index is extend wl_output*/ |
| 257 | DisplayOutput mOutput[DEFAULT_DISPLAY_OUTPUT_NUM]; //info about wl_output |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 258 | int mActiveOutput; //default is primary output |
| 259 | |
fei.deng | b9a1a57 | 2023-09-13 01:33:57 +0000 | [diff] [blame] | 260 | int mLogCategory; |
| 261 | |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 262 | std::list<uint32_t> mShmFormats; |
| 263 | std::unordered_map<uint32_t, uint64_t> mDmaBufferFormats; |
| 264 | RenderVideoFormat mBufferFormat; |
| 265 | |
fei.deng | b9a1a57 | 2023-09-13 01:33:57 +0000 | [diff] [blame] | 266 | mutable Tls::Mutex mBufferMutex; |
| 267 | mutable Tls::Mutex mMutex; |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 268 | int mFd; |
fei.deng | b9a1a57 | 2023-09-13 01:33:57 +0000 | [diff] [blame] | 269 | Tls::Poll *mPoll; |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 270 | |
| 271 | /*the followed is windows variable*/ |
fei.deng | b9a1a57 | 2023-09-13 01:33:57 +0000 | [diff] [blame] | 272 | mutable Tls::Mutex mRenderMutex; |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 273 | struct wl_surface *mAreaSurface; |
| 274 | struct wl_surface *mAreaSurfaceWrapper; |
| 275 | struct wl_surface *mVideoSurface; |
| 276 | struct wl_surface *mVideoSurfaceWrapper; |
| 277 | struct wl_subsurface *mVideoSubSurface; |
| 278 | struct xdg_surface *mXdgSurface; |
| 279 | struct xdg_toplevel *mXdgToplevel; |
| 280 | struct wp_viewport *mAreaViewport; |
| 281 | struct wp_viewport *mVideoViewport; |
| 282 | WaylandShmBuffer *mAreaShmBuffer; |
| 283 | bool mXdgSurfaceConfigured; |
fei.deng | b9a1a57 | 2023-09-13 01:33:57 +0000 | [diff] [blame] | 284 | Tls::Condition mConfigureCond; |
| 285 | Tls::Mutex mConfigureMutex; |
fei.deng | f7a0cd3 | 2023-08-29 09:36:37 +0000 | [diff] [blame] | 286 | bool mFullScreen; //default full screen |
| 287 | |
| 288 | bool mIsSendPtsToWeston; |
| 289 | |
| 290 | bool mReCommitAreaSurface; |
| 291 | |
| 292 | /* the size and position of the area_(sub)surface |
| 293 | it is full screen size now*/ |
| 294 | struct Rectangle mRenderRect; |
| 295 | |
| 296 | /*the size and position of window */ |
| 297 | struct Rectangle mWindowRect; |
| 298 | |
| 299 | /* the size and position of the video_subsurface */ |
| 300 | struct Rectangle mVideoRect; |
| 301 | /* the size of the video in the buffers */ |
| 302 | int mVideoWidth; |
| 303 | int mVideoHeight; |
| 304 | |
| 305 | //the count display buffer of committed to weston |
| 306 | int mCommitCnt; |
| 307 | |
| 308 | /*store waylandbuffers when set reusing waylandbuffer flag*/ |
| 309 | std::unordered_map<std::size_t, WaylandBuffer *> mWaylandBuffersMap; |
| 310 | bool mNoBorderUpdate; |
| 311 | |
| 312 | /*store committed to weston waylandbuffer,key is pts*/ |
| 313 | std::unordered_map<int64_t, WaylandBuffer *> mCommittedBufferMap; |
| 314 | |
| 315 | int mPip; //pip video, 1->pip, 0: main video(default) |
| 316 | bool mIsSendVideoPlaneId; //default true,otherwise false if set |
| 317 | bool mRedrawingPending;//it will be true when weston obtains a buffer rendering,otherwise false when rendered |
| 318 | }; |
| 319 | |
| 320 | #endif /*__WAYLAND_DISPLAY_H__*/ |