├── .gitignore ├── LICENSE ├── NOTES.md ├── README.md ├── XYZZY.md ├── atomic.c ├── atomic.h ├── gbm.c ├── gbm_.h ├── include ├── backend │ ├── bufmgr.h │ ├── dev.h │ ├── input.h │ ├── screen.h │ └── vulkan.h ├── legacy_wl_drm.h ├── swvkc.h └── util │ └── my_drm_handle_event.h ├── input.c ├── input.h ├── legacy_wl_drm.c ├── legacy_wl_drm_.h ├── loop.c ├── meson.build ├── meson_options.txt ├── modeset.c ├── modeset.h ├── src ├── backend │ ├── bufmgr_gbm.c │ ├── bufmgr_intel.c │ ├── dev.c │ ├── input.c │ ├── meson.build │ ├── screen.c │ └── vulkan.c ├── legacy_wl_drm.c ├── main.c ├── meson.build ├── swvkc.c └── util │ ├── meson.build │ └── my_drm_handle_event.c ├── subprojects └── libswvkc-wl │ ├── core │ ├── compositor.c │ ├── data_device.c │ ├── data_device_manager.c │ ├── data_offer.c │ ├── data_source.c │ ├── keyboard.c │ ├── output.c │ ├── region.c │ ├── seat.c │ ├── subsurface.c │ ├── wl_pointer.c │ ├── wl_subcompositor.c │ └── wl_surface.c │ ├── extensions │ ├── fullscreen-shell-unstable-v1 │ │ └── zwp_fullscreen_shell_v1.c │ ├── linux-dmabuf-unstable-v1 │ │ ├── wl_buffer_dmabuf.c │ │ ├── zwp_linux_buffer_params_v1.c │ │ └── zwp_linux_dmabuf_v1.c │ ├── linux-explicit-synchronization-v1 │ │ ├── zwp_linux_explicit_synchronization_v1.c │ │ └── zwp_linux_surface_synchronization_v1.c │ ├── server-decoration │ │ ├── org_kde_kwin_server_decoration.c │ │ └── org_kde_kwin_server_decoration_manager.c │ └── xdg_shell │ │ ├── xdg_popup.c │ │ ├── xdg_positioner.c │ │ ├── xdg_surface.c │ │ ├── xdg_toplevel.c │ │ └── xdg_wm_base.c │ ├── globals.c │ ├── include │ ├── core │ │ ├── compositor.h │ │ ├── data_device.h │ │ ├── data_device_manager.h │ │ ├── data_offer.h │ │ ├── data_source.h │ │ ├── keyboard.h │ │ ├── output.h │ │ ├── region.h │ │ ├── seat.h │ │ ├── subsurface.h │ │ ├── wl_pointer.h │ │ ├── wl_subcompositor.h │ │ ├── wl_surface.h │ │ └── wl_surface_staged_field.h │ ├── extensions │ │ ├── fullscreen-shell-unstable-v1 │ │ │ └── zwp_fullscreen_shell_v1.h │ │ ├── linux-dmabuf-unstable-v1 │ │ │ ├── wl_buffer_dmabuf.h │ │ │ ├── zwp_linux_buffer_params_v1.h │ │ │ └── zwp_linux_dmabuf_v1.h │ │ ├── linux-explicit-synchronization-v1 │ │ │ ├── zwp_linux_explicit_synchronization_v1.h │ │ │ └── zwp_linux_surface_synchronization_v1.h │ │ ├── server-decoration │ │ │ ├── org_kde_kwin_server_decoration.h │ │ │ └── org_kde_kwin_server_decoration_manager.h │ │ └── xdg_shell │ │ │ ├── xdg_popup.h │ │ │ ├── xdg_positioner.h │ │ │ ├── xdg_surface.h │ │ │ ├── xdg_toplevel.h │ │ │ └── xdg_wm_base.h │ ├── globals.h │ └── util │ │ ├── algebra.h │ │ ├── box.h │ │ ├── log.h │ │ └── util.h │ ├── meson.build │ ├── server-decoration.xml │ └── util │ ├── algebra.c │ ├── log.c │ └── util.c ├── trash ├── direct.c ├── dmabuf_map.c ├── intel_bo.c ├── vulkan_avoid_same_memory_reimport.c └── vulkan_display.c ├── wayland.c ├── wayland.h ├── xkb.c └── xkb.h /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Stefano Ragni 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | ## Issues with clients 2 | * `vkcube` and `vkcubepp` have to be compiled with DEMOS_WSI_SELECTION=WAYLAND, 3 | but even then they won't work because they require the deprecated `wl_shell` 4 | protocol 5 | `Note! This protocol is deprecated and not intended for production use. For 6 | desktop-style user interfaces, use xdg_shell. ` from 7 | https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_shell 8 | 9 | ## Vulkan extensions that we need 10 | * VK_KHR_external_memory_fd 11 | * VK_EXT_external_memory_dma_buf 12 | * VK_EXT_image_drm_format_modifier [not yet implemented by Mesa] 13 | 14 | ## Steps to import a dma_buf into the Vulkan compositor 15 | 1. Create a buffer, which is initially a virtual allocation with no backing 16 | memory 17 | `VkImage = vkCreateImage()` 18 | 2. Allocate device memory from the dma_buf fd 19 | `VkDeviceMemory = vkAllocateMemory(fd)` 20 | 3. Associate the device memory with the buffer 21 | `vkBindImageMemory(VkImage, VkDeviceMemory)` 22 | 23 | ## Steps to import a shm buffer into the Vulkan compositor 24 | 1. Get the data pointer from the shm buffer 25 | `data = wl_shm_buffer_get_data(shm_buffer)` 26 | 2. Copy the data into a staging buffer (can this be avoided?) 27 | `memcpy(dest, data)` 28 | 29 | ## Steps to export a Vulkan rendered buffer (the screen) to DRM 30 | 1. Create a bo with GBM 31 | `bo = gbm_bo_create()` 32 | 2. Get the bo fd, which should be a dma_buf fd 33 | `fd = gbm_bo_get_fd(bo)` 34 | 3. Create a buffer, which is initially a virtual allocation with no backing 35 | memory 36 | `VkImage = vkCreateImage()` 37 | 4. Allocate device memory from the dma_buf fd 38 | `VkDeviceMemory = vkAllocateMemory(fd)` 39 | 5. Associate the device memory with the buffer 40 | `vkBindImageMemory(VkImage, VkDeviceMemory)` 41 | 6. Render to the buffer 42 | `vkCmdClearColorImage` 43 | 7. Retrieve the bo handle to feed it to DRM 44 | `handle = gbm_bo_get_handle(bo).u32` 45 | 46 | ## Explicit syncronization 47 | From https://www.collabora.com/news-and-blog/blog/2017/01/26/mainline-explicit-fencing-part-3/ 48 | > On the other hand for the fences created by the kernel that are sent back to 49 | > userspace the OUT_FENCE_PTR property is used. It is a DRM CRTC property 50 | > because we only create one dma_fence per CRTC as all the buffers on it will be 51 | > scanned out at the same time. The kernel sends this fence back to userspace by 52 | > writing the fd number to the pointer provided in the OUT_FENCE_PTR property. 53 | > Note that, unlike from what Android did, when the fence signals it means the 54 | > previous buffer – the buffer removed from the screen – is free for reuse. On 55 | > Android when the signal was raised it meant the current buffer was freed. 56 | > However, the Android folks have patched SurfaceFlinger already to support the 57 | > Mainline semantics when using Explicit Fencing! 58 | 59 | ## TODO 60 | * Code cleanup 61 | * Investigate correct memory management and synchronization 62 | * clipboard: maybe we can get away with not implementing wlr-data-control by 63 | adding special behaviour for `wl-clipboard`, which seems to have become a 64 | standard tool (e.g. it is used by `neovim`). The mechanism to allow such a 65 | behavior should be based on something that a malicious program can't easily 66 | exploit to access the keyboard: maybe we can query /proc/pid/exe to match it 67 | against /usr/bin/wl-{copy,paste} 68 | 69 | ## ISSUES/NOTES 70 | * Many clients (`kitty`, `alacritty`, ...) still depend on the presence of the 71 | `wl_drm` 'legacy' extension to use dmabufs. 72 | * Is VK_EXT_external_memory_host useful for us? The shm buffer from Alacritty 73 | could be imported in this way (only one time though), but not the ones from 74 | weston-terminal or weston-simple-shm. 75 | * One gpu didn't support linear buffers for scanout, even though GBM allows 76 | their creation (error on drmModeAddFB) 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # swvkc (temporary name) 2 | `swvkc` is an experimental Wayland compositor meant to explore the possibility 3 | of using Vulkan as a rendering backend.\ 4 | `swvkc` prioritizes direct scanout of client buffers when possible. When 5 | compositing needs to be done, it renders to the screen with simple copy commands 6 | from the Vulkan API.\ 7 | Some goals/directions of the project: 8 | * Do the minimal work necessary to display client buffers, do not introduce 9 | screen tearing/stuttering or input lag. 10 | * Stick to minimal window management features. 11 | * Try to write simple, easy to understand code. 12 | 13 | ## Current status 14 | * The mechanism to import both shm and dma buffers into Vulkan has been quickly 15 | sketched, but it needs to be made more robust (some assumptions about the 16 | buffer formats should be removed too). 17 | * I tried for some time to implement tear-free single-buffered rendering (by 18 | restricting rendering to VBlank Intervals) but failed to achieve it 19 | consistently. Using double-buffering for now. 20 | * The Wayland protocol has been implemented partially so only some clients work 21 | at the moment. 22 | 23 | ## Current features (or lack thereof) 24 | * Only one surface is focused and displayed at a time 25 | * One single client can be run at startup (I suggest a terminal) 26 | * Focus can be changed (see Usage notes) 27 | * No popups [coming soon...] 28 | * No clipboard [coming soon...] 29 | 30 | ## Constraints 31 | * The hardware is required to support the modern DRM atomic commit interface 32 | * No XWayland support 33 | 34 | ## Dependencies 35 | `swvkc` tries to have minimal dependencies. Here is the full list: 36 | * Wayland 37 | * `wayland-server`, the core server API 38 | * `wayland-protocols` to generate protocol headers and code 39 | * DRM 40 | * `libdrm` for controlling the screen 41 | * `libdrm_intel` (optional) to use the intel buffer manager instead of GBM 42 | * Vulkan 43 | * `vulkan-loader` to load the appropriate vendor-specific libraries 44 | * the vendor-specific Vulkan implementation (e.g.: `vulkan_intel` or `amdvlk`) 45 | * Mesa 46 | * `gbm` for the GBM buffer manager but also required by `egl` 47 | * `egl` [legacy] I have to keep it to provide the `wl_drm` interface, on which 48 | Mesa relies to authenticate against DRM 49 | * `xkbcommon` for keyboard standardization, it is practically required by the 50 | Wayland spec 51 | * `libudev` for GPU discovery and monitor hotplugging (not yet) 52 | 53 | ## Building 54 | After installing `meson`, run the command: 55 | ``` 56 | $ meson build 57 | ``` 58 | and install any missing dependency that is reported. Then run: 59 | ``` 60 | $ ninja -C build 61 | ``` 62 | Upon successful compilation the binary is located inside the `build` directory. 63 | 64 | ## Usage notes 65 | * The presence of the environment variable `XDG_RUNTIME_DIR` is required, and it 66 | must point to an appropriate folder (this is automatically set up by `systemd` 67 | or `elogind`) 68 | * Provide the required permissions (e.g. by adding the user to group video and 69 | input) 70 | * Start the program from the Linux console (not inside another X11/Wayland 71 | compositor) 72 | * Pass it the client (and its arguments) you want to run 73 | * Hold the LEFTMETA (Win) key and press ESC to exit 74 | * To change focus: hold LEFTMETA and start to type the client name 75 | until an unambiguous match is found 76 | * Keyboard settings (such as layout) are set through XKB_DEFAULT\* environmental 77 | variables. 78 | 79 | ## An issue 80 | Importing memory created by DRM/GBM into Vulkan images is undefined behaviour 81 | without the `VK_EXT_image_drm_format_modifier` extension: even when the image 82 | is created with linear layout and without modifiers, there is no way to 83 | specify the correct row pitch (please correct me if I'm wrong):\ 84 | From Issues in https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/chap44.html#VK_EXT_external_memory_dma_buf 85 | > How does the application, when creating a VkImage that it intends to bind to 86 | > dma_buf VkDeviceMemory containing an externally produced image, specify the 87 | > memory layout (such as row pitch and DRM format modifier) of the VkImage? In 88 | > other words, how does the application achieve behavior comparable to that 89 | > provided by EGL_EXT_image_dma_buf_import and 90 | > EGL_EXT_image_dma_buf_import_modifiers?\ 91 | > +\ 92 | > RESOLVED. Features comparable to those in EGL_EXT_image_dma_buf_import and 93 | > EGL_EXT_image_dma_buf_import_modifiers will be provided by an extension layered 94 | > atop this one. 95 | 96 | The extension mentioned in the last line is precisely 97 | `VK_EXT_image_drm_format_modifier`. If you are unable to display clients like 98 | `weston-simple-shm`, `weston-terminal` and `firefox`, the absence of this 99 | extension is likely to be the problem. 100 | 101 | ### Relevant links (tracking progress of useful features) 102 | * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/1466 103 | * https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/8 104 | -------------------------------------------------------------------------------- /XYZZY.md: -------------------------------------------------------------------------------- 1 | # Running xyzzy in a minimal environment 2 | 3 | Runs without `CONFIG_VT`. 4 | Runs without `CONFIG_TTY` too, but terminal emulators won't work... 5 | 6 | ``` 7 | s6-mount -t proc proc /proc # Needed by... a lot of stuff 8 | s6-mount -t sysfs sys /sys # Needed by libdrm (vulkan-intel) 9 | mkdir -p -m0755 /dev/pts # Needed by terminal emulators 10 | mount -o mode=0620,gid=5,nosuid,noexec -n -t devpts devpts /dev/pts 11 | ``` 12 | 13 | Needed by libinput (udev context): 14 | ``` 15 | udevd --daemon 16 | udevadm trigger --action=add --type=subsystems 17 | udevadm trigger --action=add --type=devices 18 | udevadm settle 19 | ``` 20 | -------------------------------------------------------------------------------- /atomic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define die(msg) \ 15 | do { perror(msg); exit(EXIT_FAILURE); } while (0) 16 | 17 | static uint64_t find_old(int fd) { 18 | drmModeObjectPropertiesPtr ptr = drmModeObjectGetProperties(fd, 40, DRM_MODE_OBJECT_PLANE); 19 | for (int i=0; icount_props; i++) { 20 | drmModePropertyPtr prop = drmModeGetProperty(fd, ptr->props[i]); 21 | if (!strcmp(prop->name, "FB_ID")) 22 | return ptr->prop_values[i]; 23 | //printf("%s %d %u\n", prop->name, prop->prop_id, ptr->prop_values[i]); 24 | drmModeFreeProperty(prop); 25 | } 26 | drmModeFreeObjectProperties(ptr); 27 | return 0; 28 | } 29 | 30 | #include "modeset.h" 31 | 32 | /* A bit wrong because different planes could have different properties */ 33 | struct props { 34 | struct { 35 | uint32_t type; 36 | uint32_t src_x; 37 | uint32_t src_y; 38 | uint32_t src_w; 39 | uint32_t src_h; 40 | uint32_t crtc_x; 41 | uint32_t crtc_y; 42 | uint32_t crtc_w; 43 | uint32_t crtc_h; 44 | uint32_t fb_id; 45 | uint32_t in_fence_fd; 46 | uint32_t crtc_id; 47 | } plane; 48 | 49 | struct { 50 | uint32_t crtc_id; 51 | } conn; 52 | 53 | struct { 54 | uint32_t out_fence_ptr; 55 | } crtc; 56 | }; 57 | 58 | struct props find_prop_ids(int fd, uint32_t plane_id, uint32_t conn_id, uint32_t crtc_id) { 59 | struct props props; 60 | drmModeObjectProperties *obj_props; 61 | obj_props = drmModeObjectGetProperties(fd, plane_id, 62 | DRM_MODE_OBJECT_PLANE); 63 | for (size_t i=0; icount_props; i++) { 64 | drmModePropertyRes *prop = drmModeGetProperty(fd, 65 | obj_props->props[i]); 66 | if (!strcmp(prop->name, "type")) 67 | props.plane.type = prop->prop_id; 68 | if (!strcmp(prop->name, "SRC_X")) 69 | props.plane.src_x = prop->prop_id; 70 | if (!strcmp(prop->name, "SRC_Y")) 71 | props.plane.src_y = prop->prop_id; 72 | if (!strcmp(prop->name, "SRC_W")) 73 | props.plane.src_w = prop->prop_id; 74 | if (!strcmp(prop->name, "SRC_H")) 75 | props.plane.src_h = prop->prop_id; 76 | if (!strcmp(prop->name, "CRTC_X")) 77 | props.plane.crtc_x = prop->prop_id; 78 | if (!strcmp(prop->name, "CRTC_Y")) 79 | props.plane.crtc_y = prop->prop_id; 80 | if (!strcmp(prop->name, "CRTC_W")) 81 | props.plane.crtc_w = prop->prop_id; 82 | if (!strcmp(prop->name, "CRTC_H")) 83 | props.plane.crtc_h = prop->prop_id; 84 | if (!strcmp(prop->name, "FB_ID")) 85 | props.plane.fb_id = prop->prop_id; 86 | if (!strcmp(prop->name, "IN_FENCE_FD")) 87 | props.plane.in_fence_fd = prop->prop_id; 88 | if (!strcmp(prop->name, "CRTC_ID")) 89 | props.plane.crtc_id = prop->prop_id; 90 | drmModeFreeProperty(prop); 91 | } 92 | drmModeFreeObjectProperties(obj_props); 93 | obj_props = drmModeObjectGetProperties(fd, conn_id, 94 | DRM_MODE_OBJECT_CONNECTOR); 95 | for (size_t i=0; icount_props; i++) { 96 | drmModePropertyRes *prop = drmModeGetProperty(fd, 97 | obj_props->props[i]); 98 | if (!strcmp(prop->name, "CRTC_ID")) 99 | props.conn.crtc_id = prop->prop_id; 100 | drmModeFreeProperty(prop); 101 | } 102 | drmModeFreeObjectProperties(obj_props); 103 | obj_props = drmModeObjectGetProperties(fd, crtc_id, 104 | DRM_MODE_OBJECT_CRTC); 105 | for (size_t i=0; icount_props; i++) { 106 | drmModePropertyRes *prop = drmModeGetProperty(fd, 107 | obj_props->props[i]); 108 | if (!strcmp(prop->name, "OUT_FENCE_PTR")) 109 | props.crtc.out_fence_ptr = prop->prop_id; 110 | drmModeFreeProperty(prop); 111 | } 112 | drmModeFreeObjectProperties(obj_props); 113 | 114 | return props; 115 | } 116 | 117 | static int crtc_index_from_id(int fd, uint32_t crtc_id) { 118 | drmModeRes *res = drmModeGetResources(fd); 119 | for (int i=0; icount_crtcs; i++) { 120 | if (res->crtcs[i] == crtc_id) { 121 | drmModeFreeResources(res); 122 | return i; 123 | } 124 | } 125 | drmModeFreeResources(res); 126 | return -1; 127 | } 128 | 129 | static uint32_t planes(int fd, uint32_t crtc_id) { 130 | int crtc_idx = crtc_index_from_id(fd, crtc_id); 131 | int n_overlay = 0, n_cursor = 0; 132 | uint32_t plane_id = 0; 133 | 134 | drmModePlaneRes *plane_res = drmModeGetPlaneResources(fd); 135 | for (size_t i=0; icount_planes; i++) { 136 | drmModePlane *plane = drmModeGetPlane(fd, plane_res->planes[i]); 137 | if (!(plane->possible_crtcs & (1 << crtc_idx))) { 138 | drmModeFreePlane(plane); 139 | continue; 140 | } 141 | drmModeObjectProperties *obj_props; 142 | obj_props = drmModeObjectGetProperties(fd, plane->plane_id, 143 | DRM_MODE_OBJECT_PLANE); 144 | for (size_t j=0; jcount_props; j++) { 145 | drmModePropertyRes *prop = drmModeGetProperty(fd, 146 | obj_props->props[j]); 147 | if (!strcmp(prop->name, "type")) { 148 | if (obj_props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY) { 149 | printf("primary %d\n", plane->plane_id); 150 | plane_id = plane->plane_id; 151 | } else if (obj_props->prop_values[j] == DRM_PLANE_TYPE_OVERLAY) { 152 | printf("overlay %d\n", plane->plane_id); 153 | //S->overlay_plane_id = plane->plane_id; 154 | n_overlay++; 155 | } else if (obj_props->prop_values[j] == DRM_PLANE_TYPE_CURSOR) { 156 | printf("cursor %d\n", plane->plane_id); 157 | //S->cursor_plane_id = plane->plane_id; 158 | n_cursor++; 159 | } 160 | } 161 | drmModeFreeProperty(prop); 162 | } 163 | drmModeFreeObjectProperties(obj_props); 164 | drmModeFreePlane(plane); 165 | } 166 | drmModeFreePlaneResources(plane_res); 167 | //boxlog(" overlay planes: %d", n_overlay); 168 | //boxlog(" cursor planes: %d", n_cursor); 169 | return plane_id; 170 | } 171 | 172 | static uint32_t crtc; 173 | static uint32_t conn; 174 | static uint32_t plane; 175 | static struct props props; 176 | 177 | void atomic_init() { 178 | int r, fd = modeset_get_fd(); 179 | 180 | // without this we don't have access to all properties 181 | r = drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1); 182 | assert(!r); 183 | 184 | crtc = modeset_get_crtc(); 185 | conn = modeset_get_conn(); 186 | plane = planes(fd, crtc); 187 | assert(plane); 188 | 189 | props = find_prop_ids(fd, plane, conn, crtc); 190 | } 191 | 192 | uint32_t modeset_add_fb(uint32_t width, uint32_t height, uint32_t format, uint32_t handle, uint32_t pitch, uint32_t offset, uint64_t mod) { 193 | int r, fd = modeset_get_fd(); 194 | uint32_t bo_handles[4] = {handle}, pitches[4] = {pitch}, offsets[4] = {offset}; 195 | uint64_t modifier[4] = {mod}; 196 | uint32_t buf_id, flags = DRM_MODE_FB_MODIFIERS; 197 | 198 | // remove alpha otherwise fails on my (intel) gpu 199 | format = format == DRM_FORMAT_ARGB8888 ? DRM_FORMAT_XRGB8888 : format; 200 | 201 | r = drmModeAddFB2WithModifiers(fd, width, height, format, bo_handles, 202 | pitches, offsets, modifier, &buf_id, flags); 203 | if (r != 0) die("drmModeAddFB2WithModifiers"); 204 | 205 | printf("success: %dx%d\n", width, height); 206 | return buf_id; 207 | } 208 | 209 | void modeset_rem_fb(uint32_t buf_id) { 210 | int r, fd = modeset_get_fd(); 211 | 212 | r = drmModeRmFB(fd, buf_id); 213 | if (r != 0) strerr_warn1sys("drmModeAddFB2WithModifiers"); 214 | } 215 | 216 | void atomic_commit(uint32_t buf_id) { 217 | int r, fd = modeset_get_fd(); 218 | // if (width != 24) { 219 | drmModeAtomicReqPtr req = drmModeAtomicAlloc(); 220 | if (req == NULL) die("drmModeAtomicAlloc"); 221 | drmModeAtomicAddProperty(req, plane, props.plane.fb_id, buf_id); 222 | r = drmModeAtomicCommit(fd, req, DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK, NULL); 223 | if (r != 0) die("drmModeAtomicCommit"); 224 | drmModeAtomicFree(req); 225 | // } 226 | 227 | /*uint64_t old_buf_id = find_old(fd); 228 | sleep(1); 229 | 230 | req = drmModeAtomicAlloc(); 231 | if (req == NULL) die("drmModeAtomicAlloc"); 232 | drmModeAtomicAddProperty(req, 40, 16, old_buf_id); 233 | r = drmModeAtomicCommit(fd, req, 0, NULL); 234 | if (r != 0) die("drmModeAtomicCommit"); 235 | drmModeAtomicFree(req);*/ 236 | } 237 | 238 | #include "wayland.h" // meh 239 | 240 | void drm_read() { 241 | int fd = modeset_get_fd(); 242 | drmEventContext ev_context = { 243 | .version = DRM_EVENT_CONTEXT_VERSION, 244 | .page_flip_handler = page_flip_handler, 245 | }; 246 | drmHandleEvent(fd, &ev_context); 247 | } 248 | -------------------------------------------------------------------------------- /atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef atomic_h_INCLUDED 2 | #define atomic_h_INCLUDED 3 | 4 | #include 5 | 6 | void atomic_init(); 7 | uint32_t modeset_add_fb(uint32_t width, uint32_t height, uint32_t format, uint32_t handle, uint32_t pitch, uint32_t offset, uint64_t mod); 8 | void modeset_rem_fb(uint32_t buf_id); 9 | void atomic_commit(uint32_t buf_id); 10 | void drm_read(); 11 | 12 | #endif // atomic_h_INCLUDED 13 | 14 | -------------------------------------------------------------------------------- /gbm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | static struct gbm_device *gbm; 7 | 8 | void gbm_init(int drm_fd) { 9 | gbm = gbm_create_device(drm_fd); 10 | assert(gbm); 11 | } 12 | 13 | struct gbm_device *gbm_get_device() { 14 | return gbm; 15 | } 16 | 17 | struct gbm_bo *gbm_import_from_dmabuf(int num_fds, int32_t *dmabuf_fds, 18 | uint32_t width, uint32_t height, uint32_t format, uint32_t *strides, uint32_t 19 | *offsets, uint64_t modifier) { 20 | struct gbm_import_fd_modifier_data data = { 21 | .width = width, 22 | .height = height, 23 | .format = format, 24 | .num_fds = 1, 25 | .fds[0] = dmabuf_fds[0], 26 | .strides[0] = strides[0], 27 | .offsets[0] = offsets[0], 28 | .modifier = modifier 29 | }; 30 | struct gbm_bo *gbm_bo = gbm_bo_import(gbm, 31 | GBM_BO_IMPORT_FD_MODIFIER, &data, GBM_BO_USE_SCANOUT); 32 | 33 | if (!gbm_bo) { 34 | fprintf(stderr, "gbm_bo_import failed\n"); 35 | return 0; 36 | } 37 | 38 | return gbm_bo; 39 | } 40 | 41 | void gbm_destroy(struct gbm_bo *gbm_bo) { gbm_bo_destroy(gbm_bo); } 42 | 43 | uint32_t gbm_get_handle(struct gbm_bo *gbm_bo) { return gbm_bo_get_handle(gbm_bo).u32; } 44 | 45 | void gbm_fini() { 46 | gbm_device_destroy(gbm); 47 | } 48 | -------------------------------------------------------------------------------- /gbm_.h: -------------------------------------------------------------------------------- 1 | #ifndef gbm_h_INCLUDED 2 | #define gbm_h_INCLUDED 3 | 4 | void gbm_init(int drm_fd); 5 | struct gbm_device *gbm_get_device(); 6 | struct gbm_bo *gbm_import_from_dmabuf(int num_fds, int32_t *dmabuf_fds, 7 | uint32_t width, uint32_t height, uint32_t format, uint32_t *strides, uint32_t 8 | *offsets, uint64_t modifier); 9 | uint32_t gbm_get_handle(struct gbm_bo *gbm_bo); 10 | void gbm_destroy(struct gbm_bo *gbm_bo); 11 | void gbm_fini(); 12 | 13 | #endif // gbm_h_INCLUDED 14 | 15 | -------------------------------------------------------------------------------- /include/backend/bufmgr.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct bufmgr *bufmgr_create(int drm_fd); 5 | void bufmgr_destroy(struct bufmgr *self); 6 | const char *bufmgr_get_name(struct bufmgr *self); 7 | 8 | struct buffer *bufmgr_buffer_create(struct bufmgr *self, int width, int height, 9 | bool linear, int format); 10 | //struct buffer *bufmgr_buffer_import_from_dmabuf(struct bufmgr *self, int 11 | //num_fds, int32_t *dmabuf_fds); 12 | struct buffer *bufmgr_buffer_import_from_dmabuf(struct bufmgr *self, int 13 | num_fds, int32_t *dmabuf_fds, 14 | uint32_t width, uint32_t height, uint32_t format, uint32_t *strides, uint32_t *offsets, 15 | uint64_t modifier); 16 | void buffer_destroy(struct buffer *self); 17 | 18 | uint32_t buffer_get_width(struct buffer *self); 19 | uint32_t buffer_get_height(struct buffer *self); 20 | uint32_t buffer_get_format(struct buffer *self); 21 | uint32_t buffer_get_plane_count(struct buffer *self); 22 | uint32_t buffer_get_handle(struct buffer *self, int i); 23 | uint32_t buffer_get_stride(struct buffer *self, int i); 24 | uint32_t buffer_get_offset(struct buffer *self, int i); 25 | uint64_t buffer_get_modifier(struct buffer *self); 26 | int buffer_get_fd(struct buffer *self); 27 | 28 | /* GBM specific stuff */ 29 | 30 | struct gbm_device *bufmgr_get_gbm_device(struct bufmgr *self); 31 | -------------------------------------------------------------------------------- /include/backend/dev.h: -------------------------------------------------------------------------------- 1 | #include 2 | struct key_dev { 3 | char *devnode; 4 | char *name; 5 | }; 6 | 7 | char *gpu_devpath(int64_t major, int64_t minor); 8 | 9 | struct key_dev *find_keyboard_devices(int *count); 10 | struct key_dev *find_pointer_devices(int *count); 11 | -------------------------------------------------------------------------------- /include/backend/input.h: -------------------------------------------------------------------------------- 1 | struct aaa { 2 | unsigned int key; 3 | unsigned int state; 4 | char name[2]; 5 | 6 | unsigned int mods_depressed; 7 | unsigned int mods_latched; 8 | unsigned int mods_locked; 9 | unsigned int group; 10 | }; 11 | 12 | typedef void (*input_key_event_t)(struct aaa *, void *); 13 | typedef void (*input_modifers_event_t)(struct aaa *, void *); 14 | typedef void (*input_motion_event_t)(unsigned int, int, int, void *); 15 | typedef void (*input_frame_event_t)(void *); 16 | typedef void (*input_button_event_t)(unsigned int, unsigned int, unsigned int, 17 | void *); 18 | 19 | struct input_events { 20 | input_key_event_t key; 21 | input_modifers_event_t modifiers; 22 | input_motion_event_t motion; 23 | input_frame_event_t frame; 24 | input_button_event_t button; 25 | 26 | void *user_data; 27 | }; 28 | 29 | struct input; 30 | 31 | struct input *input_setup(char *kdevpath, char *pdevpath, struct input_events input_events); 32 | int input_get_key_fd(struct input *S); 33 | int input_get_poi_fd_n(struct input *S); 34 | int input_get_poi_fd(struct input *S, int i); 35 | unsigned int input_get_keymap_fd(struct input *S); 36 | unsigned int input_get_keymap_size(struct input *S); 37 | void input_release(struct input *S); 38 | -------------------------------------------------------------------------------- /include/backend/screen.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSCREEN_H 2 | #define MYSCREEN_H 3 | 4 | #include 5 | #include 6 | 7 | struct screen; 8 | struct fb; 9 | 10 | /* 11 | * The screen interface represents a physical screen where the rendering done by 12 | * the Wayland compositor is presented. 13 | */ 14 | 15 | struct screen *screen_setup(void (*vblank_notify)(int,unsigned int,unsigned int, 16 | unsigned int, void*, bool), void *user_data, bool dmabuf_mod, int64_t major, 17 | int64_t minor); 18 | 19 | void drm_handle_event(int fd); 20 | 21 | int screen_get_gpu_fd(struct screen *); 22 | int screen_get_bo_fd(struct screen *); 23 | uint32_t screen_get_bo_stride(struct screen *); 24 | uint64_t screen_get_bo_modifier(struct screen *S); 25 | struct gbm_device *screen_get_gbm_device(struct screen *); 26 | struct box screen_get_dimensions(struct screen *S); 27 | struct buffer *screen_get_back_buffer(struct screen *screen); 28 | struct buffer *screen_get_front_buffer(struct screen *screen); 29 | struct buffer *screen_get_cursor_buffer(struct screen *screen); 30 | const char *screen_get_bufmgr_impl(struct screen *screen); 31 | bool screen_is_overlay_supported(struct screen *S); 32 | void screen_post_direct(struct screen *, uint32_t width, uint32_t height, 33 | uint32_t format, int fd, int stride, int offset, uint64_t modifier); 34 | void screen_post(struct screen *S, int fence_fd); 35 | int screen_atomic_commit(struct screen *self, bool with_out_fence, int 36 | *out_fence_fd); 37 | bool screen_page_flip_is_pending(struct screen *self); 38 | void screen_main(struct screen *S); 39 | 40 | /* 41 | * DRM Framebuffer manager 42 | */ 43 | struct fb *screen_fb_create_from_dmabuf(struct screen *screen, int32_t width, 44 | int32_t height, uint32_t format, uint32_t num_planes, int32_t *fds, uint32_t 45 | *offsets, uint32_t *strides, uint64_t *modifiers); 46 | void screen_fb_schedule_destroy(struct screen *screen, struct fb *fb); 47 | 48 | void client_buffer_on_primary(struct screen *S, struct fb *fb, int in_fence_fd); 49 | void client_buffer_on_overlay(struct screen *S, struct fb *fb, uint32_t width, 50 | uint32_t height, int in_fence_fd); 51 | void alloc(struct screen *S); 52 | void cursor_on_cursor(struct screen *s, int x, int y); 53 | 54 | void screen_release(struct screen *); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/backend/vulkan.h: -------------------------------------------------------------------------------- 1 | int vulkan_init(bool *dmabuf, bool *dmabuf_mod, int64_t *major, int64_t *minor); 2 | void vulkan_render_shm_buffer(uint32_t width, uint32_t height, uint32_t stride, 3 | uint32_t format, uint8_t *data); 4 | int vulkan_main(int i, int fd, int width, int height, int stride, uint64_t modifier); 5 | void vulkan_create_screen_image(struct buffer *back, struct buffer *front); 6 | void vulkan_create_cursor_image(struct buffer *buffer); 7 | void vulkan_render_shm_buffer_cursor(uint32_t width, uint32_t height, uint32_t stride, 8 | uint32_t format, uint8_t *data); 9 | -------------------------------------------------------------------------------- /include/legacy_wl_drm.h: -------------------------------------------------------------------------------- 1 | struct wl_display; 2 | 3 | void legacy_wl_drm_setup(struct wl_display *D, int drm_fd); 4 | -------------------------------------------------------------------------------- /include/swvkc.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int swvkc_initialize(char *kdevpath, char *pdevpath); 4 | void swvkc_run(); 5 | void swvkc_terminate(); 6 | 7 | struct cursor { 8 | int32_t x; 9 | int32_t y; 10 | 11 | int hotspot_x; 12 | int hotspot_y; 13 | }; 14 | -------------------------------------------------------------------------------- /include/util/my_drm_handle_event.h: -------------------------------------------------------------------------------- 1 | int my_drmHandleEvent(int fd, drmEventContextPtr evctx); 2 | -------------------------------------------------------------------------------- /input.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "input.h" 9 | 10 | static int open_restricted(const char *path, int flags, void *user_data) { 11 | int fd = open(path, flags); 12 | return fd < 0 ? -errno : fd; 13 | } 14 | 15 | static void close_restricted(int fd, void *user_data) { 16 | close(fd); 17 | } 18 | 19 | struct libinput *input_init() { 20 | int r; 21 | 22 | const struct libinput_interface interface = { 23 | .open_restricted = open_restricted, 24 | .close_restricted = close_restricted, 25 | }; 26 | 27 | struct udev *udev = udev_new(); 28 | assert(udev); 29 | struct libinput *li = libinput_udev_create_context(&interface, NULL, udev); 30 | assert(li); 31 | r = libinput_udev_assign_seat(li, "seat0"); 32 | assert(!r); 33 | 34 | return li; 35 | 36 | /*const char *path = "/dev/input/event0"; 37 | libinput = libinput_path_create_context(&interface, NULL); 38 | assert(libinput); 39 | struct libinput_device *device = libinput_path_add_device(libinput, path); 40 | assert(device);*/ 41 | } 42 | 43 | void input_fini(struct libinput *li) { 44 | //li = libinput_unref(li); 45 | //assert(!li); 46 | } 47 | -------------------------------------------------------------------------------- /input.h: -------------------------------------------------------------------------------- 1 | #ifndef input_h_INCLUDED 2 | #define input_h_INCLUDED 3 | 4 | #include 5 | 6 | struct libinput *input_init(); 7 | void input_fini(struct libinput *li); 8 | 9 | #endif // input_h_INCLUDED 10 | -------------------------------------------------------------------------------- /legacy_wl_drm.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | static PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL = 0; 10 | 11 | void legacy_wl_drm_init(struct wl_display *D, struct gbm_device *gbm) { 12 | EGLDisplay display = eglGetPlatformDisplay(EGL_PLATFORM_GBM_MESA, gbm, 13 | NULL); 14 | if (display == EGL_NO_DISPLAY) { 15 | fprintf(stderr, "eglGetPlatformDisplay failed\n"); 16 | } 17 | 18 | EGLint major, minor; 19 | if (eglInitialize(display, &major, &minor) == EGL_FALSE) { 20 | fprintf(stderr, "eglInitialize failed\n"); 21 | } 22 | 23 | eglBindWaylandDisplayWL = (PFNEGLBINDWAYLANDDISPLAYWL) 24 | eglGetProcAddress("eglBindWaylandDisplayWL"); 25 | 26 | if (eglBindWaylandDisplayWL(display, D) == EGL_FALSE) { 27 | fprintf(stderr, "eglBindWaylandDisplayWL failed\n"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /legacy_wl_drm_.h: -------------------------------------------------------------------------------- 1 | #ifndef legacy_wl_drm_h_INCLUDED 2 | #define legacy_wl_drm_h_INCLUDED 3 | 4 | void legacy_wl_drm_init(struct wl_display *D, struct gbm_device *gbm); 5 | 6 | #endif // legacy_wl_drm_h_INCLUDED 7 | 8 | -------------------------------------------------------------------------------- /loop.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 2 2 | 3 | #include "input.h" 4 | #include "atomic.h" 5 | #include "modeset.h" 6 | #include "wayland.h" 7 | #include "xkb.h" 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define FDS 3 24 | 25 | static int kill1; 26 | 27 | static void spawn_client(char **argv) { 28 | if (fork() == 0) { 29 | execvp(argv[0], argv); 30 | fprintf(stderr, "execvp %s: %s\n", argv[0], strerror(errno)); 31 | _exit(EXIT_FAILURE); 32 | /* NOTREACHED */ 33 | } 34 | } 35 | 36 | static int handler_key(struct libinput_event *event) { 37 | struct libinput_event_keyboard *event_keyboard = 38 | libinput_event_get_keyboard_event(event); 39 | assert(event_keyboard); 40 | 41 | uint32_t key = libinput_event_keyboard_get_key(event_keyboard); 42 | int state = libinput_event_keyboard_get_key_state(event_keyboard); // WARNING 43 | 44 | xkb_update(key, state); 45 | 46 | unsigned int mods_depressed, mods_latched, mods_locked, group; 47 | xkb_get_modifiers(&mods_depressed, &mods_latched, &mods_locked, &group); 48 | 49 | if (xkb_test_ctrlalt() && key == (kill1 ? KEY_DELETE : KEY_BACKSPACE)) 50 | return 1; // exit 51 | if (xkb_test_ctrlalt() && key == KEY_ENTER) { 52 | const char* child_argv[] = {"weston-terminal", NULL}; 53 | spawn_client((char**)child_argv); // emergency terminal 54 | return 0; 55 | } 56 | 57 | wayland_send_key_and_mods(key, state, mods_depressed, mods_latched, mods_locked, group); 58 | return 0; 59 | } 60 | 61 | static void handler_pointer(struct libinput_event *event) { 62 | 63 | } 64 | 65 | static int handler_input(struct libinput *li) { 66 | int r; 67 | r = libinput_dispatch(li); 68 | assert(!r); 69 | 70 | int exit = 0; 71 | 72 | struct libinput_event *event; 73 | while ((event = libinput_get_event(li))) { 74 | switch (libinput_event_get_type(event)) { 75 | case LIBINPUT_EVENT_KEYBOARD_KEY: 76 | exit = exit || handler_key(event); 77 | break; 78 | case LIBINPUT_EVENT_POINTER_MOTION: 79 | handler_pointer(event); 80 | break; 81 | default: break; 82 | } 83 | libinput_event_destroy(event); 84 | } 85 | 86 | return exit; 87 | } 88 | 89 | static void check_3_open() { 90 | if (fcntl(3, F_GETFD) < 0) strerr_die1x(1, "readiness notification"); 91 | } 92 | 93 | const char *usage = "usage: xyzzy [-k] [client]\n\ 94 | \n\ 95 | Experimental Wayland system compositor\n\ 96 | \n\ 97 | positional arguments:\n\ 98 | client client to exec\n\ 99 | \n\ 100 | optional arguments:\n\ 101 | -h show this help message and exit\n\ 102 | -k kill PID 1 on exit (becomes Ctrl+Alt+Del)\n\ 103 | -3 notify readiness on fd 3\n"; 104 | int main(int argc, char *argv[]) { 105 | int notif = 0; 106 | 107 | int opt; 108 | while ((opt = getopt(argc, argv, "hk3")) != -1) { 109 | switch (opt) { 110 | case 'k': kill1 = 1; break; 111 | case '3': check_3_open(); notif = 1; break; 112 | default: 113 | fprintf(stderr, usage); 114 | return EXIT_FAILURE; 115 | } 116 | } 117 | 118 | struct libinput *li = input_init(); 119 | modeset_init(); 120 | atomic_init(); 121 | wayland_init(); 122 | xkb_init(); 123 | 124 | if (notif) { 125 | write(3, "\n", 1); // ready to accept connections 126 | close(3); 127 | } 128 | 129 | if (argc > optind) spawn_client(argv+optind); 130 | 131 | iopause_fd x[FDS] = { 132 | { libinput_get_fd(li), IOPAUSE_READ, 0 }, 133 | { wayland_get_fd(), IOPAUSE_READ, 0 }, 134 | { modeset_get_fd(), IOPAUSE_READ, 0 }, 135 | }; 136 | 137 | int exit = 0; 138 | while (!exit) { 139 | wayland_flush(); 140 | iopause(x, FDS, NULL, NULL); 141 | if (x[0].revents & IOPAUSE_READ) exit = handler_input(li); 142 | if (x[1].revents & IOPAUSE_READ) wayland_read(); 143 | if (x[2].revents & IOPAUSE_READ) drm_read(); 144 | } 145 | 146 | modeset_cleanup(); 147 | input_fini(li); 148 | 149 | if (kill1) kill(1, SIGINT); 150 | } 151 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('swvkc', 'c', version: 'pre-alpha', 2 | default_options: ['c_std=c11', 'warning_level=3', 'werror=true']) 3 | add_project_arguments('-pedantic-errors', '-Wno-unused-parameter', 4 | '-Wno-unused-function', language : 'c') 5 | 6 | wl_proj = subproject('libswvkc-wl') 7 | wl_dep = wl_proj.get_variable('libswvkc_wl_dep') 8 | 9 | if get_option('xyzzy') 10 | xyzzy_src = files(['atomic.c', 'input.c', 'gbm.c', 'loop.c', 'modeset.c', 'wayland.c', 'xkb.c', 'legacy_wl_drm.c']) 11 | 12 | cc = meson.get_compiler('c') 13 | skalibs = cc.find_library('skarnet') 14 | 15 | xyzzy_dep = [skalibs] 16 | xyzzy_dep += dependency('egl') 17 | xyzzy_dep += dependency('gbm') 18 | xyzzy_dep += dependency('libdrm') 19 | xyzzy_dep += dependency('libinput') 20 | xyzzy_dep += dependency('libudev') 21 | xyzzy_dep += dependency('xkbcommon') 22 | xyzzy_dep += wl_proj.get_variable('libswvkc_wl_dep') 23 | 24 | xyzzy_inc = [] 25 | 26 | executable('xyzzy', xyzzy_src, dependencies: xyzzy_dep, include_directories: xyzzy_inc, c_args: ['-Wno-error=format=', '-Wno-error=sign-compare', '-Wno-error=unused-variable']) 27 | endif 28 | 29 | src = [] 30 | subdir('src') 31 | 32 | dep = [wl_dep] 33 | dep += dependency('egl') # required for legacy wl_drm 34 | dep += dependency('gbm') # required by egl 35 | dep += dependency('libdrm') 36 | dep += dependency('libdrm_intel', required: bufmgr == 'intel') 37 | dep += dependency('libudev') 38 | dep += dependency('vulkan', version : '>=1.2.182') 39 | dep += dependency('xkbcommon') 40 | 41 | inc = include_directories('include') 42 | 43 | executable('swvkc', src, dependencies: dep, include_directories: inc, 44 | install: true) 45 | 46 | summary = [ 47 | '', 48 | '----------------', 49 | 'swvkc @0@'.format(meson.project_version()), 50 | '', 51 | ' bufmgr (buffer manager): @0@'.format(bufmgr), 52 | '----------------', 53 | '' 54 | ] 55 | message('\n'.join(summary)) 56 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('bufmgr', type: 'combo', choices: ['gbm', 'intel'], value: 'gbm', description: 'Buffer manager implementation') 2 | option('xyzzy', type: 'boolean', value: 'false', description: 'System compositor (experimental)') 3 | -------------------------------------------------------------------------------- /modeset.h: -------------------------------------------------------------------------------- 1 | #ifndef modeset_h_INCLUDED 2 | #define modeset_h_INCLUDED 3 | 4 | #include 5 | 6 | void modeset_init(); 7 | int modeset_get_fd(); 8 | uint32_t modeset_get_crtc(); 9 | uint32_t modeset_get_conn(); 10 | uint32_t modeset_get_fb(); 11 | uint32_t modeset_get_width(); 12 | uint32_t modeset_get_height(); 13 | void modeset_draw(); 14 | void modeset_copy(uint32_t stride, uint32_t width, uint32_t height, uint8_t* m); 15 | void modeset_cleanup(); 16 | 17 | #endif // modeset_h_INCLUDED 18 | 19 | -------------------------------------------------------------------------------- /src/backend/bufmgr_gbm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | /* 9 | * Implementation of the buffer manager via GBM 10 | * 11 | * ISSUES: 12 | * weston-simple-dmabuf-v4l: buffer_get_plane_count returns 2 13 | */ 14 | 15 | struct bufmgr { 16 | struct gbm_device *gbm_device; 17 | }; 18 | 19 | struct buffer { 20 | struct gbm_bo *gbm_bo; 21 | }; 22 | 23 | struct bufmgr *bufmgr_create(int drm_fd) { 24 | struct gbm_device *gbm_device = gbm_create_device(drm_fd); 25 | if (!gbm_device) { 26 | fprintf(stderr, "gbm_create_device failed\n"); 27 | return NULL; 28 | } 29 | 30 | struct bufmgr *self = malloc(sizeof(struct bufmgr)); 31 | self->gbm_device = gbm_device; 32 | return self; 33 | } 34 | 35 | void bufmgr_destroy(struct bufmgr *self) { 36 | if (!self) { 37 | fprintf(stderr, "bufmgr_destroy: invalid bufmgr\n"); 38 | return; 39 | } 40 | gbm_device_destroy(self->gbm_device); 41 | free(self); 42 | } 43 | 44 | const char *bufmgr_get_name(struct bufmgr *self) { 45 | return "GBM"; 46 | } 47 | 48 | struct buffer *bufmgr_buffer_create(struct bufmgr *self, int width, int height, 49 | bool linear, int format) { 50 | if (!self) { 51 | fprintf(stderr, "bufmgr_buffer_create: invalid bufmgr\n"); 52 | return NULL; 53 | } 54 | 55 | uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; 56 | if (linear) 57 | flags |= GBM_BO_USE_LINEAR; 58 | 59 | if (!gbm_device_is_format_supported(self->gbm_device, 60 | GBM_BO_FORMAT_XRGB8888, flags)) { 61 | fprintf(stderr, "format unsupported\n"); 62 | return NULL; 63 | } 64 | 65 | struct gbm_bo *gbm_bo = gbm_bo_create(self->gbm_device, width, 66 | height, format == 0 ? GBM_BO_FORMAT_XRGB8888 : GBM_BO_FORMAT_ARGB8888, flags); 67 | 68 | /* uint64_t modifier = I915_FORMAT_MOD_X_TILED; 69 | S->gbm_bo = gbm_bo_create_with_modifiers(S->gbm_device, 70 | screen_size.width, screen_size.height, 71 | GBM_BO_FORMAT_XRGB8888, &modifier, 1);*/ 72 | if (!gbm_bo) { 73 | fprintf(stderr, "gbm_bo_create failed\n"); 74 | return NULL; 75 | } 76 | 77 | struct buffer *buffer = malloc(sizeof(struct buffer)); 78 | buffer->gbm_bo = gbm_bo; 79 | return buffer; 80 | } 81 | 82 | struct buffer *bufmgr_buffer_import_from_dmabuf(struct bufmgr *self, int 83 | num_fds, int32_t *dmabuf_fds, 84 | uint32_t width, uint32_t height, uint32_t format, uint32_t *strides, uint32_t *offsets, 85 | uint64_t modifier) { 86 | if (!self) { 87 | fprintf(stderr, "bufmgr_buffer_import_from_dmabuf: invalid bufmgr\n"); 88 | return NULL; 89 | } 90 | struct gbm_import_fd_modifier_data data = { 91 | .width = width, 92 | .height = height, 93 | .format = format, 94 | .num_fds = 1, 95 | .fds[0] = dmabuf_fds[0], 96 | .strides[0] = strides[0], 97 | .offsets[0] = offsets[0], 98 | .modifier = modifier 99 | }; 100 | struct gbm_bo *gbm_bo = gbm_bo_import(self->gbm_device, 101 | GBM_BO_IMPORT_FD_MODIFIER, &data, GBM_BO_USE_SCANOUT); 102 | 103 | if (!gbm_bo) { 104 | fprintf(stderr, "gbm_bo_import failed\n"); 105 | return NULL; 106 | } 107 | 108 | struct buffer *buffer = malloc(sizeof(struct buffer)); 109 | buffer->gbm_bo = gbm_bo; 110 | return buffer; 111 | } 112 | 113 | void buffer_destroy(struct buffer *self) { 114 | if (!self) { 115 | fprintf(stderr, "buffer_destroy: invalid buffer\n"); 116 | return; 117 | } 118 | gbm_bo_destroy(self->gbm_bo); 119 | free(self); 120 | } 121 | 122 | uint32_t buffer_get_width(struct buffer *self) { 123 | if (!self) { 124 | fprintf(stderr, "buffer_get_width: invalid buffer\n"); 125 | return 0; 126 | } 127 | return gbm_bo_get_width(self->gbm_bo); 128 | } 129 | 130 | uint32_t buffer_get_height(struct buffer *self) { 131 | if (!self) { 132 | fprintf(stderr, "buffer_get_height: invalid buffer\n"); 133 | return 0; 134 | } 135 | return gbm_bo_get_height(self->gbm_bo); 136 | } 137 | 138 | uint32_t buffer_get_format(struct buffer *self) { 139 | if (!self) { 140 | fprintf(stderr, "buffer_get_format: invalid buffer\n"); 141 | return 0; 142 | } 143 | return gbm_bo_get_format(self->gbm_bo); 144 | } 145 | 146 | uint32_t buffer_get_plane_count(struct buffer *self) { 147 | if (!self) { 148 | fprintf(stderr, "buffer_get_plane_count: invalid buffer\n"); 149 | return 0; 150 | } 151 | return gbm_bo_get_plane_count(self->gbm_bo); 152 | } 153 | 154 | uint32_t buffer_get_handle(struct buffer *self, int i) { 155 | if (!self) { 156 | fprintf(stderr, "buffer_get_handle: invalid buffer\n"); 157 | return 0; 158 | } 159 | return gbm_bo_get_handle_for_plane(self->gbm_bo, i).u32; 160 | } 161 | 162 | uint32_t buffer_get_stride(struct buffer *self, int i) { 163 | if (!self) { 164 | fprintf(stderr, "buffer_get_stride: invalid buffer\n"); 165 | return 0; 166 | } 167 | return gbm_bo_get_stride_for_plane(self->gbm_bo, i); 168 | } 169 | 170 | uint32_t buffer_get_offset(struct buffer *self, int i) { 171 | if (!self) { 172 | fprintf(stderr, "buffer_get_offset: invalid buffer\n"); 173 | return 0; 174 | } 175 | return gbm_bo_get_offset(self->gbm_bo, i); 176 | } 177 | 178 | uint64_t buffer_get_modifier(struct buffer *self) { 179 | if (!self) { 180 | fprintf(stderr, "buffer_get_modifier: invalid buffer\n"); 181 | return 0; 182 | } 183 | return gbm_bo_get_modifier(self->gbm_bo); 184 | } 185 | 186 | int buffer_get_fd(struct buffer *self) { 187 | if (!self) { 188 | fprintf(stderr, "buffer_get_fd: invalid buffer\n"); 189 | return -1; 190 | } 191 | return gbm_bo_get_fd(self->gbm_bo); 192 | } 193 | 194 | /* GBM specific stuff */ 195 | 196 | struct gbm_device *bufmgr_get_gbm_device(struct bufmgr *self) { 197 | if (!self) { 198 | fprintf(stderr, "bufmgr_get_gbm_device: invalid bufmgr\n"); 199 | return 0; 200 | } 201 | return self->gbm_device; 202 | } 203 | -------------------------------------------------------------------------------- /src/backend/bufmgr_intel.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | /* 15 | * Implementation of the buffer manager for Intel GPUs 16 | */ 17 | 18 | struct bufmgr { 19 | drm_intel_bufmgr *bufmgr; 20 | }; 21 | 22 | struct buffer { 23 | uint32_t width; 24 | uint32_t height; 25 | uint32_t format; 26 | int bo_count; 27 | drm_intel_bo **bos; 28 | uint32_t *strides; 29 | uint32_t *offsets; 30 | uint64_t modifier; 31 | }; 32 | 33 | struct bufmgr *bufmgr_create(int drm_fd) { 34 | struct bufmgr *self = malloc(sizeof(struct bufmgr)); 35 | /* 36 | * What is batch_size? Is 32 an acceptable value? 37 | */ 38 | self->bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 32); 39 | if (!self->bufmgr) { 40 | fprintf(stderr, "drm_intel_bufmgr_gem_init failed\n"); 41 | return NULL; 42 | } 43 | return self; 44 | } 45 | 46 | void bufmgr_destroy(struct bufmgr *self) { 47 | drm_intel_bufmgr_destroy(self->bufmgr); 48 | free(self); 49 | } 50 | 51 | const char *bufmgr_get_name(struct bufmgr *self) { 52 | return "intel_bufmgr"; 53 | } 54 | 55 | struct buffer *bufmgr_buffer_create(struct bufmgr *self, int width, int height, 56 | bool linear, int format) { 57 | int bpp = 32; 58 | uint32_t tiling = linear ? I915_TILING_NONE : I915_TILING_X; 59 | long unsigned int stride; 60 | drm_intel_bo *bo = drm_intel_bo_alloc_tiled(self->bufmgr, "main", width, 61 | height, bpp/8, &tiling, &stride, 0); 62 | if (!bo) { 63 | fprintf(stderr, "drm_intel_bo_alloc failed\n"); 64 | return NULL; 65 | } 66 | printf("intel_bufmgr: allocated %dx%d, stride: %lu\n", width, height, 67 | stride); 68 | 69 | struct buffer *buffer = malloc(sizeof(struct buffer)); 70 | buffer->width = width; 71 | buffer->height = height; 72 | /* 73 | * I can choose a format with bpp = 32 74 | */ 75 | buffer->format = format == 0 ? DRM_FORMAT_XRGB8888 : DRM_FORMAT_ARGB8888; 76 | buffer->bo_count = 1; 77 | buffer->bos = malloc(sizeof(struct drm_intel_bo *)); 78 | buffer->bos[0] = bo; 79 | buffer->strides = malloc(sizeof(uint32_t)); 80 | buffer->strides[0] = stride; 81 | buffer->offsets = malloc(sizeof(uint32_t)); 82 | /* 83 | * I'll guess the offset here... 84 | */ 85 | buffer->offsets[0] = 0; 86 | switch (tiling) { 87 | case I915_TILING_NONE: 88 | buffer->modifier = DRM_FORMAT_MOD_LINEAR; 89 | break; 90 | case I915_TILING_X: 91 | buffer->modifier = I915_FORMAT_MOD_X_TILED; 92 | break; 93 | case I915_TILING_Y: 94 | buffer->modifier = I915_FORMAT_MOD_Y_TILED; 95 | break; 96 | default: 97 | buffer->modifier = DRM_FORMAT_MOD_INVALID; 98 | } 99 | return buffer; 100 | } 101 | 102 | struct buffer *bufmgr_buffer_import_from_dmabuf(struct bufmgr *self, int 103 | num_fds, int32_t *dmabuf_fds, 104 | uint32_t width, uint32_t height, uint32_t format, uint32_t *strides, uint32_t *offsets, 105 | uint64_t modifier) { 106 | drm_intel_bo **bos = malloc(num_fds*sizeof(struct drm_intel_bo *)); 107 | for (int i=0; ibufmgr, 109 | dmabuf_fds[i], 0); 110 | if (!bos[i]) { 111 | fprintf(stderr, "drm_intel_bo_gem_create_from_prime failed\n"); 112 | free(bos); 113 | return NULL; 114 | } 115 | 116 | // drm_intel_gem_bo_disable_implicit_sync(bos[i]); XXX: investigate this 117 | } 118 | struct buffer *buffer = malloc(sizeof(struct buffer)); 119 | buffer->width = width; 120 | buffer->height = height; 121 | buffer->format = format; 122 | buffer->bo_count = num_fds; 123 | buffer->bos = bos; 124 | /* 125 | * The wl_buffer_dmabuf memory should stay valid 126 | */ 127 | buffer->strides = strides; 128 | buffer->offsets = offsets; 129 | buffer->modifier = modifier; 130 | return buffer; 131 | } 132 | 133 | void buffer_destroy(struct buffer *self) { 134 | for (int i=0; ibo_count; i++) 135 | drm_intel_bo_unreference(self->bos[i]); 136 | free(self->bos); 137 | free(self); 138 | } 139 | 140 | uint32_t buffer_get_width(struct buffer *self) { 141 | if (!self) { 142 | fprintf(stderr, "buffer_get_width: invalid buffer\n"); 143 | return 0; 144 | } 145 | return self->width; 146 | } 147 | 148 | uint32_t buffer_get_height(struct buffer *self) { 149 | if (!self) { 150 | fprintf(stderr, "buffer_get_height: invalid buffer\n"); 151 | return 0; 152 | } 153 | return self->height; 154 | } 155 | 156 | uint32_t buffer_get_format(struct buffer *self) { 157 | if (!self) { 158 | fprintf(stderr, "buffer_get_format: invalid buffer\n"); 159 | return 0; 160 | } 161 | return self->format; 162 | } 163 | 164 | uint32_t buffer_get_plane_count(struct buffer *self) { 165 | if (!self) { 166 | fprintf(stderr, "buffer_get_plane_count: invalid buffer\n"); 167 | return 0; 168 | } 169 | return self->bo_count; 170 | } 171 | 172 | uint32_t buffer_get_handle(struct buffer *self, int i) { 173 | if (!self) { 174 | fprintf(stderr, "buffer_get_handle: self is NULL\n"); 175 | return 0; 176 | } else if (!self->bos[i]) { 177 | fprintf(stderr, "buffer_get_handle: buffer is invalid\n"); 178 | return 0; 179 | } 180 | return self->bos[i]->handle; 181 | } 182 | 183 | uint32_t buffer_get_stride(struct buffer *self, int i) { 184 | if (!self) { 185 | fprintf(stderr, "buffer_get_stride: invalid buffer\n"); 186 | return 0; 187 | } 188 | return self->strides[i]; 189 | } 190 | 191 | uint32_t buffer_get_offset(struct buffer *self, int i) { 192 | if (!self) { 193 | fprintf(stderr, "buffer_get_offset: invalid buffer\n"); 194 | return 0; 195 | } 196 | return self->offsets[i]; 197 | } 198 | 199 | uint64_t buffer_get_modifier(struct buffer *self) { 200 | if (!self) { 201 | fprintf(stderr, "buffer_get_modifier: invalid buffer\n"); 202 | return 0; 203 | } 204 | return self->modifier; 205 | } 206 | 207 | int buffer_get_fd(struct buffer *self) { 208 | if (!self) { 209 | fprintf(stderr, "buffer_get_fd: invalid buffer\n"); 210 | return -1; 211 | } 212 | int prime_fd; 213 | drm_intel_bo_gem_export_to_prime(self->bos[0], &prime_fd); 214 | return prime_fd; 215 | } 216 | 217 | /* GBM specific stuff */ 218 | 219 | struct gbm_device *bufmgr_get_gbm_device(struct bufmgr *self) { 220 | return NULL; 221 | } 222 | -------------------------------------------------------------------------------- /src/backend/dev.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | char *gpu_devpath(int64_t major, int64_t minor) { 10 | char *devpath = 0; 11 | struct udev *udev = udev_new(); 12 | dev_t dev = makedev(major, minor); 13 | struct udev_device *udev_dev = udev_device_new_from_devnum(udev, 'c', dev); 14 | devpath = strdup(udev_device_get_devnode(udev_dev)); 15 | udev_device_unref(udev_dev); 16 | udev_unref(udev); 17 | return devpath; 18 | } 19 | 20 | struct key_dev *find_keyboard_devices(int *count) { 21 | struct udev *udev = udev_new(); 22 | struct udev_enumerate *enu = udev_enumerate_new(udev); 23 | udev_enumerate_add_match_property(enu, "ID_INPUT_KEYBOARD", "1"); 24 | udev_enumerate_add_match_sysname(enu, "event*"); 25 | udev_enumerate_scan_devices(enu); 26 | struct udev_list_entry *cur; 27 | *count = 0; 28 | udev_list_entry_foreach(cur, udev_enumerate_get_list_entry(enu)) { 29 | (*count)++; 30 | } 31 | struct key_dev *key_devs = calloc(*count, sizeof(struct key_dev)); 32 | int i=0; 33 | udev_list_entry_foreach(cur, udev_enumerate_get_list_entry(enu)) { 34 | struct udev_device *dev = udev_device_new_from_syspath(udev, 35 | udev_list_entry_get_name(cur)); 36 | const char *devnode = udev_device_get_devnode(dev); 37 | key_devs[i].devnode = malloc((strlen(devnode)+1)*sizeof(char)); 38 | strcpy(key_devs[i].devnode, devnode); 39 | i++; 40 | } 41 | return key_devs; 42 | } 43 | 44 | struct key_dev *find_pointer_devices(int *count) { 45 | struct udev *udev = udev_new(); 46 | struct udev_enumerate *enu = udev_enumerate_new(udev); 47 | udev_enumerate_add_match_property(enu, "ID_INPUT_MOUSE", "1"); 48 | udev_enumerate_add_match_property(enu, "ID_INPUT_TOUCHPAD", "1"); 49 | udev_enumerate_add_match_sysname(enu, "event*"); 50 | udev_enumerate_scan_devices(enu); 51 | struct udev_list_entry *cur; 52 | *count = 0; 53 | udev_list_entry_foreach(cur, udev_enumerate_get_list_entry(enu)) { 54 | (*count)++; 55 | } 56 | struct key_dev *key_devs = calloc(*count, sizeof(struct key_dev)); 57 | int i=0; 58 | udev_list_entry_foreach(cur, udev_enumerate_get_list_entry(enu)) { 59 | struct udev_device *dev = udev_device_new_from_syspath(udev, 60 | udev_list_entry_get_name(cur)); 61 | const char *devnode = udev_device_get_devnode(dev); 62 | key_devs[i].devnode = malloc((strlen(devnode)+1)*sizeof(char)); 63 | strcpy(key_devs[i].devnode, devnode); 64 | i++; 65 | } 66 | return key_devs; 67 | } 68 | -------------------------------------------------------------------------------- /src/backend/input.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | struct input { 19 | int key_fd; 20 | int pointer_fds[16]; 21 | int n_pointer_fds; 22 | int keymap_fd; 23 | unsigned int keymap_size; 24 | 25 | struct xkb_context *context; 26 | struct xkb_keymap *keymap; 27 | struct xkb_state *state; 28 | 29 | struct input_events input_events; 30 | }; 31 | 32 | void free_keyboard_devices(struct key_dev *key_devs, int count) { 33 | for (int i=0; i= 0) { 61 | long flags = fcntl(fd, F_GETFD); 62 | fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 63 | unlink(name); 64 | } 65 | 66 | free(name); 67 | 68 | if (fd < 0) 69 | return -1; 70 | 71 | do { 72 | ret = posix_fallocate(fd, 0, size); 73 | } while (ret == EINTR); 74 | if (ret != 0) { 75 | close(fd); 76 | errno = ret; 77 | return -1; 78 | } 79 | 80 | return fd; 81 | } 82 | 83 | struct input *input_setup(char *kdevpath, char *pdevpath, struct input_events input_events) { 84 | printf("├─ INPUT (Linux Input Subsystem)\n"); 85 | int count, n; 86 | struct key_dev *key_devs; 87 | if (kdevpath) { 88 | key_devs = calloc(1, sizeof(struct key_dev)); 89 | key_devs->devnode = kdevpath; 90 | count = 1; 91 | } 92 | else 93 | key_devs = find_keyboard_devices(&count); 94 | 95 | if (count > 1) { 96 | printf("Found multiple keyboards:\n"); 97 | for (int i=0; idevnode = pdevpath; 114 | S->n_pointer_fds = 1; 115 | } 116 | else 117 | key_devs_ = find_pointer_devices(&S->n_pointer_fds); 118 | 119 | for (int i=0; in_pointer_fds; i++) { 120 | boxlog(" Pointer device node: %s", key_devs_[i].devnode); 121 | S->pointer_fds[i] = open(key_devs_[i].devnode, O_RDONLY | O_CLOEXEC); 122 | if (S->pointer_fds[i] < 0) { 123 | fprintf(stderr, "open %s: %s\n", key_devs_[i].devnode, strerror(errno)); 124 | return 0; 125 | } 126 | } 127 | 128 | S->input_events = input_events; 129 | S->key_fd = open(key_devs[n].devnode, O_RDONLY | O_CLOEXEC); 130 | if (S->key_fd < 0) { 131 | fprintf(stderr, "open %s: %s\n", key_devs[n].devnode, strerror(errno)); 132 | return 0; 133 | } 134 | free_keyboard_devices(key_devs, kdevpath ? 0 : count); 135 | free_keyboard_devices(key_devs_, pdevpath ? 0 : S->n_pointer_fds); 136 | 137 | ioctl(S->key_fd, EVIOCGRAB, 1); 138 | 139 | S->context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 140 | if (!S->context) { 141 | printf("Cannot create XKB context\n"); 142 | } 143 | 144 | struct xkb_rule_names rules = { 145 | getenv("XKB_DEFAULT_RULES"), 146 | getenv("XKB_DEFAULT_MODEL"), 147 | getenv("XKB_DEFAULT_LAYOUT"), 148 | getenv("XKB_DEFAULT_VARIANT"), 149 | getenv("XKB_DEFAULT_OPTIONS") 150 | }; 151 | 152 | S->keymap = xkb_map_new_from_names(S->context, &rules, 153 | XKB_KEYMAP_COMPILE_NO_FLAGS); 154 | if (S->keymap == NULL) { 155 | xkb_context_unref(S->context); 156 | printf("Cannot create XKB keymap\n"); 157 | return 0; 158 | } 159 | 160 | char *keymap_str = NULL; 161 | keymap_str = xkb_keymap_get_as_string(S->keymap, 162 | XKB_KEYMAP_FORMAT_TEXT_V1); 163 | S->keymap_size = strlen(keymap_str) + 1; 164 | S->keymap_fd = create_file(S->keymap_size); 165 | if (S->keymap_fd < 0) { 166 | printf("creating a keymap file for %u bytes failed\n", S->keymap_size); 167 | return 0; 168 | } 169 | void *ptr = mmap(NULL, S->keymap_size, 170 | PROT_READ | PROT_WRITE, MAP_SHARED, S->keymap_fd, 0); 171 | if (ptr == (void*)-1) { 172 | printf("failed to mmap() %u bytes", S->keymap_size); 173 | return 0; 174 | } 175 | strcpy(ptr, keymap_str); 176 | free(keymap_str); 177 | 178 | S->state = xkb_state_new(S->keymap); 179 | 180 | return S; 181 | } 182 | 183 | int input_get_key_fd(struct input *S) { 184 | return S->key_fd; 185 | } 186 | 187 | int input_get_poi_fd_n(struct input *S) { 188 | return S->n_pointer_fds; 189 | } 190 | 191 | int input_get_poi_fd(struct input *S, int i) { 192 | return S->pointer_fds[i]; 193 | } 194 | 195 | unsigned int input_get_keymap_fd(struct input *S) { 196 | return S->keymap_fd; 197 | } 198 | 199 | unsigned int input_get_keymap_size(struct input *S) { 200 | return S->keymap_size; 201 | } 202 | 203 | 204 | int key_ev_handler(int fd, uint32_t mask, void *data) { 205 | static struct aaa aaa; 206 | struct input *S = data; 207 | 208 | struct input_event ev; 209 | read(fd, &ev, sizeof(struct input_event)); 210 | 211 | if (ev.type == EV_KEY) { 212 | if (ev.value == 2) 213 | return 0; 214 | aaa.key = ev.code; 215 | aaa.state = ev.value > 0 ? 1 : 0; 216 | xkb_keycode_t keycode = aaa.key + 8; 217 | xkb_state_key_get_utf8(S->state, keycode, aaa.name, 2); 218 | enum xkb_key_direction direction = aaa.state ? XKB_KEY_DOWN : XKB_KEY_UP; 219 | 220 | xkb_state_update_key(S->state, keycode, direction); 221 | 222 | aaa.mods_depressed = xkb_state_serialize_mods(S->state, 223 | XKB_STATE_MODS_DEPRESSED); 224 | aaa.mods_latched = xkb_state_serialize_mods(S->state, 225 | XKB_STATE_MODS_LATCHED); 226 | aaa.mods_locked = xkb_state_serialize_mods(S->state, 227 | XKB_STATE_MODS_LOCKED); 228 | aaa.group = xkb_state_serialize_layout(S->state, 229 | XKB_STATE_LAYOUT_EFFECTIVE); 230 | 231 | S->input_events.key(&aaa, S->input_events.user_data); 232 | } 233 | 234 | return 0; 235 | } 236 | 237 | int32_t abs_x = 0; 238 | int32_t abs_y = 0; 239 | /* 240 | * For touchpads, we track beginning/end of the gesture via motion_{x,y} 241 | * motion_{x,y} is true while finger is sliding on touchpad, and becomes false 242 | * when the finger is lifted 243 | */ 244 | bool motion_x = false; 245 | bool motion_y = false; 246 | 247 | int pointer_ev_handler(int fd, uint32_t mask, void *data) { 248 | struct input *S = data; 249 | 250 | struct input_event ev; 251 | read(fd, &ev, sizeof(struct input_event)); 252 | 253 | if (ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 0) { 254 | motion_x = false, motion_y = false; 255 | return 0; 256 | } else if (ev.type == EV_ABS && ev.code == ABS_X) { 257 | if (motion_x) { 258 | int dx = (ev.value - abs_x)/2; 259 | S->input_events.motion(0, dx, 0, S->input_events.user_data); 260 | } else 261 | motion_x = true; 262 | abs_x = ev.value; 263 | return 0; 264 | } else if (ev.type == EV_ABS && ev.code == ABS_Y) { 265 | if (motion_y) { 266 | int dy = (ev.value - abs_y)/2; 267 | S->input_events.motion(0, 0, dy, S->input_events.user_data); 268 | } else 269 | motion_y = true; 270 | abs_y = ev.value; 271 | return 0; 272 | } else if (ev.type == EV_SYN) { 273 | S->input_events.frame(S->input_events.user_data); 274 | return 0; 275 | } else if (ev.type == EV_KEY && ev.code == BTN_LEFT) { 276 | S->input_events.button(0, BTN_LEFT, ev.value, 277 | S->input_events.user_data); 278 | return 0; 279 | } else if (ev.type == EV_REL && ev.code == REL_X) { 280 | int dx = ev.value; 281 | S->input_events.motion(0, dx, 0, S->input_events.user_data); 282 | return 0; 283 | } else if (ev.type == EV_REL && ev.code == REL_Y) { 284 | int dy = ev.value; 285 | S->input_events.motion(0, 0, dy, S->input_events.user_data); 286 | return 0; 287 | } else 288 | return 0; 289 | } 290 | 291 | void input_release(struct input *S) { 292 | xkb_state_unref(S->state); 293 | xkb_keymap_unref(S->keymap); 294 | xkb_context_unref(S->context); 295 | close(S->key_fd); 296 | close(S->pointer_fds[0]); 297 | free(S); 298 | } 299 | -------------------------------------------------------------------------------- /src/backend/meson.build: -------------------------------------------------------------------------------- 1 | bufmgr = get_option('bufmgr') 2 | 3 | src += files(['bufmgr_'+bufmgr+'.c', 'dev.c', 'input.c', 'screen.c', 'vulkan.c']) 4 | -------------------------------------------------------------------------------- /src/legacy_wl_drm.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | static PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL = 0; 13 | 14 | void legacy_wl_drm_setup(struct wl_display *D, int drm_fd) { 15 | struct gbm_device *gbm = gbm_create_device(drm_fd); 16 | EGLDisplay display = eglGetPlatformDisplay(EGL_PLATFORM_GBM_MESA, gbm, 17 | NULL); 18 | if (display == EGL_NO_DISPLAY) { 19 | fprintf(stderr, "eglGetPlatformDisplay failed\n"); 20 | } 21 | 22 | EGLint major, minor; 23 | if (eglInitialize(display, &major, &minor) == EGL_FALSE) { 24 | fprintf(stderr, "eglInitialize failed\n"); 25 | } 26 | // printf("EGL %i.%i initialized\n", major, minor); 27 | 28 | eglBindWaylandDisplayWL = (PFNEGLBINDWAYLANDDISPLAYWL) 29 | eglGetProcAddress("eglBindWaylandDisplayWL"); 30 | 31 | if (eglBindWaylandDisplayWL(display, D) == EGL_FALSE) { 32 | fprintf(stderr, "eglBindWaylandDisplayWL failed\n"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static void spawn_client(char **argv) { 14 | if (fork() == 0) { 15 | execvp(argv[0], argv); 16 | fprintf(stderr, "execvp %s: %s\n", argv[0], strerror(errno)); 17 | errlog("Could not start client %s", argv[0]); 18 | _exit(EXIT_FAILURE); 19 | /* NOTREACHED */ 20 | } 21 | } 22 | 23 | const char *usage = "usage: swvkc [-k ] [-p ] [client]\n\ 24 | \n\ 25 | Experimental Wayland compositor\n\ 26 | \n\ 27 | positional arguments:\n\ 28 | client client to exec\n\ 29 | \n\ 30 | optional arguments:\n\ 31 | -h show this help message and exit\n\ 32 | -k keyboard device node\n\ 33 | -p pointer device node\n"; 34 | 35 | int main(int argc, char *argv[]) { 36 | char *kdevpath = NULL, *pdevpath = NULL; 37 | 38 | int opt; 39 | while ((opt = getopt(argc, argv, "hk:p:")) != -1) { 40 | switch (opt) { 41 | case 'k': kdevpath = optarg; break; 42 | case 'p': pdevpath = optarg; break; 43 | default: 44 | printf("%s", usage); 45 | return EXIT_FAILURE; 46 | } 47 | } 48 | 49 | if (kdevpath) 50 | printf("%s\n", kdevpath); 51 | if (pdevpath) 52 | printf("%s\n", pdevpath); 53 | 54 | if (swvkc_initialize(kdevpath, pdevpath)) 55 | return EXIT_FAILURE; 56 | 57 | if (argc > optind) 58 | spawn_client(argv+optind); 59 | 60 | swvkc_run(); 61 | 62 | swvkc_terminate(); 63 | } 64 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | subdir('backend') 2 | subdir('util') 3 | 4 | src += files(['legacy_wl_drm.c', 'swvkc.c', 'main.c']) 5 | -------------------------------------------------------------------------------- /src/util/meson.build: -------------------------------------------------------------------------------- 1 | src += files(['my_drm_handle_event.c']) 2 | -------------------------------------------------------------------------------- /src/util/my_drm_handle_event.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #define U642VOID(x) ((void *)(unsigned long)(x)) 7 | 8 | /* 9 | * Function modified so that page_flip_handler gets called before vblank_handler 10 | */ 11 | 12 | int my_drmHandleEvent(int fd, drmEventContextPtr evctx) 13 | { 14 | char buffer[1024]; 15 | int len, i; 16 | struct drm_event *e; 17 | struct drm_event_vblank *vblank = 0; //silence a warning in release build 18 | struct drm_event_crtc_sequence *seq; 19 | void *user_data; 20 | 21 | bool vblank_handler_call = false; 22 | bool page_flip_handler_call = false; 23 | 24 | /* The DRM read semantics guarantees that we always get only 25 | * complete events. */ 26 | 27 | len = read(fd, buffer, sizeof buffer); 28 | if (len == 0) 29 | return 0; 30 | if (len < (int)sizeof *e) 31 | return -1; 32 | 33 | i = 0; 34 | while (i < len) { 35 | e = (struct drm_event *)(buffer + i); 36 | switch (e->type) { 37 | case DRM_EVENT_VBLANK: 38 | if (evctx->version < 1 || 39 | evctx->vblank_handler == NULL) 40 | break; 41 | vblank = (struct drm_event_vblank *) e; 42 | vblank_handler_call = true; 43 | /* evctx->vblank_handler(fd, 44 | vblank->sequence, 45 | vblank->tv_sec, 46 | vblank->tv_usec, 47 | U642VOID (vblank->user_data));*/ 48 | break; 49 | case DRM_EVENT_FLIP_COMPLETE: 50 | vblank = (struct drm_event_vblank *) e; 51 | user_data = U642VOID (vblank->user_data); 52 | 53 | if (evctx->version >= 3 && evctx->page_flip_handler2) 54 | evctx->page_flip_handler2(fd, 55 | vblank->sequence, 56 | vblank->tv_sec, 57 | vblank->tv_usec, 58 | vblank->crtc_id, 59 | user_data); 60 | else if (evctx->version >= 2 && evctx->page_flip_handler) 61 | page_flip_handler_call = true; 62 | /* evctx->page_flip_handler(fd, 63 | vblank->sequence, 64 | vblank->tv_sec, 65 | vblank->tv_usec, 66 | user_data);*/ 67 | break; 68 | case DRM_EVENT_CRTC_SEQUENCE: 69 | seq = (struct drm_event_crtc_sequence *) e; 70 | if (evctx->version >= 4 && evctx->sequence_handler) 71 | evctx->sequence_handler(fd, 72 | seq->sequence, 73 | seq->time_ns, 74 | seq->user_data); 75 | break; 76 | default: 77 | break; 78 | } 79 | i += e->length; 80 | } 81 | 82 | if (page_flip_handler_call) { 83 | evctx->page_flip_handler(fd, 84 | vblank->sequence, 85 | vblank->tv_sec, 86 | vblank->tv_usec, 87 | user_data); 88 | } 89 | 90 | if (vblank_handler_call) { 91 | evctx->vblank_handler(fd, 92 | vblank->sequence, 93 | vblank->tv_sec, 94 | vblank->tv_usec, 95 | U642VOID (vblank->user_data)); 96 | } 97 | 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/compositor.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | static void compositor_create_surface(struct wl_client *client, struct 13 | wl_resource *resource, uint32_t id) { 14 | struct compositor *compositor = wl_resource_get_user_data(resource); 15 | struct wl_resource *surface_resource = wl_resource_create(client, 16 | &wl_surface_interface, 4, id); 17 | surface_new(surface_resource, compositor->surface_events); 18 | } 19 | 20 | static void compositor_create_region(struct wl_client *client, struct 21 | wl_resource *resource, uint32_t id) { 22 | struct wl_resource *region_resource = wl_resource_create(client, 23 | &wl_region_interface, 1, id); 24 | region_new(region_resource); 25 | } 26 | 27 | static const struct wl_compositor_interface impl = { 28 | .create_surface = compositor_create_surface, 29 | .create_region = compositor_create_region 30 | }; 31 | 32 | void compositor_free(struct wl_resource *resource) { 33 | struct compositor *compositor = wl_resource_get_user_data(resource); 34 | free(compositor); 35 | } 36 | 37 | struct compositor *compositor_new(struct wl_resource *resource, struct 38 | surface_events surface_events) { 39 | struct compositor *compositor = calloc(1, sizeof(struct compositor)); 40 | compositor->surface_events = surface_events; 41 | wl_resource_set_implementation(resource, &impl, compositor, 42 | compositor_free); 43 | return compositor; 44 | } 45 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/data_device.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | static void start_drag(struct wl_client *client, struct wl_resource *resource, 8 | struct wl_resource *source, struct wl_resource *origin, struct 9 | wl_resource *icon, uint32_t serial) { 10 | 11 | } 12 | 13 | static enum wl_iterator_result set_selection_all(struct wl_resource *resource, 14 | void *user_data) { 15 | if (!strcmp(wl_resource_get_class(resource), "wl_data_device")) { 16 | struct wl_client *client = wl_resource_get_client(resource); 17 | struct wl_resource *source = user_data; 18 | struct wl_resource *offer = wl_resource_create(client, 19 | &wl_data_offer_interface, 3, 0); 20 | wl_data_device_send_data_offer(resource, offer); 21 | data_offer_new(offer, source); 22 | wl_data_device_send_selection(resource, offer); 23 | } 24 | return WL_ITERATOR_CONTINUE; 25 | } 26 | 27 | static void set_selection(struct wl_client *client, struct wl_resource 28 | *resource, struct wl_resource *source, uint32_t serial) { 29 | if (source == NULL) 30 | return; 31 | // struct wl_display *display = wl_client_get_display(client); 32 | // struct wl_list *list = wl_display_get_client_list(display); 33 | // struct wl_client *client_; 34 | // wl_client_for_each(client_, list) { 35 | /* 36 | * For some reason Firefox wants the selection to be set on a different 37 | * `wl_data_device` resource than the one calling this 38 | */ 39 | wl_client_for_each_resource(client, set_selection_all, source); 40 | // } 41 | // TODO: The mechanism for inter-client clipboard works but we must design 42 | // a better way to do it: 43 | // 1) Advertise the selection on focus too 44 | // 2) Watch out for `wl_data_source` destruction events 45 | } 46 | 47 | static void release(struct wl_client *client, struct wl_resource *resource) { 48 | 49 | } 50 | 51 | static const struct wl_data_device_interface impl = { 52 | .start_drag = start_drag, 53 | .set_selection = set_selection, 54 | .release = release 55 | }; 56 | 57 | void data_device_new(struct wl_resource *resource) { 58 | wl_resource_set_implementation(resource, &impl, 0, 0); 59 | } 60 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/data_device_manager.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | void data_device_manager_create_data_source(struct wl_client *client, struct 8 | wl_resource *resource, uint32_t id) { 9 | struct wl_resource *data_source_resource = wl_resource_create(client, 10 | &wl_data_source_interface, 3, id); 11 | data_source_new(data_source_resource); 12 | } 13 | 14 | void data_device_manager_get_data_device(struct wl_client *client, struct 15 | wl_resource *resource, uint32_t id, struct wl_resource *seat) { 16 | struct wl_resource *data_device_resource = wl_resource_create(client, 17 | &wl_data_device_interface, 1, id); 18 | data_device_new(data_device_resource); 19 | } 20 | 21 | static const struct wl_data_device_manager_interface impl = { 22 | .create_data_source = data_device_manager_create_data_source, 23 | .get_data_device = data_device_manager_get_data_device 24 | }; 25 | 26 | void data_device_manager_new(struct wl_resource *resource) { 27 | wl_resource_set_implementation(resource, &impl, 0, 0); 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/data_offer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | static void accept(struct wl_client *client, struct wl_resource *resource, 9 | uint32_t serial, const char *mime_type) { 10 | 11 | } 12 | 13 | static void receive(struct wl_client *client, struct wl_resource *resource, 14 | const char *mime_type, int32_t fd) { 15 | struct wl_resource *source = wl_resource_get_user_data(resource); 16 | wl_data_source_send_send(source, mime_type, fd); 17 | close(fd); 18 | } 19 | 20 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 21 | 22 | } 23 | 24 | static void finish(struct wl_client *client, struct wl_resource *resource) { 25 | 26 | } 27 | 28 | static void set_actions(struct wl_client *client, struct wl_resource *resource, 29 | uint32_t dnd_actions, uint32_t preferred_action) { 30 | 31 | } 32 | 33 | static const struct wl_data_offer_interface impl = { 34 | .accept = accept, 35 | .receive = receive, 36 | .destroy = destroy, 37 | .finish = finish, 38 | .set_actions = set_actions 39 | }; 40 | 41 | void data_offer_new(struct wl_resource *resource, struct wl_resource *source) { 42 | wl_resource_set_implementation(resource, &impl, source, 0); 43 | struct wl_list *list = wl_resource_get_user_data(source); 44 | struct mime_node *node; 45 | wl_list_for_each_reverse(node, list, link) 46 | wl_data_offer_send_offer(resource, node->mime_type); 47 | } 48 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/data_source.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | static void offer(struct wl_client *client, struct wl_resource *resource, const 11 | char *mime_type) { 12 | struct wl_list *list = wl_resource_get_user_data(resource); 13 | struct mime_node *node = malloc(sizeof(struct mime_node)); 14 | node->mime_type = strdup(mime_type); 15 | wl_list_insert(list, &node->link); 16 | } 17 | 18 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 19 | wl_resource_destroy(resource); 20 | } 21 | 22 | static void set_actions(struct wl_client *client, struct wl_resource *resource, 23 | uint32_t dnd_actions) { 24 | 25 | } 26 | 27 | static const struct wl_data_source_interface impl = { 28 | .offer = offer, 29 | .destroy = destroy, 30 | .set_actions = set_actions 31 | }; 32 | 33 | void data_source_free(struct wl_resource *resource) { 34 | struct wl_list *list = wl_resource_get_user_data(resource); 35 | struct mime_node *node, *tmp; 36 | wl_list_for_each_safe(node, tmp, list, link) { 37 | wl_list_remove(&node->link); 38 | free(node->mime_type); 39 | free(node); 40 | } 41 | free(list); 42 | } 43 | 44 | void data_source_new(struct wl_resource *resource) { 45 | struct wl_list *list = malloc(sizeof(struct wl_list)); 46 | wl_list_init(list); 47 | wl_resource_set_implementation(resource, &impl, list, data_source_free); 48 | } 49 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/keyboard.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | struct keyboard { 9 | struct wl_resource *resource; 10 | 11 | struct keyboard_events keyboard_events; 12 | }; 13 | 14 | static void keyboard_release(struct wl_client *client, struct wl_resource 15 | *resource) { 16 | wl_resource_destroy(resource); 17 | } 18 | 19 | static const struct wl_keyboard_interface impl = { 20 | .release = keyboard_release 21 | }; 22 | 23 | void keyboard_new(struct wl_resource *resource, struct 24 | keyboard_events keyboard_events) { 25 | struct keyboard *keyboard = malloc(sizeof(struct keyboard)); 26 | keyboard->resource = resource; 27 | keyboard->keyboard_events = keyboard_events; 28 | 29 | wl_resource_set_implementation(resource, &impl, keyboard, 0); 30 | 31 | if (wl_resource_get_version(resource) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) 32 | wl_keyboard_send_repeat_info(resource, 30, 300); 33 | 34 | keyboard_events.init(keyboard, keyboard_events.user_data); 35 | } 36 | 37 | void keyboard_send_keymap(struct keyboard *keyboard, int32_t fd, uint32_t size) { 38 | struct wl_resource *resource = keyboard->resource; 39 | if (wl_resource_get_version(resource) >= WL_KEYBOARD_KEYMAP_SINCE_VERSION) 40 | wl_keyboard_send_keymap(resource, 41 | WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, size); 42 | } 43 | 44 | void keyboard_send_key(struct keyboard *keyboard, uint32_t key, uint32_t state) { 45 | struct wl_resource *resource = keyboard->resource; 46 | if (wl_resource_get_version(resource) >= WL_KEYBOARD_KEY_SINCE_VERSION) 47 | wl_keyboard_send_key(resource, 0, 0, key, state); 48 | } 49 | 50 | void keyboard_send_modifiers(struct keyboard *keyboard, uint32_t mods_depressed, 51 | uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { 52 | struct wl_resource *resource = keyboard->resource; 53 | if (wl_resource_get_version(resource) >= WL_KEYBOARD_MODIFIERS_SINCE_VERSION) 54 | wl_keyboard_send_modifiers(resource, 0, mods_depressed, 55 | mods_latched, mods_locked, group); 56 | } 57 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/output.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | #include 4 | 5 | static void output_release(struct wl_client *client, struct wl_resource 6 | *resource) { 7 | 8 | } 9 | 10 | static const struct wl_output_interface impl = { 11 | .release = output_release 12 | }; 13 | 14 | void output_new(struct wl_resource *resource) { 15 | wl_resource_set_implementation(resource, &impl, 0, 0); 16 | wl_output_send_geometry(resource, 0, 0, 0, 0, 17 | WL_OUTPUT_SUBPIXEL_UNKNOWN, "aaa", "bbb", 18 | WL_OUTPUT_TRANSFORM_NORMAL); 19 | wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT | 20 | WL_OUTPUT_MODE_PREFERRED, 1366, 768, 60000); 21 | wl_output_send_scale(resource, 1); 22 | wl_output_send_done(resource); 23 | } 24 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/region.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | #include 4 | 5 | static void region_destroy(struct wl_client *client, struct wl_resource 6 | *resource) { 7 | 8 | } 9 | 10 | static void region_add(struct wl_client *client, struct wl_resource *resource, 11 | int32_t x, int32_t y, int32_t width, int32_t height) { 12 | 13 | } 14 | 15 | static void region_subtract(struct wl_client *client, struct wl_resource 16 | *resource, int32_t x, int32_t y, int32_t width, int32_t height) { 17 | 18 | } 19 | 20 | static const struct wl_region_interface impl = { 21 | .destroy = region_destroy, 22 | .add = region_add, 23 | .subtract = region_subtract 24 | }; 25 | 26 | void region_new(struct wl_resource *resource) { 27 | wl_resource_set_implementation(resource, &impl, 0, 0); 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/seat.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | static void get_pointer(struct wl_client *client, struct wl_resource *resource, 10 | uint32_t id) { 11 | struct wl_resource *pointer_resource = wl_resource_create(client, 12 | &wl_pointer_interface, wl_resource_get_version(resource), id); 13 | wl_pointer_new(pointer_resource); 14 | } 15 | 16 | static void seat_release(struct wl_client *client, struct wl_resource *resource) { 17 | wl_resource_destroy(resource); 18 | } 19 | 20 | static void seat_get_keyboard(struct wl_client *client, struct wl_resource 21 | *resource, uint32_t id) { 22 | struct seat *seat = wl_resource_get_user_data(resource); 23 | struct wl_resource *keyboard_resource = wl_resource_create(client, 24 | &wl_keyboard_interface, wl_resource_get_version(resource), id); 25 | keyboard_new(keyboard_resource, seat->keyboard_events); 26 | } 27 | 28 | static const struct wl_seat_interface impl = { 29 | .get_pointer = get_pointer, 30 | .get_keyboard = seat_get_keyboard, 31 | .get_touch = 0, // should post a protocol error instead 32 | .release = seat_release 33 | }; 34 | 35 | void seat_free(struct wl_resource *resource) { 36 | struct seat *seat = wl_resource_get_user_data(resource); 37 | free(seat); 38 | } 39 | 40 | struct seat *seat_new(struct wl_resource *resource, struct 41 | keyboard_events keyboard_events) { 42 | struct seat *seat = calloc(1, sizeof(struct seat)); 43 | seat->keyboard_events = keyboard_events; 44 | 45 | wl_resource_set_implementation(resource, &impl, seat, seat_free); 46 | 47 | if (wl_resource_get_version(resource) >= WL_SEAT_CAPABILITIES_SINCE_VERSION) 48 | wl_seat_send_capabilities(resource, WL_SEAT_CAPABILITY_KEYBOARD 49 | | WL_SEAT_CAPABILITY_POINTER); 50 | if (wl_resource_get_version(resource) >= WL_SEAT_NAME_SINCE_VERSION) 51 | wl_seat_send_name(resource, "seat0"); 52 | 53 | return seat; 54 | } 55 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/subsurface.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | enum staged_field { 12 | PARENT = 1 << 0, 13 | }; 14 | 15 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 16 | 17 | } 18 | 19 | static void set_position(struct wl_client *client, struct wl_resource *resource, 20 | int32_t x, int32_t y) { 21 | 22 | } 23 | 24 | static void place_above(struct wl_client *client, struct wl_resource *resource, 25 | struct wl_resource *sibling) { 26 | 27 | } 28 | 29 | static void place_below(struct wl_client *client, struct wl_resource *resource, 30 | struct wl_resource *sibling) { 31 | 32 | } 33 | 34 | static void set_sync(struct wl_client *client, struct wl_resource *resource) { 35 | 36 | } 37 | 38 | static void set_desync(struct wl_client *client, struct wl_resource *resource) { 39 | 40 | } 41 | 42 | static const struct wl_subsurface_interface impl = { 43 | .destroy = destroy, 44 | .set_position = set_position, 45 | .place_above = place_above, 46 | .place_below = place_below, 47 | .set_sync = set_sync, 48 | .set_desync = set_desync, 49 | }; 50 | 51 | enum map_condition_field { 52 | MAP_CONDITION_BUFFER_COMMIT = 1 << 0, 53 | MAP_CONDITION_PARENT_MAPPED = 1 << 1, 54 | }; 55 | 56 | bool subsurface_is_mapped(struct subsurface *subsurface) { 57 | static const uint8_t all_conditions_set = 58 | MAP_CONDITION_BUFFER_COMMIT | 59 | MAP_CONDITION_PARENT_MAPPED; 60 | return subsurface->map_conditions == all_conditions_set; 61 | } 62 | 63 | bool subsurface_map_condition_check(struct subsurface *subsurface, enum 64 | map_condition_field condition) { 65 | return subsurface->map_conditions & condition; 66 | } 67 | 68 | void subsurface_map_condition_satisfied(struct subsurface *subsurface, enum 69 | map_condition_field condition) { 70 | subsurface->map_conditions |= condition; 71 | if (subsurface_is_mapped(subsurface)) { 72 | struct surface *surface = wl_resource_get_user_data(subsurface->surface); 73 | // TODO: lump the following lines in a func in surface.c 74 | void *user_data = surface->surface_events.user_data; 75 | surface->surface_events.map(surface, user_data); 76 | surface->is_mapped = true; 77 | } 78 | } 79 | 80 | static void commit_notify(struct wl_listener *listener, void *data) { 81 | // errlog("subsurface_commit_notify"); 82 | struct subsurface *subsurface; 83 | subsurface = wl_container_of(listener, subsurface, commit); 84 | struct surface *surface = data; 85 | if (!subsurface_map_condition_check(subsurface, 86 | MAP_CONDITION_BUFFER_COMMIT) && surface->current->buffer) { 87 | subsurface_map_condition_satisfied(subsurface, 88 | MAP_CONDITION_BUFFER_COMMIT); 89 | } 90 | } 91 | 92 | static void parent_commit_notify(struct wl_listener *listener, void *data) { 93 | // errlog("subsurface_parent_commit_notify"); 94 | struct subsurface *subsurface; 95 | subsurface = wl_container_of(listener, subsurface, parent_commit); 96 | 97 | struct subsurface_dbuf_state *current = subsurface->current; 98 | struct subsurface_dbuf_state *pending = subsurface->pending; 99 | 100 | if (subsurface->staged & PARENT) 101 | current->parent = pending->parent; 102 | 103 | subsurface->staged &= ~PARENT; 104 | 105 | struct surface *parent = wl_resource_get_user_data(current->parent); 106 | if (parent->is_mapped) 107 | subsurface_map_condition_satisfied(subsurface, 108 | MAP_CONDITION_PARENT_MAPPED); 109 | // TODO: else listen for parent map signal 110 | 111 | wl_list_remove(&subsurface->parent_commit.link); 112 | } 113 | 114 | static void parent_map_notify(struct wl_listener *listener, void *data) { 115 | // TODO: let's hope that the parent comes already mapped for now 116 | // Will have to add a surface.map signal 117 | } 118 | 119 | static void subsurface_free(struct wl_resource *resource) { 120 | struct subsurface *subsurface = wl_resource_get_user_data(resource); 121 | free(subsurface->current); 122 | free(subsurface->pending); 123 | free(subsurface); 124 | } 125 | 126 | struct subsurface *wl_subsurface_new(struct wl_resource *subsurface_resource, struct 127 | wl_resource *surface_resource, struct wl_resource *parent_resource) { 128 | errlog("subsurface_new"); 129 | struct surface *surface = wl_resource_get_user_data(surface_resource); 130 | struct surface *parent = wl_resource_get_user_data(parent_resource); 131 | 132 | struct subsurface *subsurface = calloc(1, sizeof(struct subsurface)); 133 | subsurface->surface = surface_resource; 134 | 135 | subsurface->pending = calloc(1, sizeof(struct subsurface_dbuf_state)); 136 | subsurface->pending->parent = parent_resource; 137 | subsurface->staged |= PARENT; 138 | 139 | subsurface->current = calloc(1, sizeof(struct subsurface_dbuf_state)); 140 | 141 | subsurface->commit.notify = commit_notify; 142 | wl_signal_add(&surface->commit, &subsurface->commit); 143 | subsurface->parent_commit.notify = parent_commit_notify; 144 | wl_signal_add(&parent->commit, &subsurface->parent_commit); 145 | 146 | wl_resource_set_implementation(subsurface_resource, &impl, subsurface, 147 | subsurface_free); 148 | return subsurface; 149 | } 150 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/wl_pointer.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | static void set_cursor(struct wl_client *client, struct wl_resource *resource, 12 | uint32_t serial, struct wl_resource *surface_resource, int32_t hotspot_x, 13 | int32_t hotspot_y) { 14 | if (surface_resource == NULL) 15 | return; 16 | struct pointer *pointer = wl_resource_get_user_data(resource); 17 | pointer->hotspot_x = hotspot_x; 18 | pointer->hotspot_y = hotspot_y; 19 | /* 20 | * Assign a role to the surface 21 | */ 22 | struct surface *surface = wl_resource_get_user_data(surface_resource); 23 | bool role_check = surface->role == ROLE_NONE || 24 | surface->role == ROLE_CURSOR; 25 | bool base_role_check = surface->base_role == BASE_ROLE_NONE; 26 | if (!(role_check && base_role_check)) { 27 | wl_resource_post_error(resource, WL_POINTER_ERROR_ROLE, 28 | "Given wl_surface has another role"); 29 | return; 30 | } 31 | surface->role = ROLE_CURSOR; 32 | surface->role_object = pointer; 33 | if (!surface->is_mapped) { 34 | void *user_data = surface->surface_events.user_data; 35 | surface->surface_events.map(surface, user_data); 36 | surface->is_mapped = true; 37 | } 38 | } 39 | 40 | static void release(struct wl_client *client, struct wl_resource *resource) { 41 | 42 | } 43 | 44 | static const struct wl_pointer_interface impl = { 45 | .set_cursor = set_cursor, 46 | .release = release 47 | }; 48 | 49 | void wl_pointer_new(struct wl_resource *resource) { 50 | struct pointer *pointer = calloc(1, sizeof(struct pointer)); 51 | wl_resource_set_implementation(resource, &impl, pointer, 0); 52 | } 53 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/wl_subcompositor.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 9 | wl_resource_destroy(resource); 10 | } 11 | 12 | static void get_subsurface(struct wl_client *client, struct wl_resource 13 | *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource 14 | *parent) { 15 | struct surface *surface = wl_resource_get_user_data(surface_resource); 16 | bool role_check = surface->role == ROLE_NONE || 17 | surface->role == ROLE_SUBSURFACE; 18 | if (!role_check) { 19 | wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, 20 | "the to-be sub-surface must not already have another role"); 21 | return; 22 | } else if (surface->role_object) { 23 | wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, 24 | "the to-be sub-surface must not have an existing wl_subsurface object"); 25 | return; 26 | } 27 | 28 | struct wl_resource *subsurface_resource = wl_resource_create(client, 29 | &wl_subsurface_interface, 1, id); 30 | struct subsurface *subsurface = wl_subsurface_new(subsurface_resource, 31 | surface_resource, parent); 32 | 33 | surface->role = ROLE_SUBSURFACE; 34 | surface->role_object = subsurface; 35 | } 36 | 37 | static const struct wl_subcompositor_interface impl = { 38 | .destroy = destroy, 39 | .get_subsurface = get_subsurface 40 | }; 41 | 42 | void wl_subcompositor_new(struct wl_resource *resource) { 43 | wl_resource_set_implementation(resource, &impl, 0, 0); 44 | } 45 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/core/wl_surface.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | static void destroy(struct wl_client *client, struct wl_resource 12 | *resource) { 13 | wl_resource_destroy(resource); 14 | } 15 | 16 | static void attach(struct wl_client *client, struct wl_resource 17 | *resource, struct wl_resource *buffer, int32_t x, int32_t y) { 18 | // I didn't understand how to treat nonzero x and y 19 | if (x || y) 20 | errlog("surface.attach called with nonzero x=%d y=%d", x, y); 21 | struct surface *surface = wl_resource_get_user_data(resource); 22 | surface->pending->buffer = buffer; 23 | surface->staged |= BUFFER; 24 | } 25 | 26 | static void damage(struct wl_client *client, struct wl_resource 27 | *resource, int32_t x, int32_t y, int32_t width, int32_t height) { 28 | struct surface *surface = wl_resource_get_user_data(resource); 29 | surface->pending->damage.x = x; 30 | surface->pending->damage.y = y; 31 | surface->pending->damage.width = width; 32 | surface->pending->damage.height = height; 33 | surface->staged |= DAMAGE; 34 | } 35 | 36 | static void frame(struct wl_client *client, struct wl_resource 37 | *resource, uint32_t callback) { 38 | struct surface *surface = wl_resource_get_user_data(resource); 39 | if (surface->frame) { 40 | wl_callback_send_done(surface->frame, 0); 41 | wl_resource_destroy(surface->frame); 42 | } 43 | 44 | surface->frame = wl_resource_create(client, &wl_callback_interface, 1, callback); 45 | } 46 | 47 | static void set_opaque_region(struct wl_client *client, struct 48 | wl_resource *resource, struct wl_resource *region) { 49 | struct surface *surface = wl_resource_get_user_data(resource); 50 | surface->pending->opaque_region = region; 51 | surface->staged |= OPAQUE_REGION; 52 | } 53 | 54 | static void set_input_region(struct wl_client *client, struct 55 | wl_resource *resource, struct wl_resource *region) { 56 | struct surface *surface = wl_resource_get_user_data(resource); 57 | surface->pending->input_region = region; 58 | surface->staged |= INPUT_REGION; 59 | } 60 | 61 | static void commit(struct wl_client *client, struct wl_resource 62 | *resource) { 63 | struct surface *surface = wl_resource_get_user_data(resource); 64 | struct dbuf_state *current = surface->current; 65 | struct dbuf_state *pending = surface->pending; 66 | 67 | // "On commit, a pending wl_buffer is applied first, and all other state second" 68 | if (surface->staged & BUFFER) 69 | current->buffer = pending->buffer; 70 | 71 | if (surface->staged & DAMAGE) 72 | current->damage = pending->damage; 73 | 74 | if (surface->staged & OPAQUE_REGION) 75 | current->opaque_region = pending->opaque_region; 76 | 77 | if (surface->staged & INPUT_REGION) 78 | current->input_region = pending->input_region; 79 | 80 | if (surface->staged & BUFFER_TRANSFORM) 81 | current->buffer_transform = pending->buffer_transform; 82 | 83 | if (surface->staged & BUFFER_SCALE) 84 | current->buffer_scale = pending->buffer_scale; 85 | 86 | if (surface->staged & BUFFER_DAMAGE) 87 | current->buffer_damage = pending->buffer_damage; 88 | /* 89 | * Commit every other possible role-specific state 90 | */ 91 | wl_signal_emit(&surface->commit, surface); 92 | 93 | if (surface->staged & BUFFER && surface->is_mapped) 94 | surface->surface_events.contents_update(surface, 95 | surface->surface_events.user_data); 96 | 97 | surface->staged = 0; 98 | } 99 | 100 | static void set_buffer_transform(struct wl_client *client, struct 101 | wl_resource *resource, int32_t transform) { 102 | if (transform < WL_OUTPUT_TRANSFORM_NORMAL || 103 | transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) { 104 | wl_resource_post_error(resource, 105 | WL_SURFACE_ERROR_INVALID_TRANSFORM, 106 | "Buffer transform value %d is invalid", transform); 107 | return; 108 | } 109 | struct surface *surface = wl_resource_get_user_data(resource); 110 | surface->pending->buffer_transform = transform; 111 | surface->staged |= BUFFER_TRANSFORM; 112 | } 113 | 114 | static void set_buffer_scale(struct wl_client *client, struct 115 | wl_resource *resource, int32_t scale) { 116 | if (scale < 1) { 117 | wl_resource_post_error(resource, WL_SURFACE_ERROR_INVALID_SCALE, 118 | "Buffer scale value %d is not positive", scale); 119 | return; 120 | } 121 | struct surface *surface = wl_resource_get_user_data(resource); 122 | surface->pending->buffer_scale = scale; 123 | surface->staged |= BUFFER_SCALE; 124 | } 125 | 126 | static void damage_buffer(struct wl_client *client, struct wl_resource 127 | *resource, int32_t x, int32_t y, int32_t width, int32_t height) { 128 | struct surface *surface = wl_resource_get_user_data(resource); 129 | surface->pending->buffer_damage.x = x; 130 | surface->pending->buffer_damage.y = y; 131 | surface->pending->buffer_damage.width = width; 132 | surface->pending->buffer_damage.height = height; 133 | surface->staged |= BUFFER_DAMAGE; 134 | } 135 | 136 | static const struct wl_surface_interface impl = { 137 | destroy, attach, damage, frame, set_opaque_region, set_input_region, 138 | commit, set_buffer_transform, set_buffer_scale, damage_buffer 139 | }; 140 | 141 | void surface_free(struct wl_resource *resource) { 142 | errlog("surface destroyed"); 143 | struct surface *surface = wl_resource_get_user_data(resource); 144 | if (surface->is_mapped) { 145 | surface->surface_events.unmap(surface, 146 | surface->surface_events.user_data); 147 | surface->is_mapped = false; 148 | } 149 | free(surface->pending); 150 | free(surface->current); 151 | free(surface); 152 | } 153 | 154 | struct surface *surface_new(struct wl_resource *resource, struct surface_events 155 | surface_events) { 156 | struct surface *surface = calloc(1, sizeof(struct surface)); 157 | surface->pending = calloc(1, sizeof(struct dbuf_state)); 158 | surface->current = calloc(1, sizeof(struct dbuf_state)); 159 | 160 | wl_list_init(&surface->extensions); 161 | 162 | surface->resource = resource; 163 | 164 | // Buffered state initialization 165 | surface->current->buffer_transform = WL_OUTPUT_TRANSFORM_NORMAL; 166 | surface->current->buffer_scale = 1; 167 | 168 | surface->surface_events = surface_events; 169 | wl_signal_init(&surface->commit); 170 | wl_resource_set_implementation(resource, &impl, surface, surface_free); 171 | return surface; 172 | } 173 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/fullscreen-shell-unstable-v1/zwp_fullscreen_shell_v1.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | static void release(struct wl_client *client, struct wl_resource *resource) { 9 | wl_resource_destroy(resource); 10 | } 11 | 12 | static void present_surface(struct wl_client *client, struct wl_resource 13 | *resource, struct wl_resource *surface_resource, uint32_t method, struct 14 | wl_resource *output) { 15 | errlog("PRESENT SURFACE"); 16 | struct surface *surface = wl_resource_get_user_data(surface_resource); 17 | surface->role = ROLE_FULLSCREEN; 18 | surface->surface_events.map(surface, surface->surface_events.user_data); 19 | surface->is_mapped = true; 20 | } 21 | 22 | static void present_surface_for_mode(struct wl_client *client, struct 23 | wl_resource *resource, struct wl_resource *surface, struct wl_resource *output, 24 | int32_t framerate, uint32_t feedback) { 25 | errlog("PRESENT SURFACE FOR MODE"); 26 | } 27 | 28 | static const struct zwp_fullscreen_shell_v1_interface impl = {release, 29 | present_surface, present_surface_for_mode}; 30 | 31 | void zwp_fullscreen_shell_v1_new(struct wl_resource *resource) { 32 | errlog("BOUND TO FULLSCREEN SHELL"); 33 | wl_resource_set_implementation(resource, &impl, NULL, NULL); 34 | 35 | // zwp_fullscreen_shell_v1_send_capability(resource, ZWP_FULLSCREEN_SHELL_V1_CAPABILITY_ARBITRARY_MODES); 36 | // zwp_fullscreen_shell_v1_send_capability(resource, ZWP_FULLSCREEN_SHELL_V1_CAPABILITY_CURSOR_PLANE); 37 | } 38 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/linux-dmabuf-unstable-v1/wl_buffer_dmabuf.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 12 | wl_resource_destroy(resource); 13 | } 14 | 15 | static const struct wl_buffer_interface impl = {destroy}; 16 | 17 | static void free_data(struct wl_resource *resource) { 18 | struct wl_buffer_dmabuf_data *dmabuf = wl_resource_get_user_data(resource); 19 | /* 20 | * buffer_dmabuf will be destroyed, notify subsystems for cleaning 21 | */ 22 | if (dmabuf->buffer_dmabuf_events.destroy) 23 | dmabuf->buffer_dmabuf_events.destroy(dmabuf, 24 | dmabuf->buffer_dmabuf_events.user_data); 25 | 26 | for (size_t i=0; inum_planes; i++) 27 | close(dmabuf->fds[i]); 28 | free(dmabuf->fds); 29 | free(dmabuf->offsets); 30 | free(dmabuf->strides); 31 | free(dmabuf->modifiers); 32 | free(dmabuf); 33 | } 34 | 35 | struct wl_buffer_dmabuf_data *wl_buffer_dmabuf_new(struct wl_resource *resource, 36 | int32_t width, int32_t height, uint32_t format, uint32_t flags, uint32_t 37 | num_planes, struct buffer_dmabuf_events buffer_dmabuf_events) { 38 | struct wl_buffer_dmabuf_data *dmabuf = malloc(sizeof(*dmabuf)); 39 | dmabuf->width = width; 40 | dmabuf->height = height; 41 | dmabuf->format = format; 42 | dmabuf->flags = flags; 43 | dmabuf->num_planes = num_planes; 44 | dmabuf->fds = malloc(num_planes*sizeof(int32_t)); 45 | dmabuf->offsets = malloc(num_planes*sizeof(uint32_t)); 46 | dmabuf->strides = malloc(num_planes*sizeof(uint32_t)); 47 | dmabuf->modifiers = malloc(num_planes*sizeof(uint64_t)); 48 | dmabuf->buffer_dmabuf_events = buffer_dmabuf_events; 49 | memset(dmabuf->subsystem_object, 0, sizeof(dmabuf->subsystem_object)); 50 | wl_resource_set_implementation(resource, &impl, dmabuf, free_data); 51 | return dmabuf; 52 | } 53 | 54 | bool wl_buffer_is_dmabuf(struct wl_resource *resource) { 55 | return wl_resource_instance_of(resource, &wl_buffer_interface, &impl); 56 | } 57 | 58 | int32_t wl_buffer_dmabuf_get_width(struct wl_resource *resource) { 59 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 60 | return data->width; 61 | } 62 | 63 | int32_t wl_buffer_dmabuf_get_height(struct wl_resource *resource) { 64 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 65 | return data->height; 66 | } 67 | 68 | uint32_t wl_buffer_dmabuf_get_format(struct wl_resource *resource) { 69 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 70 | return data->format; 71 | } 72 | 73 | uint32_t wl_buffer_dmabuf_get_num_planes(struct wl_resource *resource) { 74 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 75 | return data->num_planes; 76 | } 77 | 78 | uint32_t *wl_buffer_dmabuf_get_offsets(struct wl_resource *resource) { 79 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 80 | return data->offsets; 81 | } 82 | 83 | uint32_t *wl_buffer_dmabuf_get_strides(struct wl_resource *resource) { 84 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 85 | return data->strides; 86 | } 87 | 88 | uint64_t *wl_buffer_dmabuf_get_mods(struct wl_resource *resource) { 89 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 90 | return data->modifiers; 91 | } 92 | 93 | void *wl_buffer_dmabuf_get_subsystem_object(struct wl_resource *resource, enum 94 | subsystem subsystem) { 95 | struct wl_buffer_dmabuf_data *data = wl_resource_get_user_data(resource); 96 | return data->subsystem_object[subsystem]; 97 | } 98 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/linux-dmabuf-unstable-v1/zwp_linux_buffer_params_v1.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | uint32_t format_get_plane_number(uint32_t format) { 15 | switch (format) { 16 | default: 17 | return 1; 18 | } 19 | } 20 | 21 | size_t fd_get_size(int fd) { 22 | size_t curr = lseek(fd, 0, SEEK_CUR); 23 | size_t size = lseek(fd, 0, SEEK_END); 24 | lseek(fd, curr, SEEK_SET); 25 | return size; 26 | } 27 | 28 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 29 | wl_resource_destroy(resource); 30 | } 31 | 32 | static void add(struct wl_client *client, struct wl_resource *resource, int32_t 33 | fd, uint32_t plane_idx, uint32_t offset, uint32_t stride, uint32_t modifier_hi, 34 | uint32_t modifier_lo) { 35 | struct zwp_linux_buffer_params_v1_data* data = 36 | wl_resource_get_user_data(resource); 37 | 38 | struct plane *plane; 39 | wl_list_for_each(plane, &data->plane_list, link) { 40 | if (plane->plane_idx == plane_idx) { 41 | wl_resource_post_error(resource, 42 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET, 43 | "the plane index was already set"); 44 | return; 45 | } 46 | } 47 | 48 | plane = malloc(sizeof(struct plane)); 49 | plane->fd = fd; 50 | plane->plane_idx = plane_idx; 51 | plane->offset = offset; 52 | plane->stride = stride; 53 | plane->modifier = ((uint64_t)modifier_hi << 32) | modifier_lo; 54 | wl_list_insert(&data->plane_list, &plane->link); 55 | } 56 | 57 | void create_(struct wl_client *client, struct wl_resource *resource, uint32_t 58 | buffer_id, int32_t width, int32_t height, uint32_t format, uint32_t flags) { 59 | struct zwp_linux_buffer_params_v1_data* params = 60 | wl_resource_get_user_data(resource); 61 | 62 | if (params->already_used) { 63 | wl_resource_post_error(resource, 64 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, 65 | "The dmabuf_batch object has already been used to create a wl_buffer"); 66 | goto failed; 67 | } 68 | params->already_used = true; 69 | 70 | if (format != DRM_FORMAT_XRGB8888 && format != DRM_FORMAT_ARGB8888 && format != DRM_FORMAT_YUYV) { 71 | wl_resource_post_error(resource, 72 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, 73 | "Format not supported"); 74 | goto failed; 75 | } 76 | 77 | if (width <= 0) { 78 | wl_resource_post_error(resource, 79 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, 80 | "Invalid width"); 81 | goto failed; 82 | } 83 | if (height <= 0) { 84 | wl_resource_post_error(resource, 85 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, 86 | "Invalid height"); 87 | goto failed; 88 | } 89 | 90 | uint32_t num_planes = format_get_plane_number(format); 91 | uint32_t num_added = wl_list_length(¶ms->plane_list); 92 | if (num_added < num_planes) { 93 | wl_resource_post_error(resource, 94 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, 95 | "Missing planes to create a buffer"); 96 | goto failed; 97 | } 98 | if (num_added > num_planes) { 99 | wl_resource_post_error(resource, 100 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, 101 | "Too many planes to create a buffer"); 102 | goto failed; 103 | } 104 | 105 | struct wl_resource *child = wl_resource_create(client, 106 | &wl_buffer_interface, 1, buffer_id); 107 | struct wl_buffer_dmabuf_data *dmabuf = wl_buffer_dmabuf_new(child, 108 | width, height, format, flags, num_planes, params->buffer_dmabuf_events); 109 | 110 | struct plane *plane; 111 | wl_list_for_each(plane, ¶ms->plane_list, link) { 112 | uint32_t i = plane->plane_idx; 113 | if (i >= dmabuf->num_planes) { 114 | wl_resource_post_error(resource, 115 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, 116 | "Plane index out of bounds"); 117 | wl_resource_destroy(child); 118 | goto failed; 119 | } 120 | if (dmabuf->offsets[i]+dmabuf->strides[i]*height > 121 | fd_get_size(dmabuf->fds[i])) { 122 | wl_resource_post_error(resource, 123 | ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS, 124 | "offset + stride * height goes out of dmabuf bounds"); 125 | wl_resource_destroy(child); 126 | goto failed; 127 | } 128 | dmabuf->fds[i] = plane->fd; 129 | dmabuf->offsets[i] = plane->offset; 130 | dmabuf->strides[i] = plane->stride; 131 | dmabuf->modifiers[i] = plane->modifier; 132 | } 133 | /* 134 | * buffer_dmabuf creation was successful, notify subsystems for importing 135 | */ 136 | if (dmabuf->buffer_dmabuf_events.create) 137 | dmabuf->buffer_dmabuf_events.create(dmabuf, 138 | dmabuf->buffer_dmabuf_events.user_data); 139 | 140 | if (buffer_id == 0) // `create` request 141 | zwp_linux_buffer_params_v1_send_created(resource, child); 142 | return; 143 | failed: 144 | if (buffer_id == 0) // `create` request 145 | zwp_linux_buffer_params_v1_send_failed(resource); 146 | } 147 | 148 | static void create(struct wl_client *client, struct wl_resource *resource, 149 | int32_t width, int32_t height, uint32_t format, uint32_t flags) { 150 | create_(client, resource, 0, width, height, format, flags); 151 | } 152 | 153 | static void create_immed(struct wl_client *client, struct wl_resource *resource, 154 | uint32_t buffer_id, int32_t width, int32_t height, uint32_t format, uint32_t 155 | flags) { 156 | create_(client, resource, buffer_id, width, height, format, flags); 157 | } 158 | 159 | static const struct zwp_linux_buffer_params_v1_interface impl = {destroy, 160 | add, create, create_immed}; 161 | 162 | static void free_data(struct wl_resource *resource) { 163 | struct zwp_linux_buffer_params_v1_data* data = 164 | wl_resource_get_user_data(resource); 165 | struct plane *plane, *tmp; 166 | wl_list_for_each_safe(plane, tmp, &data->plane_list, link) { 167 | wl_list_remove(&plane->link); 168 | free(plane); 169 | } 170 | free(data); 171 | } 172 | 173 | struct zwp_linux_buffer_params_v1_data *zwp_linux_buffer_params_v1_new(struct 174 | wl_resource *resource, struct buffer_dmabuf_events buffer_dmabuf_events) { 175 | struct zwp_linux_buffer_params_v1_data* data = calloc(1, sizeof(*data)); 176 | wl_list_init(&data->plane_list); 177 | data->buffer_dmabuf_events = buffer_dmabuf_events; 178 | wl_resource_set_implementation(resource, &impl, data, free_data); 179 | return data; 180 | } 181 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/linux-dmabuf-unstable-v1/zwp_linux_dmabuf_v1.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 13 | wl_resource_destroy(resource); 14 | } 15 | 16 | static void create_params(struct wl_client *client, struct wl_resource 17 | *resource, uint32_t params_id) { 18 | struct linux_dmabuf *linux_dmabuf = wl_resource_get_user_data(resource); 19 | int version = wl_resource_get_version(resource); 20 | struct wl_resource *child = wl_resource_create(client, 21 | &zwp_linux_buffer_params_v1_interface, version, params_id); 22 | zwp_linux_buffer_params_v1_new(child, linux_dmabuf->buffer_dmabuf_events); 23 | } 24 | 25 | static const struct zwp_linux_dmabuf_v1_interface impl = {destroy, 26 | create_params}; 27 | 28 | void send_format(struct wl_resource *resource, uint32_t format, uint64_t modifier) { 29 | uint32_t hi = modifier >> 32; 30 | uint32_t lo = modifier & 0xFFFFFFFF; 31 | zwp_linux_dmabuf_v1_send_modifier(resource, format, hi, lo); 32 | } 33 | 34 | void linux_dmabuf_free(struct wl_resource *resource) { 35 | struct linux_dmabuf *linux_dmabuf = wl_resource_get_user_data(resource); 36 | free(linux_dmabuf); 37 | } 38 | 39 | void zwp_linux_dmabuf_v1_new(struct wl_resource *resource, struct 40 | buffer_dmabuf_events buffer_dmabuf_events) { 41 | struct linux_dmabuf *linux_dmabuf = malloc(sizeof(struct linux_dmabuf)); 42 | linux_dmabuf->buffer_dmabuf_events = buffer_dmabuf_events; 43 | wl_resource_set_implementation(resource, &impl, linux_dmabuf, 44 | linux_dmabuf_free); 45 | /* 46 | * Some common formats (Intel GPU) 47 | */ 48 | if (wl_resource_get_version(resource) >= 3) { 49 | send_format(resource, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR); 50 | send_format(resource, DRM_FORMAT_XRGB8888, I915_FORMAT_MOD_X_TILED); 51 | send_format(resource, DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR); 52 | send_format(resource, DRM_FORMAT_ARGB8888, I915_FORMAT_MOD_X_TILED); 53 | } else { 54 | zwp_linux_dmabuf_v1_send_format(resource, DRM_FORMAT_XRGB8888); 55 | zwp_linux_dmabuf_v1_send_format(resource, DRM_FORMAT_ARGB8888); 56 | zwp_linux_dmabuf_v1_send_format(resource, DRM_FORMAT_YUYV); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/linux-explicit-synchronization-v1/zwp_linux_explicit_synchronization_v1.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | 12 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 13 | wl_resource_destroy(resource); 14 | } 15 | 16 | static void get_synchronization(struct wl_client *client, struct wl_resource 17 | *resource, uint32_t id, struct wl_resource *surface_resource) { 18 | struct surface *surface = wl_resource_get_user_data(surface_resource); 19 | if (util_get_extension(&surface->extensions, 20 | "zwp_linux_surface_synchronization_v1")) 21 | wl_resource_post_error(resource, 22 | ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_V1_ERROR_SYNCHRONIZATION_EXISTS, 23 | "the surface already has a synchronization object associated"); 24 | 25 | struct wl_resource *child = wl_resource_create(client, 26 | &zwp_linux_surface_synchronization_v1_interface, 1, id); 27 | linux_surface_synchronization_new(child, surface); 28 | } 29 | 30 | static const struct zwp_linux_explicit_synchronization_v1_interface impl = { 31 | .destroy = destroy, 32 | .get_synchronization = get_synchronization 33 | }; 34 | 35 | void linux_explicit_synchronization_new(struct wl_resource *resource) { 36 | wl_resource_set_implementation(resource, &impl, 0, 0); 37 | } 38 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/linux-explicit-synchronization-v1/zwp_linux_surface_synchronization_v1.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | /* 15 | * TODO: Protocol errors 16 | */ 17 | 18 | enum staged_field { 19 | FD = 1 << 0 20 | }; 21 | 22 | struct dbuf_state_ { 23 | int fd; 24 | }; 25 | 26 | struct linux_surface_synchronization { 27 | struct dbuf_state_ *current, *pending; 28 | uint8_t staged; // bitmask 29 | struct wl_listener commit; 30 | 31 | struct surface *surface; 32 | struct wl_resource *buffer_release_resource; 33 | }; 34 | 35 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 36 | struct linux_surface_synchronization *self 37 | = wl_resource_get_user_data(resource); 38 | if (self->staged & FD) 39 | close(self->pending->fd); 40 | wl_resource_destroy(resource); 41 | } 42 | 43 | static void set_acquire_fence(struct wl_client *client, struct wl_resource 44 | *resource, int32_t fd) { 45 | struct linux_surface_synchronization *self 46 | = wl_resource_get_user_data(resource); 47 | self->pending->fd = fd; 48 | self->staged |= FD; 49 | } 50 | 51 | static void get_release(struct wl_client *client, struct wl_resource *resource, 52 | uint32_t release) { 53 | struct linux_surface_synchronization *self 54 | = wl_resource_get_user_data(resource); 55 | struct wl_resource *buffer_release_resource = wl_resource_create(client, 56 | &zwp_linux_buffer_release_v1_interface, 1, release); 57 | self->buffer_release_resource = buffer_release_resource; 58 | } 59 | 60 | static const struct zwp_linux_surface_synchronization_v1_interface impl = { 61 | .destroy = destroy, 62 | .set_acquire_fence = set_acquire_fence, 63 | .get_release = get_release 64 | }; 65 | 66 | static void commit_notify(struct wl_listener *listener, void *data) { 67 | struct linux_surface_synchronization *self; 68 | self = wl_container_of(listener, self, commit); 69 | 70 | if (self->staged & FD) 71 | self->current->fd = self->pending->fd; 72 | 73 | self->staged = 0; 74 | } 75 | 76 | static void destroyed(struct wl_resource *resource) { 77 | struct linux_surface_synchronization *self 78 | = wl_resource_get_user_data(resource); 79 | /* 80 | * Unregister this object as an extension to the surface 81 | */ 82 | struct extension_node *node; 83 | wl_list_for_each(node, &self->surface->extensions, link) 84 | if (node->resource == resource) 85 | break; 86 | wl_list_remove(&node->link); 87 | free(node); 88 | 89 | free(self); 90 | } 91 | 92 | void linux_surface_synchronization_new(struct wl_resource *resource, struct 93 | surface *surface) { 94 | struct linux_surface_synchronization *self 95 | = calloc(1, sizeof(struct linux_surface_synchronization)); 96 | self->pending = malloc(sizeof(struct dbuf_state_)); 97 | self->pending->fd = -1; 98 | self->current = malloc(sizeof(struct dbuf_state_)); 99 | self->current->fd = -1; 100 | 101 | self->commit.notify = commit_notify; 102 | wl_signal_add(&surface->commit, &self->commit); 103 | 104 | self->surface = surface; 105 | 106 | wl_resource_set_implementation(resource, &impl, self, destroyed); 107 | /* 108 | * Register this object as an extension to the surface 109 | */ 110 | struct extension_node *node = malloc(sizeof(struct extension_node)); 111 | node->resource = resource; 112 | wl_list_insert(&surface->extensions, &node->link); 113 | } 114 | 115 | int linux_surface_synchronization_get_fence(struct linux_surface_synchronization 116 | *self) { 117 | return self->current->fd; 118 | } 119 | 120 | void linux_surface_synchronization_send_immediate_release(struct 121 | linux_surface_synchronization *self) { 122 | if (!self || !self->buffer_release_resource) 123 | return; 124 | zwp_linux_buffer_release_v1_send_immediate_release(self->buffer_release_resource); 125 | wl_resource_destroy(self->buffer_release_resource); 126 | self->buffer_release_resource = NULL; 127 | } 128 | 129 | void linux_surface_synchronization_send_fenced_release(struct 130 | linux_surface_synchronization *self, int fence_fd) { 131 | if (!self || !self->buffer_release_resource || fence_fd < 0) { 132 | close(fence_fd); 133 | return; 134 | } 135 | zwp_linux_buffer_release_v1_send_fenced_release(self->buffer_release_resource, 136 | fence_fd); 137 | /* 138 | * Wayland has duped the fd so we can close it right away 139 | */ 140 | close(fence_fd); 141 | wl_resource_destroy(self->buffer_release_resource); 142 | self->buffer_release_resource = NULL; 143 | } 144 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/server-decoration/org_kde_kwin_server_decoration.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | static void release(struct wl_client *client, struct wl_resource *resource) { 6 | 7 | } 8 | 9 | static void request_mode(struct wl_client *client, struct wl_resource *resource, uint32_t mode) { 10 | org_kde_kwin_server_decoration_send_mode(resource, 11 | ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER); 12 | } 13 | 14 | static const struct org_kde_kwin_server_decoration_interface impl = { 15 | .release = release, 16 | .request_mode = request_mode 17 | }; 18 | 19 | void org_kde_kwin_server_decoration_new(struct wl_resource *resource) { 20 | wl_resource_set_implementation(resource, &impl, 0, 0); 21 | org_kde_kwin_server_decoration_send_mode(resource, 22 | ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER); 23 | } 24 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/server-decoration/org_kde_kwin_server_decoration_manager.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | static void create(struct wl_client *client, struct wl_resource *resource, 8 | uint32_t id, struct wl_resource *surface) { 9 | struct wl_resource *child = wl_resource_create(client, 10 | &org_kde_kwin_server_decoration_interface, 1, id); 11 | org_kde_kwin_server_decoration_new(child); 12 | } 13 | 14 | static const struct org_kde_kwin_server_decoration_manager_interface impl = { 15 | .create = create 16 | }; 17 | 18 | void org_kde_kwin_server_decoration_manager_new(struct wl_resource *resource) { 19 | wl_resource_set_implementation(resource, &impl, 0, 0); 20 | org_kde_kwin_server_decoration_manager_send_default_mode(resource, 21 | ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER); 22 | } 23 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/xdg_shell/xdg_popup.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | 5 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 6 | 7 | } 8 | 9 | static void grab(struct wl_client *client, struct wl_resource *resource, struct 10 | wl_resource *seat, uint32_t serial) { 11 | 12 | } 13 | 14 | static const struct xdg_popup_interface impl = { 15 | .destroy = destroy, 16 | .grab = grab 17 | }; 18 | 19 | // version 1 20 | 21 | void xdg_popup_new(struct wl_resource *resource) { 22 | wl_resource_set_implementation(resource, &impl, 0, 0); 23 | } 24 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/xdg_shell/xdg_positioner.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | 5 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 6 | 7 | } 8 | 9 | static void set_size(struct wl_client *client, struct wl_resource *resource, 10 | int32_t width, int32_t height) { 11 | 12 | } 13 | 14 | static void set_anchor_rect(struct wl_client *client, struct wl_resource 15 | *resource, int32_t x, int32_t y, int32_t width, int32_t height) { 16 | 17 | } 18 | 19 | static void set_anchor(struct wl_client *client, struct wl_resource *resource, 20 | uint32_t anchor) { 21 | 22 | } 23 | 24 | static void set_gravity(struct wl_client *client, struct wl_resource *resource, 25 | uint32_t gravity) { 26 | 27 | } 28 | 29 | static void set_constraint_adjustment(struct wl_client *client, struct 30 | wl_resource *resource, uint32_t constraint_adjustment) { 31 | 32 | } 33 | 34 | static void set_offset(struct wl_client *client, struct wl_resource *resource, 35 | int32_t x, int32_t y) { 36 | 37 | } 38 | 39 | static const struct xdg_positioner_interface impl = { 40 | .destroy = destroy, 41 | .set_size = set_size, 42 | .set_anchor_rect = set_anchor_rect, 43 | .set_anchor = set_anchor, 44 | .set_gravity = set_gravity, 45 | .set_constraint_adjustment = set_constraint_adjustment, 46 | .set_offset = set_offset, 47 | }; 48 | 49 | // version 1 50 | 51 | void xdg_positioner_new(struct wl_resource *resource) { 52 | wl_resource_set_implementation(resource, &impl, 0, 0); 53 | } 54 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/xdg_shell/xdg_surface.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | 6 | #include // Just for one event 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /*static enum wl_iterator_result keyboard_set(struct wl_resource *resource, 16 | void *user_data) { 17 | if (!strcmp(wl_resource_get_class(resource), "wl_keyboard")) { 18 | struct xdg_surface0 *xdg_surface = user_data; 19 | xdg_surface->keyboard = resource; 20 | return WL_ITERATOR_STOP; 21 | } 22 | return WL_ITERATOR_CONTINUE; 23 | }*/ 24 | 25 | bool xdg_surface_is_mapped(struct xdg_surface0 *xdg_surface) { 26 | static const uint8_t all_conditions_set = 27 | MAP_CONDITION_ROLE_ASSIGNED | 28 | MAP_CONDITION_BASE_ROLE_INIT_COMMIT | 29 | MAP_CONDITION_ROLE_INIT_COMMIT | 30 | MAP_CONDITION_BUFFER_COMMIT; 31 | return xdg_surface->map_conditions == all_conditions_set; 32 | } 33 | 34 | bool xdg_surface_map_condition_check(struct xdg_surface0 *xdg_surface, enum 35 | map_condition_field condition) { 36 | return xdg_surface->map_conditions & condition; 37 | } 38 | 39 | void xdg_surface_map_condition_satisfied(struct xdg_surface0 *xdg_surface, enum 40 | map_condition_field condition) { 41 | xdg_surface->map_conditions |= condition; 42 | if (xdg_surface_is_mapped(xdg_surface)) { 43 | struct surface *surface = wl_resource_get_user_data(xdg_surface->surface); 44 | // TODO: lump the following lines in a func in surface.c 45 | void *user_data = surface->surface_events.user_data; 46 | /* struct wl_client *client = wl_resource_get_client(xdg_surface->surface); 47 | wl_surface_send_enter(xdg_surface->surface, util_wl_client_get_output(client));*/ 48 | surface->surface_events.map(surface, user_data); 49 | surface->is_mapped = true; 50 | } 51 | } 52 | 53 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 54 | wl_resource_destroy(resource); 55 | } 56 | 57 | static void get_toplevel(struct wl_client *client, struct wl_resource *resource, 58 | uint32_t id) { 59 | struct xdg_surface0 *data = wl_resource_get_user_data(resource); 60 | struct wl_resource *toplevel_resource = wl_resource_create(client, 61 | &xdg_toplevel_interface, 1, id); 62 | struct xdg_toplevel_data *xdg_toplevel = 63 | xdg_toplevel_new(toplevel_resource, data, data->xdg_toplevel_events); 64 | /* 65 | * Assign a role to the surface 66 | */ 67 | struct surface *surface = wl_resource_get_user_data(data->surface); 68 | bool role_check = surface->role == ROLE_NONE || 69 | surface->role == ROLE_XDG_TOPLEVEL; 70 | bool base_role_check = surface->base_role == BASE_ROLE_XDG_SURFACE; 71 | if (!(role_check && base_role_check)) { 72 | wl_resource_post_error(data->wm_base, XDG_WM_BASE_ERROR_ROLE, 73 | "Given wl_surface has another role"); 74 | return; 75 | } 76 | surface->role = ROLE_XDG_TOPLEVEL; 77 | surface->role_object = xdg_toplevel; 78 | xdg_surface_map_condition_satisfied(data, 79 | MAP_CONDITION_ROLE_ASSIGNED); 80 | } 81 | 82 | static void get_popup(struct wl_client *client, struct wl_resource *resource, 83 | uint32_t id, struct wl_resource *parent, struct wl_resource *positioner) { 84 | struct wl_resource *popup = wl_resource_create(client, 85 | &xdg_popup_interface, 1, id); 86 | xdg_popup_new(popup); 87 | } 88 | 89 | static void set_window_geometry(struct wl_client *client, struct wl_resource 90 | *resource, int32_t x, int32_t y, int32_t width, int32_t height) { 91 | struct xdg_surface0 *xdg_surface = wl_resource_get_user_data(resource); 92 | xdg_surface->pending->window_geometry.x = x; 93 | xdg_surface->pending->window_geometry.y = y; 94 | xdg_surface->pending->window_geometry.width = width; 95 | xdg_surface->pending->window_geometry.height = height; 96 | 97 | } 98 | 99 | static void ack_configure(struct wl_client *client, struct wl_resource 100 | *resource, uint32_t serial) { 101 | } 102 | 103 | static const struct xdg_surface_interface impl = { 104 | .destroy = destroy, 105 | .get_toplevel = get_toplevel, 106 | .get_popup = get_popup, 107 | .set_window_geometry = set_window_geometry, 108 | .ack_configure = ack_configure 109 | }; 110 | 111 | static void commit_notify(struct wl_listener *listener, void *data) { 112 | struct xdg_surface0 *xdg_surface; 113 | xdg_surface = wl_container_of(listener, xdg_surface, commit); 114 | struct xdg_surface_state0 *pending = xdg_surface->pending, *current = 115 | xdg_surface->current; 116 | 117 | current->window_geometry.x = pending->window_geometry.x; 118 | current->window_geometry.y = pending->window_geometry.y; 119 | current->window_geometry.width = pending->window_geometry.width; 120 | current->window_geometry.height = pending->window_geometry.height; 121 | 122 | if (!xdg_surface_map_condition_check(xdg_surface, 123 | MAP_CONDITION_BASE_ROLE_INIT_COMMIT)) { 124 | xdg_surface_map_condition_satisfied(xdg_surface, 125 | MAP_CONDITION_BASE_ROLE_INIT_COMMIT); 126 | } 127 | } 128 | 129 | static void xdg_surface_free(struct wl_resource *resource) { 130 | errlog("xdg_surface destroyed"); 131 | struct xdg_surface0 *xdg_surface = wl_resource_get_user_data(resource); 132 | xdg_surface->child_destroy_notify(xdg_surface->data); 133 | free(xdg_surface->current); 134 | free(xdg_surface->pending); 135 | free(xdg_surface); 136 | } 137 | 138 | struct xdg_surface0 *xdg_surface_new(struct wl_resource *resource, struct 139 | wl_resource *surface_resource, struct wl_resource *wm_base, struct 140 | xdg_toplevel_events xdg_toplevel_events, callback_t child_destroy_notify, void 141 | *data) { 142 | struct surface *surface = wl_resource_get_user_data(surface_resource); 143 | struct xdg_surface0 *xdg_surface = calloc(1, sizeof(struct 144 | xdg_surface0)); 145 | xdg_surface->self = resource; 146 | xdg_surface->wm_base = wm_base; 147 | xdg_surface->pending = calloc(1, sizeof(struct xdg_surface_state0)); 148 | xdg_surface->current = calloc(1, sizeof(struct xdg_surface_state0)); 149 | xdg_surface->surface = surface_resource; 150 | 151 | xdg_surface->xdg_toplevel_events = xdg_toplevel_events; 152 | 153 | xdg_surface->child_destroy_notify = child_destroy_notify; 154 | xdg_surface->data = data; 155 | 156 | xdg_surface->commit.notify = commit_notify; 157 | wl_signal_add(&surface->commit, &xdg_surface->commit); 158 | wl_resource_set_implementation(resource, &impl, xdg_surface, 159 | xdg_surface_free); 160 | return xdg_surface; 161 | } 162 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/xdg_shell/xdg_toplevel.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 14 | 15 | } 16 | 17 | static void set_parent(struct wl_client *client, struct wl_resource *resource, 18 | struct wl_resource *parent) { 19 | 20 | } 21 | 22 | static void set_title(struct wl_client *client, struct wl_resource *resource, 23 | const char *title) { 24 | 25 | } 26 | 27 | static void set_app_id(struct wl_client *client, struct wl_resource *resource, 28 | const char *app_id) { 29 | struct xdg_toplevel_data *data = wl_resource_get_user_data(resource); 30 | data->app_id = strdup(app_id); 31 | } 32 | 33 | static void show_window_menu(struct wl_client *client, struct wl_resource 34 | *resource, struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y) { 35 | /* 36 | * No window menu 37 | */ 38 | } 39 | 40 | static void move(struct wl_client *client, struct wl_resource *resource, struct 41 | wl_resource *seat, uint32_t serial) { 42 | /* 43 | * Windows can't be moved 44 | */ 45 | } 46 | 47 | static void resize(struct wl_client *client, struct wl_resource *resource, 48 | struct wl_resource *seat, uint32_t serial, uint32_t edges) { 49 | /* 50 | * Windows can't be resized 51 | */ 52 | } 53 | 54 | static void set_max_size(struct wl_client *client, struct wl_resource *resource, 55 | int32_t width, int32_t height) { 56 | 57 | } 58 | 59 | static void set_min_size(struct wl_client *client, struct wl_resource *resource, 60 | int32_t width, int32_t height) { 61 | 62 | } 63 | 64 | static void set_maximized(struct wl_client *client, struct wl_resource 65 | *resource) { 66 | 67 | } 68 | 69 | static void unset_maximized(struct wl_client *client, struct wl_resource 70 | *resource) { 71 | 72 | } 73 | 74 | static void set_fullscreen(struct wl_client *client, struct wl_resource 75 | *resource, struct wl_resource *output) { 76 | 77 | } 78 | 79 | static void unset_fullscreen(struct wl_client *client, struct wl_resource 80 | *resource) { 81 | 82 | } 83 | 84 | static void set_minimized(struct wl_client *client, struct wl_resource 85 | *resource) { 86 | 87 | } 88 | 89 | static const struct xdg_toplevel_interface impl = { 90 | .destroy = destroy, 91 | .set_parent = set_parent, 92 | .set_title = set_title, 93 | .set_app_id = set_app_id, 94 | .show_window_menu = show_window_menu, 95 | .move = move, 96 | .resize = resize, 97 | .set_max_size = set_max_size, 98 | .set_min_size = set_min_size, 99 | .set_maximized = set_maximized, 100 | .unset_maximized = unset_maximized, 101 | .set_fullscreen = set_fullscreen, 102 | .unset_fullscreen = unset_fullscreen, 103 | .set_minimized = set_minimized, 104 | }; 105 | 106 | static void commit_notify(struct wl_listener *listener, void *data) { 107 | struct xdg_toplevel_data *xdg_toplevel; 108 | xdg_toplevel = wl_container_of(listener, xdg_toplevel, commit); 109 | struct xdg_surface0 *xdg_surface = xdg_toplevel->xdg_surface_data; 110 | struct surface *surface = data; 111 | 112 | if (!xdg_surface_map_condition_check(xdg_surface, 113 | MAP_CONDITION_ROLE_INIT_COMMIT)) { 114 | void *user_data = xdg_toplevel->events.user_data; 115 | xdg_toplevel->events.init(xdg_toplevel, user_data); 116 | xdg_surface_map_condition_satisfied(xdg_surface, 117 | MAP_CONDITION_ROLE_INIT_COMMIT); 118 | } 119 | 120 | if (!xdg_surface_map_condition_check(xdg_surface, 121 | MAP_CONDITION_BUFFER_COMMIT) && surface->current->buffer) { 122 | xdg_surface_map_condition_satisfied(xdg_surface, 123 | MAP_CONDITION_BUFFER_COMMIT); 124 | } 125 | } 126 | 127 | static void destroyed(struct wl_resource *resource) { 128 | errlog("xdg_toplevel destroyed"); 129 | struct xdg_toplevel_data *data = wl_resource_get_user_data(resource); 130 | /* struct surface *surface = wl_resource_get_user_data(data->xdg_surface_data->surface); 131 | errlog("%p", surface); 132 | if (surface->is_mapped) { 133 | surface->surface_events.unmap(surface, 134 | surface->surface_events.user_data); 135 | surface->is_mapped = false; 136 | }*/ 137 | errlog("Destroyed the window '%s'", data->app_id); //TODO move to main 138 | free(data->app_id); 139 | free(data); 140 | } 141 | 142 | // version 1 143 | 144 | struct xdg_toplevel_data *xdg_toplevel_new(struct wl_resource *resource, struct xdg_surface0 145 | *xdg_surface_data, struct xdg_toplevel_events events) { 146 | struct xdg_toplevel_data *toplevel_data = calloc(1, sizeof(struct 147 | xdg_toplevel_data)); 148 | toplevel_data->resource = resource; 149 | toplevel_data->xdg_surface_data = xdg_surface_data; 150 | struct surface *surface_data = 151 | wl_resource_get_user_data(xdg_surface_data->surface); 152 | toplevel_data->commit.notify = commit_notify; 153 | wl_signal_add(&surface_data->commit, &toplevel_data->commit); 154 | toplevel_data->app_id = get_a_name(wl_resource_get_client(resource)); 155 | toplevel_data->events = events; 156 | wl_resource_set_implementation(resource, &impl, toplevel_data, 157 | destroyed); 158 | return toplevel_data; 159 | } 160 | 161 | char *xdg_toplevel_get_app_id(struct xdg_toplevel_data *data) { 162 | return data->app_id; 163 | } 164 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/extensions/xdg_shell/xdg_wm_base.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | static void destroy(struct wl_client *client, struct wl_resource *resource) { 13 | struct xdg_wm_base *xdg_wm_base = wl_resource_get_user_data(resource); 14 | if (xdg_wm_base->xdg_surface_count != 0) { 15 | wl_resource_post_error(resource, 16 | XDG_WM_BASE_ERROR_DEFUNCT_SURFACES, "xdg_wm_base was destroyed \ 17 | before children"); 18 | return; 19 | } 20 | wl_resource_destroy(resource); 21 | } 22 | 23 | static void create_positioner(struct wl_client *client, struct wl_resource 24 | *resource, uint32_t id) { 25 | struct wl_resource *positioner = wl_resource_create(client, 26 | &xdg_positioner_interface, 1, id); 27 | xdg_positioner_new(positioner); 28 | } 29 | 30 | static void child_destroy_notify(void *user_data) { 31 | int *xdg_surface_count = user_data; 32 | (*xdg_surface_count)--; 33 | } 34 | 35 | static void get_xdg_surface(struct wl_client *client, struct wl_resource 36 | *resource, uint32_t id, struct wl_resource *surface_resource) { 37 | struct xdg_wm_base *xdg_wm_base = wl_resource_get_user_data(resource); 38 | struct wl_resource *xdg_surf_resource = wl_resource_create(client, 39 | &xdg_surface_interface, 1, id); 40 | struct xdg_surface0 *xdg_surface = xdg_surface_new(xdg_surf_resource, 41 | surface_resource, resource, xdg_wm_base->xdg_toplevel_events, 42 | child_destroy_notify, &xdg_wm_base->xdg_surface_count); 43 | /* 44 | * Assign a role to the surface 45 | */ 46 | struct surface *surface = wl_resource_get_user_data(surface_resource); 47 | bool role_check = surface->role == ROLE_NONE || 48 | surface->role == ROLE_XDG_POPUP || 49 | surface->role == ROLE_XDG_TOPLEVEL; 50 | bool base_role_check = surface->base_role == BASE_ROLE_NONE || 51 | surface->base_role == BASE_ROLE_XDG_SURFACE; 52 | if (!(role_check && base_role_check)) { 53 | wl_resource_post_error(resource, XDG_WM_BASE_ERROR_ROLE, 54 | "Given wl_surface has another role"); 55 | return; 56 | } 57 | surface->base_role = BASE_ROLE_XDG_SURFACE; 58 | surface->base_role_object = xdg_surface; 59 | xdg_wm_base->xdg_surface_count++; 60 | } 61 | 62 | static void pong(struct wl_client *client, struct wl_resource *resource, 63 | uint32_t serial) { 64 | /* 65 | * Never sending ping at the moment 66 | */ 67 | } 68 | 69 | static const struct xdg_wm_base_interface impl = { 70 | .destroy = destroy, 71 | .create_positioner = create_positioner, 72 | .get_xdg_surface = get_xdg_surface, 73 | .pong = pong 74 | }; 75 | 76 | struct xdg_wm_base *xdg_wm_base_new(struct wl_resource *resource, struct 77 | xdg_toplevel_events xdg_toplevel_events) { 78 | struct xdg_wm_base *xdg_wm_base = calloc(1, sizeof(struct xdg_wm_base)); 79 | xdg_wm_base->xdg_toplevel_events = xdg_toplevel_events; 80 | wl_resource_set_implementation(resource, &impl, xdg_wm_base, 0); 81 | return xdg_wm_base; 82 | } 83 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/globals.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | /* 28 | * Defined in main.c 29 | */ 30 | extern void surface_map_notify(struct surface *surface, void *user_data); 31 | extern void surface_unmap_notify(struct surface *surface, void *user_data); 32 | extern void surface_contents_update_notify(struct surface *surface, void *user_data); 33 | extern void xdg_toplevel_init_notify(struct xdg_toplevel_data *xdg_toplevel, void 34 | *user_data); 35 | extern void buffer_dmabuf_create_notify(struct wl_buffer_dmabuf_data *dmabuf, void 36 | *user_data); 37 | extern void buffer_dmabuf_destroy_notify(struct wl_buffer_dmabuf_data *dmabuf, void 38 | *user_data); 39 | extern void keyboard_init_notify(struct keyboard *keyboard, void *user_data); 40 | 41 | static void compositor_bind(struct wl_client *client, void *data, uint32_t 42 | version, uint32_t id) { 43 | struct wl_resource *resource = wl_resource_create(client, 44 | &wl_compositor_interface, version, id); 45 | struct surface_events surface_events = { 46 | .map = surface_map_notify, 47 | .unmap = surface_unmap_notify, 48 | .contents_update = surface_contents_update_notify, 49 | .user_data = data 50 | }; 51 | compositor_new(resource, surface_events); 52 | } 53 | 54 | static void data_device_manager_bind(struct wl_client *client, void *data, 55 | uint32_t version, uint32_t id) { 56 | struct wl_resource *resource = wl_resource_create(client, 57 | &wl_data_device_manager_interface, version, id); 58 | data_device_manager_new(resource); 59 | } 60 | 61 | static void seat_bind(struct wl_client *client, void *data, uint32_t version, 62 | uint32_t id) { 63 | struct wl_resource *resource = wl_resource_create(client, 64 | &wl_seat_interface, version, id); 65 | struct keyboard_events keyboard_events = { 66 | .init = keyboard_init_notify, 67 | .user_data = data 68 | }; 69 | seat_new(resource, keyboard_events); 70 | } 71 | 72 | static void subcompositor_bind(struct wl_client *client, void *data, uint32_t 73 | version, uint32_t id) { 74 | struct wl_resource *resource = wl_resource_create(client, 75 | &wl_subcompositor_interface, version, id); 76 | wl_subcompositor_new(resource); 77 | } 78 | 79 | static void output_bind(struct wl_client *client, void *data, uint32_t version, 80 | uint32_t id) { 81 | struct wl_resource *resource = wl_resource_create(client, 82 | &wl_output_interface, version, id); 83 | output_new(resource); 84 | } 85 | 86 | static void xdg_wm_base_bind(struct wl_client *client, void *data, uint32_t 87 | version, uint32_t id) { 88 | struct wl_resource *resource = wl_resource_create(client, 89 | &xdg_wm_base_interface, version, id); 90 | struct xdg_toplevel_events xdg_toplevel_events = { 91 | .init = xdg_toplevel_init_notify, 92 | .user_data = data 93 | }; 94 | xdg_wm_base_new(resource, xdg_toplevel_events); 95 | } 96 | 97 | static void zwp_linux_dmabuf_v1_bind(struct wl_client *client, void *data, uint32_t 98 | version, uint32_t id) { 99 | struct wl_resource *resource = wl_resource_create(client, 100 | &zwp_linux_dmabuf_v1_interface, version, id); 101 | struct buffer_dmabuf_events buffer_dmabuf_events = { 102 | .create = buffer_dmabuf_create_notify, 103 | .destroy = buffer_dmabuf_destroy_notify, 104 | .user_data = data 105 | }; 106 | zwp_linux_dmabuf_v1_new(resource, buffer_dmabuf_events); 107 | } 108 | 109 | static void zwp_linux_explicit_synchronization_v1_bind(struct wl_client *client, 110 | void *data, uint32_t version, uint32_t id) { 111 | struct wl_resource *resource = wl_resource_create(client, 112 | &zwp_linux_explicit_synchronization_v1_interface, version, id); 113 | linux_explicit_synchronization_new(resource); 114 | } 115 | 116 | static void zwp_fullscreen_shell_v1_bind(struct wl_client *client, void *data, uint32_t 117 | version, uint32_t id) { 118 | struct wl_resource *resource = wl_resource_create(client, 119 | &zwp_fullscreen_shell_v1_interface, version, id); 120 | zwp_fullscreen_shell_v1_new(resource); 121 | } 122 | 123 | static void org_kde_kwin_server_decoration_manager_bind(struct wl_client 124 | *client, void *data, uint32_t version, uint32_t id) { 125 | struct wl_resource *resource = wl_resource_create(client, 126 | &org_kde_kwin_server_decoration_manager_interface, version, id); 127 | org_kde_kwin_server_decoration_manager_new(resource); 128 | } 129 | 130 | // For debugging 131 | static bool global_filter(const struct wl_client *client, const struct wl_global 132 | *global, void *data) { 133 | char *client_name = get_a_name((struct wl_client*)client); 134 | bool condition = wl_global_get_interface(global) == &zwp_fullscreen_shell_v1_interface; 135 | if (!strcmp(client_name, "weston-simple-d") && condition) { 136 | free(client_name); 137 | return false; 138 | } 139 | free(client_name); 140 | return true; 141 | } 142 | 143 | void create_globals(struct wl_display *D, bool dmabuf, void *user_data) { 144 | wl_global_create(D, &wl_compositor_interface, 4, user_data, 145 | compositor_bind); 146 | wl_global_create(D, &wl_subcompositor_interface, 1, 0, 147 | subcompositor_bind); 148 | wl_global_create(D, &wl_data_device_manager_interface, 3, 0, 149 | data_device_manager_bind); 150 | wl_global_create(D, &wl_seat_interface, 5, user_data, seat_bind); 151 | wl_global_create(D, &wl_output_interface, 3, 0, output_bind); 152 | wl_display_init_shm(D); 153 | wl_global_create(D, &xdg_wm_base_interface, 1, user_data, 154 | xdg_wm_base_bind); 155 | if (dmabuf) 156 | wl_global_create(D, &zwp_linux_dmabuf_v1_interface, 3, user_data, 157 | zwp_linux_dmabuf_v1_bind); 158 | wl_global_create(D, &zwp_linux_explicit_synchronization_v1_interface, 1, 159 | user_data, zwp_linux_explicit_synchronization_v1_bind); 160 | wl_global_create(D, &zwp_fullscreen_shell_v1_interface, 1, NULL, 161 | zwp_fullscreen_shell_v1_bind); 162 | wl_global_create(D, &org_kde_kwin_server_decoration_manager_interface, 163 | 1, NULL, org_kde_kwin_server_decoration_manager_bind); 164 | 165 | // wl_display_set_global_filter(D, global_filter, 0); 166 | } 167 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/compositor.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct compositor { 4 | struct surface_events surface_events; 5 | }; 6 | 7 | struct compositor *compositor_new(struct wl_resource *resource, struct 8 | surface_events surface_events); 9 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/data_device.h: -------------------------------------------------------------------------------- 1 | void data_device_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/data_device_manager.h: -------------------------------------------------------------------------------- 1 | void data_device_manager_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/data_offer.h: -------------------------------------------------------------------------------- 1 | void data_offer_new(struct wl_resource *resource, struct wl_resource *source); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/data_source.h: -------------------------------------------------------------------------------- 1 | struct mime_node { 2 | char *mime_type; 3 | struct wl_list link; 4 | }; 5 | 6 | void data_source_new(struct wl_resource *resource); 7 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/keyboard.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct keyboard; 4 | struct wl_resource; 5 | typedef void (*keyboard_init_t)(struct keyboard *, void *); 6 | 7 | struct keyboard_events { 8 | keyboard_init_t init; 9 | 10 | void *user_data; 11 | }; 12 | 13 | void keyboard_new(struct wl_resource *resource, struct keyboard_events 14 | keyboard_events); 15 | void keyboard_send_keymap(struct keyboard *keyboard, int32_t fd, uint32_t size); 16 | void keyboard_send_key(struct keyboard *keyboard, uint32_t key, uint32_t state); 17 | void keyboard_send_modifiers(struct keyboard *keyboard, uint32_t mods_depressed, 18 | uint32_t mods_latched, uint32_t mods_locked, uint32_t group); 19 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/output.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void output_new(struct wl_resource *resource); 4 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/region.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void region_new(struct wl_resource *resource); 4 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/seat.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct seat { 5 | struct keyboard_events keyboard_events; 6 | }; 7 | 8 | struct seat *seat_new(struct wl_resource *resource, struct 9 | keyboard_events keyboard_events); 10 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/subsurface.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | /* 6 | * The double-buffered state 7 | */ 8 | 9 | struct subsurface_dbuf_state { 10 | struct wl_resource *parent; 11 | }; 12 | 13 | struct subsurface { 14 | struct subsurface_dbuf_state *current, *pending; 15 | uint8_t staged; // bitmask 16 | 17 | struct wl_resource *surface; 18 | 19 | uint8_t map_conditions; // bitmask 20 | 21 | struct wl_listener commit; 22 | struct wl_listener parent_commit; 23 | }; 24 | 25 | struct subsurface *wl_subsurface_new(struct wl_resource *subsurface_resource, struct 26 | wl_resource *surface_resource, struct wl_resource *parent_resource); 27 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/wl_pointer.h: -------------------------------------------------------------------------------- 1 | void wl_pointer_new(struct wl_resource *); 2 | 3 | struct pointer { 4 | int hotspot_x; 5 | int hotspot_y; 6 | }; 7 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/wl_subcompositor.h: -------------------------------------------------------------------------------- 1 | void wl_subcompositor_new(struct wl_resource *); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/wl_surface.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSURFACE_H 2 | #define MYSURFACE_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | /* 10 | * A surface is the fundamental Wayland object involved in presentation of 11 | * client-provided content to the display. 12 | * The compositor can access only those surfaces that are added to the surface 13 | * tree 14 | */ 15 | 16 | struct surface; 17 | typedef void (*surface_map_t)(struct surface *, void *); 18 | typedef void (*surface_unmap_t)(struct surface *, void *); 19 | typedef void (*surface_contents_update_t)(struct surface *, void *); 20 | 21 | struct surface_events { 22 | surface_map_t map; 23 | surface_unmap_t unmap; 24 | surface_contents_update_t contents_update; 25 | 26 | void *user_data; 27 | }; 28 | 29 | enum role { 30 | ROLE_NONE, 31 | ROLE_CURSOR, 32 | ROLE_DRAG_AND_DROP_ICON, 33 | ROLE_SUBSURFACE, 34 | ROLE_FULLSCREEN, // from fullscreen-shell 35 | ROLE_XDG_POPUP, // from xdg-shell 36 | ROLE_XDG_TOPLEVEL // from xdg-shell 37 | }; 38 | 39 | enum base_role { 40 | BASE_ROLE_NONE, 41 | BASE_ROLE_XDG_SURFACE // from xdg-shell 42 | }; 43 | 44 | /* 45 | * The double-buffered state 46 | */ 47 | 48 | struct dbuf_state { 49 | struct wl_resource *buffer; 50 | struct box damage; 51 | struct box buffer_damage; 52 | struct wl_resource *opaque_region; 53 | struct wl_resource *input_region; 54 | enum wl_output_transform buffer_transform; 55 | int32_t buffer_scale; 56 | }; 57 | 58 | struct surface { 59 | struct wl_resource *resource; 60 | 61 | struct dbuf_state *current, *pending; 62 | 63 | uint8_t staged; // bitmask 64 | 65 | struct wl_resource *frame; 66 | 67 | enum role role; 68 | enum base_role base_role; 69 | void *role_object; 70 | void *base_role_object; 71 | 72 | struct wl_list extensions; 73 | 74 | bool is_mapped; 75 | 76 | struct wl_signal commit; 77 | 78 | struct surface_events surface_events; 79 | }; 80 | 81 | struct surface *surface_new(struct wl_resource *resource, struct surface_events 82 | surface_events); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/core/wl_surface_staged_field.h: -------------------------------------------------------------------------------- 1 | enum staged_field { 2 | BUFFER = 1 << 0, 3 | DAMAGE = 1 << 1, 4 | OPAQUE_REGION = 1 << 2, 5 | INPUT_REGION = 1 << 3, 6 | BUFFER_TRANSFORM = 1 << 4, 7 | BUFFER_SCALE = 1 << 5, 8 | BUFFER_DAMAGE = 1 << 6 9 | }; 10 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/fullscreen-shell-unstable-v1/zwp_fullscreen_shell_v1.h: -------------------------------------------------------------------------------- 1 | void zwp_fullscreen_shell_v1_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/linux-dmabuf-unstable-v1/wl_buffer_dmabuf.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_WL_BUFFER_DMABUF_H 2 | #define MY_WL_BUFFER_DMABUF_H 3 | 4 | #include 5 | #include 6 | 7 | struct wl_buffer_dmabuf_data; 8 | typedef void (*buffer_dmabuf_create_t)(struct wl_buffer_dmabuf_data *, void *); 9 | typedef void (*buffer_dmabuf_destroy_t)(struct wl_buffer_dmabuf_data *, void *); 10 | 11 | struct buffer_dmabuf_events { 12 | buffer_dmabuf_create_t create; 13 | buffer_dmabuf_destroy_t destroy; 14 | 15 | void *user_data; 16 | }; 17 | 18 | enum subsystem { 19 | SUBSYSTEM_DRM, 20 | SUBSYSTEM_VULKAN, 21 | SUBSYSTEM_N}; 22 | 23 | struct wl_buffer_dmabuf_data { 24 | int32_t width; 25 | int32_t height; 26 | uint32_t format; 27 | uint32_t flags; 28 | 29 | uint32_t num_planes; 30 | int32_t *fds; 31 | uint32_t *offsets; 32 | uint32_t *strides; 33 | uint64_t *modifiers; 34 | 35 | struct buffer_dmabuf_events buffer_dmabuf_events; 36 | /* 37 | * Subsystem-specific object for this buffer 38 | */ 39 | void *subsystem_object[SUBSYSTEM_N]; 40 | }; 41 | 42 | struct wl_resource; 43 | 44 | struct wl_buffer_dmabuf_data *wl_buffer_dmabuf_new(struct wl_resource *resource, 45 | int32_t width, int32_t height, uint32_t format, uint32_t flags, uint32_t 46 | num_planes, struct buffer_dmabuf_events buffer_dmabuf_events); 47 | 48 | bool wl_buffer_is_dmabuf(struct wl_resource *); 49 | 50 | int32_t wl_buffer_dmabuf_get_width(struct wl_resource *); 51 | int32_t wl_buffer_dmabuf_get_height(struct wl_resource *); 52 | uint32_t wl_buffer_dmabuf_get_format(struct wl_resource *); 53 | uint32_t wl_buffer_dmabuf_get_num_planes(struct wl_resource *); 54 | uint32_t *wl_buffer_dmabuf_get_offsets(struct wl_resource *); 55 | uint32_t *wl_buffer_dmabuf_get_strides(struct wl_resource *); 56 | uint64_t *wl_buffer_dmabuf_get_mods(struct wl_resource *); 57 | 58 | void *wl_buffer_dmabuf_get_subsystem_object(struct wl_resource *, enum subsystem); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/linux-dmabuf-unstable-v1/zwp_linux_buffer_params_v1.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | struct plane { 8 | int32_t fd; 9 | uint32_t plane_idx; 10 | uint32_t offset; 11 | uint32_t stride; 12 | uint64_t modifier; 13 | 14 | struct wl_list link; 15 | }; 16 | 17 | struct zwp_linux_buffer_params_v1_data { 18 | bool already_used; 19 | struct wl_list plane_list; 20 | struct buffer_dmabuf_events buffer_dmabuf_events; 21 | }; 22 | 23 | struct zwp_linux_buffer_params_v1_data *zwp_linux_buffer_params_v1_new(struct 24 | wl_resource *, struct buffer_dmabuf_events buffer_dmabuf_events); 25 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/linux-dmabuf-unstable-v1/zwp_linux_dmabuf_v1.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | struct linux_dmabuf { 6 | struct buffer_dmabuf_events buffer_dmabuf_events; 7 | }; 8 | 9 | void zwp_linux_dmabuf_v1_new(struct wl_resource *resource, struct 10 | buffer_dmabuf_events buffer_dmabuf_events); 11 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/linux-explicit-synchronization-v1/zwp_linux_explicit_synchronization_v1.h: -------------------------------------------------------------------------------- 1 | void linux_explicit_synchronization_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/linux-explicit-synchronization-v1/zwp_linux_surface_synchronization_v1.h: -------------------------------------------------------------------------------- 1 | struct linux_surface_synchronization; 2 | struct surface; 3 | 4 | void linux_surface_synchronization_new(struct wl_resource *resource, struct 5 | surface *surface); 6 | int linux_surface_synchronization_get_fence(struct linux_surface_synchronization 7 | *self); 8 | void linux_surface_synchronization_send_immediate_release(struct 9 | linux_surface_synchronization *self); 10 | void linux_surface_synchronization_send_fenced_release(struct 11 | linux_surface_synchronization *self, int fence_fd); 12 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/server-decoration/org_kde_kwin_server_decoration.h: -------------------------------------------------------------------------------- 1 | void org_kde_kwin_server_decoration_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/server-decoration/org_kde_kwin_server_decoration_manager.h: -------------------------------------------------------------------------------- 1 | void org_kde_kwin_server_decoration_manager_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/xdg_shell/xdg_popup.h: -------------------------------------------------------------------------------- 1 | void xdg_popup_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/xdg_shell/xdg_positioner.h: -------------------------------------------------------------------------------- 1 | void xdg_positioner_new(struct wl_resource *resource); 2 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/xdg_shell/xdg_surface.h: -------------------------------------------------------------------------------- 1 | #ifndef MYXDGSURFACE_H 2 | #define MYXDGSURFACE_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | typedef void (*callback_t)(void *); 10 | 11 | enum map_condition_field { 12 | MAP_CONDITION_ROLE_ASSIGNED = 1 << 0, 13 | MAP_CONDITION_BASE_ROLE_INIT_COMMIT = 1 << 1, 14 | MAP_CONDITION_ROLE_INIT_COMMIT = 1 << 2, 15 | MAP_CONDITION_BUFFER_COMMIT = 1 << 3, 16 | }; 17 | 18 | struct xdg_surface_state0 { 19 | struct box window_geometry; 20 | }; 21 | 22 | struct xdg_surface0 { 23 | struct wl_resource *self; 24 | struct wl_resource *wm_base; 25 | struct wl_resource *surface; 26 | struct server *server; 27 | uint8_t map_conditions; // bitmask 28 | struct xdg_surface_state0 *pending, *current; 29 | struct wl_listener commit; 30 | struct wl_list link; 31 | 32 | struct wl_signal contents_update; 33 | 34 | struct xdg_toplevel_events xdg_toplevel_events; 35 | 36 | callback_t child_destroy_notify; 37 | void *data; 38 | }; 39 | 40 | struct xdg_surface0 *xdg_surface_new 41 | ( 42 | struct wl_resource *resource, 43 | struct wl_resource *surface_resource, 44 | struct wl_resource *wm_base, 45 | struct xdg_toplevel_events xdg_toplevel_events, 46 | callback_t child_destroy_notify, 47 | void *data 48 | ); 49 | void xdg_surface_map_condition_satisfied 50 | ( 51 | struct xdg_surface0 *xdg_surface, 52 | enum map_condition_field condition 53 | ); 54 | bool xdg_surface_map_condition_check(struct xdg_surface0 *xdg_surface, enum 55 | map_condition_field condition); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/xdg_shell/xdg_toplevel.h: -------------------------------------------------------------------------------- 1 | #ifndef MYXDGTOPLEVEL_H 2 | #define MYXDGTOPLEVEL_H 3 | 4 | #include 5 | 6 | struct xdg_toplevel_data; 7 | 8 | typedef void (*xdg_toplevel_init_t)(struct xdg_toplevel_data *, void *); 9 | 10 | struct xdg_toplevel_events { 11 | xdg_toplevel_init_t init; 12 | 13 | void *user_data; 14 | }; 15 | 16 | struct xdg_toplevel_data { 17 | struct wl_resource *resource; 18 | struct xdg_surface0 *xdg_surface_data; 19 | struct wl_listener commit; 20 | char *app_id; 21 | 22 | struct xdg_toplevel_events events; 23 | }; 24 | 25 | struct xdg_toplevel_data *xdg_toplevel_new(struct wl_resource *, struct 26 | xdg_surface0 *, struct xdg_toplevel_events events); 27 | 28 | char *xdg_toplevel_get_app_id(struct xdg_toplevel_data *); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/extensions/xdg_shell/xdg_wm_base.h: -------------------------------------------------------------------------------- 1 | #ifndef MYXDGWMBASE_H 2 | #define MYXDGWMBASE_H 3 | 4 | #include 5 | #include 6 | 7 | struct xdg_wm_base { 8 | int xdg_surface_count; 9 | struct xdg_toplevel_events xdg_toplevel_events; 10 | }; 11 | 12 | struct xdg_wm_base *xdg_wm_base_new(struct wl_resource *resource, struct 13 | xdg_toplevel_events xdg_toplevel_events); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/globals.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void create_globals(struct wl_display *D, bool dmabuf, void *user_data); 4 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/util/algebra.h: -------------------------------------------------------------------------------- 1 | #ifndef MYALGEBRA_H 2 | #define MYALGEBRA_H 3 | 4 | void algebra_matrix_rotation_x(float *matrix, float theta); 5 | void algebra_matrix_rotation_y(float *matrix, float theta); 6 | void algebra_matrix_traslation(float *matrix, float x, float y, float z); 7 | void algebra_matrix_multiply(float *product, float *a, float *b); 8 | void algebra_matrix_ortho(float *matrix, float left, float right, float bottom, 9 | float top, float near, float far); 10 | void algebra_matrix_persp(float *m, float fov, float ratio, float n, float f); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/util/box.h: -------------------------------------------------------------------------------- 1 | #ifndef MYBOX_H 2 | #define MYBOX_H 3 | 4 | #include 5 | 6 | struct box { 7 | int32_t x; 8 | int32_t y; 9 | int32_t width; 10 | int32_t height; 11 | }; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/util/log.h: -------------------------------------------------------------------------------- 1 | #ifndef MY_LOG_H 2 | #define MY_LOG_H 3 | 4 | void errlog(const char *fmt, ...); 5 | void boxlog(const char *fmt, ...); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/include/util/util.h: -------------------------------------------------------------------------------- 1 | struct wl_client; 2 | 3 | struct extension_node { 4 | struct wl_resource *resource; 5 | struct wl_list link; 6 | }; 7 | 8 | struct wl_resource *util_wl_client_get_keyboard(struct wl_client *); 9 | struct wl_resource *util_wl_client_get_pointer(struct wl_client *client); 10 | struct wl_resource *util_wl_client_get_output(struct wl_client *client); 11 | struct wl_resource *util_get_extension(struct wl_list *extensions, const char 12 | *class); 13 | char *read_file(const char *); 14 | char *get_a_name(struct wl_client *client); 15 | void dmabuf_save_to_disk(int fd); 16 | int a(); 17 | void fd_test(int n); 18 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/meson.build: -------------------------------------------------------------------------------- 1 | project('libswvkc-wl', 'c', version: 'pre-alpha', 2 | default_options: ['c_std=c11', 'warning_level=3', 'werror=true']) 3 | add_project_arguments('-pedantic-errors', '-Wno-unused-parameter', 4 | '-Wno-unused-function', language: 'c') 5 | add_project_link_arguments('-lm', language: 'c') 6 | 7 | c = 'core/' 8 | u = 'util/' 9 | x = 'extensions/' 10 | 11 | src = [c+'compositor.c', c+'data_device.c', c+'data_device_manager.c', 12 | c+'data_offer.c', c+'data_source.c', c+'keyboard.c', c+'output.c', 13 | c+'wl_pointer.c', c+'region.c', c+'seat.c', c+'wl_subcompositor.c', 14 | c+'subsurface.c', c+'wl_surface.c'] 15 | src += [u+'algebra.c', u+'log.c', u+'util.c'] 16 | src += [x+'xdg_shell/xdg_wm_base.c', 17 | x+'xdg_shell/xdg_positioner.c', x+'xdg_shell/xdg_surface.c', 18 | x+'xdg_shell/xdg_toplevel.c', x+'xdg_shell/xdg_popup.c', 19 | x+'linux-dmabuf-unstable-v1/zwp_linux_dmabuf_v1.c', 20 | x+'linux-dmabuf-unstable-v1/zwp_linux_buffer_params_v1.c', 21 | x+'linux-dmabuf-unstable-v1/wl_buffer_dmabuf.c', 22 | x+'linux-explicit-synchronization-v1/zwp_linux_explicit_synchronization_v1.c', 23 | x+'linux-explicit-synchronization-v1/zwp_linux_surface_synchronization_v1.c', 24 | x+'fullscreen-shell-unstable-v1/zwp_fullscreen_shell_v1.c', 25 | x+'server-decoration/org_kde_kwin_server_decoration_manager.c', 26 | x+'server-decoration/org_kde_kwin_server_decoration.c'] 27 | src += ['globals.c'] 28 | 29 | wayland_protocols_dep = dependency('wayland-protocols', native: true) 30 | protocols_path = wayland_protocols_dep.get_pkgconfig_variable('pkgdatadir') 31 | 32 | wayland_scanner_dep = dependency('wayland-scanner', native: true) 33 | wayland_scanner = wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner') 34 | 35 | protocols = [ 36 | 'stable/xdg-shell/xdg-shell.xml', 37 | 'unstable/fullscreen-shell/fullscreen-shell-unstable-v1.xml', 38 | 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', 39 | 'unstable/linux-explicit-synchronization/linux-explicit-synchronization-unstable-v1.xml' 40 | ] 41 | 42 | gen = [] 43 | 44 | foreach p : protocols 45 | gen += custom_target( 46 | p.underscorify()+'_server_protocol', 47 | output: '@BASENAME@-server-protocol.h', 48 | input: protocols_path/p, 49 | command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'] 50 | ) 51 | gen += custom_target( 52 | p.underscorify()+'_code', 53 | output: '@BASENAME@-code.c', 54 | input: protocols_path/p, 55 | command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'] 56 | ) 57 | endforeach 58 | 59 | gen += custom_target( 60 | 'server_decoration_xml_server_protocol', 61 | output: '@BASENAME@-server-protocol.h', 62 | input: 'server-decoration.xml', 63 | command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'] 64 | ) 65 | gen += custom_target( 66 | 'server_decoration_xml_code', 67 | output: '@BASENAME@-code.c', 68 | input: 'server-decoration.xml', 69 | command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'] 70 | ) 71 | 72 | dep = [wayland_protocols_dep] 73 | dep += [wayland_scanner_dep] 74 | dep += dependency('wayland-server') 75 | 76 | inc = include_directories('include') 77 | 78 | libswvkc_wl = static_library('swvkc-wl', [src, gen], dependencies: dep, 79 | include_directories: inc) 80 | libswvkc_wl_dep = declare_dependency(include_directories: inc, 81 | link_with: libswvkc_wl, sources: gen) 82 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/server-decoration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | . 18 | ]]> 19 | 20 | 21 | This interface allows to coordinate whether the server should create 22 | a server-side window decoration around a wl_surface representing a 23 | shell surface (wl_shell_surface or similar). By announcing support 24 | for this interface the server indicates that it supports server 25 | side decorations. 26 | 27 | 28 | 29 | When a client creates a server-side decoration object it indicates 30 | that it supports the protocol. The client is supposed to tell the 31 | server whether it wants server-side decorations or will provide 32 | client-side decorations. 33 | 34 | If the client does not create a server-side decoration object for 35 | a surface the server interprets this as lack of support for this 36 | protocol and considers it as client-side decorated. Nevertheless a 37 | client-side decorated surface should use this protocol to indicate 38 | to the server that it does not want a server-side deco. 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | This event is emitted directly after binding the interface. It contains 52 | the default mode for the decoration. When a new server decoration object 53 | is created this new object will be in the default mode until the first 54 | request_mode is requested. 55 | 56 | The server may change the default mode at any time. 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | This event is emitted directly after the decoration is created and 78 | represents the base decoration policy by the server. E.g. a server 79 | which wants all surfaces to be client-side decorated will send Client, 80 | a server which wants server-side decoration will send Server. 81 | 82 | The client can request a different mode through the decoration request. 83 | The server will acknowledge this by another event with the same mode. So 84 | even if a server prefers server-side decoration it's possible to force a 85 | client-side decoration. 86 | 87 | The server may emit this event at any time. In this case the client can 88 | again request a different mode. It's the responsibility of the server to 89 | prevent a feedback loop. 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/util/algebra.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | void algebra_matrix_rotation_x(float *m, float theta) 7 | { 8 | m[0]=1.0f, m[1]=0.0f, m[2]=0.0f, m[3]=0.0f; 9 | m[4]=0.0f, m[5]=cos(theta), m[6]=-sin(theta), m[7]=0.0f; 10 | m[8]=0.0f, m[9]=sin(theta), m[10]=cos(theta), m[11]=0.0f; 11 | m[12]=0.0f, m[13]=0.0f, m[14]=0.0f, m[15]=1.0f; 12 | } 13 | 14 | 15 | void algebra_matrix_rotation_y(float *m, float theta) 16 | { 17 | m[0]=cos(theta), m[1]=0.0f, m[2]=sin(theta), m[3]=0.0f; 18 | m[4]=0.0f, m[5]=1.0f, m[6]=0.0f, m[7]=0.0f; 19 | m[8]=-sin(theta), m[9]=0.0f, m[10]=cos(theta), m[11]=0.0f; 20 | m[12]=0.0f, m[13]=0.0f, m[14]=0.0f, m[15]=1.0f; 21 | } 22 | 23 | void algebra_matrix_traslation(float *m, float x, float y, float z) 24 | { 25 | m[0]=1.0f, m[1]=0.0f, m[2]=0.0f, m[3]=x; 26 | m[4]=0.0f, m[5]=1.0f, m[6]=0.0f, m[7]=y; 27 | m[8]=0.0f, m[9]=0.0f, m[10]=1.0f, m[11]=z; 28 | m[12]=0.0f, m[13]=0.0f, m[14]=0.0f, m[15]=1.0f; 29 | } 30 | 31 | void algebra_matrix_multiply(float *product, float *a, float *b) 32 | { 33 | for (int i=0; i<16; i++) 34 | product[i]=a[i/4*4]*b[i%4]+a[i/4*4+1]*b[i%4+4]+ 35 | a[i/4*4+2]*b[i%4+8]+a[i/4*4+3]*b[i%4+12]; 36 | } 37 | 38 | // Projection matrices define a way to project a given region of view space 39 | // onto a plane. 40 | 41 | void algebra_matrix_ortho(float *m, float left, float right, float bottom, 42 | float top, float near, float far) { 43 | m[0]=2/(right-left), m[1]=0.0f, m[2]=0.0f, m[3]=-(right+left)/(right-left); 44 | m[4]=0.0f, m[5]=2/(top-bottom), m[6]=0.0f, m[7]=-(top+bottom)/(top-bottom); 45 | m[8]=0.0f, m[9]=0.0f, m[10]=2/(far-near), m[11]=-(far+near)/(far-near); 46 | m[12]=0.0f, m[13]=0.0f, m[14]=0.0f, m[15]=1.0f; 47 | } 48 | 49 | void algebra_matrix_persp(float *m, float fov, float ratio, float n, float f) { 50 | float t = n*tanf(fov/2); //t=h/2 51 | float r = t*ratio; //r=w/2 52 | m[0]=n/r, m[1]=0.0f, m[2]=0.0f, m[3]=0.0f; 53 | m[4]=0.0f, m[5]=n/t, m[6]=0.0f, m[7]=0.0f; 54 | m[8]=0.0f, m[9]=0.0f, m[10]=-(f+n)/(f-n), m[11]=-2*f*n/(f-n); 55 | m[12]=0.0f, m[13]=0.0f, m[14]=-1.0f, m[15]=0.0f; 56 | } 57 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/util/log.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200809L 2 | #include 3 | #include 4 | #include 5 | 6 | void errlog(const char *fmt, ...) { 7 | va_list args; 8 | va_start(args, fmt); 9 | 10 | struct timespec tp; 11 | unsigned int time; 12 | clock_gettime(CLOCK_REALTIME, &tp); 13 | time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000); 14 | 15 | fprintf(stderr, "[%10.3f] ", time / 1000.0); 16 | vfprintf(stderr, fmt, args); 17 | fprintf(stderr, "\n"); 18 | va_end(args); 19 | } 20 | 21 | void boxlog(const char *fmt, ...) { 22 | va_list args; 23 | va_start(args, fmt); 24 | 25 | fprintf(stdout, "│ "); 26 | vfprintf(stdout, fmt, args); 27 | fprintf(stdout, "\n"); 28 | va_end(args); 29 | } 30 | -------------------------------------------------------------------------------- /subprojects/libswvkc-wl/util/util.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // O_TMPFILE on glibc 2 | #define _POSIX_C_SOURCE 200809L 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static enum wl_iterator_result find_keyboard(struct wl_resource *resource, 16 | void *user_data) { 17 | if (!strcmp(wl_resource_get_class(resource), "wl_keyboard")) { 18 | struct wl_resource **keyboard_resource = user_data; 19 | *keyboard_resource = resource; 20 | return WL_ITERATOR_STOP; 21 | } 22 | return WL_ITERATOR_CONTINUE; 23 | } 24 | 25 | static enum wl_iterator_result find_pointer(struct wl_resource *resource, 26 | void *user_data) { 27 | if (!strcmp(wl_resource_get_class(resource), "wl_pointer")) { 28 | struct wl_resource **keyboard_resource = user_data; 29 | *keyboard_resource = resource; 30 | return WL_ITERATOR_STOP; 31 | } 32 | return WL_ITERATOR_CONTINUE; 33 | } 34 | 35 | static enum wl_iterator_result find_output(struct wl_resource *resource, 36 | void *user_data) { 37 | if (!strcmp(wl_resource_get_class(resource), "wl_output")) { 38 | struct wl_resource **keyboard_resource = user_data; 39 | *keyboard_resource = resource; 40 | return WL_ITERATOR_STOP; 41 | } 42 | return WL_ITERATOR_CONTINUE; 43 | } 44 | 45 | struct wl_resource *util_wl_client_get_keyboard(struct wl_client *client) { 46 | struct wl_resource *keyboard_resource = NULL; 47 | wl_client_for_each_resource(client, find_keyboard, &keyboard_resource); 48 | return keyboard_resource; 49 | } 50 | 51 | struct wl_resource *util_wl_client_get_pointer(struct wl_client *client) { 52 | struct wl_resource *pointer_resource = NULL; 53 | wl_client_for_each_resource(client, find_pointer, &pointer_resource); 54 | return pointer_resource; 55 | } 56 | 57 | struct wl_resource *util_wl_client_get_output(struct wl_client *client) { 58 | struct wl_resource *output_resource = NULL; 59 | wl_client_for_each_resource(client, find_output, &output_resource); 60 | return output_resource; 61 | } 62 | 63 | /* 64 | * Assuming that there is a single extension with a given class in the list 65 | */ 66 | struct wl_resource *util_get_extension(struct wl_list *extensions, const char 67 | *class) { 68 | bool found = false; 69 | struct extension_node *node; 70 | wl_list_for_each(node, extensions, link) 71 | if (!strcmp(wl_resource_get_class(node->resource), class)) { 72 | found = true; 73 | break; 74 | } 75 | 76 | if (found) 77 | return node->resource; 78 | else 79 | return NULL; 80 | } 81 | 82 | char *read_file(const char *path) 83 | { 84 | // char *buffer = 0; 85 | // long lenght; 86 | FILE *f = fopen(path, "r"); 87 | if (f == NULL) { 88 | fprintf(stderr, "fopen on %s failed\n", path); 89 | return NULL; 90 | } 91 | 92 | char *line = NULL; 93 | size_t len = 0; 94 | getline(&line, &len, f); 95 | 96 | /* fseek(f, 0, SEEK_END); 97 | lenght = ftell(f); 98 | fseek(f, 0, SEEK_SET); 99 | buffer = malloc(lenght); 100 | if (buffer == NULL) { 101 | fprintf(stderr, "malloc failed\n"); 102 | fclose(f); 103 | return NULL; 104 | } 105 | 106 | fread(buffer, 1, lenght, f); 107 | fclose(f); 108 | buffer[lenght-1] = '\0';*/ 109 | line[len-3] = '\0'; 110 | return line; 111 | } 112 | 113 | char *get_a_name(struct wl_client *client) { 114 | pid_t pid; 115 | uid_t uid; 116 | gid_t gid; 117 | wl_client_get_credentials(client, &pid, &uid, &gid); 118 | char path[64]; 119 | sprintf(path, "/proc/%d/comm", pid); 120 | return read_file(path); 121 | } 122 | 123 | void dmabuf_save_to_disk(int fd) { 124 | const int size = lseek(fd, 0, SEEK_END); 125 | lseek(fd, 0, SEEK_SET); 126 | unsigned char *buffer = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); 127 | if (buffer == MAP_FAILED) { 128 | perror("ERROR"); 129 | return; 130 | } 131 | // for (int i=5504*768-60; i<5504*768-30; i++) 132 | // errlog("[%d] byte %i: %x", size, i, buffer[i]); 133 | // errlog("size %d", ); 134 | FILE* file = fopen("image.data", "w"); 135 | fwrite(buffer, size, 1, file); 136 | fclose(file); 137 | munmap(buffer, size); 138 | /*const int size = 1366*768*4; 139 | char *buffer = malloc(size); 140 | read(fd, buffer, 256); 141 | for (int i=0; i<256; i++) 142 | errlog("%d", buffer[i]); 143 | free(buffer);*/ 144 | } 145 | 146 | static struct timespec t0 = {0}; 147 | 148 | int a() { 149 | struct timespec t; 150 | clock_gettime(CLOCK_MONOTONIC_RAW, &t); 151 | int s = t.tv_sec - t0.tv_sec; 152 | int ns = t.tv_nsec - t0.tv_nsec; 153 | t0 = t; 154 | return s * 1000 + ns / 1000000; 155 | } 156 | 157 | void fd_test(int n) { 158 | int fd[64] = {-1}; 159 | for (int i=0; i 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | // XXX temp duplicate am lazy XXX 17 | /* A bit wrong because different planes could have different properties */ 18 | struct props { 19 | struct { 20 | uint32_t type; 21 | uint32_t src_x; 22 | uint32_t src_y; 23 | uint32_t src_w; 24 | uint32_t src_h; 25 | uint32_t crtc_x; 26 | uint32_t crtc_y; 27 | uint32_t crtc_w; 28 | uint32_t crtc_h; 29 | uint32_t fb_id; 30 | uint32_t in_fence_fd; 31 | uint32_t crtc_id; 32 | } plane; 33 | 34 | struct { 35 | uint32_t crtc_id; 36 | } conn; 37 | 38 | struct { 39 | uint32_t out_fence_ptr; 40 | } crtc; 41 | }; 42 | 43 | struct screen { 44 | // DRM 45 | int gpu_fd; 46 | uint32_t plane_id; 47 | uint32_t overlay_plane_id; 48 | uint32_t crtc_id; 49 | uint32_t props_plane_fb_id; 50 | uint32_t old_fb_id; 51 | uint32_t fb_id[2]; 52 | drmModeAtomicReq *req; 53 | 54 | struct props props; 55 | 56 | // GBM 57 | struct gbm_device *gbm_device; 58 | struct gbm_surface *gbm_surface; 59 | struct gbm_bo *gbm_bo; 60 | 61 | struct bufmgr *bufmgr; 62 | 63 | // vblank callback 64 | void (*vblank_notify)(int,unsigned int,unsigned int, unsigned int, 65 | void*, bool); 66 | void *user_data; 67 | // out_fence callback 68 | void (*listen_to_out_fence)(int, void*); 69 | void *user_data2; 70 | 71 | bool vblank_has_page_flip; 72 | }; 73 | 74 | void screen_post_direct(struct screen *S, uint32_t width, uint32_t height, 75 | uint32_t format, int fd, int stride, int offset, uint64_t modifier) { 76 | static int i = 0; 77 | drmModeAtomicReq *req = drmModeAtomicAlloc(); 78 | if (!req) 79 | fprintf(stderr, "atomic allocation failed\n"); 80 | 81 | errlog("%d %d %d %d %d %d %d", width, height, format, fd, stride, offset, modifier); 82 | 83 | uint32_t bo_width = gbm_bo_get_width(bo); 84 | uint32_t bo_height = gbm_bo_get_height(bo); 85 | errlog("%d", bo_width); 86 | errlog("%d", bo_height); 87 | 88 | uint32_t bo_handles[4] = {0}; 89 | uint32_t bo_strides[4] = {0}; 90 | uint32_t bo_offsets[4] = {0}; 91 | uint64_t bo_modifiers[4] = {0}; 92 | for (int j = 0; j < gbm_bo_get_plane_count(bo); j++) { 93 | bo_handles[j] = gbm_bo_get_handle_for_plane(bo, j).u32; 94 | bo_strides[j] = gbm_bo_get_stride_for_plane(bo, j); 95 | bo_offsets[j] = gbm_bo_get_offset(bo, j); 96 | // KMS requires all BO planes to have the same modifier 97 | bo_modifiers[j] = gbm_bo_get_modifier(bo); 98 | errlog("%d", bo_handles[j]); 99 | errlog("%d", bo_strides[j]); 100 | errlog("%d", bo_offsets[j]); 101 | errlog("ciccioc %d", bo_modifiers[j] == I915_FORMAT_MOD_Y_TILED); 102 | } 103 | 104 | // uint32_t handle = gbm_bo_get_handle(bo).u32; 105 | uint32_t bo_format = format; 106 | errlog("%d %d %d", bo_format, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888); 107 | 108 | /* if (drmModeAddFB2WithModifiers(S->gpu_fd, width, height, COLOR_DEPTH, BIT_PER_PIXEL, 109 | stride, handle, &S->fb_id[i])) {*/ 110 | if (drmModeAddFB2WithModifiers(S->gpu_fd, bo_width, bo_height, bo_format, 111 | bo_handles, bo_strides, bo_offsets, bo_modifiers, &S->fb_id[i], DRM_MODE_FB_MODIFIERS)) { 112 | perror("AddFB"); 113 | } 114 | 115 | printf("%d %d\n", S->fb_id[i], S->fb_id[!i]); 116 | 117 | if (drmModeAtomicAddProperty(req, S->plane_id, 118 | S->props_plane_fb_id, S->fb_id[i]) < 0) 119 | fprintf(stderr, "atomic add property failed\n"); 120 | // drmModeAtomicAddProperty(req, S->plane_id, 10, 1366 << 16); //W 121 | // drmModeAtomicAddProperty(req, S->plane_id, 11, 768 << 16); //H 122 | // drmModeAtomicAddProperty(req, S->plane_id, 12, 10); //W 123 | // drmModeAtomicAddProperty(req, S->plane_id, 13, 10); //H 124 | // drmModeAtomicAddProperty(req, S->plane_id, 14, 1366); //W 125 | // drmModeAtomicAddProperty(req, S->plane_id, 15, 768); //H 126 | 127 | errlog("Trying to post the new buffer"); 128 | if (drmModeAtomicCommit(S->gpu_fd, req, DRM_MODE_ATOMIC_TEST_ONLY | 129 | DRM_MODE_ATOMIC_ALLOW_MODESET, 0)) 130 | perror("test failed"); 131 | else { 132 | fprintf(stderr, "test success\n"); 133 | } 134 | if (drmModeAtomicCommit(S->gpu_fd, req, DRM_MODE_PAGE_FLIP_EVENT | 135 | DRM_MODE_ATOMIC_NONBLOCK, S)) 136 | perror("atomic commit failed"); 137 | else { 138 | fprintf(stderr, "atomic commit success\n"); 139 | if (S->fb_id[!i]) 140 | drmModeRmFB(S->gpu_fd, S->fb_id[!i]); 141 | } 142 | drmModeAtomicFree(req); 143 | errlog("Trying to post the new buffer 2"); 144 | // errlog("B"); 145 | // errlog("C"); 146 | i = !i; 147 | } 148 | 149 | uint32_t fb_id[2] = {0}; 150 | struct gbm_bo *bo[2] = {0}; 151 | 152 | /*void import_dmabuf_with_gbm() { 153 | struct gbm_import_fd_modifier_data buffer = { 154 | .width = width, 155 | .height = height, 156 | .format = format, 157 | .num_fds = 1, 158 | .fds[0] = fd, 159 | .strides[0] = stride, 160 | .offsets[0] = offset, 161 | .modifier = modifier 162 | }; 163 | bo[i] = gbm_bo_import(S->gbm_device, GBM_BO_IMPORT_FD_MODIFIER, &buffer, 164 | GBM_BO_USE_SCANOUT); 165 | 166 | if (!bo[i]) { 167 | perror("import"); 168 | } 169 | 170 | uint32_t bo_width = gbm_bo_get_width(bo[i]); 171 | uint32_t bo_height = gbm_bo_get_height(bo[i]); 172 | 173 | uint32_t bo_handles[4] = {0}; 174 | uint32_t bo_strides[4] = {0}; 175 | uint32_t bo_offsets[4] = {0}; 176 | uint64_t bo_modifiers[4] = {0}; 177 | // errlog("number of planes: %d", gbm_bo_get_plane_count(bo)); 178 | for (int j = 0; j < 1; j++) { 179 | bo_handles[j] = gbm_bo_get_handle_for_plane(bo[i], j).u32; 180 | // errlog("bo handle %d: %d", j, bo_handles[j]); 181 | bo_strides[j] = gbm_bo_get_stride_for_plane(bo[i], j); 182 | bo_offsets[j] = gbm_bo_get_offset(bo[i], j); 183 | // KMS requires all BO planes to have the same modifier 184 | bo_modifiers[j] = gbm_bo_get_modifier(bo[i]); 185 | } 186 | 187 | // uint32_t handle = gbm_bo_get_handle(bo).u32; 188 | uint32_t bo_format = gbm_bo_get_format(bo[i]); 189 | }*/ 190 | 191 | 192 | -------------------------------------------------------------------------------- /trash/dmabuf_map.c: -------------------------------------------------------------------------------- 1 | const int size = lseek(fd, 0, SEEK_END); 2 | lseek(fd, 0, SEEK_SET); 3 | unsigned char *buffer = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); 4 | if (buffer == MAP_FAILED) { 5 | perror("ERROR"); 6 | return; 7 | } 8 | for (int i=5504*768-60; i<5504*768-30; i++) 9 | errlog("[%d] byte %i: %x", size, i, buffer[i]); 10 | // errlog("size %d", ); 11 | // FILE* file = fopen("image.data", "w"); 12 | // fwrite(buffer, size, 1, file); 13 | // fclose(file); 14 | munmap(buffer, size); 15 | // free(buffer);*/ 16 | /*const int size = 1366*768*4; 17 | char *buffer = malloc(size); 18 | read(fd, buffer, 256); 19 | for (int i=0; i<256; i++) 20 | errlog("%d", buffer[i]); 21 | free(buffer);*/ 22 | 23 | -------------------------------------------------------------------------------- /trash/intel_bo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | drm_intel_bufmgr *bufmgr = 0; 5 | drm_intel_bo *intel_bo = 0; 6 | 7 | int bpp = 32; 8 | uint32_t tiling = I915_TILING_NONE; 9 | 10 | long unsigned int stride; 11 | 12 | int b(int width, int height) { 13 | bufmgr = drm_intel_bufmgr_gem_init(fd, 32); 14 | if (!bufmgr) { 15 | fprintf(stderr, "drm_intel_bufmgr_gem_init failed\n"); 16 | return -1; 17 | } 18 | 19 | intel_bo = drm_intel_bo_alloc_tiled(bufmgr, "main", width, height, 20 | bpp/8, &tiling, &stride, 0); 21 | if (!intel_bo) { 22 | fprintf(stderr, "drm_intel_bo_alloc failed\n"); 23 | return -1; 24 | } 25 | printf("success, stride: %lu\n", stride); 26 | } 27 | 28 | uint32_t get_handle() { 29 | return intel_bo->handle; 30 | } 31 | 32 | void y() { 33 | drm_intel_bo_unreference(intel_bo); 34 | drm_intel_bufmgr_destroy(bufmgr); 35 | } 36 | -------------------------------------------------------------------------------- /trash/vulkan_display.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | VkInstance create_instance() { 8 | const char *extensions[] = { 9 | VK_KHR_SURFACE_EXTENSION_NAME, 10 | VK_KHR_DISPLAY_EXTENSION_NAME, 11 | VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, 12 | }; 13 | const char *layers[] = {"VK_LAYER_LUNARG_standard_validation"}; 14 | VkInstanceCreateInfo info = { 15 | .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 16 | .enabledLayerCount = sizeof(layers)/sizeof(char*), 17 | .ppEnabledLayerNames = layers, 18 | .enabledExtensionCount = sizeof(extensions)/sizeof(char*), 19 | .ppEnabledExtensionNames = extensions 20 | }; 21 | VkInstance inst; 22 | if (vkCreateInstance(&info, NULL, &inst)) { 23 | fprintf(stderr, "ERROR: create_instance() failed.\n"); 24 | return VK_NULL_HANDLE; 25 | } 26 | return inst; 27 | } 28 | 29 | VkPhysicalDevice get_physical_device(VkInstance inst) { 30 | uint32_t n = 1; 31 | VkPhysicalDevice pdev; 32 | vkEnumeratePhysicalDevices(inst, &n, &pdev); 33 | if (n == 0) { 34 | fprintf(stderr, "ERROR: get_physical_device() failed.\n"); 35 | return VK_NULL_HANDLE; 36 | } 37 | return pdev; 38 | } 39 | 40 | VkDevice create_device(VkInstance inst, VkPhysicalDevice pdev) { 41 | const char *extensions[] = { 42 | VK_KHR_SWAPCHAIN_EXTENSION_NAME, 43 | VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, 44 | VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, 45 | VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, 46 | }; 47 | float priority = 1.0f; 48 | VkDeviceQueueCreateInfo infoQueue = { 49 | .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 50 | .queueCount = 1, 51 | .pQueuePriorities = &priority 52 | }; 53 | VkDeviceCreateInfo info = { 54 | .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 55 | .queueCreateInfoCount = 1, 56 | .pQueueCreateInfos = &infoQueue, 57 | .enabledExtensionCount = sizeof(extensions)/sizeof(char*), 58 | .ppEnabledExtensionNames = extensions, 59 | }; 60 | VkDevice dev; 61 | if (vkCreateDevice(pdev, &info, NULL, &dev)) { 62 | fprintf(stderr, "ERROR: create_device() failed.\n"); 63 | return VK_NULL_HANDLE; 64 | } 65 | return dev; 66 | } 67 | 68 | VkBuffer create_buffer(int size, VkDevice dev) { 69 | VkExternalMemoryBufferCreateInfo info_next = { 70 | .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, 71 | .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 72 | }; 73 | VkBufferCreateInfo info = { 74 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 75 | .pNext = &info_next, 76 | .size = size, // stride * height 77 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT 78 | }; 79 | VkBuffer buf; 80 | if (vkCreateBuffer(dev, &info, NULL, &buf)) { 81 | fprintf(stderr, "ERROR: create_buffer() failed.\n"); 82 | return VK_NULL_HANDLE; 83 | } 84 | return buf; 85 | } 86 | 87 | VkDeviceMemory import_memory(int fd, int size, VkDevice dev) { 88 | VkImportMemoryFdInfoKHR info_next = { 89 | .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, 90 | .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 91 | // or maybe VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT 92 | .fd = fd, 93 | }; 94 | VkMemoryAllocateInfo info = { 95 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 96 | .pNext = &info_next, 97 | .allocationSize = size// same as buffer size 98 | }; 99 | VkDeviceMemory mem; 100 | if (vkAllocateMemory(dev, &info, NULL, &mem)) { 101 | fprintf(stderr, "ERROR: import_memory() failed.\n"); 102 | return VK_NULL_HANDLE; 103 | } 104 | return mem; 105 | } 106 | 107 | VkResult bind_buffer_memory(VkDevice dev, VkBuffer buf, VkDeviceMemory mem) { 108 | return vkBindBufferMemory(dev, buf, mem, 0); 109 | } 110 | 111 | VkSurfaceKHR create_surface(VkInstance inst, VkPhysicalDevice pdev) { 112 | uint32_t n = 1; 113 | VkDisplayPropertiesKHR propsDisplay; 114 | vkGetPhysicalDeviceDisplayPropertiesKHR(pdev, &n, &propsDisplay); 115 | if (n == 0) { 116 | fprintf(stderr, "ERROR: create_surface() failed.\n"); 117 | return VK_NULL_HANDLE; 118 | } 119 | 120 | VkDisplayModePropertiesKHR props; 121 | vkGetDisplayModePropertiesKHR(pdev, propsDisplay.display, &n, &props); 122 | 123 | VkDisplaySurfaceCreateInfoKHR info = { 124 | .sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, 125 | .displayMode = props.displayMode, 126 | .transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, 127 | .alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, 128 | .imageExtent = props.parameters.visibleRegion 129 | }; 130 | VkSurfaceKHR surf; 131 | if (vkCreateDisplayPlaneSurfaceKHR(inst, &info, NULL, &surf)) { 132 | fprintf(stderr, "ERROR: create_surface() failed.\n"); 133 | return VK_NULL_HANDLE; 134 | } 135 | return surf; 136 | } 137 | 138 | VkSwapchainKHR create_swapchain(VkPhysicalDevice pdev, VkDevice dev, VkSurfaceKHR surf) { 139 | VkSurfaceCapabilitiesKHR caps; 140 | vkGetPhysicalDeviceSurfaceCapabilitiesKHR(pdev, surf, &caps); 141 | 142 | VkSwapchainCreateInfoKHR info = { 143 | .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 144 | .surface = surf, 145 | .minImageCount = 1, 146 | .imageFormat = VK_FORMAT_B8G8R8A8_UNORM, 147 | .imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, 148 | .imageExtent = caps.currentExtent, 149 | .imageArrayLayers = 1, 150 | .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 151 | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 152 | .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, 153 | .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, 154 | .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, 155 | .presentMode = VK_PRESENT_MODE_FIFO_KHR, 156 | .clipped = VK_TRUE, 157 | .oldSwapchain = VK_NULL_HANDLE, 158 | }; 159 | VkSwapchainKHR swp; 160 | if (vkCreateSwapchainKHR(dev, &info, NULL, &swp)) { 161 | fprintf(stderr, "ERROR: create_swapchain() failed.\n"); 162 | return VK_NULL_HANDLE; 163 | } 164 | return swp; 165 | } 166 | 167 | VkCommandPool create_command_pool(VkDevice dev) { 168 | VkCommandPoolCreateInfo info = { 169 | .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 170 | }; 171 | VkCommandPool pool; 172 | if (vkCreateCommandPool(dev, &info, NULL, &pool)) { 173 | fprintf(stderr, "ERROR: create_command_pool() failed.\n"); 174 | return VK_NULL_HANDLE; 175 | } 176 | return pool; 177 | } 178 | 179 | VkCommandBuffer record_command_clear(VkDevice dev, VkCommandPool pool, VkImage img) { 180 | VkCommandBufferAllocateInfo info = { 181 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 182 | .commandPool = pool, 183 | .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 184 | .commandBufferCount = 1 185 | }; 186 | VkCommandBuffer cmdbuf; 187 | vkAllocateCommandBuffers(dev, &info, &cmdbuf); 188 | 189 | VkCommandBufferBeginInfo infoBegin = { 190 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 191 | .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT 192 | }; 193 | vkBeginCommandBuffer(cmdbuf, &infoBegin); 194 | 195 | VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; 196 | VkClearColorValue color = {{0.8984375f, 0.8984375f, 0.9765625f, 1.0f}}; 197 | vkCmdClearColorImage(cmdbuf, img, 198 | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range); 199 | 200 | vkEndCommandBuffer(cmdbuf); 201 | return cmdbuf; 202 | } 203 | 204 | int32_t data[2] = {0xFF00FFFF, 0xFF0000FF}; 205 | 206 | VkCommandBuffer record_command_clear2(VkDevice dev, VkCommandPool pool, VkBuffer buf) { 207 | static int i=0; 208 | VkCommandBufferAllocateInfo info = { 209 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 210 | .commandPool = pool, 211 | .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 212 | .commandBufferCount = 1 213 | }; 214 | VkCommandBuffer cmdbuf; 215 | vkAllocateCommandBuffers(dev, &info, &cmdbuf); 216 | 217 | VkCommandBufferBeginInfo infoBegin = { 218 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 219 | .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT 220 | }; 221 | vkBeginCommandBuffer(cmdbuf, &infoBegin); 222 | 223 | vkCmdFillBuffer(cmdbuf, buf, 0, VK_WHOLE_SIZE, data[i]); 224 | 225 | vkEndCommandBuffer(cmdbuf); 226 | i++; 227 | return cmdbuf; 228 | } 229 | 230 | VkCommandBuffer record_command_copy(VkDevice dev, VkCommandPool pool, VkBuffer 231 | buf, VkImage img) { 232 | VkCommandBufferAllocateInfo info = { 233 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 234 | .commandPool = pool, 235 | .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 236 | .commandBufferCount = 1 237 | }; 238 | VkCommandBuffer cmdbuf; 239 | vkAllocateCommandBuffers(dev, &info, &cmdbuf); 240 | 241 | VkCommandBufferBeginInfo infoBegin = { 242 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 243 | .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT 244 | }; 245 | vkBeginCommandBuffer(cmdbuf, &infoBegin); 246 | 247 | VkImageSubresourceLayers imageSubresource = { 248 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 249 | .mipLevel = 0, 250 | .baseArrayLayer = 0, 251 | .layerCount = 1 252 | }; 253 | 254 | VkBufferImageCopy region = { 255 | .bufferOffset = 0, 256 | .bufferRowLength = 0, 257 | .bufferImageHeight = 0, 258 | .imageSubresource = imageSubresource, 259 | .imageOffset = {200,100,0}, 260 | .imageExtent = {256,256,0}, 261 | }; 262 | vkCmdCopyBufferToImage(cmdbuf, buf, img, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); 263 | 264 | vkEndCommandBuffer(cmdbuf); 265 | return cmdbuf; 266 | } 267 | 268 | VkCommandBuffer record_command_copy2(VkDevice dev, VkCommandPool pool, VkBuffer 269 | buf, VkBuffer buf2) { 270 | VkCommandBufferAllocateInfo info = { 271 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 272 | .commandPool = pool, 273 | .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 274 | .commandBufferCount = 1 275 | }; 276 | VkCommandBuffer cmdbuf; 277 | vkAllocateCommandBuffers(dev, &info, &cmdbuf); 278 | 279 | VkCommandBufferBeginInfo infoBegin = { 280 | .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 281 | .flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT 282 | }; 283 | vkBeginCommandBuffer(cmdbuf, &infoBegin); 284 | 285 | VkBufferCopy region = { 286 | .srcOffset = 0, 287 | .dstOffset = 0, 288 | .size = 262144, 289 | }; 290 | vkCmdCopyBuffer(cmdbuf, buf, buf2, 1, ®ion); 291 | 292 | vkEndCommandBuffer(cmdbuf); 293 | return cmdbuf; 294 | } 295 | 296 | int vulkan_main(int fd) { 297 | VkInstance instance = create_instance(); 298 | if (instance == VK_NULL_HANDLE) 299 | return EXIT_FAILURE; 300 | 301 | VkPhysicalDevice physical_device = get_physical_device(instance); 302 | if (physical_device == VK_NULL_HANDLE) 303 | return EXIT_FAILURE; 304 | 305 | /* VkSurfaceKHR surface = create_surface(instance, physical_device); 306 | if (surface == VK_NULL_HANDLE) 307 | return EXIT_FAILURE;*/ 308 | 309 | VkDevice device = create_device(instance, physical_device); 310 | if (device == VK_NULL_HANDLE) 311 | return EXIT_FAILURE; 312 | 313 | /* VkSwapchainKHR swapchain = create_swapchain(physical_device, device, surface); 314 | if (swapchain == VK_NULL_HANDLE) 315 | return EXIT_FAILURE;*/ 316 | 317 | VkQueue queue; 318 | vkGetDeviceQueue(device, 0, 0, &queue); 319 | 320 | /* uint32_t n = 1; 321 | VkImage image; 322 | vkGetSwapchainImagesKHR(device, swapchain, &n, &image);*/ 323 | 324 | VkCommandPool command_pool = create_command_pool(device); 325 | if (command_pool == VK_NULL_HANDLE) 326 | return EXIT_FAILURE; 327 | 328 | VkCommandBuffer commands[2] = {0}; 329 | // commands[0] = record_command_clear(device, command_pool, image); 330 | 331 | /* 332 | * Trying to post the dmabuf 333 | */ 334 | 335 | /* VkBuffer buffer = create_buffer(262144, device); 336 | VkDeviceMemory memory = import_memory(13, 262144, device); //TODO: properly get the fd 337 | bind_buffer_memory(device, buffer, memory);*/ 338 | VkBuffer screen_buffer = create_buffer(4325376, device); 339 | VkDeviceMemory screen_memory = import_memory(fd, 4325376, device); 340 | bind_buffer_memory(device, screen_buffer, screen_memory); 341 | commands[0] = record_command_clear2(device, command_pool, screen_buffer); 342 | 343 | // END 344 | 345 | /* uint32_t index; 346 | vkAcquireNextImageKHR(device, swapchain, UINT64_MAX, VK_NULL_HANDLE, VK_NULL_HANDLE, &index);*/ 347 | 348 | VkSubmitInfo submitInfo = { 349 | .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 350 | .commandBufferCount = 1, 351 | .pCommandBuffers = commands 352 | }; 353 | vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); 354 | 355 | /* VkPresentInfoKHR presentInfo = { 356 | .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 357 | .swapchainCount = 1, 358 | .pSwapchains = &swapchain, 359 | .pImageIndices = &index 360 | }; 361 | vkQueuePresentKHR(queue, &presentInfo);*/ 362 | 363 | vkFreeCommandBuffers(device, command_pool, 1, commands); 364 | 365 | vkDestroyCommandPool(device, command_pool, NULL); 366 | /* vkDestroySwapchainKHR(device, swapchain, NULL); 367 | vkDestroySurfaceKHR(instance, surface, NULL);*/ 368 | vkDestroyDevice(device, NULL); 369 | vkDestroyInstance(instance, NULL); 370 | 371 | return EXIT_SUCCESS; 372 | } 373 | -------------------------------------------------------------------------------- /wayland.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_C_SOURCE 200112L 2 | 3 | #include 4 | 5 | #include // libswvkc-wl 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "gbm_.h" 17 | #include "atomic.h" 18 | #include "modeset.h" // WARNING: probably bad design, try to decouple (if possible) 19 | #include "legacy_wl_drm_.h" 20 | 21 | #include 22 | #include 23 | 24 | static struct wl_display *D; 25 | static struct keyboard * keyboard_g; 26 | static struct surface* surface_g; 27 | 28 | struct bufstate { 29 | struct gbm_bo *bo; 30 | uint32_t fb_id; 31 | }; 32 | 33 | void wayland_init() { 34 | D = wl_display_create(); 35 | assert(D); 36 | 37 | setenv("XDG_RUNTIME_DIR", "/tmp", 0); 38 | 39 | const char *socket = wl_display_add_socket_auto(D); 40 | assert(socket); 41 | 42 | setenv("WAYLAND_DISPLAY", socket, 0); 43 | 44 | create_globals(D, 1, NULL); 45 | legacy_wl_drm_init(D, gbm_get_device()); 46 | } 47 | 48 | void wayland_flush() { 49 | wl_display_flush_clients(D); 50 | } 51 | 52 | int wayland_get_fd() { 53 | struct wl_event_loop *el = wl_display_get_event_loop(D); 54 | assert(el); 55 | return wl_event_loop_get_fd(el); 56 | } 57 | 58 | void wayland_read() { 59 | struct wl_event_loop *el = wl_display_get_event_loop(D); 60 | assert(el); 61 | wl_event_loop_dispatch(el, 0); 62 | // We don't assert its return code because the first time it returns -1... 63 | } 64 | 65 | void wayland_send_key_and_mods(uint32_t key, uint32_t state, unsigned int mods_depressed, unsigned int mods_latched, unsigned int mods_locked, unsigned int group) { 66 | if (keyboard_g) { 67 | keyboard_send_key(keyboard_g, key, state); 68 | keyboard_send_modifiers(keyboard_g, mods_depressed, mods_latched, mods_locked, group); 69 | } 70 | } 71 | 72 | static void shmbuf(struct wl_resource *buffer) { 73 | struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get(buffer); 74 | uint32_t width = wl_shm_buffer_get_width(shm_buffer); 75 | uint32_t height = wl_shm_buffer_get_height(shm_buffer); 76 | uint32_t stride = wl_shm_buffer_get_stride(shm_buffer); 77 | //uint32_t format = wl_shm_buffer_get_format(shm_buffer); 78 | uint8_t *data = wl_shm_buffer_get_data(shm_buffer); 79 | wl_shm_buffer_begin_access(shm_buffer); 80 | modeset_copy(stride, width, height, data); 81 | wl_shm_buffer_end_access(shm_buffer); 82 | wl_buffer_send_release(buffer); 83 | } 84 | 85 | static struct wl_resource *to_release[2]; 86 | 87 | static void dmabuf(struct wl_resource *dmabuf) { 88 | struct bufstate *bufstate = wl_buffer_dmabuf_get_subsystem_object(dmabuf, 89 | SUBSYSTEM_DRM); 90 | 91 | atomic_commit(bufstate->fb_id); 92 | 93 | if (!to_release[0]) 94 | to_release[0] = dmabuf; 95 | else if (!to_release[1]) 96 | to_release[1] = dmabuf; 97 | else 98 | assert(false); 99 | } 100 | 101 | /* 102 | * Handle events produced by Wayland objects: `object`_`event`_notify 103 | */ 104 | 105 | #include 106 | 107 | void surface_map_notify(struct surface *surface, void *user_data) { 108 | if (surface->role == ROLE_CURSOR) 109 | return; 110 | if (surface->role == ROLE_SUBSURFACE) 111 | return; 112 | 113 | struct wl_array array; 114 | wl_array_init(&array); //Need the currently pressed keys 115 | struct wl_client *client = wl_resource_get_client(surface->resource); 116 | struct wl_resource *keyboard = NULL; 117 | keyboard = util_wl_client_get_keyboard(client); 118 | if (keyboard) 119 | wl_keyboard_send_enter(keyboard, 0, surface->resource, &array); 120 | struct wl_resource *pointer = NULL; 121 | pointer = util_wl_client_get_pointer(client); 122 | if (pointer) { 123 | wl_pointer_send_enter(pointer, 1, surface->resource, 124 | wl_fixed_from_int(0), wl_fixed_from_int(0)); 125 | if (wl_resource_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION) 126 | wl_pointer_send_frame(pointer); 127 | } 128 | 129 | surface_g = surface; 130 | } 131 | 132 | void surface_unmap_notify(struct surface *surface, void *user_data) { 133 | } 134 | 135 | void surface_contents_update_notify(struct surface *surface, void *user_data) { 136 | struct wl_resource *buffer = surface->current->buffer; 137 | /* 138 | * If the buffer has been detached, do nothing 139 | */ 140 | if (!buffer) 141 | return; 142 | 143 | if (surface->role == ROLE_CURSOR) { 144 | // TODO 145 | return; 146 | } 147 | 148 | if (wl_buffer_is_dmabuf(buffer)) { 149 | dmabuf(buffer); 150 | } else { 151 | shmbuf(buffer); 152 | // still not vblank driven here 153 | if (surface && surface->frame) { 154 | wl_callback_send_done(surface->frame, 0); 155 | wl_resource_destroy(surface->frame); 156 | surface->frame = 0; 157 | } 158 | } 159 | } 160 | 161 | void xdg_toplevel_init_notify(struct xdg_toplevel_data *xdg_toplevel, void 162 | *user_data) { 163 | struct wl_array array; 164 | wl_array_init(&array); 165 | int32_t *state1 = wl_array_add(&array, sizeof(int32_t)); 166 | *state1 = XDG_TOPLEVEL_STATE_ACTIVATED; 167 | int32_t *state2 = wl_array_add(&array, sizeof(int32_t)); 168 | *state2 = XDG_TOPLEVEL_STATE_MAXIMIZED; 169 | xdg_toplevel_send_configure(xdg_toplevel->resource, modeset_get_width(), 170 | modeset_get_height(), &array); 171 | xdg_surface_send_configure(xdg_toplevel->xdg_surface_data->self, 0); 172 | } 173 | 174 | void buffer_dmabuf_create_notify(struct wl_buffer_dmabuf_data *dmabuf, void 175 | *user_data) { 176 | uint32_t num_planes = 1; 177 | int32_t *fds = dmabuf->fds; 178 | uint32_t width = dmabuf->width; 179 | uint32_t height = dmabuf->height; 180 | uint32_t format = dmabuf->format; 181 | uint32_t *strides = dmabuf->strides; 182 | uint32_t *offsets = dmabuf->offsets; 183 | uint64_t *mods = dmabuf->modifiers; 184 | 185 | struct gbm_bo *bo = gbm_import_from_dmabuf(num_planes, fds, width, height, format, strides, offsets, mods[0]); 186 | // TODO: migrate to drmPrimeFDToHandle (but refcounting issues?) 187 | assert(bo); 188 | 189 | struct bufstate *bufstate = malloc(sizeof(*bufstate)); 190 | bufstate->bo = bo; 191 | bufstate->fb_id = modeset_add_fb(width, height, format, gbm_get_handle(bo), strides[0], offsets[0], mods[0]); 192 | dmabuf->subsystem_object[SUBSYSTEM_DRM] = bufstate; 193 | } 194 | 195 | void buffer_dmabuf_destroy_notify(struct wl_buffer_dmabuf_data *dmabuf, void 196 | *user_data) { 197 | struct bufstate *bufstate = dmabuf->subsystem_object[SUBSYSTEM_DRM]; 198 | // TODO: Not sure if we can destroy it immediately 199 | modeset_rem_fb(bufstate->fb_id); 200 | gbm_destroy(bufstate->bo); 201 | free(bufstate); 202 | } 203 | 204 | #include "xkb.h" 205 | 206 | void keyboard_init_notify(struct keyboard *keyboard, void *user_data) { 207 | int32_t fd = xkb_get_keymap_fd(); 208 | uint32_t size = xkb_get_keymap_size(); 209 | keyboard_send_keymap(keyboard, fd, size); 210 | keyboard_g = keyboard; //WARNING 211 | } 212 | 213 | void page_flip_handler(int fd, unsigned int sequence, unsigned int 214 | tv_sec, unsigned int tv_usec, void *user_data) { 215 | if (surface_g && surface_g->frame) { 216 | uint32_t ms = tv_sec * 1000 + tv_usec / 1000; 217 | wl_callback_send_done(surface_g->frame, ms); 218 | wl_resource_destroy(surface_g->frame); 219 | surface_g->frame = 0; 220 | } 221 | if (to_release[1]) { 222 | wl_buffer_send_release(to_release[1]); 223 | to_release[1] = NULL; 224 | } 225 | if (to_release[0]) { 226 | to_release[1] = to_release[0]; 227 | to_release[0] = NULL; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /wayland.h: -------------------------------------------------------------------------------- 1 | #ifndef wayland_h_INCLUDED 2 | #define wayland_h_INCLUDED 3 | 4 | void wayland_init(); 5 | int wayland_get_fd(); 6 | void wayland_read(); 7 | void wayland_send_key_and_mods(uint32_t key, uint32_t state, unsigned int mods_depressed, unsigned int mods_latched, unsigned int mods_locked, unsigned int group); 8 | void wayland_flush(); 9 | 10 | void page_flip_handler(int fd, unsigned int sequence, unsigned int 11 | tv_sec, unsigned int tv_usec, void *user_data); 12 | 13 | #endif // wayland_h_INCLUDED 14 | 15 | -------------------------------------------------------------------------------- /xkb.c: -------------------------------------------------------------------------------- 1 | //#define _POSIX_C_SOURCE 200112L 2 | #define _POSIX_C_SOURCE 200809L 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | static int create_file(off_t size) { 16 | static const char template[] = "/swvkc-XXXXXX"; 17 | const char *path; 18 | char *name; 19 | int ret; 20 | 21 | path = getenv("XDG_RUNTIME_DIR"); 22 | if (!path) { 23 | errno = ENOENT; 24 | return -1; 25 | } 26 | 27 | name = malloc(strlen(path) + sizeof(template)); 28 | if (!name) 29 | return -1; 30 | 31 | strcpy(name, path); 32 | strcat(name, template); 33 | 34 | int fd = mkstemp(name); 35 | if (fd >= 0) { 36 | long flags = fcntl(fd, F_GETFD); 37 | fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 38 | unlink(name); 39 | } 40 | 41 | free(name); 42 | 43 | if (fd < 0) 44 | return -1; 45 | 46 | do { 47 | ret = posix_fallocate(fd, 0, size); 48 | } while (ret == EINTR); 49 | if (ret != 0) { 50 | close(fd); 51 | errno = ret; 52 | return -1; 53 | } 54 | 55 | return fd; 56 | } 57 | 58 | static struct xkb_context *context; 59 | static struct xkb_keymap *keymap; 60 | static int keymap_size; 61 | static int keymap_fd; 62 | static struct xkb_state *state; 63 | 64 | void xkb_init() { 65 | context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 66 | assert(context); 67 | 68 | struct xkb_rule_names rules = { 69 | getenv("XKB_DEFAULT_RULES"), 70 | getenv("XKB_DEFAULT_MODEL"), 71 | getenv("XKB_DEFAULT_LAYOUT"), 72 | getenv("XKB_DEFAULT_VARIANT"), 73 | getenv("XKB_DEFAULT_OPTIONS") 74 | }; 75 | 76 | keymap = xkb_map_new_from_names(context, &rules, 77 | XKB_KEYMAP_COMPILE_NO_FLAGS); 78 | assert(keymap); 79 | 80 | char *keymap_str = NULL; 81 | keymap_str = xkb_keymap_get_as_string(keymap, 82 | XKB_KEYMAP_FORMAT_TEXT_V1); 83 | keymap_size = strlen(keymap_str) + 1; 84 | keymap_fd = create_file(keymap_size); 85 | if (keymap_fd < 0) { 86 | printf("creating a keymap file for %u bytes failed\n", keymap_size); 87 | return; 88 | } 89 | void *ptr = mmap(NULL, keymap_size, 90 | PROT_READ | PROT_WRITE, MAP_SHARED, keymap_fd, 0); 91 | if (ptr == (void*)-1) { 92 | printf("failed to mmap() %u bytes", keymap_size); 93 | return; 94 | } 95 | strcpy(ptr, keymap_str); 96 | free(keymap_str); 97 | 98 | state = xkb_state_new(keymap); 99 | } 100 | 101 | int32_t xkb_get_keymap_fd() { return keymap_fd; } 102 | uint32_t xkb_get_keymap_size() { return keymap_size; } 103 | 104 | void xkb_update(uint32_t key, int state_) { 105 | xkb_keycode_t keycode = key + 8; 106 | enum xkb_key_direction direction = state_ ? XKB_KEY_DOWN : XKB_KEY_UP; 107 | 108 | xkb_state_update_key(state, keycode, direction); 109 | } 110 | 111 | void xkb_get_modifiers(unsigned int *mods_depressed, unsigned int *mods_latched, unsigned int *mods_locked, unsigned int *group) { 112 | *mods_depressed = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); 113 | *mods_latched = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED); 114 | *mods_locked = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED); 115 | *group = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); 116 | } 117 | 118 | int xkb_test_ctrlalt() { 119 | return xkb_state_mod_names_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, NULL); 120 | } 121 | -------------------------------------------------------------------------------- /xkb.h: -------------------------------------------------------------------------------- 1 | #ifndef xkb_h_INCLUDED 2 | #define xkb_h_INCLUDED 3 | 4 | void xkb_init(); 5 | int32_t xkb_get_keymap_fd(); 6 | uint32_t xkb_get_keymap_size(); 7 | void xkb_update(uint32_t key, int state_); 8 | void xkb_get_modifiers(unsigned int *mods_depressed, unsigned int *mods_latched, unsigned int *mods_locked, unsigned int *group); 9 | int xkb_test_ctrlalt(); 10 | 11 | #endif // xkb_h_INCLUDED 12 | 13 | --------------------------------------------------------------------------------