├── .github └── workflows │ └── release.yml ├── .gitignore ├── COPYING ├── NEWS ├── README.md ├── docs ├── kmscon.service.in ├── kmsconvt@.service.in ├── man │ ├── kmscon.1.xml.in │ └── kmscon.conf.1.xml.in ├── meson.build ├── unicode-test.txt └── vte.txt ├── external ├── htable.c ├── htable.h └── meson.build ├── meson.build ├── meson_options.txt ├── scripts └── kmscon.in ├── src ├── conf.c ├── conf.h ├── eloop.c ├── eloop.h ├── font.c ├── font.h ├── font_8x16.c ├── font_pango.c ├── font_unifont.c ├── font_unifont_data.hex ├── genunifont.c ├── genversion.sh ├── kmscon_conf.c ├── kmscon_conf.h ├── kmscon_dummy.c ├── kmscon_dummy.h ├── kmscon_main.c ├── kmscon_mod_bbulk.c ├── kmscon_mod_gltex.c ├── kmscon_mod_pango.c ├── kmscon_mod_pixman.c ├── kmscon_mod_unifont.c ├── kmscon_module.c ├── kmscon_module.h ├── kmscon_module_interface.h ├── kmscon_mouse.c ├── kmscon_mouse.h ├── kmscon_seat.c ├── kmscon_seat.h ├── kmscon_terminal.c ├── kmscon_terminal.h ├── meson.build ├── mouse_pointer.frag ├── mouse_pointer.vert ├── pty.c ├── pty.h ├── shl_array.h ├── shl_dlist.h ├── shl_flagset.h ├── shl_githead.c.in ├── shl_githead.h ├── shl_gl.h ├── shl_gl_math.c ├── shl_gl_shader.c ├── shl_hashtable.h ├── shl_hook.h ├── shl_llog.h ├── shl_log.c ├── shl_log.h ├── shl_misc.h ├── shl_register.h ├── shl_ring.h ├── shl_timer.h ├── text.c ├── text.h ├── text_bblit.c ├── text_bbulk.c ├── text_gltex.c ├── text_gltex_atlas.frag ├── text_gltex_atlas.vert ├── text_pixman.c ├── uterm_drm2d_internal.h ├── uterm_drm2d_render.c ├── uterm_drm2d_video.c ├── uterm_drm3d_blend.frag ├── uterm_drm3d_blend.vert ├── uterm_drm3d_blit.frag ├── uterm_drm3d_blit.vert ├── uterm_drm3d_fill.frag ├── uterm_drm3d_fill.vert ├── uterm_drm3d_internal.h ├── uterm_drm3d_render.c ├── uterm_drm3d_video.c ├── uterm_drm_shared.c ├── uterm_drm_shared_internal.h ├── uterm_fbdev_internal.h ├── uterm_fbdev_render.c ├── uterm_fbdev_video.c ├── uterm_input.c ├── uterm_input.h ├── uterm_input_fallback.xkb ├── uterm_input_internal.h ├── uterm_input_uxkb.c ├── uterm_monitor.c ├── uterm_monitor.h ├── uterm_systemd.c ├── uterm_systemd_internal.h ├── uterm_video.c ├── uterm_video.h ├── uterm_video_internal.h ├── uterm_vt.c └── uterm_vt.h ├── tests ├── meson.build ├── test_common.h ├── test_include.h ├── test_input.c ├── test_key.c ├── test_output.c ├── test_shl.c └── test_vt.c └── tools ├── embedded_file.py └── extract_release_note.py /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | # Enable when testing release infrastructure on a branch. 5 | branches: 6 | - release-* 7 | tags: 8 | - 'v[0-9]+.[0-9]+.[0-9]+' 9 | jobs: 10 | create-release: 11 | name: create-release 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-python@v3 16 | with: 17 | python-version: '3.x' 18 | - name: Install meson 19 | run: pip install meson ninja 20 | - name: Install dependencies 21 | run: | 22 | sudo apt-get install -y check libudev-dev libxkbcommon-dev libdrm-dev libgbm-dev libegl1-mesa-dev libgles-dev libpango1.0-dev libsystemd-dev 23 | - name: Install libtsm 24 | run: | 25 | pip install cmake 26 | curl -L -o libtsm.tar.gz $(curl -s https://api.github.com/repos/Aetf/libtsm/releases/latest \ 27 | | grep "tarball_url" \ 28 | | awk '{ print $2 }' \ 29 | | sed 's/,$//' \ 30 | | sed 's/"//g' ) 31 | mkdir libtsm 32 | tar -xf libtsm.tar.gz -C libtsm --strip 1 33 | cd libtsm 34 | cmake -Bbuilddir 35 | cmake --build builddir 36 | sudo cmake --install builddir 37 | - name: Meson setup 38 | run: meson setup builddir/ 39 | - name: Create source distribution 40 | # no unit tests yet 41 | run: meson dist -C builddir/ 42 | - name: Create release note 43 | run: tools/extract_release_note.py NEWS ${{ github.workspace }}-release-note.txt 44 | - name: Upload Artifact 45 | uses: actions/upload-artifact@v3 46 | with: 47 | name: release-files 48 | path: | 49 | builddir/meson-dist/* 50 | ${{ github.workspace }}-release-note.txt 51 | - name: Release 52 | uses: softprops/action-gh-release@v1 53 | # only actually create the release when run on tag 54 | if: startsWith(github.ref, 'refs/tags/') 55 | with: 56 | files: builddir/meson-dist/* 57 | body_path: ${{ github.workspace }}-release-note.txt 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | *.o 4 | *.lo 5 | *.la 6 | kmscon 7 | /test_* 8 | Makefile 9 | Makefile.in 10 | aclocal.m4 11 | autom4te.cache/ 12 | build-aux/ 13 | build/ 14 | compile_commands.json 15 | config.h 16 | config.h.in 17 | config.h.in~ 18 | config.log 19 | config.status 20 | configure 21 | *.tar.xz 22 | libtool 23 | libeloop.pc 24 | libuterm.pc 25 | m4/ 26 | stamp-* 27 | .deps 28 | .dirstamp 29 | .libs 30 | .man_fixup 31 | genunifont 32 | src/shl_githead.c 33 | src/font_unifont_data.bin 34 | src/font_unifont_data.bin.c 35 | docs/reference/*.txt 36 | docs/reference/*.bak 37 | docs/reference/kmscon.????* 38 | docs/reference/*.stamp 39 | docs/reference/version.xml 40 | docs/reference/*/ 41 | docs/man/*.1 42 | docs/man/*.3 43 | docs/man/*.5 44 | docs/man/*.7 45 | src/*.vert.bin 46 | src/*.frag.bin 47 | src/*.xkb.bin 48 | src/*.vert.bin.c 49 | src/*.frag.bin.c 50 | src/*.xkb.bin.c 51 | .cache/ 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KMSCON 2 | 3 | Kmscon is a simple terminal emulator based on linux kernel mode setting (KMS). 4 | It is an attempt to replace the in-kernel VT implementation with a userspace 5 | console. See kmscon(1) man-page for usage information. 6 | 7 | ## Requirements 8 | 9 | Kmscon requires the following software: 10 | - [libtsm](https://github.com/Aetf/libtsm): terminal emulator state machine 11 | - [libudev](https://www.freedesktop.org/software/systemd/man/libudev.html): providing input, video, etc. device hotplug support (>=v172) 12 | - [libxkbcommon](https://xkbcommon.org/): providing internationalized keyboard handling 13 | - [libdrm](https://gitlab.freedesktop.org/mesa/drm): graphics access to DRM/KMS subsystem 14 | - linux-headers: linux kernel headers for ABI definitions 15 | 16 | Everything else is optional: 17 | 18 | For video output at least one of the following is required: 19 | - fbdev: For framebuffer video output the kernel headers must be installed and located in the default include path. 20 | - DRM: For unaccelerated drm output the "libdrm" library must be installed and accessible via pkg-config. 21 | - OpenGLES2: For accelerated video output via OpenGLESv2 the following must be installed: libdrm, libgbm, egl, glesv2 (i.e., mesa) 22 | 23 | For font handling the following is required: 24 | - 8x16: The 8x16 font is a static built-in font which does not require external dependencies. 25 | - unifont: Static font without external dependencies. 26 | - pango: drawing text with pango Pango requires: glib, pango, fontconfig, freetype2 and more 27 | 28 | For multi-seat support you need the following packages: 29 | - systemd: Actually only the systemd-logind daemon and library is required. 30 | 31 | ## Download 32 | 33 | Released tarballs can be found at: https://github.com/Aetf/kmscon/releases 34 | 35 | ## Install 36 | 37 | To compile the kmscon binary, run the standard meson commands: 38 | ```bash 39 | meson builddir/ 40 | ```` 41 | 42 | By default this will install into `/usr/local`, you can change your prefix with `--prefix=/usr` 43 | (or `meson configure builddir/ -Dprefix=/usr` after the initial meson setup). 44 | 45 | Then build and install. Note that this requires ninja. 46 | ```bash 47 | meson -C builddir/ install 48 | ``` 49 | 50 | The following meson options are available. 51 | They can be used to select backends for several subsystems in kmscon. 52 | If build-time dependencies cannot be satisfied, an option is automatically turned off, except if you 53 | explicitly enable it via command line: 54 | 55 | | option | default | description | 56 | |:------|:-------:|:-----------| 57 | |`extra_debug`| `false` | Additional debug outputs | 58 | |`multi_seat`| `auto` | This requires the systemd-logind library to provide multi-seat support for kmscon | 59 | |`video_fbdev`| `auto` | Linux fbdev video backend | 60 | |`video_drm2d`| `auto` | Linux DRM software-rendering backend | 61 | |`video_drm3d`| `auto` | Linux DRM hardware-rendering backend | 62 | |`font_unifont`| `auto` | Static built-in non-scalable font (Unicode Unifont) | 63 | |`font_pango`| `auto` | Pango based scalable font renderer | 64 | |`renderer_bbulk`| `auto` | Simple 2D software-renderer (bulk-mode) | 65 | |`renderer_gltex`| `auto` | OpenGLESv2 accelerated renderer | 66 | |`renderer_pixman`| `auto` | pixman based renderer | 67 | |`session_dummy`| `auto` | Dummy fallback session | 68 | |`session_terminal`| `auto` | Terminal-emulator sessions | 69 | 70 | ## Running 71 | 72 | To get usage information, run: 73 | ```bash 74 | kmscon --help 75 | ``` 76 | You can then run kmscon with: 77 | ```bash 78 | kmscon [options] 79 | ``` 80 | 81 | ### Locale 82 | 83 | Kmscon queries and setups system locale settings before starting if systemd-localed is available. 84 | Otherwise, you can change locale settings via `--xkb-{model,layout,variant,options}` command line options. 85 | See `man kmscon` for more information. 86 | 87 | ### Config file 88 | 89 | The default configuration file is `/etc/kmscon/kmscon.conf`. Any command line option can be put in the config file in 90 | its long form without the leading `--` (double dash). See `man kmscon` for more information. 91 | 92 | ## License 93 | 94 | This software is licensed under the terms of an MIT-like license. Please see 95 | [`COPYING`](./COPYING) for further information. 96 | 97 | ## History 98 | 99 | This is a personal fork from https://www.freedesktop.org/wiki/Software/kmscon, which hasn't been updated since 2014. 100 | 101 | -------------------------------------------------------------------------------- /docs/kmscon.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=KMS System Console 3 | Documentation=man:kmscon(1) 4 | 5 | [Service] 6 | ExecStart=@bindir@/kmscon -l /bin/login 7 | 8 | [Install] 9 | WantedBy=multi-user.target 10 | -------------------------------------------------------------------------------- /docs/kmsconvt@.service.in: -------------------------------------------------------------------------------- 1 | # 2 | # KMSCON system console on VTs on seat0 3 | # This unit takes as template argument a VT name (same as getty@.service) and 4 | # spawns KMSCON on this VT. Note that this does automatically limit KMSCON to 5 | # seat0. You cannot spawn KMSCON on other seats with this unit. 6 | # 7 | # You can replace the default getty@.service that is shipped with systemd by 8 | # linking it with: 9 | # ln -s /usr/lib/systemd/system/kmsconvt@.service /etc/systemd/system/autovt@.service 10 | # This will make systemd start KMSCON instead of agetty on each VT. Or more 11 | # precisely, this will make systemd-logind use kmsconvt@.service instead of 12 | # getty@.service for new VTs. In fact, all other units/scripts/... that use 13 | # getty@.service will not be affected by this change. 14 | # 15 | # Note that by default getty@.service installs itself as getty@tty1.service. 16 | # This unit does the same and overrules getty@tty1.service via the "Conflict" 17 | # line below. 18 | # 19 | # If KMSCON cannot start for whatever reason, this unit will cause 20 | # getty@.service to be started instead. So you will always have a safe fallback. 21 | # Furthermore, if no VTs are available, this unit will not start anything. 22 | # 23 | # You can still use getty@.service and kmsconvt@.service simultaneously on 24 | # different VTs, but you cannot use both on the same VT (and this wouldn't make 25 | # any sense). 26 | # 27 | 28 | [Unit] 29 | Description=KMS System Console on %I 30 | Documentation=man:kmscon(1) 31 | After=systemd-user-sessions.service 32 | After=plymouth-quit-wait.service 33 | Before=getty.target 34 | Conflicts=getty@%i.service 35 | OnFailure=getty@%i.service 36 | IgnoreOnIsolate=yes 37 | ConditionPathExists=/dev/tty0 38 | 39 | [Service] 40 | ExecStart=@bindir@/kmscon "--vt=%I" --seats=seat0 --no-switchvt 41 | UtmpIdentifier=%I 42 | TTYPath=/dev/%I 43 | TTYReset=yes 44 | TTYVHangup=yes 45 | TTYVTDisallocate=yes 46 | 47 | [Install] 48 | WantedBy=getty.target 49 | -------------------------------------------------------------------------------- /docs/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Aetf 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | manpages = [ 6 | 'kmscon.1.xml.in', 7 | 'kmscon.conf.1.xml.in', 8 | ] 9 | 10 | data = configuration_data() 11 | data.set('CONFIG_DIR', prefix / sysconfdir) 12 | 13 | foreach man : manpages 14 | xml = configure_file(input: f'man/@man@', output: '@BASENAME@', configuration: data) 15 | name = fs.replace_suffix(fs.replace_suffix(man, ''), '') 16 | custom_target( 17 | name, 18 | command: [ 19 | xsltproc, 20 | '--stringparam', 'man.authors.section.enabled', '0', 21 | '--stringparam', 'man.copyright.section.enabled', '0', 22 | '--stringparam', 'funcsynopsis.style', 'ansi', 23 | '--stringparam', 'man.output.quietly', '1', 24 | '--nonet', 25 | '-o', '@OUTPUT@', 26 | manpages_stylesheet, 27 | '@INPUT@' 28 | ], 29 | input: [ 30 | xml 31 | ], 32 | output: name, 33 | build_by_default: true, 34 | install: true, 35 | install_dir: mandir / 'man1', 36 | ) 37 | endforeach 38 | 39 | -------------------------------------------------------------------------------- /docs/unicode-test.txt: -------------------------------------------------------------------------------- 1 | This file contains a collection of common unicode symbols encoded in UTF-8. 2 | Displaying this file can be useful to test terminal/font unicode support. 3 | 4 | 什麽是Unicode(統一碼/標準萬國碼)? 5 | 6 | most wanted symbols: "☺", "☻", "✌", "✍", "✎", "✉", "☀", "☃", "☁", "☂", "★", "☆" 7 | , "☮", "☯", "〠", "☎", "☏", "♕", "❏", "☐", "☑", "☒", "✓", "✗", "¢", "€", "£", 8 | "❤", "❣", "❦", "♣", "♤", "♥", "♦", "♧", "►", "❝", "❞", "☜", "☝", "☞", "☟", "☚", 9 | "☛", "☹", "త", "☣", "☠" 10 | 11 | more symbols: "✑", "✒", "÷", "‰", "√", "≠", "∞", "❛", "❜", "™", "©", "®", "✄", 12 | "✁", "✂", "✇", "✿", "❀", "“", "”", "„", "‟", "«", "»", "♪", "♫", "…", "◆", "◇", 13 | "✣", "✪", "✰", "✧", "✦", "☔", "☕", "☼", "☾", "❆", "❅", "❄", "✵", "♲", "♻", "♿", 14 | "⚅", "⚑", "⚐" 15 | 16 | arrows: "←", "↑", "→", "↓", "↔", "↕", "⇄", "⇅", "↲", "↳", "↴", "↵", "↶", "↷", 17 | "↺", "↻", "➔", "➘", "➙", "➚", "➜", "➟", "➠", "➤", "➥", "➨", "➫", "➬", "➭", "➮", 18 | "➯", "➲", "➳", "➵", "➶", "➷", "➸", "➹", "➺", "➻", "➼", "➽", "➾", "◀", "▶", "◁", 19 | "▷", "◊" 20 | 21 | other symbols: "⚒", "⚓", "⚔", "⚕", "⚘", "⚖", "⚛", "⚚", "⚠", "⚡", "♀", "♂", 22 | "⚢", "⚣", "⚤", "⚰", "⚱", "☢", "☤", "✝", "☦", "☧", "☨", "☩", "☪", "☭", "♈", 23 | "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓", "⌚", "⌛", "⌨", "⏎", "✈", 24 | "♨", "☸", "⚭", "⚮", "⚯" 25 | 26 | mathematical: "∧", "∨", "∀", "∃", "∄", "¬", "∆", "∇", "∈", "∉", "∋", "∌", "∩", 27 | "∪", "⊂", "⊃", "⊄", "⊅", "⊆", "⊇", "∏", "∑", "Ω", "×", "±", "÷", "∅", "∗", "∙", 28 | "∂", "√", "∛", "∜", "∝", "∞", "∁", "∟", "∠", "∡", "∢", "∥", "∦", "⊕", "⊗", "≤", 29 | "≥", "≪", "≫" 30 | 31 | mathematical 2: "∫", "∬", "∭", "∮", "∯", "∰", "∱", "∲", "∳", "∴", "∵", "∻", "∼", 32 | "∽", "∾", "≀", "≁", "≈", "≂", "≃", "≅", "≡", "≢", "≣", "≉", "≊", "≋", "≌", "≍", 33 | "≎", "≏", "≐", "≑", "≒", "≓", "≖", "≗", "≘", "≙", "≚", "≛", "≜", "≝", "≞", "≟", 34 | "≠", "⊧", "⊥" 35 | 36 | mathematical 3: "¹", "²", "³", "⁴", "⁵", "ⁱ", "⁺", "⁻", "⁼", "⁽", "⁾", "ⁿ", "ℕ", 37 | "ℝ", "ℚ", "ℙ", "ℂ", "ℤ", "½", "¼", "¾", "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", 38 | "λ", "μ", "ξ", "ω", "Φ", "Ψ", "⊨", "⊭", "⊻", "⊼", "⊽", "⋅", "⅀", "⌀", "⌈", "⌉", 39 | "⌊", "⌋", "ₓ" 40 | 41 | mixed symbols: "♔", "♕", "♖", "♗", "♘", "♙", "♚", "♛", "♜", "♝", "♞", "♟", "℗", 42 | "♭", "♮", "♯", "♩", "☊", "♒", "☄", "✆", "ꁚ", "ꀪ", "ꀎ", "ꂔ", "℅", "℆", "℀", "℁", 43 | "№", "℮", "✜", "☇", "☈", "☉", "❖", "❶", "❷", "❸", "☘", "⌖", "ℹ", "⚀", "⚁", "⚂", 44 | "⚃", "⚄", "⚅" 45 | 46 | international: "¡", "¿", "Á", "á", "À", "à", "Å", "å", "Ä", "ä", "Æ", "æ", "Ç", 47 | "ç", "É", "é", "È", "è", "Í", "í", "Ì", "ì", "Î", "î", "Ñ", "ñ", "Ó", "ó", "Ò", 48 | "ò", "Ô", "ô", "Ö", "ö", "Ø", "ø", "Ú", "ú", "Ù", "ù", "Ü", "ü", "Ž", "ž", "ß", 49 | "¥", "€", "£" 50 | 51 | "❶", "❷", "❸", "☘" 52 | -------------------------------------------------------------------------------- /docs/vte.txt: -------------------------------------------------------------------------------- 1 | = KMSCON Virtual Terminal Emulator = 2 | 3 | The KMSCON Virtual Terminal Emulator (VTE) tries to be linux-console, xterm and 4 | vt102 compatible. This documentations contains links to several resources 5 | related to VT100-like terminals. 6 | 7 | Resources: 8 | Terminfo database: 9 | man 5 terminfo 10 | man infocmp 11 | infocmp -L xterm-new 12 | Linux Console Codes: 13 | man console_codes 14 | VT100 User Manual: 15 | http://vt100.net/docs/vt100-ug/chapter3.html 16 | VT510 User Manual: 17 | http://vt100.net/docs/vt510-rm/contents 18 | XTerm Escape Sequences: 19 | http://invisible-island.net/xterm/ctlseqs/ctlseqs.html 20 | C0 and C1 Control Codes: 21 | http://en.wikipedia.org/wiki/C0_and_C1_control_codes 22 | ANSI Escape Sequences / Control Sequence Introducer (CSI) 23 | http://en.wikipedia.org/wiki/Control_Sequence_Introducer 24 | vttest Terminal Tests: 25 | http://invisible-island.net/vttest/ 26 | vt100-vt520 docs: 27 | http://vt100.net/ 28 | 29 | Implementations: 30 | XTerm: 31 | http://invisible-island.net/xterm/ 32 | libVTE: 33 | http://developer.gnome.org/vte/unstable/ 34 | Google JavaScript HTerm: 35 | http://git.chromium.org/gitweb/?p=chromiumos/platform/assets.git;a=tree;f=chromeapps/hterm/js;hb=HEAD 36 | Wayland Terminal Widget: 37 | http://cgit.freedesktop.org/wayland/weston/tree/clients/terminal.c 38 | -------------------------------------------------------------------------------- /external/htable.h: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2+ - see LICENSE file for details */ 2 | #ifndef CCAN_HTABLE_H 3 | #define CCAN_HTABLE_H 4 | #include 5 | #include 6 | #include 7 | 8 | /** 9 | * struct htable - private definition of a htable. 10 | * 11 | * It's exposed here so you can put it in your structures and so we can 12 | * supply inline functions. 13 | */ 14 | struct htable { 15 | size_t (*rehash)(const void *elem, void *priv); 16 | void *priv; 17 | unsigned int bits; 18 | size_t elems, deleted, max, max_with_deleted; 19 | /* These are the bits which are the same in all pointers. */ 20 | uintptr_t common_mask, common_bits; 21 | uintptr_t perfect_bit; 22 | uintptr_t *table; 23 | }; 24 | 25 | /** 26 | * HTABLE_INITIALIZER - static initialization for a hash table. 27 | * @name: name of this htable. 28 | * @rehash: hash function to use for rehashing. 29 | * @priv: private argument to @rehash function. 30 | * 31 | * This is useful for setting up static and global hash tables. 32 | * 33 | * Example: 34 | * // For simplicity's sake, say hash value is contents of elem. 35 | * static size_t rehash(const void *elem, void *unused) 36 | * { 37 | * return *(size_t *)elem; 38 | * } 39 | * static struct htable ht = HTABLE_INITIALIZER(ht, rehash, NULL); 40 | */ 41 | #define HTABLE_INITIALIZER(name, rehash, priv) \ 42 | { rehash, priv, 0, 0, 0, 0, 0, -1, 0, 0, &name.perfect_bit } 43 | 44 | /** 45 | * htable_init - initialize an empty hash table. 46 | * @ht: the hash table to initialize 47 | * @rehash: hash function to use for rehashing. 48 | * @priv: private argument to @rehash function. 49 | */ 50 | void htable_init(struct htable *ht, 51 | size_t (*rehash)(const void *elem, void *priv), void *priv); 52 | 53 | /** 54 | * htable_clear - empty a hash table. 55 | * @ht: the hash table to clear 56 | * 57 | * This doesn't do anything to any pointers left in it. 58 | */ 59 | void htable_clear(struct htable *ht); 60 | 61 | /** 62 | * htable_rehash - use a hashtree's rehash function 63 | * @elem: the argument to rehash() 64 | * 65 | */ 66 | size_t htable_rehash(const void *elem); 67 | 68 | /** 69 | * htable_add - add a pointer into a hash table. 70 | * @ht: the htable 71 | * @hash: the hash value of the object 72 | * @p: the non-NULL pointer 73 | * 74 | * Also note that this can only fail due to allocation failure. Otherwise, it 75 | * returns true. 76 | */ 77 | bool htable_add(struct htable *ht, size_t hash, const void *p); 78 | 79 | /** 80 | * htable_del - remove a pointer from a hash table 81 | * @ht: the htable 82 | * @hash: the hash value of the object 83 | * @p: the pointer 84 | * 85 | * Returns true if the pointer was found (and deleted). 86 | */ 87 | bool htable_del(struct htable *ht, size_t hash, const void *p); 88 | 89 | /** 90 | * struct htable_iter - iterator or htable_first or htable_firstval etc. 91 | * 92 | * This refers to a location inside the hashtable. 93 | */ 94 | struct htable_iter { 95 | size_t off; 96 | }; 97 | 98 | /** 99 | * htable_firstval - find a candidate for a given hash value 100 | * @htable: the hashtable 101 | * @i: the struct htable_iter to initialize 102 | * @hash: the hash value 103 | * 104 | * You'll need to check the value is what you want; returns NULL if none. 105 | * See Also: 106 | * htable_delval() 107 | */ 108 | void *htable_firstval(const struct htable *htable, 109 | struct htable_iter *i, size_t hash); 110 | 111 | /** 112 | * htable_nextval - find another candidate for a given hash value 113 | * @htable: the hashtable 114 | * @i: the struct htable_iter to initialize 115 | * @hash: the hash value 116 | * 117 | * You'll need to check the value is what you want; returns NULL if no more. 118 | */ 119 | void *htable_nextval(const struct htable *htable, 120 | struct htable_iter *i, size_t hash); 121 | 122 | /** 123 | * htable_get - find an entry in the hash table 124 | * @ht: the hashtable 125 | * @h: the hash value of the entry 126 | * @cmp: the comparison function 127 | * @ptr: the pointer to hand to the comparison function. 128 | * 129 | * Convenient inline wrapper for htable_firstval/htable_nextval loop. 130 | */ 131 | static inline void *htable_get(const struct htable *ht, 132 | size_t h, 133 | bool (*cmp)(const void *candidate, void *ptr), 134 | const void *ptr) 135 | { 136 | struct htable_iter i; 137 | void *c; 138 | 139 | for (c = htable_firstval(ht,&i,h); c; c = htable_nextval(ht,&i,h)) { 140 | if (cmp(c, (void *)ptr)) 141 | return c; 142 | } 143 | return NULL; 144 | } 145 | 146 | /** 147 | * htable_first - find an entry in the hash table 148 | * @ht: the hashtable 149 | * @i: the struct htable_iter to initialize 150 | * 151 | * Get an entry in the hashtable; NULL if empty. 152 | */ 153 | void *htable_first(const struct htable *htable, struct htable_iter *i); 154 | 155 | /** 156 | * htable_next - find another entry in the hash table 157 | * @ht: the hashtable 158 | * @i: the struct htable_iter to use 159 | * 160 | * Get another entry in the hashtable; NULL if all done. 161 | * This is usually used after htable_first or prior non-NULL htable_next. 162 | */ 163 | void *htable_next(const struct htable *htable, struct htable_iter *i); 164 | 165 | /** 166 | * htable_delval - remove an iterated pointer from a hash table 167 | * @ht: the htable 168 | * @i: the htable_iter 169 | * 170 | * Usually used to delete a hash entry after it has been found with 171 | * htable_firstval etc. 172 | */ 173 | void htable_delval(struct htable *ht, struct htable_iter *i); 174 | 175 | #endif /* CCAN_HTABLE_H */ 176 | -------------------------------------------------------------------------------- /external/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Aetf 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | # 6 | # htable - hash table 7 | # 8 | htable = static_library('ext-htable', ['htable.c']) 9 | 10 | htable_deps = declare_dependency( 11 | link_with: [htable], 12 | include_directories: [ 13 | include_directories('.'), 14 | ] 15 | ) 16 | 17 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('extra_debug', type: 'boolean', value: false, 2 | description: 'Additional non-standard debug options') 3 | option('tests', type: 'boolean', value: true, 4 | description: 'Build unit tests') 5 | option('docs', type: 'feature', value: 'auto', 6 | description: 'Build documentation') 7 | 8 | # multi-seat 9 | option('multi_seat', type: 'feature', value: 'auto', 10 | description: 'Multi-seat support with systemd') 11 | 12 | # video backends 13 | option('video_fbdev', type: 'feature', value: 'auto', 14 | description: 'fbdev video backend') 15 | option('video_drm2d', type: 'feature', value: 'auto', 16 | description: 'drm2d video backend') 17 | option('video_drm3d', type: 'feature', value: 'auto', 18 | description: 'drm3d video backend') 19 | 20 | # renderers 21 | option('renderer_bbulk', type: 'feature', value: 'auto', 22 | description: 'bbulk renderer') 23 | option('renderer_gltex', type: 'feature', value: 'auto', 24 | description: 'gltex renderer') 25 | option('renderer_pixman', type: 'feature', value: 'auto', 26 | description: 'pixman renderer') 27 | 28 | # font backends 29 | option('font_unifont', type: 'feature', value: 'auto', 30 | description: 'unifont font backend') 31 | option('font_pango', type: 'feature', value: 'auto', 32 | description: 'pango font backend') 33 | 34 | # kmscon sessions 35 | option('session_dummy', type: 'feature', value: 'auto', 36 | description: 'dummy session') 37 | option('session_terminal', type: 'feature', value: 'auto', 38 | description: 'terminal session') 39 | 40 | # terminal options 41 | option('backspace_sends_delete', type: 'boolean', value: 'false', 42 | description: 'backspace sends ASCII delete (0177) instead of ASCII backspace (010)') 43 | -------------------------------------------------------------------------------- /scripts/kmscon.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Aetf 4 | # Copyright (c) 2018 Fabian Vogt 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in all 14 | # copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | 24 | # configuration path 25 | helperdir=@libexecdir@ 26 | 27 | # Get a property from org.freedesktop.locale1 28 | queryLocale1() { 29 | dbus-send --system --print-reply=literal --dest=org.freedesktop.locale1 /org/freedesktop/locale1 org.freedesktop.DBus.Properties.Get "string:org.freedesktop.locale1" "string:$1" | awk '{print $2}' 30 | } 31 | 32 | # Query and setup system locale settings before start kmscon 33 | setupLocale() { 34 | # Fallback to do nothing if we don't have the command 35 | if ! command -v dbus-send >/dev/null 2>/dev/null; then 36 | return 37 | fi 38 | 39 | # Don't override existing values. Also there is no point in setting only some of them 40 | # as then they would not match anymore. 41 | if test -n "${XKB_DEFAULT_MODEL}" -o -n "${XKB_DEFAULT_LAYOUT}" -o -n "${XKB_DEFAULT_VARIANT}" -o -n "${XKB_DEFAULT_OPTIONS}"; then 42 | return 43 | fi 44 | 45 | X11MODEL="$(queryLocale1 X11Model)" 46 | X11LAYOUT="$(queryLocale1 X11Layout)" 47 | X11VARIANT="$(queryLocale1 X11Variant)" 48 | X11OPTIONS="$(queryLocale1 X11Options)" 49 | [ -n "${X11MODEL}" ] && export XKB_DEFAULT_MODEL="${X11MODEL}" 50 | [ -n "${X11LAYOUT}" ] && export XKB_DEFAULT_LAYOUT="${X11LAYOUT}" 51 | [ -n "${X11VARIANT}" ] && export XKB_DEFAULT_VARIANT="${X11VARIANT}" 52 | [ -n "${X11OPTIONS}" ] && export XKB_DEFAULT_OPTIONS="${X11OPTIONS}" 53 | } 54 | 55 | setupLocale 56 | exec ${helperdir}/kmscon "$@" 57 | -------------------------------------------------------------------------------- /src/font.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Font Renderer 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Font Renderer 28 | */ 29 | 30 | #ifndef KMSCON_FONT_H 31 | #define KMSCON_FONT_H 32 | 33 | #include 34 | #include 35 | #include "kmscon_module.h" 36 | #include "uterm_video.h" 37 | 38 | /* fonts */ 39 | 40 | struct kmscon_font_attr; 41 | struct kmscon_glyph; 42 | struct kmscon_font; 43 | struct kmscon_font_ops; 44 | 45 | #define KMSCON_FONT_MAX_NAME 128 46 | #define KMSCON_FONT_DEFAULT_NAME "monospace" 47 | #define KMSCON_FONT_DEFAULT_PPI 72 48 | 49 | struct kmscon_font_attr { 50 | char name[KMSCON_FONT_MAX_NAME]; 51 | unsigned int ppi; 52 | unsigned int points; 53 | bool bold; 54 | bool italic; 55 | bool underline; 56 | unsigned int height; 57 | unsigned int width; 58 | }; 59 | 60 | void kmscon_font_attr_normalize(struct kmscon_font_attr *attr); 61 | bool kmscon_font_attr_match(const struct kmscon_font_attr *a1, 62 | const struct kmscon_font_attr *a2); 63 | 64 | struct kmscon_glyph { 65 | struct uterm_video_buffer buf; 66 | unsigned int width; 67 | void *data; 68 | }; 69 | 70 | struct kmscon_font { 71 | unsigned long ref; 72 | struct shl_register_record *record; 73 | const struct kmscon_font_ops *ops; 74 | struct kmscon_font_attr attr; 75 | unsigned int baseline; 76 | void *data; 77 | }; 78 | 79 | struct kmscon_font_ops { 80 | const char *name; 81 | struct kmscon_module *owner; 82 | int (*init) (struct kmscon_font *out, 83 | const struct kmscon_font_attr *attr); 84 | void (*destroy) (struct kmscon_font *font); 85 | int (*render) (struct kmscon_font *font, 86 | uint64_t id, const uint32_t *ch, size_t len, 87 | const struct kmscon_glyph **out); 88 | int (*render_empty) (struct kmscon_font *font, 89 | const struct kmscon_glyph **out); 90 | int (*render_inval) (struct kmscon_font *font, 91 | const struct kmscon_glyph **out); 92 | }; 93 | 94 | int kmscon_font_register(const struct kmscon_font_ops *ops); 95 | void kmscon_font_unregister(const char *name); 96 | 97 | int kmscon_font_find(struct kmscon_font **out, 98 | const struct kmscon_font_attr *attr, 99 | const char *backend); 100 | void kmscon_font_ref(struct kmscon_font *font); 101 | void kmscon_font_unref(struct kmscon_font *font); 102 | 103 | int kmscon_font_render(struct kmscon_font *font, 104 | uint64_t id, const uint32_t *ch, size_t len, 105 | const struct kmscon_glyph **out); 106 | int kmscon_font_render_empty(struct kmscon_font *font, 107 | const struct kmscon_glyph **out); 108 | int kmscon_font_render_inval(struct kmscon_font *font, 109 | const struct kmscon_glyph **out); 110 | 111 | /* modularized backends */ 112 | 113 | extern struct kmscon_font_ops kmscon_font_8x16_ops; 114 | extern struct kmscon_font_ops kmscon_font_unifont_ops; 115 | extern struct kmscon_font_ops kmscon_font_pango_ops; 116 | 117 | #endif /* KMSCON_FONT_H */ 118 | -------------------------------------------------------------------------------- /src/genversion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Generate $1 with: 5 | # const char shl_git_head[] = ""; 6 | # But do not touch $1 if the git-revision is already up-to-date. 7 | # 8 | 9 | if test "x$1" = "x" ; then 10 | echo "usage: ./genversion " 11 | exit 1 12 | fi 13 | 14 | # 15 | # Check whether this is a valid git repository. 16 | # Set ISGIT to 1=true or 0=false. 17 | # 18 | 19 | ISGIT=0 20 | REV=`git rev-parse --git-dir 2>/dev/null` 21 | if test "x$?" = "x0" ; then 22 | ISGIT=1 23 | fi 24 | 25 | # 26 | # Check the old revision from $1. 27 | # 28 | 29 | if test -f "$1" ; then 30 | OLDREV=`cat "$1"` 31 | else 32 | if test $ISGIT = 0 ; then 33 | echo "WARNING: version file $1 is missing" 34 | echo "const char shl_git_head[] = \"UnknownRevision\";" >"$1" 35 | exit 0 36 | fi 37 | 38 | OLDREV="" 39 | fi 40 | 41 | # 42 | # Check new revision from "git describe". However, if this is no valid 43 | # git-repository, return success and do nothing. 44 | # 45 | 46 | if test $ISGIT = 0 ; then 47 | exit 0 48 | fi 49 | 50 | NEWREV=`git describe` 51 | NEWREV="const char shl_git_head[] = \"$NEWREV\";" 52 | 53 | # 54 | # Exit if the file is already up to date. 55 | # Otherwise, write the new revision into the file. 56 | # 57 | 58 | if test "x$OLDREV" = "x$NEWREV" ; then 59 | exit 0 60 | fi 61 | 62 | echo "$NEWREV" >"$1" 63 | -------------------------------------------------------------------------------- /src/kmscon_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Main App 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * This includes global data for the whole kmscon application. For instance, 28 | * global parameters can be accessed via this header. 29 | */ 30 | 31 | #ifndef KMSCON_MAIN_H 32 | #define KMSCON_MAIN_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "conf.h" 39 | #include "shl_dlist.h" 40 | 41 | enum kmscon_conf_gpu_selection { 42 | KMSCON_GPU_ALL, 43 | KMSCON_GPU_AUX, 44 | KMSCON_GPU_PRIMARY, 45 | }; 46 | 47 | typedef uint8_t palette_t[TSM_COLOR_NUM][3]; 48 | 49 | struct kmscon_conf_t { 50 | /* header information */ 51 | bool seat_config; 52 | 53 | /* General Options */ 54 | /* show help/usage information */ 55 | bool help; 56 | /* exit application after parsing options */ 57 | bool exit; 58 | /* enable verbose info messages */ 59 | bool verbose; 60 | /* enable debug messages */ 61 | bool debug; 62 | /* disable notices and warnings */ 63 | bool silent; 64 | /* config directory name */ 65 | char *configdir; 66 | /* listen mode */ 67 | bool listen; 68 | 69 | /* Seat Options */ 70 | /* VT number to run on */ 71 | char *vt; 72 | /* enter new VT directly */ 73 | bool switchvt; 74 | /* seats */ 75 | char **seats; 76 | 77 | /* Session Options */ 78 | /* sessions */ 79 | unsigned int session_max; 80 | /* allow keyboard session control */ 81 | bool session_control; 82 | /* run terminal session */ 83 | bool terminal_session; 84 | 85 | /* Terminal Options */ 86 | /* custom login process */ 87 | bool login; 88 | /* argv for login process */ 89 | char **argv; 90 | /* TERM value */ 91 | char *term; 92 | /* reset environment */ 93 | bool reset_env; 94 | /* terminal scroll-back buffer size */ 95 | unsigned int sb_size; 96 | 97 | /* Input Options */ 98 | /* input KBD model */ 99 | char *xkb_model; 100 | /* input KBD layout */ 101 | char *xkb_layout; 102 | /* input KBD variant */ 103 | char *xkb_variant; 104 | /* input KBD options */ 105 | char *xkb_options; 106 | /* input predefined KBD keymap */ 107 | char *xkb_keymap; 108 | /* input predefined KBD compose file */ 109 | char *xkb_compose_file; 110 | /* keyboard key-repeat delay */ 111 | unsigned int xkb_repeat_delay; 112 | /* keyboard key-repeat rate */ 113 | unsigned int xkb_repeat_rate; 114 | 115 | /* Grabs / Keyboard-Shortcuts */ 116 | /* scroll-up grab */ 117 | struct conf_grab *grab_scroll_up; 118 | /* scroll-down grab */ 119 | struct conf_grab *grab_scroll_down; 120 | /* page-up grab */ 121 | struct conf_grab *grab_page_up; 122 | /* page-down grab */ 123 | struct conf_grab *grab_page_down; 124 | /* zoom-in grab */ 125 | struct conf_grab *grab_zoom_in; 126 | /* zoom-out grab */ 127 | struct conf_grab *grab_zoom_out; 128 | /* session-next grab */ 129 | struct conf_grab *grab_session_next; 130 | /* session-prev grab */ 131 | struct conf_grab *grab_session_prev; 132 | /* session-dummy grab */ 133 | struct conf_grab *grab_session_dummy; 134 | /* session-close grab */ 135 | struct conf_grab *grab_session_close; 136 | /* terminal-new grab */ 137 | struct conf_grab *grab_terminal_new; 138 | /* rotate output clock-wise grab */ 139 | struct conf_grab *grab_rotate_cw; 140 | /* rotate output counter-clock-wise grab */ 141 | struct conf_grab *grab_rotate_ccw; 142 | 143 | /* Video Options */ 144 | /* use DRM if available */ 145 | bool drm; 146 | /* use 3D hardware-acceleration if available */ 147 | bool hwaccel; 148 | /* gpu selection mode */ 149 | unsigned int gpus; 150 | /* render engine */ 151 | char *render_engine; 152 | /* orientation/rotation of output */ 153 | char *rotate; 154 | 155 | /* Font Options */ 156 | /* font engine */ 157 | char *font_engine; 158 | /* font size */ 159 | unsigned int font_size; 160 | /* font name */ 161 | char *font_name; 162 | /* font ppi (overrides per monitor PPI) */ 163 | unsigned int font_ppi; 164 | 165 | /* Palette Options */ 166 | /* color palette */ 167 | char *palette; 168 | /* custom palette */ 169 | palette_t custom_palette; 170 | }; 171 | 172 | int kmscon_conf_new(struct conf_ctx **out); 173 | void kmscon_conf_free(struct conf_ctx *ctx); 174 | int kmscon_conf_load_main(struct conf_ctx *ctx, int argc, char **argv); 175 | int kmscon_conf_load_seat(struct conf_ctx *ctx, const struct conf_ctx *main, 176 | const char *seat); 177 | 178 | static inline bool kmscon_conf_is_current_seat(struct kmscon_conf_t *conf) 179 | { 180 | return conf && shl_string_list_is(conf->seats, "current"); 181 | } 182 | 183 | static inline bool kmscon_conf_is_all_seats(struct kmscon_conf_t *conf) 184 | { 185 | return conf && shl_string_list_is(conf->seats, "all"); 186 | } 187 | 188 | static inline bool kmscon_conf_is_single_seat(struct kmscon_conf_t *conf) 189 | { 190 | return conf && !kmscon_conf_is_all_seats(conf) && 191 | shl_string_list_count(conf->seats, true) == 1; 192 | } 193 | 194 | #endif /* KMSCON_MAIN_H */ 195 | -------------------------------------------------------------------------------- /src/kmscon_dummy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Dummy Session 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Dummy Session 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include "kmscon_dummy.h" 34 | #include "kmscon_seat.h" 35 | #include "shl_dlist.h" 36 | #include "shl_log.h" 37 | 38 | #define LOG_SUBSYSTEM "dummy" 39 | 40 | struct display { 41 | struct shl_dlist list; 42 | struct uterm_display *disp; 43 | }; 44 | 45 | struct kmscon_dummy { 46 | struct kmscon_session *session; 47 | struct shl_dlist displays; 48 | bool active; 49 | }; 50 | 51 | static void dummy_redraw(struct kmscon_dummy *dummy, struct display *d) 52 | { 53 | struct uterm_mode *mode; 54 | unsigned int w, h; 55 | 56 | mode = uterm_display_get_current(d->disp); 57 | w = uterm_mode_get_width(mode); 58 | h = uterm_mode_get_height(mode); 59 | 60 | uterm_display_fill(d->disp, 0, 0, 0, 0, 0, w, h); 61 | uterm_display_swap(d->disp, false); 62 | } 63 | 64 | static int dummy_session_event(struct kmscon_session *session, 65 | struct kmscon_session_event *ev, void *data) 66 | { 67 | struct kmscon_dummy *dummy = data; 68 | struct display *d; 69 | struct shl_dlist *iter; 70 | 71 | switch (ev->type) { 72 | case KMSCON_SESSION_DISPLAY_NEW: 73 | d = malloc(sizeof(*d)); 74 | if (!d) { 75 | log_error("cannot allocate memory for new display"); 76 | break; 77 | } 78 | memset(d, 0, sizeof(*d)); 79 | d->disp = ev->disp; 80 | shl_dlist_link_tail(&dummy->displays, &d->list); 81 | if (dummy->active) 82 | dummy_redraw(dummy, d); 83 | break; 84 | case KMSCON_SESSION_DISPLAY_GONE: 85 | shl_dlist_for_each(iter, &dummy->displays) { 86 | d = shl_dlist_entry(iter, struct display, list); 87 | if (d->disp != ev->disp) 88 | continue; 89 | 90 | shl_dlist_unlink(&d->list); 91 | free(d); 92 | break; 93 | } 94 | break; 95 | case KMSCON_SESSION_DISPLAY_REFRESH: 96 | shl_dlist_for_each(iter, &dummy->displays) { 97 | d = shl_dlist_entry(iter, struct display, list); 98 | if (d->disp != ev->disp) 99 | continue; 100 | 101 | if (dummy->active) 102 | dummy_redraw(dummy, d); 103 | break; 104 | } 105 | break; 106 | case KMSCON_SESSION_ACTIVATE: 107 | dummy->active = true; 108 | shl_dlist_for_each(iter, &dummy->displays) { 109 | d = shl_dlist_entry(iter, struct display, list); 110 | dummy_redraw(dummy, d); 111 | } 112 | break; 113 | case KMSCON_SESSION_DEACTIVATE: 114 | dummy->active = false; 115 | break; 116 | case KMSCON_SESSION_UNREGISTER: 117 | while (!shl_dlist_empty(&dummy->displays)) { 118 | d = shl_dlist_entry(dummy->displays.prev, 119 | struct display, list); 120 | shl_dlist_unlink(&d->list); 121 | free(d); 122 | } 123 | 124 | free(dummy); 125 | break; 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | int kmscon_dummy_register(struct kmscon_session **out, 132 | struct kmscon_seat *seat) 133 | { 134 | struct kmscon_dummy *dummy; 135 | int ret; 136 | 137 | if (!out || !seat) 138 | return -EINVAL; 139 | 140 | dummy = malloc(sizeof(*dummy)); 141 | if (!dummy) 142 | return -ENOMEM; 143 | memset(dummy, 0, sizeof(*dummy)); 144 | shl_dlist_init(&dummy->displays); 145 | 146 | ret = kmscon_seat_register_session(seat, &dummy->session, 147 | dummy_session_event, dummy); 148 | if (ret) { 149 | log_error("cannot register session for dummy: %d", ret); 150 | goto err_free; 151 | } 152 | 153 | *out = dummy->session; 154 | log_debug("new dummy object %p", dummy); 155 | return 0; 156 | 157 | err_free: 158 | free(dummy); 159 | return ret; 160 | } 161 | -------------------------------------------------------------------------------- /src/kmscon_dummy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Dummy Session 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Dummy Session 28 | */ 29 | 30 | #ifndef KMSCON_DUMMY_H 31 | #define KMSCON_DUMMY_H 32 | 33 | #include 34 | #include 35 | #include "kmscon_seat.h" 36 | 37 | #ifdef BUILD_ENABLE_SESSION_DUMMY 38 | 39 | int kmscon_dummy_register(struct kmscon_session **out, 40 | struct kmscon_seat *seat); 41 | 42 | #else /* !BUILD_ENABLE_SESSION_DUMMY */ 43 | 44 | static inline int kmscon_dummy_register(struct kmscon_session **out, 45 | struct kmscon_seat *seat) 46 | { 47 | return -EOPNOTSUPP; 48 | } 49 | 50 | #endif /* BUILD_ENABLE_SESSION_DUMMY */ 51 | 52 | #endif /* KMSCON_DUMMY_H */ 53 | -------------------------------------------------------------------------------- /src/kmscon_mod_bbulk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - BBulk rendering backend module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * BBulk rendering backend module 28 | * This module provides the bbulk renderer backend. 29 | */ 30 | 31 | #include 32 | #include 33 | #include "text.h" 34 | #include "kmscon_module_interface.h" 35 | #include "shl_log.h" 36 | 37 | #define LOG_SUBSYSTEM "mod_bbulk" 38 | 39 | static int kmscon_bbulk_load(void) 40 | { 41 | int ret; 42 | 43 | kmscon_text_bbulk_ops.owner = KMSCON_THIS_MODULE; 44 | ret = kmscon_text_register(&kmscon_text_bbulk_ops); 45 | if (ret) { 46 | log_error("cannot register bbulk renderer"); 47 | return ret; 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | static void kmscon_bbulk_unload(void) 54 | { 55 | kmscon_text_unregister(kmscon_text_bbulk_ops.name); 56 | } 57 | 58 | KMSCON_MODULE(NULL, kmscon_bbulk_load, kmscon_bbulk_unload, NULL); 59 | -------------------------------------------------------------------------------- /src/kmscon_mod_gltex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - OpenGL Texture based rendering backend module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * OpenGL Texture based rendering backend module 28 | * This module provides the gltex renderer backend. 29 | */ 30 | 31 | #include 32 | #include 33 | #include "text.h" 34 | #include "kmscon_module_interface.h" 35 | #include "shl_log.h" 36 | 37 | #define LOG_SUBSYSTEM "mod_gltex" 38 | 39 | static int kmscon_gltex_load(void) 40 | { 41 | int ret; 42 | 43 | kmscon_text_gltex_ops.owner = KMSCON_THIS_MODULE; 44 | ret = kmscon_text_register(&kmscon_text_gltex_ops); 45 | if (ret) { 46 | log_error("cannot register gltex renderer"); 47 | return ret; 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | static void kmscon_gltex_unload(void) 54 | { 55 | kmscon_text_unregister(kmscon_text_gltex_ops.name); 56 | } 57 | 58 | KMSCON_MODULE(NULL, kmscon_gltex_load, kmscon_gltex_unload, NULL); 59 | -------------------------------------------------------------------------------- /src/kmscon_mod_pango.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Pango font backend module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Pango font backend module 28 | * This module registers the text-font pango backend with kmscon. 29 | */ 30 | 31 | #include 32 | #include 33 | #include "font.h" 34 | #include "kmscon_module_interface.h" 35 | #include "shl_log.h" 36 | 37 | #define LOG_SUBSYSTEM "mod_pango" 38 | 39 | static int kmscon_pango_load(void) 40 | { 41 | int ret; 42 | 43 | kmscon_font_pango_ops.owner = KMSCON_THIS_MODULE; 44 | ret = kmscon_font_register(&kmscon_font_pango_ops); 45 | if (ret) { 46 | log_error("cannot register pango font"); 47 | return ret; 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | static void kmscon_pango_unload(void) 54 | { 55 | kmscon_font_unregister(kmscon_font_pango_ops.name); 56 | } 57 | 58 | KMSCON_MODULE(NULL, kmscon_pango_load, kmscon_pango_unload, NULL); 59 | -------------------------------------------------------------------------------- /src/kmscon_mod_pixman.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Pixman based rendering backend module 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Pixman based rendering backend 28 | */ 29 | 30 | #include 31 | #include 32 | #include "text.h" 33 | #include "kmscon_module_interface.h" 34 | #include "shl_log.h" 35 | 36 | #define LOG_SUBSYSTEM "mod_pixman" 37 | 38 | static int kmscon_pixman_load(void) 39 | { 40 | int ret; 41 | 42 | kmscon_text_pixman_ops.owner = KMSCON_THIS_MODULE; 43 | ret = kmscon_text_register(&kmscon_text_pixman_ops); 44 | if (ret) { 45 | log_error("cannot register pixman renderer"); 46 | return ret; 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | static void kmscon_pixman_unload(void) 53 | { 54 | kmscon_text_unregister(kmscon_text_pixman_ops.name); 55 | } 56 | 57 | KMSCON_MODULE(NULL, kmscon_pixman_load, kmscon_pixman_unload, NULL); 58 | -------------------------------------------------------------------------------- /src/kmscon_mod_unifont.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Unifont font backend module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Unifont font backend module 28 | * This module registers the unifont font backend with kmscon. 29 | */ 30 | 31 | #include 32 | #include 33 | #include "font.h" 34 | #include "kmscon_module_interface.h" 35 | #include "shl_log.h" 36 | 37 | #define LOG_SUBSYSTEM "mod_unifont" 38 | 39 | static int kmscon_unifont_load(void) 40 | { 41 | int ret; 42 | 43 | kmscon_font_unifont_ops.owner = KMSCON_THIS_MODULE; 44 | ret = kmscon_font_register(&kmscon_font_unifont_ops); 45 | if (ret) { 46 | log_error("cannot register pango font"); 47 | return ret; 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | static void kmscon_unifont_unload(void) 54 | { 55 | kmscon_font_unregister(kmscon_font_unifont_ops.name); 56 | } 57 | 58 | KMSCON_MODULE(NULL, kmscon_unifont_load, kmscon_unifont_unload, NULL); 59 | -------------------------------------------------------------------------------- /src/kmscon_module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Module handling 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Module Handling 28 | * Several subsystems of kmscon provide a generic interface that is implemented 29 | * by different backends. The user can choose a backend that is then used. 30 | * To make out-of-tree development easier and, more importantly, to reduce the 31 | * direct dependencies to external libraries, this subsystem implements a 32 | * dynamically-loadable module system. 33 | * 34 | * Modules can be loaded and unloaded during runtime. A module basically 35 | * provides memory-storage for code. As long as any code of a module is still 36 | * used (that is, registered as callback) we must not unload the module. 37 | * Therefore, we use reference-counting to allow other subsystems to acquire and 38 | * release code sections. 39 | * 40 | * A module needs to provide "module_init". Everything else is optional. 41 | * "module_init" is called after the module has been loaded and should 42 | * initialize the module. "module_exit" is called after the module has been 43 | * unloaded and the last reference to the module has been dropped. Therefore, it 44 | * is safe to release all allocated resources in "module_exit". 45 | * 46 | * "module_load" is called after "module_init". A module should register its 47 | * resources here. "module_unload" is called when the module is scheduled for 48 | * removal. A module should unregister its resources here. However, it must not 49 | * release the resources as there might still be users of it. Only when 50 | * "module_exit" is called, kmscon guarantees that there are no more users and 51 | * the module can release its resources. 52 | */ 53 | 54 | #ifndef KMSCON_MODULE_H 55 | #define KMSCON_MODULE_H 56 | 57 | #include 58 | 59 | struct kmscon_module; 60 | 61 | int kmscon_module_open(struct kmscon_module **out, const char *file); 62 | void kmscon_module_ref(struct kmscon_module *module); 63 | void kmscon_module_unref(struct kmscon_module *module); 64 | 65 | int kmscon_module_load(struct kmscon_module *module); 66 | void kmscon_module_unload(struct kmscon_module *module); 67 | 68 | void kmscon_load_modules(void); 69 | void kmscon_unload_modules(void); 70 | 71 | #endif /* KMSCON_MODULE_H */ 72 | -------------------------------------------------------------------------------- /src/kmscon_module_interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Module Interface 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Public Module Interface 28 | */ 29 | 30 | #ifndef KMSCON_MODULE_INTERFACE_H 31 | #define KMSCON_MODULE_INTERFACE_H 32 | 33 | #include 34 | #include 35 | #include "kmscon_module.h" 36 | #include "shl_dlist.h" 37 | #include "shl_githead.h" 38 | #include "shl_misc.h" 39 | 40 | struct kmscon_module_info { 41 | const char *githead; 42 | const char *date; 43 | const char *time; 44 | int (*init) (void); 45 | int (*load) (void); 46 | void (*unload) (void); 47 | void (*exit) (void); 48 | }; 49 | 50 | struct kmscon_module { 51 | struct kmscon_module_info info; 52 | struct shl_dlist list; 53 | unsigned long ref; 54 | bool loaded; 55 | void *handle; 56 | char *file; 57 | }; 58 | 59 | #define KMSCON_MODULE(_init, _load, _unload, _exit) \ 60 | struct kmscon_module module = { \ 61 | .info = { \ 62 | .githead = shl_git_head, \ 63 | .date = __DATE__, \ 64 | .time = __TIME__, \ 65 | .init = _init, \ 66 | .load = _load, \ 67 | .unload = _unload, \ 68 | .exit = _exit, \ 69 | }, \ 70 | }; 71 | 72 | SHL_EXPORT 73 | extern struct kmscon_module module; 74 | #define KMSCON_THIS_MODULE (&module) 75 | 76 | #endif /* KMSCON_MODULE_INTERFACE_H */ 77 | -------------------------------------------------------------------------------- /src/kmscon_mouse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Mouse 3 | * 4 | * Copyright (c) 2023 Mirco Müller 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Mouse 28 | * 29 | * Support for mouse/pointer-devices (usb-mice, trackpoints, 30 | * trackpads etc.) and text copy&paste à la gpm is implemented here. 31 | * 32 | * You can get x- and y-coordinates (in character-cells) and check if 33 | * LMB, MMB or RMB are up, down, pressed or released. You can also check 34 | * for single- or double-click of LMB, MMB or RMB. 35 | * 36 | * There should only ever be one kmscon_mouse_info structure be 37 | * created via kmscon_mouse_init() in all of kmscon. It will handle 38 | * everything that's plugged into the system via the Linux kernels 39 | * input sub-system. 40 | * 41 | * It is written in a way to be easy to read and understand, not waste 42 | * cpu-cycles and just support enough features in order to implement 43 | * gpm-like cursor- and copy&paste-functionality. Take note that scroll- 44 | * -wheels are currently NOT supported. 45 | * 46 | * Do not use this in a general UI-toolkit manner like mouse-support in 47 | * Qt, gtk+ or the like. 48 | */ 49 | 50 | #ifndef KMSCON_MOUSE_H 51 | #define KMSCON_MOUSE_H 52 | 53 | #include 54 | #include 55 | #include 56 | 57 | #include "eloop.h" 58 | 59 | #define MAX_DEVNAME_SIZE 16 60 | #define DEVNAME_TEMPLATE "/dev/input/mice" 61 | #define BUTTON_MASK_LEFT 0x01 62 | #define BUTTON_MASK_RIGHT 0x02 63 | #define BUTTON_MASK_MIDDLE 0x04 64 | #define MOTION_SCALE 2 65 | #define BUFFER_SIZE 3 66 | 67 | #define KMSCON_MOUSE_BUTTON_LEFT 0 68 | #define KMSCON_MOUSE_BUTTON_MIDDLE 1 69 | #define KMSCON_MOUSE_BUTTON_RIGHT 2 70 | 71 | typedef enum { 72 | KMSCON_MOUSE_BUTTON_UNDEFINED = -1, 73 | KMSCON_MOUSE_BUTTON_PRESSED = 0, 74 | KMSCON_MOUSE_BUTTON_RELEASED = 1, 75 | KMSCON_MOUSE_BUTTON_DOWN = 2, 76 | KMSCON_MOUSE_BUTTON_UP = 3 77 | } kmscon_mouse_button_state; 78 | 79 | struct kmscon_selection_info { 80 | char* buffer; 81 | int buffer_length; 82 | }; 83 | 84 | struct kmscon_mouse_info { 85 | struct kmscon_selection_info* selection; 86 | 87 | struct ev_timer* query_timer; 88 | struct itimerspec query_timer_spec; 89 | 90 | struct ev_timer* hide_timer; 91 | struct itimerspec hide_timer_spec; 92 | 93 | int device; 94 | float x; 95 | float y; 96 | int hide; 97 | 98 | kmscon_mouse_button_state state[3]; 99 | int clicked[3]; 100 | int dbl_clicked[3]; 101 | 102 | struct timeval last_up; 103 | struct timeval last_down; 104 | struct timeval click; 105 | 106 | struct uterm_display* disp; 107 | struct kmscon_text* txt; 108 | struct kmscon_seat* seat; 109 | }; 110 | 111 | struct kmscon_mouse_info* kmscon_mouse_init(struct ev_eloop* eloop, 112 | struct kmscon_seat* seat); 113 | void kmscon_mouse_cleanup(struct kmscon_mouse_info* mouse); 114 | 115 | void kmscon_mouse_set_mapping(struct kmscon_mouse_info* mouse, 116 | struct uterm_display* disp, 117 | struct kmscon_text* txt); 118 | 119 | int kmscon_mouse_get_x(struct kmscon_mouse_info* mouse); 120 | int kmscon_mouse_get_y(struct kmscon_mouse_info* mouse); 121 | 122 | int kmscon_mouse_is_clicked(struct kmscon_mouse_info* mouse, int button); 123 | void kmscon_mouse_clear_clicked(struct kmscon_mouse_info* mouse, int button); 124 | int kmscon_mouse_is_dbl_clicked(struct kmscon_mouse_info* mouse, int button); 125 | void kmscon_mouse_clear_dbl_clicked(struct kmscon_mouse_info* mouse, int button); 126 | 127 | int kmscon_mouse_is_up(struct kmscon_mouse_info* mouse, int button); 128 | int kmscon_mouse_is_down(struct kmscon_mouse_info* mouse, int button); 129 | int kmscon_mouse_is_released(struct kmscon_mouse_info* mouse, int button); 130 | int kmscon_mouse_is_pressed(struct kmscon_mouse_info* mouse, int button); 131 | int kmscon_mouse_is_hidden(struct kmscon_mouse_info* mouse); 132 | 133 | void kmscon_mouse_selection_copy(struct kmscon_mouse_info* mouse, 134 | struct tsm_screen *console); 135 | 136 | int kmscon_mouse_is_selection_empty(struct kmscon_mouse_info* mouse); 137 | 138 | #endif /* KMSCON_MOUSE_H */ 139 | -------------------------------------------------------------------------------- /src/kmscon_seat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Seats 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Seats 28 | * A seat is a single session that is self-hosting and provides all the 29 | * interaction for a single logged-in user. 30 | */ 31 | 32 | #ifndef KMSCON_SEAT_H 33 | #define KMSCON_SEAT_H 34 | 35 | #include 36 | #include 37 | #include 38 | #include "kmscon_mouse.h" 39 | #include "conf.h" 40 | #include "eloop.h" 41 | #include "uterm_input.h" 42 | #include "uterm_video.h" 43 | #include "uterm_vt.h" 44 | 45 | struct kmscon_seat; 46 | struct kmscon_session; 47 | 48 | enum kmscon_seat_event { 49 | KMSCON_SEAT_WAKE_UP, 50 | KMSCON_SEAT_SLEEP, 51 | KMSCON_SEAT_BACKGROUND, 52 | KMSCON_SEAT_FOREGROUND, 53 | KMSCON_SEAT_HUP, 54 | }; 55 | 56 | typedef int (*kmscon_seat_cb_t) (struct kmscon_seat *seat, 57 | unsigned int event, 58 | void *data); 59 | 60 | enum kmscon_session_event_type { 61 | KMSCON_SESSION_DISPLAY_NEW, 62 | KMSCON_SESSION_DISPLAY_GONE, 63 | KMSCON_SESSION_DISPLAY_REFRESH, 64 | KMSCON_SESSION_ACTIVATE, 65 | KMSCON_SESSION_DEACTIVATE, 66 | KMSCON_SESSION_UNREGISTER, 67 | }; 68 | 69 | struct kmscon_session_event { 70 | unsigned int type; 71 | struct uterm_display *disp; 72 | }; 73 | 74 | typedef int (*kmscon_session_cb_t) (struct kmscon_session *session, 75 | struct kmscon_session_event *event, 76 | void *data); 77 | 78 | int kmscon_seat_new(struct kmscon_seat **out, 79 | struct conf_ctx *main_conf, 80 | struct ev_eloop *eloop, 81 | struct uterm_vt_master *vtm, 82 | unsigned int vt_types, 83 | const char *seatname, 84 | kmscon_seat_cb_t cb, 85 | void *data); 86 | void kmscon_seat_free(struct kmscon_seat *seat); 87 | void kmscon_seat_startup(struct kmscon_seat *seat); 88 | 89 | int kmscon_seat_add_display(struct kmscon_seat *seat, 90 | struct uterm_display *disp); 91 | void kmscon_seat_remove_display(struct kmscon_seat *seat, 92 | struct uterm_display *disp); 93 | void kmscon_seat_refresh_display(struct kmscon_seat *seat, 94 | struct uterm_display *disp); 95 | int kmscon_seat_add_input(struct kmscon_seat *seat, const char *node); 96 | void kmscon_seat_remove_input(struct kmscon_seat *seat, const char *node); 97 | 98 | const char *kmscon_seat_get_name(struct kmscon_seat *seat); 99 | struct uterm_input *kmscon_seat_get_input(struct kmscon_seat *seat); 100 | struct ev_eloop *kmscon_seat_get_eloop(struct kmscon_seat *seat); 101 | struct conf_ctx *kmscon_seat_get_conf(struct kmscon_seat *seat); 102 | 103 | struct kmscon_mouse_info *kmscon_seat_get_mouse(struct kmscon_seat *seat); 104 | struct shl_dlist kmscon_seat_get_displays(struct kmscon_seat *seat); 105 | 106 | void kmscon_seat_schedule(struct kmscon_seat *seat, unsigned int id); 107 | 108 | int kmscon_seat_register_session(struct kmscon_seat *seat, 109 | struct kmscon_session **out, 110 | kmscon_session_cb_t cb, 111 | void *data); 112 | 113 | void kmscon_session_ref(struct kmscon_session *sess); 114 | void kmscon_session_unref(struct kmscon_session *sess); 115 | void kmscon_session_unregister(struct kmscon_session *sess); 116 | bool kmscon_session_is_registered(struct kmscon_session *sess); 117 | 118 | bool kmscon_session_is_active(struct kmscon_session *sess); 119 | int kmscon_session_set_foreground(struct kmscon_session *sess); 120 | int kmscon_session_set_background(struct kmscon_session *sess); 121 | void kmscon_session_schedule(struct kmscon_session *sess); 122 | 123 | void kmscon_session_enable(struct kmscon_session *sess); 124 | void kmscon_session_disable(struct kmscon_session *sess); 125 | bool kmscon_session_is_enabled(struct kmscon_session *sess); 126 | 127 | void kmscon_session_notify_deactivated(struct kmscon_session *sess); 128 | 129 | #endif /* KMSCON_SEAT_H */ 130 | -------------------------------------------------------------------------------- /src/kmscon_terminal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Terminal 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Terminal 29 | * This provides the basic terminal object. This ties together the vt emulation 30 | * and the output console. 31 | */ 32 | 33 | #ifndef KMSCON_TERMINAL_H 34 | #define KMSCON_TERMINAL_H 35 | 36 | #include 37 | #include 38 | #include "kmscon_seat.h" 39 | 40 | #ifdef BUILD_ENABLE_SESSION_TERMINAL 41 | 42 | int kmscon_terminal_register(struct kmscon_session **out, 43 | struct kmscon_seat *seat, 44 | unsigned int vtnr); 45 | 46 | #else /* !BUILD_ENABLE_SESSION_TERMINAL */ 47 | 48 | static inline int kmscon_terminal_register(struct kmscon_session **out, 49 | struct kmscon_seat *seat, 50 | unsigned int vtnr) 51 | { 52 | return -EOPNOTSUPP; 53 | } 54 | 55 | #endif /* BUILD_ENABLE_SESSION_TERMINAL */ 56 | 57 | #endif /* KMSCON_TERMINAL_H */ 58 | -------------------------------------------------------------------------------- /src/mouse_pointer.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Fragment Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Fragment Shader 29 | * A basic fragment shader for drawing a simple mouse-pointer. 30 | */ 31 | 32 | precision mediump float; 33 | 34 | uniform vec4 color; 35 | 36 | void main() 37 | { 38 | gl_FragColor = vec4(color); 39 | } -------------------------------------------------------------------------------- /src/mouse_pointer.vert: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Vertex Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Vertex Shader 29 | * A basic vertex shader for drawing a simple mouse-pointer. 30 | */ 31 | 32 | uniform mat4 projection; 33 | uniform float orientation; 34 | uniform vec2 offset; 35 | 36 | attribute vec2 position; 37 | 38 | vec2 opRotate(in vec2 p, in float degrees) 39 | { 40 | float rad = radians(degrees); 41 | float c = cos(rad); 42 | float s = sin(rad); 43 | return p * mat2(vec2(c, s), vec2(-s, c)); 44 | } 45 | 46 | void main() 47 | { 48 | vec2 rotatedPosition = opRotate(position + offset, orientation); 49 | gl_Position = projection * vec4(rotatedPosition, 0.0, 1.0); 50 | } -------------------------------------------------------------------------------- /src/pty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Pseudo Terminal Handling 3 | * 4 | * Copyright (c) 2012 Ran Benita 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * The pty object provides an interface for communicating with a child process 28 | * over a pseudo terminal. The child is the host, we act as the TTY terminal, 29 | * and the kernel is the driver. 30 | * 31 | * To use this, create a new pty object and open it. You will start receiving 32 | * output notifications through the output_cb callback. To communicate with 33 | * the other end of the terminal, use the kmscon_pty_input method. All 34 | * communication is done using byte streams (presumably UTF-8). 35 | * 36 | * The pty can be closed voluntarily using the kmson_pty_close method. The 37 | * child process can also exit at will; this will be communicated through the 38 | * input callback. The pty object does not wait on the child processes it 39 | * spawns; this is the responsibility of the object's user. 40 | */ 41 | 42 | #ifndef KMSCON_PTY_H 43 | #define KMSCON_PTY_H 44 | 45 | #include 46 | #include 47 | 48 | struct kmscon_pty; 49 | 50 | typedef void (*kmscon_pty_input_cb) 51 | (struct kmscon_pty *pty, const char *u8, size_t len, void *data); 52 | 53 | int kmscon_pty_new(struct kmscon_pty **out, kmscon_pty_input_cb input_cb, 54 | void *data); 55 | void kmscon_pty_ref(struct kmscon_pty *pty); 56 | void kmscon_pty_unref(struct kmscon_pty *pty); 57 | int kmscon_pty_set_term(struct kmscon_pty *pty, const char *term); 58 | int kmscon_pty_set_colorterm(struct kmscon_pty *pty, const char *colorterm); 59 | int kmscon_pty_set_argv(struct kmscon_pty *pty, char **argv); 60 | int kmscon_pty_set_seat(struct kmscon_pty *pty, const char *seat); 61 | int kmscon_pty_set_vtnr(struct kmscon_pty *pty, unsigned int vtnr); 62 | void kmscon_pty_set_env_reset(struct kmscon_pty *pty, bool do_reset); 63 | 64 | int kmscon_pty_get_fd(struct kmscon_pty *pty); 65 | void kmscon_pty_dispatch(struct kmscon_pty *pty); 66 | 67 | int kmscon_pty_open(struct kmscon_pty *pty, unsigned short width, 68 | unsigned short height); 69 | void kmscon_pty_close(struct kmscon_pty *pty); 70 | 71 | int kmscon_pty_write(struct kmscon_pty *pty, const char *u8, size_t len); 72 | void kmscon_pty_signal(struct kmscon_pty *pty, int signum); 73 | void kmscon_pty_resize(struct kmscon_pty *pty, 74 | unsigned short width, unsigned short height); 75 | 76 | #endif /* KMSCON_PTY_H */ 77 | -------------------------------------------------------------------------------- /src/shl_array.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - Dynamic Array 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * A dynamic array implementation 29 | */ 30 | 31 | #ifndef SHL_ARRAY_H 32 | #define SHL_ARRAY_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "shl_misc.h" 39 | 40 | struct shl_array { 41 | size_t element_size; 42 | size_t length; 43 | size_t size; 44 | void *data; 45 | }; 46 | 47 | #define SHL_ARRAY_AT(_arr, _type, _pos) \ 48 | (&((_type*)shl_array_get_array(_arr))[(_pos)]) 49 | 50 | static inline int shl_array_new(struct shl_array **out, size_t element_size, 51 | size_t initial_size) 52 | { 53 | struct shl_array *arr; 54 | 55 | if (!out || !element_size) 56 | return -EINVAL; 57 | 58 | if (!initial_size) 59 | initial_size = 4; 60 | 61 | arr = malloc(sizeof(*arr)); 62 | if (!arr) 63 | return -ENOMEM; 64 | memset(arr, 0, sizeof(*arr)); 65 | arr->element_size = element_size; 66 | arr->length = 0; 67 | arr->size = initial_size; 68 | 69 | arr->data = malloc(arr->element_size * arr->size); 70 | if (!arr->data) { 71 | free(arr); 72 | return -ENOMEM; 73 | } 74 | 75 | *out = arr; 76 | return 0; 77 | } 78 | 79 | static inline void shl_array_free(struct shl_array *arr) 80 | { 81 | if (!arr) 82 | return; 83 | 84 | free(arr->data); 85 | free(arr); 86 | } 87 | 88 | /* resize to length=size and zero out new array entries */ 89 | static inline int shl_array_zresize(struct shl_array *arr, size_t size) 90 | { 91 | void *tmp; 92 | size_t newsize; 93 | 94 | if (!arr) 95 | return -EINVAL; 96 | 97 | if (size > arr->size) { 98 | newsize = shl_next_pow2(size); 99 | tmp = realloc(arr->data, arr->element_size * newsize); 100 | if (!tmp) 101 | return -ENOMEM; 102 | 103 | arr->data = tmp; 104 | arr->size = newsize; 105 | 106 | memset(((uint8_t*)arr->data) + arr->element_size * arr->length, 107 | 0, arr->element_size * (size - arr->length)); 108 | } 109 | 110 | arr->length = size; 111 | return 0; 112 | } 113 | 114 | static inline int shl_array_push(struct shl_array *arr, const void *data) 115 | { 116 | void *tmp; 117 | size_t newsize; 118 | 119 | if (!arr || !data) 120 | return -EINVAL; 121 | 122 | if (arr->length >= arr->size) { 123 | newsize = arr->size * 2; 124 | tmp = realloc(arr->data, arr->element_size * newsize); 125 | if (!tmp) 126 | return -ENOMEM; 127 | 128 | arr->data = tmp; 129 | arr->size = newsize; 130 | } 131 | 132 | memcpy(((uint8_t*)arr->data) + arr->element_size * arr->length, 133 | data, arr->element_size); 134 | ++arr->length; 135 | 136 | return 0; 137 | } 138 | 139 | static inline void shl_array_pop(struct shl_array *arr) 140 | { 141 | if (!arr || !arr->length) 142 | return; 143 | 144 | --arr->length; 145 | } 146 | 147 | static inline void *shl_array_get_array(struct shl_array *arr) 148 | { 149 | if (!arr) 150 | return NULL; 151 | 152 | return arr->data; 153 | } 154 | 155 | static inline size_t shl_array_get_length(struct shl_array *arr) 156 | { 157 | if (!arr) 158 | return 0; 159 | 160 | return arr->length; 161 | } 162 | 163 | static inline size_t shl_array_get_bsize(struct shl_array *arr) 164 | { 165 | if (!arr) 166 | return 0; 167 | 168 | return arr->length * arr->element_size; 169 | } 170 | 171 | static inline size_t shl_array_get_element_size(struct shl_array *arr) 172 | { 173 | if (!arr) 174 | return 0; 175 | 176 | return arr->element_size; 177 | } 178 | 179 | #endif /* SHL_ARRAY_H */ 180 | -------------------------------------------------------------------------------- /src/shl_dlist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - Double Linked List 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * A simple double linked list implementation 29 | */ 30 | 31 | #ifndef SHL_DLIST_H 32 | #define SHL_DLIST_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | /* miscellaneous */ 40 | 41 | #define shl_offsetof(pointer, type, member) ({ \ 42 | const typeof(((type*)0)->member) *__ptr = (pointer); \ 43 | (type*)(((char*)__ptr) - offsetof(type, member)); \ 44 | }) 45 | 46 | /* double linked list */ 47 | 48 | struct shl_dlist { 49 | struct shl_dlist *next; 50 | struct shl_dlist *prev; 51 | }; 52 | 53 | #define SHL_DLIST_INIT(head) { &(head), &(head) } 54 | 55 | static inline void shl_dlist_init(struct shl_dlist *list) 56 | { 57 | list->next = list; 58 | list->prev = list; 59 | } 60 | 61 | static inline void shl_dlist__link(struct shl_dlist *prev, 62 | struct shl_dlist *next, 63 | struct shl_dlist *n) 64 | { 65 | next->prev = n; 66 | n->next = next; 67 | n->prev = prev; 68 | prev->next = n; 69 | } 70 | 71 | static inline void shl_dlist_link(struct shl_dlist *head, 72 | struct shl_dlist *n) 73 | { 74 | return shl_dlist__link(head, head->next, n); 75 | } 76 | 77 | static inline void shl_dlist_link_tail(struct shl_dlist *head, 78 | struct shl_dlist *n) 79 | { 80 | return shl_dlist__link(head->prev, head, n); 81 | } 82 | 83 | static inline void shl_dlist__unlink(struct shl_dlist *prev, 84 | struct shl_dlist *next) 85 | { 86 | next->prev = prev; 87 | prev->next = next; 88 | } 89 | 90 | static inline void shl_dlist_unlink(struct shl_dlist *e) 91 | { 92 | shl_dlist__unlink(e->prev, e->next); 93 | e->prev = NULL; 94 | e->next = NULL; 95 | } 96 | 97 | static inline bool shl_dlist_empty(struct shl_dlist *head) 98 | { 99 | return head->next == head; 100 | } 101 | 102 | #define shl_dlist_entry(ptr, type, member) \ 103 | shl_offsetof((ptr), type, member) 104 | 105 | #define shl_dlist_first(head, type, member) \ 106 | shl_dlist_entry((head)->next, type, member) 107 | 108 | #define shl_dlist_last(head, type, member) \ 109 | shl_dlist_entry((head)->prev, type, member) 110 | 111 | #define shl_dlist_for_each(iter, head) \ 112 | for (iter = (head)->next; iter != (head); iter = iter->next) 113 | 114 | #define shl_dlist_for_each_but_one(iter, start, head) \ 115 | for (iter = ((start)->next == (head)) ? \ 116 | (start)->next->next : \ 117 | (start)->next; \ 118 | iter != (start); \ 119 | iter = (iter->next == (head) && (start) != (head)) ? \ 120 | iter->next->next : \ 121 | iter->next) 122 | 123 | #define shl_dlist_for_each_safe(iter, tmp, head) \ 124 | for (iter = (head)->next, tmp = iter->next; iter != (head); \ 125 | iter = tmp, tmp = iter->next) 126 | 127 | #define shl_dlist_for_each_reverse(iter, head) \ 128 | for (iter = (head)->prev; iter != (head); iter = iter->prev) 129 | 130 | #define shl_dlist_for_each_reverse_but_one(iter, start, head) \ 131 | for (iter = ((start)->prev == (head)) ? \ 132 | (start)->prev->prev : \ 133 | (start)->prev; \ 134 | iter != (start); \ 135 | iter = (iter->prev == (head) && (start) != (head)) ? \ 136 | iter->prev->prev : \ 137 | iter->prev) 138 | 139 | #define shl_dlist_for_each_reverse_safe(iter, tmp, head) \ 140 | for (iter = (head)->prev, tmp = iter->prev; iter != (head); \ 141 | iter = tmp, tmp = iter->prev) 142 | 143 | #endif /* SHL_DLIST_H */ 144 | -------------------------------------------------------------------------------- /src/shl_flagset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - Flagset 3 | * 4 | * Copyright (c) 2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * A dynamic flagset implementation 28 | */ 29 | 30 | #ifndef SHL_FLAGSET_H 31 | #define SHL_FLAGSET_H 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "shl_array.h" 39 | #include "shl_misc.h" 40 | 41 | static inline int shl_flagset_new(struct shl_array **out) 42 | { 43 | return shl_array_new(out, sizeof(unsigned long), 1); 44 | } 45 | 46 | static inline void shl_flagset_free(struct shl_array *arr) 47 | { 48 | return shl_array_free(arr); 49 | } 50 | 51 | static inline int shl_flagset_alloc(struct shl_array *arr, unsigned int *out) 52 | { 53 | static const unsigned long one = 1; 54 | unsigned int i, j; 55 | unsigned long *data; 56 | int ret; 57 | 58 | if (!arr) 59 | return -EINVAL; 60 | 61 | for (i = 0; i < arr->length; ++i) { 62 | data = SHL_ARRAY_AT(arr, unsigned long, i); 63 | for (j = 0; j < SHL_ULONG_BITS; ++j) { 64 | if (!(*data & (1UL << j))) { 65 | *data |= 1UL << j; 66 | *out = i * SHL_ULONG_BITS + j; 67 | return 0; 68 | } 69 | } 70 | } 71 | 72 | ret = shl_array_push(arr, &one); 73 | if (ret) 74 | return ret; 75 | 76 | *out = (arr->length - 1) * SHL_ULONG_BITS; 77 | return 0; 78 | } 79 | 80 | static inline int shl_flagset_reserve(struct shl_array *arr, unsigned int num) 81 | { 82 | int ret; 83 | unsigned int idx, off; 84 | unsigned long *data; 85 | 86 | if (!arr) 87 | return -EINVAL; 88 | 89 | idx = num / SHL_ULONG_BITS; 90 | off = num % SHL_ULONG_BITS; 91 | 92 | if (idx >= arr->length) { 93 | ret = shl_array_zresize(arr, idx + 1); 94 | if (ret) 95 | return ret; 96 | } 97 | 98 | data = SHL_ARRAY_AT(arr, unsigned long, idx); 99 | if (*data & (1UL << off)) 100 | return -EEXIST; 101 | 102 | *data |= 1UL << off; 103 | return 0; 104 | } 105 | 106 | static inline int shl_flagset_set(struct shl_array *arr, unsigned int num) 107 | { 108 | int ret; 109 | 110 | ret = shl_flagset_reserve(arr, num); 111 | if (ret == -EEXIST) 112 | return 0; 113 | 114 | return ret; 115 | } 116 | 117 | static inline void shl_flagset_unset(struct shl_array *arr, unsigned int num) 118 | { 119 | unsigned int idx, off; 120 | unsigned long *data; 121 | 122 | if (!arr) 123 | return; 124 | 125 | idx = num / SHL_ULONG_BITS; 126 | off = num % SHL_ULONG_BITS; 127 | 128 | if (idx >= arr->length) 129 | return; 130 | 131 | data = SHL_ARRAY_AT(arr, unsigned long, idx); 132 | *data &= ~(1UL << off); 133 | } 134 | 135 | #endif /* SHL_FLAGSET_H */ 136 | -------------------------------------------------------------------------------- /src/shl_githead.c.in: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022 Aetf 3 | * 4 | * SPDX-License-Identifier: MIT 5 | */ 6 | 7 | const char shl_git_head[] = "@VCS_TAG@"; 8 | -------------------------------------------------------------------------------- /src/shl_githead.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - GIT-HEAD 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef SHL_GITHEAD_H 27 | #define SHL_GITHEAD_H 28 | 29 | extern const char shl_git_head[]; 30 | 31 | #endif /* SHL_GITHEAD_H */ 32 | -------------------------------------------------------------------------------- /src/shl_gl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - OpenGL Helpers 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * OpenGL Helpers 28 | * This file provides several helper functions that are commonly used when 29 | * working with OpenGL. 30 | * TODO: Rename to shl_gl_* prefix. 31 | */ 32 | 33 | #ifndef SHL_GL_H 34 | #define SHL_GL_H 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "shl_llog.h" 42 | 43 | /* 44 | * Math Helpers 45 | * The gl_m4 type is a 4x4 matrix of floats. The gl_m4_stack is a stack of m4 46 | * matrices where you can only access the top-most member. 47 | */ 48 | 49 | struct gl_m4_stack; 50 | 51 | void gl_m4_identity(float *m); 52 | void gl_m4_copy(float *dest, const float *src); 53 | void gl_m4_mult_dest(float *dest, const float *n, const float *m); 54 | void gl_m4_mult(float *n, const float *m); 55 | void gl_m4_translate(float *m, float x, float y, float z); 56 | void gl_m4_scale(float *m, float x, float y, float z); 57 | void gl_m4_transpose_dest(float *dest, const float *src); 58 | void gl_m4_transpose(float *m); 59 | 60 | int gl_m4_stack_new(struct gl_m4_stack **out); 61 | void gl_m4_stack_free(struct gl_m4_stack *stack); 62 | float *gl_m4_stack_push(struct gl_m4_stack *stack); 63 | float *gl_m4_stack_pop(struct gl_m4_stack *stack); 64 | float *gl_m4_stack_tip(struct gl_m4_stack *stack); 65 | 66 | /* 67 | * Shader Helpers 68 | * These helpers load, compile and link shaders and allow easy attribute/uniform 69 | * access. 70 | */ 71 | 72 | struct gl_shader; 73 | 74 | int gl_shader_new(struct gl_shader **out, const char *vert, int vert_len, 75 | const char *frag, int frag_len, 76 | char **attr, size_t attr_count, llog_submit_t llog, 77 | void *llog_data); 78 | void gl_shader_ref(struct gl_shader *shader); 79 | void gl_shader_unref(struct gl_shader *shader); 80 | GLuint gl_shader_get_uniform(struct gl_shader *shader, const char *name); 81 | void gl_shader_use(struct gl_shader *shader); 82 | 83 | void gl_tex_new(GLuint *tex, size_t num); 84 | void gl_tex_free(GLuint *tex, size_t num); 85 | void gl_tex_load(GLuint tex, unsigned int width, unsigned int stride, 86 | unsigned int height, uint8_t *buf); 87 | 88 | void gl_clear_error(); 89 | bool gl_has_error(struct gl_shader *shader); 90 | const char *gl_err_to_str(GLenum err); 91 | 92 | #endif /* SHL_GL_H */ 93 | -------------------------------------------------------------------------------- /src/shl_hashtable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - Dynamic Array 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * A dynamic hash table implementation 29 | */ 30 | 31 | #ifndef SHL_HASHTABLE_H 32 | #define SHL_HASHTABLE_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "htable.h" 40 | 41 | struct shl_hashtable; 42 | 43 | typedef unsigned int (*shl_hash_cb) (uint64_t data); 44 | typedef bool (*shl_equal_cb) (uint64_t data1, uint64_t data2); 45 | typedef void (*shl_free_cb) (void *data); 46 | 47 | struct shl_hashentry { 48 | uint64_t key; 49 | void *value; 50 | }; 51 | 52 | struct shl_hashtable { 53 | struct htable tbl; 54 | shl_hash_cb hash_cb; 55 | shl_equal_cb equal_cb; 56 | shl_free_cb free_value; 57 | }; 58 | 59 | static inline unsigned int shl_direct_hash(uint64_t data) 60 | { 61 | return (unsigned int)data; 62 | } 63 | 64 | static inline bool shl_direct_equal(uint64_t data1, uint64_t data2) 65 | { 66 | return data1 == data2; 67 | } 68 | 69 | static size_t shl_rehash(const void *ele, void *priv) 70 | { 71 | struct shl_hashtable *tbl = priv; 72 | const struct shl_hashentry *ent = ele; 73 | 74 | return tbl->hash_cb(ent->key); 75 | } 76 | 77 | static inline int shl_hashtable_new(struct shl_hashtable **out, 78 | shl_hash_cb hash_cb, 79 | shl_equal_cb equal_cb, 80 | shl_free_cb free_value) 81 | { 82 | struct shl_hashtable *tbl; 83 | 84 | if (!out || !hash_cb || !equal_cb) 85 | return -EINVAL; 86 | 87 | tbl = malloc(sizeof(*tbl)); 88 | if (!tbl) 89 | return -ENOMEM; 90 | memset(tbl, 0, sizeof(*tbl)); 91 | tbl->hash_cb = hash_cb; 92 | tbl->equal_cb = equal_cb; 93 | tbl->free_value = free_value; 94 | 95 | htable_init(&tbl->tbl, shl_rehash, tbl); 96 | 97 | *out = tbl; 98 | return 0; 99 | } 100 | 101 | static inline void shl_hashtable_free(struct shl_hashtable *tbl) 102 | { 103 | struct htable_iter i; 104 | struct shl_hashentry *entry; 105 | 106 | if (!tbl) 107 | return; 108 | 109 | for (entry = htable_first(&tbl->tbl, &i); 110 | entry; 111 | entry = htable_next(&tbl->tbl, &i)) { 112 | htable_delval(&tbl->tbl, &i); 113 | if (tbl->free_value) 114 | tbl->free_value(entry->value); 115 | free(entry); 116 | } 117 | 118 | htable_clear(&tbl->tbl); 119 | free(tbl); 120 | } 121 | 122 | static inline int shl_hashtable_insert(struct shl_hashtable *tbl, uint64_t key, 123 | void *value) 124 | { 125 | struct shl_hashentry *entry; 126 | size_t hash; 127 | 128 | if (!tbl) 129 | return -EINVAL; 130 | 131 | entry = malloc(sizeof(*entry)); 132 | if (!entry) 133 | return -ENOMEM; 134 | entry->key = key; 135 | entry->value = value; 136 | 137 | hash = tbl->hash_cb(key); 138 | 139 | if (!htable_add(&tbl->tbl, hash, entry)) { 140 | free(entry); 141 | return -ENOMEM; 142 | } 143 | 144 | return 0; 145 | } 146 | 147 | static inline void shl_hashtable_remove(struct shl_hashtable *tbl, uint64_t key) 148 | { 149 | struct htable_iter i; 150 | struct shl_hashentry *entry; 151 | size_t hash; 152 | 153 | if (!tbl) 154 | return; 155 | 156 | hash = tbl->hash_cb(key); 157 | 158 | for (entry = htable_firstval(&tbl->tbl, &i, hash); 159 | entry; 160 | entry = htable_nextval(&tbl->tbl, &i, hash)) { 161 | if (tbl->equal_cb(key, entry->key)) { 162 | htable_delval(&tbl->tbl, &i); 163 | return; 164 | } 165 | } 166 | } 167 | 168 | static inline bool shl_hashtable_find(struct shl_hashtable *tbl, void **out, 169 | uint64_t key) 170 | { 171 | struct htable_iter i; 172 | struct shl_hashentry *entry; 173 | size_t hash; 174 | 175 | if (!tbl) 176 | return false; 177 | 178 | hash = tbl->hash_cb(key); 179 | 180 | for (entry = htable_firstval(&tbl->tbl, &i, hash); 181 | entry; 182 | entry = htable_nextval(&tbl->tbl, &i, hash)) { 183 | if (tbl->equal_cb(key, entry->key)) { 184 | if (out) 185 | *out = entry->value; 186 | return true; 187 | } 188 | } 189 | 190 | return false; 191 | } 192 | 193 | #endif /* SHL_HASHTABLE_H */ 194 | -------------------------------------------------------------------------------- /src/shl_hook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - Hook Handling 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Simply hook-implementation 29 | */ 30 | 31 | #ifndef SHL_HOOK_H 32 | #define SHL_HOOK_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "shl_dlist.h" 41 | 42 | struct shl_hook; 43 | struct shl_hook_entry; 44 | typedef void (*shl_hook_cb) (void *parent, void *arg, void *data); 45 | 46 | #define shl_hook_add_cast(hook, cb, data, oneshot) \ 47 | shl_hook_add((hook), (shl_hook_cb)(cb), (data), (oneshot)) 48 | #define shl_hook_add_single_cast(hook, cb, data, oneshot) \ 49 | shl_hook_add_single((hook), (shl_hook_cb)(cb), (data), (oneshot)) 50 | #define shl_hook_rm_cast(hook, cb, data) \ 51 | shl_hook_rm((hook), (shl_hook_cb)(cb), (data)) 52 | #define shl_hook_rm_all_cast(hook, cb, data) \ 53 | shl_hook_rm_all((hook), (shl_hook_cb)(cb), (data)) 54 | 55 | struct shl_hook_entry { 56 | struct shl_dlist list; 57 | shl_hook_cb cb; 58 | void *data; 59 | bool oneshot; 60 | }; 61 | 62 | struct shl_hook { 63 | unsigned int num; 64 | struct shl_dlist entries; 65 | struct shl_dlist *cur_entry; 66 | bool dead; 67 | }; 68 | 69 | static inline int shl_hook_new(struct shl_hook **out) 70 | { 71 | struct shl_hook *hook; 72 | 73 | if (!out) 74 | return -EINVAL; 75 | 76 | hook = malloc(sizeof(*hook)); 77 | if (!hook) 78 | return -ENOMEM; 79 | memset(hook, 0, sizeof(*hook)); 80 | shl_dlist_init(&hook->entries); 81 | 82 | *out = hook; 83 | return 0; 84 | } 85 | 86 | static inline void shl_hook_free(struct shl_hook *hook) 87 | { 88 | struct shl_hook_entry *entry; 89 | 90 | if (!hook) 91 | return; 92 | 93 | if (hook->cur_entry) { 94 | hook->dead = true; 95 | return; 96 | } 97 | 98 | while (!shl_dlist_empty(&hook->entries)) { 99 | entry = shl_dlist_entry(hook->entries.prev, 100 | struct shl_hook_entry, 101 | list); 102 | shl_dlist_unlink(&entry->list); 103 | free(entry); 104 | } 105 | 106 | free(hook); 107 | } 108 | 109 | static inline unsigned int shl_hook_num(struct shl_hook *hook) 110 | { 111 | if (!hook) 112 | return 0; 113 | 114 | return hook->num; 115 | } 116 | 117 | static inline int shl_hook_add(struct shl_hook *hook, shl_hook_cb cb, 118 | void *data, bool oneshot) 119 | { 120 | struct shl_hook_entry *entry; 121 | 122 | if (!hook || !cb) 123 | return -EINVAL; 124 | 125 | entry = malloc(sizeof(*entry)); 126 | if (!entry) 127 | return -ENOMEM; 128 | memset(entry, 0, sizeof(*entry)); 129 | entry->cb = cb; 130 | entry->data = data; 131 | entry->oneshot = oneshot; 132 | 133 | shl_dlist_link_tail(&hook->entries, &entry->list); 134 | hook->num++; 135 | return 0; 136 | } 137 | 138 | /* This adds an entry only if it is not already in the list. But notice that if 139 | * the entry is already registered twice or with a different \oneshot flag, the 140 | * list will _not_ be changed! */ 141 | static inline int shl_hook_add_single(struct shl_hook *hook, shl_hook_cb cb, 142 | void *data, bool oneshot) 143 | { 144 | struct shl_hook_entry *entry; 145 | struct shl_dlist *iter; 146 | 147 | if (!hook || !cb) 148 | return -EINVAL; 149 | 150 | shl_dlist_for_each(iter, &hook->entries) { 151 | entry = shl_dlist_entry(iter, struct shl_hook_entry, list); 152 | if (entry->cb == cb && entry->data == data) 153 | return 0; 154 | } 155 | 156 | return shl_hook_add(hook, cb, data, oneshot); 157 | } 158 | 159 | static inline void shl_hook_rm(struct shl_hook *hook, shl_hook_cb cb, 160 | void *data) 161 | { 162 | struct shl_dlist *iter; 163 | struct shl_hook_entry *entry; 164 | 165 | if (!hook || !cb) 166 | return; 167 | 168 | shl_dlist_for_each_reverse(iter, &hook->entries) { 169 | entry = shl_dlist_entry(iter, struct shl_hook_entry, list); 170 | if (entry->cb == cb && entry->data == data) { 171 | /* if *_call() is running we must not disturb it */ 172 | if (hook->cur_entry == iter) 173 | hook->cur_entry = iter->next; 174 | shl_dlist_unlink(&entry->list); 175 | free(entry); 176 | hook->num--; 177 | return; 178 | } 179 | } 180 | } 181 | 182 | static inline void shl_hook_rm_all(struct shl_hook *hook, shl_hook_cb cb, 183 | void *data) 184 | { 185 | struct shl_dlist *iter, *tmp; 186 | struct shl_hook_entry *entry; 187 | 188 | if (!hook || !cb) 189 | return; 190 | 191 | shl_dlist_for_each_reverse_safe(iter, tmp, &hook->entries) { 192 | entry = shl_dlist_entry(iter, struct shl_hook_entry, list); 193 | if (entry->cb == cb && entry->data == data) { 194 | /* if *_call() is running we must not disturb it */ 195 | if (hook->cur_entry == iter) 196 | hook->cur_entry = iter->next; 197 | shl_dlist_unlink(&entry->list); 198 | free(entry); 199 | hook->num--; 200 | } 201 | } 202 | } 203 | 204 | static inline void shl_hook_call(struct shl_hook *hook, void *parent, 205 | void *arg) 206 | { 207 | struct shl_hook_entry *entry; 208 | bool oneshot; 209 | 210 | if (!hook || hook->cur_entry) 211 | return; 212 | 213 | for (hook->cur_entry = hook->entries.next; 214 | hook->cur_entry != &hook->entries; ) { 215 | entry = shl_dlist_entry(hook->cur_entry, 216 | struct shl_hook_entry, list); 217 | hook->cur_entry = entry->list.next; 218 | oneshot = entry->oneshot; 219 | 220 | if (oneshot) 221 | shl_dlist_unlink(&entry->list); 222 | 223 | entry->cb(parent, arg, entry->data); 224 | 225 | if (oneshot) { 226 | free(entry); 227 | --hook->num; 228 | } 229 | } 230 | 231 | hook->cur_entry = NULL; 232 | if (hook->dead) 233 | shl_hook_free(hook); 234 | } 235 | 236 | #endif /* SHL_HOOK_H */ 237 | -------------------------------------------------------------------------------- /src/shl_ring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - Dynamic Array 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * A circular memory ring implementation 29 | */ 30 | 31 | #ifndef SHL_RING_H 32 | #define SHL_RING_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define SHL_RING_SIZE 512 40 | 41 | struct shl_ring_entry { 42 | struct shl_ring_entry *next; 43 | size_t len; 44 | char buf[]; 45 | }; 46 | 47 | struct shl_ring { 48 | struct shl_ring_entry *first; 49 | struct shl_ring_entry *last; 50 | }; 51 | 52 | static inline int shl_ring_new(struct shl_ring **out) 53 | { 54 | struct shl_ring *ring; 55 | 56 | if (!out) 57 | return -EINVAL; 58 | 59 | ring = malloc(sizeof(*ring)); 60 | if (!ring) 61 | return -ENOMEM; 62 | 63 | memset(ring, 0, sizeof(*ring)); 64 | 65 | *out = ring; 66 | return 0; 67 | } 68 | 69 | static inline void shl_ring_free(struct shl_ring *ring) 70 | { 71 | struct shl_ring_entry *tmp; 72 | 73 | if (!ring) 74 | return; 75 | 76 | while (ring->first) { 77 | tmp = ring->first; 78 | ring->first = tmp->next; 79 | free(tmp); 80 | } 81 | free(ring); 82 | } 83 | 84 | static inline bool shl_ring_is_empty(struct shl_ring *ring) 85 | { 86 | if (!ring) 87 | return true; 88 | 89 | return ring->first == NULL; 90 | } 91 | 92 | static inline int shl_ring_write(struct shl_ring *ring, const char *val, 93 | size_t len) 94 | { 95 | struct shl_ring_entry *ent; 96 | size_t space, cp; 97 | 98 | if (!ring || !val || !len) 99 | return -EINVAL; 100 | 101 | next: 102 | ent = ring->last; 103 | if (!ent || ent->len >= SHL_RING_SIZE) { 104 | ent = malloc(sizeof(*ent) + SHL_RING_SIZE); 105 | if (!ent) 106 | return -ENOMEM; 107 | 108 | ent->len = 0; 109 | ent->next = NULL; 110 | if (ring->last) 111 | ring->last->next = ent; 112 | else 113 | ring->first = ent; 114 | ring->last = ent; 115 | } 116 | 117 | space = SHL_RING_SIZE - ent->len; 118 | if (len >= space) 119 | cp = space; 120 | else 121 | cp = len; 122 | 123 | memcpy(&ent->buf[ent->len], val, cp); 124 | ent->len += cp; 125 | 126 | val = &val[cp]; 127 | len -= cp; 128 | if (len > 0) 129 | goto next; 130 | 131 | return 0; 132 | } 133 | 134 | static inline const char *shl_ring_peek(struct shl_ring *ring, size_t *len, 135 | size_t offset) 136 | { 137 | struct shl_ring_entry *iter; 138 | 139 | if (!ring || !ring->first || !len) { 140 | if (len) 141 | *len = 0; 142 | return NULL; 143 | } 144 | 145 | iter = ring->first; 146 | while (iter->len <= offset) { 147 | if (!iter->next) { 148 | *len = 0; 149 | return NULL; 150 | } 151 | 152 | offset -= iter->len; 153 | iter = iter->next; 154 | } 155 | 156 | *len = ring->first->len - offset; 157 | return &ring->first->buf[offset]; 158 | } 159 | 160 | static inline void shl_ring_drop(struct shl_ring *ring, size_t len) 161 | { 162 | struct shl_ring_entry *ent; 163 | 164 | if (!ring || !len) 165 | return; 166 | 167 | next: 168 | ent = ring->first; 169 | if (!ent) 170 | return; 171 | 172 | if (len >= ent->len) { 173 | len -= ent->len; 174 | ring->first = ent->next; 175 | free(ent); 176 | if (!ring->first) 177 | ring->last = NULL; 178 | 179 | if (len) 180 | goto next; 181 | } else { 182 | memmove(ent->buf, &ent->buf[len], ent->len - len); 183 | ent->len -= len; 184 | } 185 | } 186 | 187 | static inline void shl_ring_flush(struct shl_ring *ring) 188 | { 189 | struct shl_ring_entry *tmp; 190 | 191 | if (!ring) 192 | return; 193 | 194 | while (ring->first) { 195 | tmp = ring->first; 196 | ring->first = tmp->next; 197 | free(tmp); 198 | } 199 | ring->last = NULL; 200 | } 201 | 202 | #endif /* SHL_RING_H */ 203 | -------------------------------------------------------------------------------- /src/shl_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * shl - Timers 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Timers 29 | */ 30 | 31 | #ifndef SHL_TIMER_H 32 | #define SHL_TIMER_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | struct shl_timer { 42 | struct timespec start; 43 | uint64_t elapsed; 44 | }; 45 | 46 | static inline void shl_timer_reset(struct shl_timer *timer) 47 | { 48 | if (!timer) 49 | return; 50 | 51 | clock_gettime(CLOCK_MONOTONIC, &timer->start); 52 | timer->elapsed = 0; 53 | } 54 | 55 | static inline int shl_timer_new(struct shl_timer **out) 56 | { 57 | struct shl_timer *timer; 58 | 59 | if (!out) 60 | return -EINVAL; 61 | 62 | timer = malloc(sizeof(*timer)); 63 | if (!timer) 64 | return -ENOMEM; 65 | memset(timer, 0, sizeof(*timer)); 66 | shl_timer_reset(timer); 67 | 68 | *out = timer; 69 | return 0; 70 | } 71 | 72 | static inline void shl_timer_free(struct shl_timer *timer) 73 | { 74 | if (!timer) 75 | return; 76 | 77 | free(timer); 78 | } 79 | 80 | static inline void shl_timer_start(struct shl_timer *timer) 81 | { 82 | if (!timer) 83 | return; 84 | 85 | clock_gettime(CLOCK_MONOTONIC, &timer->start); 86 | } 87 | 88 | static inline uint64_t shl_timer_stop(struct shl_timer *timer) 89 | { 90 | struct timespec spec; 91 | int64_t off, nsec; 92 | 93 | if (!timer) 94 | return 0; 95 | 96 | clock_gettime(CLOCK_MONOTONIC, &spec); 97 | off = spec.tv_sec - timer->start.tv_sec; 98 | nsec = spec.tv_nsec - timer->start.tv_nsec; 99 | if (nsec < 0) { 100 | --off; 101 | nsec += 1000000000ULL; 102 | } 103 | off *= 1000000; 104 | off += nsec / 1000; 105 | 106 | memcpy(&timer->start, &spec, sizeof(spec)); 107 | timer->elapsed += off; 108 | return timer->elapsed; 109 | } 110 | 111 | static inline uint64_t shl_timer_elapsed(struct shl_timer *timer) 112 | { 113 | struct timespec spec; 114 | int64_t off, nsec; 115 | 116 | if (!timer) 117 | return 0; 118 | 119 | clock_gettime(CLOCK_MONOTONIC, &spec); 120 | off = spec.tv_sec - timer->start.tv_sec; 121 | nsec = spec.tv_nsec - timer->start.tv_nsec; 122 | if (nsec < 0) { 123 | --off; 124 | nsec += 1000000000ULL; 125 | } 126 | off *= 1000000; 127 | off += nsec / 1000; 128 | 129 | return timer->elapsed + off; 130 | } 131 | 132 | #endif /* SHL_TIMER_H */ 133 | -------------------------------------------------------------------------------- /src/text.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Text Renderer 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Text Renderer 28 | * The Text-Renderer subsystem provides a simple way to draw text into a 29 | * framebuffer. The system is modular and several different backends are 30 | * available that can be used. 31 | */ 32 | 33 | #ifndef KMSCON_TEXT_H 34 | #define KMSCON_TEXT_H 35 | 36 | #include 37 | #include 38 | #include 39 | #include "font.h" 40 | #include "kmscon_module.h" 41 | #include "uterm_video.h" 42 | 43 | /* text renderer */ 44 | 45 | enum Orientation { 46 | ORIENTATION_UNDEFINED = 0, 47 | ORIENTATION_NORMAL, 48 | ORIENTATION_RIGHT, 49 | ORIENTATION_INVERTED, 50 | ORIENTATION_LEFT, 51 | ORIENTATION_MAX 52 | }; 53 | 54 | struct kmscon_text; 55 | struct kmscon_text_ops; 56 | 57 | struct kmscon_text { 58 | unsigned long ref; 59 | struct shl_register_record *record; 60 | const struct kmscon_text_ops *ops; 61 | void *data; 62 | 63 | struct kmscon_font *font; 64 | struct kmscon_font *bold_font; 65 | struct uterm_display *disp; 66 | unsigned int cols; 67 | unsigned int rows; 68 | bool rendering; 69 | unsigned int orientation; 70 | }; 71 | 72 | struct kmscon_text_ops { 73 | const char *name; 74 | struct kmscon_module *owner; 75 | int (*init) (struct kmscon_text *txt); 76 | void (*destroy) (struct kmscon_text *txt); 77 | int (*set) (struct kmscon_text *txt); 78 | void (*unset) (struct kmscon_text *txt); 79 | int (*rotate) (struct kmscon_text *txt, unsigned int orientation); 80 | int (*prepare) (struct kmscon_text *txt); 81 | int (*draw) (struct kmscon_text *txt, 82 | uint64_t id, const uint32_t *ch, size_t len, 83 | unsigned int width, 84 | unsigned int posx, unsigned int posy, 85 | const struct tsm_screen_attr *attr); 86 | int (*render) (struct kmscon_text *txt); 87 | int (*render_pointer) (struct kmscon_text *txt, int cursor_x, int cursor_y); 88 | void (*abort) (struct kmscon_text *txt); 89 | }; 90 | 91 | int kmscon_text_register(const struct kmscon_text_ops *ops); 92 | void kmscon_text_unregister(const char *name); 93 | 94 | int kmscon_text_new(struct kmscon_text **out, const char *backend, const char *rotate); 95 | void kmscon_text_ref(struct kmscon_text *txt); 96 | void kmscon_text_unref(struct kmscon_text *txt); 97 | 98 | int kmscon_text_set(struct kmscon_text *txt, 99 | struct kmscon_font *font, 100 | struct kmscon_font *bold_font, 101 | struct uterm_display *disp); 102 | void kmscon_text_unset(struct kmscon_text *txt); 103 | unsigned int kmscon_text_get_cols(struct kmscon_text *txt); 104 | unsigned int kmscon_text_get_rows(struct kmscon_text *txt); 105 | 106 | unsigned int kmscon_text_get_orientation(struct kmscon_text *txt); 107 | int kmscon_text_rotate(struct kmscon_text *txt, unsigned int orientation); 108 | 109 | int kmscon_text_prepare(struct kmscon_text *txt); 110 | int kmscon_text_draw(struct kmscon_text *txt, 111 | uint64_t id, const uint32_t *ch, size_t len, 112 | unsigned int width, 113 | unsigned int posx, unsigned int posy, 114 | const struct tsm_screen_attr *attr); 115 | int kmscon_text_render(struct kmscon_text *txt); 116 | int kmscon_text_render_pointer(struct kmscon_text *txt, 117 | int cursor_x, 118 | int cursor_y); 119 | void kmscon_text_abort(struct kmscon_text *txt); 120 | 121 | int kmscon_text_draw_cb(struct tsm_screen *con, 122 | uint64_t id, const uint32_t *ch, size_t len, 123 | unsigned int width, 124 | unsigned int posx, unsigned int posy, 125 | const struct tsm_screen_attr *attr, 126 | tsm_age_t age, void *data); 127 | 128 | /* modularized backends */ 129 | 130 | extern struct kmscon_text_ops kmscon_text_bblit_ops; 131 | extern struct kmscon_text_ops kmscon_text_bbulk_ops; 132 | extern struct kmscon_text_ops kmscon_text_gltex_ops; 133 | extern struct kmscon_text_ops kmscon_text_pixman_ops; 134 | 135 | #endif /* KMSCON_TEXT_H */ 136 | -------------------------------------------------------------------------------- /src/text_bblit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Bit-Blitting Text Renderer Backend 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /** 27 | * SECTION:text_bblit.c 28 | * @short_description: Bit-Blitting Text Renderer Backend 29 | * @include: text.h 30 | * 31 | * The bit-blitting renderer requires framebuffer access to the output device 32 | * and simply blits the glyphs into the buffer. 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "shl_log.h" 40 | #include "text.h" 41 | #include "uterm_video.h" 42 | 43 | #define LOG_SUBSYSTEM "text_bblit" 44 | 45 | static int bblit_set(struct kmscon_text *txt) 46 | { 47 | unsigned int sw, sh, fw, fh; 48 | struct uterm_mode *mode; 49 | 50 | fw = txt->font->attr.width; 51 | fh = txt->font->attr.height; 52 | mode = uterm_display_get_current(txt->disp); 53 | if (!mode) 54 | return -EINVAL; 55 | sw = uterm_mode_get_width(mode); 56 | sh = uterm_mode_get_height(mode); 57 | 58 | txt->cols = sw / fw; 59 | txt->rows = sh / fh; 60 | 61 | return 0; 62 | } 63 | 64 | static int bblit_draw(struct kmscon_text *txt, 65 | uint64_t id, const uint32_t *ch, size_t len, 66 | unsigned int width, 67 | unsigned int posx, unsigned int posy, 68 | const struct tsm_screen_attr *attr) 69 | { 70 | const struct kmscon_glyph *glyph; 71 | int ret; 72 | struct kmscon_font *font; 73 | 74 | if (!width) 75 | return 0; 76 | 77 | if (attr->bold) 78 | font = txt->bold_font; 79 | else 80 | font = txt->font; 81 | 82 | if (attr->underline) 83 | font->attr.underline = true; 84 | else 85 | font->attr.underline = false; 86 | 87 | if (attr->italic) 88 | font->attr.italic = true; 89 | else 90 | font->attr.italic = false; 91 | 92 | if (!len) { 93 | ret = kmscon_font_render_empty(font, &glyph); 94 | } else { 95 | ret = kmscon_font_render(font, id, ch, len, &glyph); 96 | } 97 | 98 | if (ret) { 99 | ret = kmscon_font_render_inval(font, &glyph); 100 | if (ret) 101 | return ret; 102 | } 103 | 104 | /* draw glyph */ 105 | if (attr->inverse) { 106 | ret = uterm_display_fake_blend(txt->disp, &glyph->buf, 107 | posx * txt->font->attr.width, 108 | posy * txt->font->attr.height, 109 | attr->br, attr->bg, attr->bb, 110 | attr->fr, attr->fg, attr->fb); 111 | } else { 112 | ret = uterm_display_fake_blend(txt->disp, &glyph->buf, 113 | posx * txt->font->attr.width, 114 | posy * txt->font->attr.height, 115 | attr->fr, attr->fg, attr->fb, 116 | attr->br, attr->bg, attr->bb); 117 | } 118 | 119 | return ret; 120 | } 121 | 122 | struct kmscon_text_ops kmscon_text_bblit_ops = { 123 | .name = "bblit", 124 | .owner = NULL, 125 | .init = NULL, 126 | .destroy = NULL, 127 | .set = bblit_set, 128 | .unset = NULL, 129 | .prepare = NULL, 130 | .draw = bblit_draw, 131 | .render = NULL, 132 | .abort = NULL, 133 | }; 134 | -------------------------------------------------------------------------------- /src/text_bbulk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Bit-Blitting Bulk Text Renderer Backend 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /** 27 | * SECTION:text_bbulk.c 28 | * @short_description: Bit-Blitting Bulk Text Renderer Backend 29 | * @include: text.h 30 | * 31 | * Similar to the bblit renderer but assembles an array of blit-requests and 32 | * pushes all of them at once to the video device. 33 | */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "shl_log.h" 40 | #include "text.h" 41 | #include "uterm_video.h" 42 | 43 | #define LOG_SUBSYSTEM "text_bbulk" 44 | 45 | struct bbulk { 46 | struct uterm_video_blend_req *reqs; 47 | }; 48 | 49 | #define FONT_WIDTH(txt) ((txt)->font->attr.width) 50 | #define FONT_HEIGHT(txt) ((txt)->font->attr.height) 51 | 52 | static int bbulk_init(struct kmscon_text *txt) 53 | { 54 | struct bbulk *bb; 55 | 56 | bb = malloc(sizeof(*bb)); 57 | if (!bb) 58 | return -ENOMEM; 59 | 60 | txt->data = bb; 61 | return 0; 62 | } 63 | 64 | static void bbulk_destroy(struct kmscon_text *txt) 65 | { 66 | struct bbulk *bb = txt->data; 67 | 68 | free(bb); 69 | } 70 | 71 | static int bbulk_set(struct kmscon_text *txt) 72 | { 73 | struct bbulk *bb = txt->data; 74 | unsigned int sw, sh, i, j; 75 | struct uterm_video_blend_req *req; 76 | struct uterm_mode *mode; 77 | 78 | memset(bb, 0, sizeof(*bb)); 79 | 80 | mode = uterm_display_get_current(txt->disp); 81 | if (!mode) 82 | return -EINVAL; 83 | sw = uterm_mode_get_width(mode); 84 | sh = uterm_mode_get_height(mode); 85 | 86 | txt->cols = sw / FONT_WIDTH(txt); 87 | txt->rows = sh / FONT_HEIGHT(txt); 88 | 89 | bb->reqs = malloc(sizeof(*bb->reqs) * txt->cols * txt->rows); 90 | if (!bb->reqs) 91 | return -ENOMEM; 92 | memset(bb->reqs, 0, sizeof(*bb->reqs) * txt->cols * txt->rows); 93 | 94 | for (i = 0; i < txt->rows; ++i) { 95 | for (j = 0; j < txt->cols; ++j) { 96 | req = &bb->reqs[i * txt->cols + j]; 97 | req->x = j * FONT_WIDTH(txt); 98 | req->y = i * FONT_HEIGHT(txt); 99 | } 100 | } 101 | 102 | return 0; 103 | } 104 | 105 | static void bbulk_unset(struct kmscon_text *txt) 106 | { 107 | struct bbulk *bb = txt->data; 108 | 109 | free(bb->reqs); 110 | bb->reqs = NULL; 111 | } 112 | 113 | static int bbulk_draw(struct kmscon_text *txt, 114 | uint64_t id, const uint32_t *ch, size_t len, 115 | unsigned int width, 116 | unsigned int posx, unsigned int posy, 117 | const struct tsm_screen_attr *attr) 118 | { 119 | struct bbulk *bb = txt->data; 120 | const struct kmscon_glyph *glyph; 121 | int ret; 122 | struct uterm_video_blend_req *req; 123 | struct kmscon_font *font; 124 | 125 | if (!width) { 126 | bb->reqs[posy * txt->cols + posx].buf = NULL; 127 | return 0; 128 | } 129 | 130 | if (attr->bold) 131 | font = txt->bold_font; 132 | else 133 | font = txt->font; 134 | 135 | if (attr->underline) 136 | font->attr.underline = true; 137 | else 138 | font->attr.underline = false; 139 | 140 | if (attr->italic) 141 | font->attr.italic = true; 142 | else 143 | font->attr.italic = false; 144 | 145 | if (!len) { 146 | ret = kmscon_font_render_empty(font, &glyph); 147 | } else { 148 | ret = kmscon_font_render(font, id, ch, len, &glyph); 149 | } 150 | 151 | if (ret) { 152 | ret = kmscon_font_render_inval(font, &glyph); 153 | if (ret) 154 | return ret; 155 | } 156 | 157 | req = &bb->reqs[posy * txt->cols + posx]; 158 | req->buf = &glyph->buf; 159 | if (attr->inverse) { 160 | req->fr = attr->br; 161 | req->fg = attr->bg; 162 | req->fb = attr->bb; 163 | req->br = attr->fr; 164 | req->bg = attr->fg; 165 | req->bb = attr->fb; 166 | } else { 167 | req->fr = attr->fr; 168 | req->fg = attr->fg; 169 | req->fb = attr->fb; 170 | req->br = attr->br; 171 | req->bg = attr->bg; 172 | req->bb = attr->bb; 173 | } 174 | 175 | return 0; 176 | } 177 | 178 | static int bbulk_render(struct kmscon_text *txt) 179 | { 180 | struct bbulk *bb = txt->data; 181 | 182 | return uterm_display_fake_blendv(txt->disp, bb->reqs, 183 | txt->cols * txt->rows); 184 | } 185 | 186 | struct kmscon_text_ops kmscon_text_bbulk_ops = { 187 | .name = "bbulk", 188 | .owner = NULL, 189 | .init = bbulk_init, 190 | .destroy = bbulk_destroy, 191 | .set = bbulk_set, 192 | .unset = bbulk_unset, 193 | .prepare = NULL, 194 | .draw = bbulk_draw, 195 | .render = bbulk_render, 196 | .abort = NULL, 197 | }; 198 | -------------------------------------------------------------------------------- /src/text_gltex_atlas.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Fragment Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Fragment Shader 29 | * A basic fragment shader which applies a 2D texture and blends foreground and 30 | * background colors. 31 | */ 32 | 33 | precision mediump float; 34 | 35 | uniform sampler2D atlas; 36 | uniform float advance_htex; 37 | uniform float advance_vtex; 38 | 39 | varying vec2 texpos; 40 | varying vec3 fgcol; 41 | varying vec3 bgcol; 42 | 43 | void main() 44 | { 45 | vec2 pos = vec2(texpos.x * advance_htex, texpos.y * advance_vtex); 46 | float alpha = texture2D(atlas, pos).a; 47 | vec3 val = alpha * fgcol + (1.0 - alpha) * bgcol; 48 | gl_FragColor = vec4(val, 1.0); 49 | } 50 | -------------------------------------------------------------------------------- /src/text_gltex_atlas.vert: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Vertex Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Vertex Shader 29 | * This shader is a very basic vertex shader which forwards all data and 30 | * performs basic matrix multiplications. 31 | */ 32 | 33 | uniform mat4 projection; 34 | uniform float orientation; 35 | 36 | attribute vec2 position; 37 | attribute vec2 texture_position; 38 | attribute vec3 fgcolor; 39 | attribute vec3 bgcolor; 40 | 41 | varying vec2 texpos; 42 | varying vec3 fgcol; 43 | varying vec3 bgcol; 44 | 45 | vec2 opRotate(in vec2 p, in float degrees) 46 | { 47 | float rad = radians(degrees); 48 | float c = cos(rad); 49 | float s = sin(rad); 50 | return p * mat2(vec2(c, s), vec2(-s, c)); 51 | } 52 | 53 | void main() 54 | { 55 | vec2 rotatedPosition = opRotate(position, orientation); 56 | gl_Position = projection * vec4(rotatedPosition, 0.0, 1.0); 57 | texpos = texture_position; 58 | fgcol = fgcolor; 59 | bgcol = bgcolor; 60 | } 61 | -------------------------------------------------------------------------------- /src/uterm_drm2d_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal drm2d module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Internal definitions */ 27 | 28 | #ifndef UTERM_DRM2D_INTERNAL_H 29 | #define UTERM_DRM2D_INTERNAL_H 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "uterm_video.h" 36 | 37 | struct uterm_drm2d_rb { 38 | uint32_t fb; 39 | uint32_t handle; 40 | uint32_t stride; 41 | uint64_t size; 42 | void *map; 43 | }; 44 | 45 | struct uterm_drm2d_display { 46 | int current_rb; 47 | struct uterm_drm2d_rb rb[2]; 48 | }; 49 | 50 | struct uterm_drm2d_video { 51 | int fd; 52 | struct ev_fd *efd; 53 | }; 54 | 55 | int uterm_drm2d_display_blit(struct uterm_display *disp, 56 | const struct uterm_video_buffer *buf, 57 | unsigned int x, unsigned int y); 58 | int uterm_drm2d_display_fake_blendv(struct uterm_display *disp, 59 | const struct uterm_video_blend_req *req, 60 | size_t num); 61 | int uterm_drm2d_display_fill(struct uterm_display *disp, 62 | uint8_t r, uint8_t g, uint8_t b, 63 | unsigned int x, unsigned int y, 64 | unsigned int width, unsigned int height); 65 | 66 | #endif /* UTERM_DRM2D_INTERNAL_H */ 67 | -------------------------------------------------------------------------------- /src/uterm_drm2d_render.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal drm2d module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * DRM2D Video backend rendering functions 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "eloop.h" 41 | #include "shl_log.h" 42 | #include "uterm_drm_shared_internal.h" 43 | #include "uterm_drm2d_internal.h" 44 | #include "uterm_video.h" 45 | #include "uterm_video_internal.h" 46 | 47 | #define LOG_SUBSYSTEM "uterm_drm2d_render" 48 | 49 | int uterm_drm2d_display_blit(struct uterm_display *disp, 50 | const struct uterm_video_buffer *buf, 51 | unsigned int x, unsigned int y) 52 | { 53 | unsigned int tmp; 54 | uint8_t *dst, *src; 55 | unsigned int width, height; 56 | unsigned int sw, sh; 57 | struct uterm_drm2d_rb *rb; 58 | struct uterm_drm2d_display *d2d = uterm_drm_display_get_data(disp); 59 | 60 | if (!buf || buf->format != UTERM_FORMAT_XRGB32) 61 | return -EINVAL; 62 | 63 | rb = &d2d->rb[d2d->current_rb ^ 1]; 64 | sw = uterm_drm_mode_get_width(disp->current_mode); 65 | sh = uterm_drm_mode_get_height(disp->current_mode); 66 | 67 | tmp = x + buf->width; 68 | if (tmp < x || x >= sw) 69 | return -EINVAL; 70 | if (tmp > sw) 71 | width = sw - x; 72 | else 73 | width = buf->width; 74 | 75 | tmp = y + buf->height; 76 | if (tmp < y || y >= sh) 77 | return -EINVAL; 78 | if (tmp > sh) 79 | height = sh - y; 80 | else 81 | height = buf->height; 82 | 83 | dst = rb->map; 84 | dst = &dst[y * rb->stride + x * 4]; 85 | src = buf->data; 86 | 87 | while (height--) { 88 | memcpy(dst, src, 4 * width); 89 | dst += rb->stride; 90 | src += buf->stride; 91 | } 92 | 93 | return 0; 94 | } 95 | 96 | int uterm_drm2d_display_fake_blendv(struct uterm_display *disp, 97 | const struct uterm_video_blend_req *req, 98 | size_t num) 99 | { 100 | unsigned int tmp; 101 | uint8_t *dst, *src; 102 | unsigned int width, height, i, j; 103 | unsigned int sw, sh; 104 | uint_fast32_t r, g, b, out; 105 | struct uterm_drm2d_rb *rb; 106 | struct uterm_drm2d_display *d2d = uterm_drm_display_get_data(disp); 107 | 108 | if (!req) 109 | return -EINVAL; 110 | 111 | rb = &d2d->rb[d2d->current_rb ^ 1]; 112 | sw = uterm_drm_mode_get_width(disp->current_mode); 113 | sh = uterm_drm_mode_get_height(disp->current_mode); 114 | 115 | for (j = 0; j < num; ++j, ++req) { 116 | if (!req->buf) 117 | continue; 118 | 119 | if (req->buf->format != UTERM_FORMAT_GREY) 120 | return -EOPNOTSUPP; 121 | 122 | tmp = req->x + req->buf->width; 123 | if (tmp < req->x || req->x >= sw) 124 | return -EINVAL; 125 | if (tmp > sw) 126 | width = sw - req->x; 127 | else 128 | width = req->buf->width; 129 | 130 | tmp = req->y + req->buf->height; 131 | if (tmp < req->y || req->y >= sh) 132 | return -EINVAL; 133 | if (tmp > sh) 134 | height = sh - req->y; 135 | else 136 | height = req->buf->height; 137 | 138 | dst = rb->map; 139 | dst = &dst[req->y * rb->stride + req->x * 4]; 140 | src = req->buf->data; 141 | 142 | while (height--) { 143 | for (i = 0; i < width; ++i) { 144 | /* Division by 255 (t /= 255) is done with: 145 | * t += 0x80 146 | * t = (t + (t >> 8)) >> 8 147 | * This speeds up the computation by ~20% as the 148 | * division is not needed. */ 149 | if (src[i] == 0) { 150 | r = req->br; 151 | g = req->bg; 152 | b = req->bb; 153 | out = (r << 16) | (g << 8) | b; 154 | } else if (src[i] == 255) { 155 | r = req->fr; 156 | g = req->fg; 157 | b = req->fb; 158 | out = (r << 16) | (g << 8) | b; 159 | } else { 160 | r = req->fr * src[i] + 161 | req->br * (255 - src[i]); 162 | r += 0x80; 163 | r = (r + (r >> 8)) >> 8; 164 | 165 | g = req->fg * src[i] + 166 | req->bg * (255 - src[i]); 167 | g += 0x80; 168 | g = (g + (g >> 8)) >> 8; 169 | 170 | b = req->fb * src[i] + 171 | req->bb * (255 - src[i]); 172 | b += 0x80; 173 | b = (b + (b >> 8)) >> 8; 174 | out = (r << 16) | (g << 8) | b; 175 | } 176 | 177 | ((uint32_t*)dst)[i] = out; 178 | } 179 | dst += rb->stride; 180 | src += req->buf->stride; 181 | } 182 | } 183 | 184 | return 0; 185 | } 186 | 187 | int uterm_drm2d_display_fill(struct uterm_display *disp, 188 | uint8_t r, uint8_t g, uint8_t b, 189 | unsigned int x, unsigned int y, 190 | unsigned int width, unsigned int height) 191 | { 192 | unsigned int tmp, i; 193 | uint8_t *dst; 194 | unsigned int sw, sh; 195 | struct uterm_drm2d_rb *rb; 196 | struct uterm_drm2d_display *d2d = uterm_drm_display_get_data(disp); 197 | 198 | rb = &d2d->rb[d2d->current_rb ^ 1]; 199 | sw = uterm_drm_mode_get_width(disp->current_mode); 200 | sh = uterm_drm_mode_get_height(disp->current_mode); 201 | 202 | tmp = x + width; 203 | if (tmp < x || x >= sw) 204 | return -EINVAL; 205 | if (tmp > sw) 206 | width = sw - x; 207 | tmp = y + height; 208 | if (tmp < y || y >= sh) 209 | return -EINVAL; 210 | if (tmp > sh) 211 | height = sh - y; 212 | 213 | dst = rb->map; 214 | dst = &dst[y * rb->stride + x * 4]; 215 | 216 | while (height--) { 217 | for (i = 0; i < width; ++i) 218 | ((uint32_t*)dst)[i] = (r << 16) | (g << 8) | b; 219 | dst += rb->stride; 220 | } 221 | 222 | return 0; 223 | } 224 | -------------------------------------------------------------------------------- /src/uterm_drm3d_blend.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Fragment Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Fragment Shader 29 | * A basic fragment shader which applies a 2D texture. 30 | */ 31 | 32 | precision mediump float; 33 | 34 | uniform sampler2D texture; 35 | uniform vec3 fgcolor; 36 | uniform vec3 bgcolor; 37 | varying vec2 texpos; 38 | 39 | void main() 40 | { 41 | float alpha = texture2D(texture, texpos).a; 42 | vec3 val = alpha * fgcolor + (1.0 - alpha) * bgcolor; 43 | gl_FragColor = vec4(val, 1.0); 44 | } 45 | -------------------------------------------------------------------------------- /src/uterm_drm3d_blend.vert: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Vertex Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Vertex Shader 29 | * This shader is a very basic vertex shader which forwards all data and 30 | * performs basic matrix multiplications. 31 | */ 32 | 33 | uniform mat4 projection; 34 | attribute vec2 position; 35 | attribute vec2 texture_position; 36 | varying vec2 texpos; 37 | 38 | void main() 39 | { 40 | gl_Position = projection * vec4(position, 0.0, 1.0); 41 | texpos = texture_position; 42 | } 43 | -------------------------------------------------------------------------------- /src/uterm_drm3d_blit.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Fragment Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Fragment Shader 29 | * A basic fragment shader which applies a 2D texture. 30 | */ 31 | 32 | precision mediump float; 33 | 34 | uniform sampler2D texture; 35 | varying vec2 texpos; 36 | 37 | void main() 38 | { 39 | gl_FragColor = texture2D(texture, texpos); 40 | } 41 | -------------------------------------------------------------------------------- /src/uterm_drm3d_blit.vert: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Vertex Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Vertex Shader 29 | * This shader is a very basic vertex shader which forwards all data and 30 | * performs basic matrix multiplications. 31 | */ 32 | 33 | uniform mat4 projection; 34 | attribute vec2 position; 35 | attribute vec2 texture_position; 36 | varying vec2 texpos; 37 | 38 | void main() 39 | { 40 | gl_Position = projection * vec4(position, 0.0, 1.0); 41 | texpos = texture_position; 42 | } 43 | -------------------------------------------------------------------------------- /src/uterm_drm3d_fill.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Fragment Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Default Fragment Shader 29 | * A basic fragment shader which applies a color directly. 30 | */ 31 | 32 | precision mediump float; 33 | 34 | varying vec4 col; 35 | 36 | void main() 37 | { 38 | gl_FragColor = col; 39 | } 40 | -------------------------------------------------------------------------------- /src/uterm_drm3d_fill.vert: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Vertex Shader 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Default Vertex Shader 29 | * This shader is a very basic vertex shader which forwards all data and 30 | * performs basic matrix multiplications. 31 | */ 32 | 33 | uniform mat4 projection; 34 | attribute vec2 position; 35 | attribute vec4 color; 36 | varying vec4 col; 37 | 38 | void main() 39 | { 40 | col = color; 41 | gl_Position = projection * vec4(position, 0.0, 1.0); 42 | } 43 | -------------------------------------------------------------------------------- /src/uterm_drm3d_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal drm3d module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Internal definitions */ 27 | 28 | #ifndef UTERM_DRM3D_INTERNAL_H 29 | #define UTERM_DRM3D_INTERNAL_H 30 | 31 | #define EGL_EGLEXT_PROTOTYPES 32 | #define GL_GLEXT_PROTOTYPES 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include "uterm_video.h" 49 | 50 | /* thanks khronos for breaking backwards compatibility.. */ 51 | #if !defined(GL_UNPACK_ROW_LENGTH) && defined(GL_UNPACK_ROW_LENGTH_EXT) 52 | # define GL_UNPACK_ROW_LENGTH GL_UNPACK_ROW_LENGTH_EXT 53 | #endif 54 | 55 | struct uterm_drm3d_rb { 56 | struct uterm_display *disp; 57 | struct gbm_bo *bo; 58 | uint32_t fb; 59 | }; 60 | 61 | struct uterm_drm3d_display { 62 | struct gbm_surface *gbm; 63 | EGLSurface surface; 64 | struct uterm_drm3d_rb *current; 65 | struct uterm_drm3d_rb *next; 66 | }; 67 | 68 | struct uterm_drm3d_video { 69 | struct gbm_device *gbm; 70 | EGLDisplay disp; 71 | EGLConfig conf; 72 | EGLContext ctx; 73 | 74 | unsigned int sinit; 75 | bool supports_rowlen; 76 | GLuint tex; 77 | 78 | struct gl_shader *fill_shader; 79 | GLuint uni_fill_proj; 80 | 81 | struct gl_shader *blend_shader; 82 | GLuint uni_blend_proj; 83 | GLuint uni_blend_tex; 84 | GLuint uni_blend_fgcol; 85 | GLuint uni_blend_bgcol; 86 | 87 | struct gl_shader *blit_shader; 88 | GLuint uni_blit_proj; 89 | GLuint uni_blit_tex; 90 | }; 91 | 92 | int uterm_drm3d_display_use(struct uterm_display *disp, bool *opengl); 93 | void uterm_drm3d_deinit_shaders(struct uterm_video *video); 94 | int uterm_drm3d_display_blit(struct uterm_display *disp, 95 | const struct uterm_video_buffer *buf, 96 | unsigned int x, unsigned int y); 97 | int uterm_drm3d_display_fake_blendv(struct uterm_display *disp, 98 | const struct uterm_video_blend_req *req, 99 | size_t num); 100 | int uterm_drm3d_display_fill(struct uterm_display *disp, 101 | uint8_t r, uint8_t g, uint8_t b, 102 | unsigned int x, unsigned int y, 103 | unsigned int width, unsigned int height); 104 | 105 | #endif /* UTERM_DRM3D_INTERNAL_H */ 106 | -------------------------------------------------------------------------------- /src/uterm_drm_shared_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Internal definitions */ 27 | 28 | #ifndef UTERM_DRM_SHARED_INTERNAL_H 29 | #define UTERM_DRM_SHARED_INTERNAL_H 30 | 31 | #include 32 | #include 33 | #include 34 | #include "eloop.h" 35 | #include "shl_timer.h" 36 | #include "uterm_video.h" 37 | #include "uterm_video_internal.h" 38 | 39 | /* drm mode */ 40 | 41 | struct uterm_drm_mode { 42 | drmModeModeInfo info; 43 | }; 44 | 45 | int uterm_drm_mode_init(struct uterm_mode *mode); 46 | void uterm_drm_mode_destroy(struct uterm_mode *mode); 47 | const char *uterm_drm_mode_get_name(const struct uterm_mode *mode); 48 | unsigned int uterm_drm_mode_get_width(const struct uterm_mode *mode); 49 | unsigned int uterm_drm_mode_get_height(const struct uterm_mode *mode); 50 | void uterm_drm_mode_set(struct uterm_mode *mode, drmModeModeInfo *info); 51 | 52 | static inline drmModeModeInfo *uterm_drm_mode_get_info(struct uterm_mode *m) 53 | { 54 | struct uterm_drm_mode *mode = m->data; 55 | 56 | return &mode->info; 57 | } 58 | 59 | extern const struct mode_ops uterm_drm_mode_ops; 60 | 61 | /* drm dpms */ 62 | 63 | int uterm_drm_set_dpms(int fd, uint32_t conn_id, int state); 64 | int uterm_drm_get_dpms(int fd, drmModeConnector *conn); 65 | 66 | /* drm display */ 67 | 68 | struct uterm_drm_display { 69 | uint32_t conn_id; 70 | int crtc_id; 71 | drmModeCrtc *saved_crtc; 72 | void *data; 73 | }; 74 | 75 | int uterm_drm_display_init(struct uterm_display *disp, void *data); 76 | void uterm_drm_display_destroy(struct uterm_display *disp); 77 | int uterm_drm_display_activate(struct uterm_display *disp, int fd); 78 | void uterm_drm_display_deactivate(struct uterm_display *disp, int fd); 79 | int uterm_drm_display_set_dpms(struct uterm_display *disp, int state); 80 | int uterm_drm_display_wait_pflip(struct uterm_display *disp); 81 | int uterm_drm_display_swap(struct uterm_display *disp, uint32_t fb, 82 | bool immediate); 83 | 84 | static inline void *uterm_drm_display_get_data(struct uterm_display *disp) 85 | { 86 | struct uterm_drm_display *d = disp->data; 87 | 88 | return d->data; 89 | } 90 | 91 | /* drm video */ 92 | 93 | typedef void (*uterm_drm_page_flip_t) (struct uterm_display *disp); 94 | 95 | struct uterm_drm_video { 96 | int fd; 97 | struct ev_fd *efd; 98 | uterm_drm_page_flip_t page_flip; 99 | void *data; 100 | struct shl_timer *timer; 101 | struct ev_timer *vt_timer; 102 | const struct display_ops *display_ops; 103 | }; 104 | 105 | int uterm_drm_video_init(struct uterm_video *video, const char *node, 106 | const struct display_ops *display_ops, 107 | uterm_drm_page_flip_t pflip, void *data); 108 | void uterm_drm_video_destroy(struct uterm_video *video); 109 | int uterm_drm_video_find_crtc(struct uterm_video *video, drmModeRes *res, 110 | drmModeEncoder *enc); 111 | int uterm_drm_video_hotplug(struct uterm_video *video, bool read_dpms, 112 | bool modeset); 113 | int uterm_drm_video_wake_up(struct uterm_video *video); 114 | void uterm_drm_video_sleep(struct uterm_video *video); 115 | int uterm_drm_video_poll(struct uterm_video *video); 116 | int uterm_drm_video_wait_pflip(struct uterm_video *video, 117 | unsigned int *mtimeout); 118 | void uterm_drm_video_arm_vt_timer(struct uterm_video *video); 119 | 120 | static inline void *uterm_drm_video_get_data(struct uterm_video *video) 121 | { 122 | struct uterm_drm_video *v = video->data; 123 | 124 | return v->data; 125 | } 126 | 127 | #endif /* UTERM_DRM_SHARED_INTERNAL_H */ 128 | -------------------------------------------------------------------------------- /src/uterm_fbdev_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal fbdev module 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Internal definitions */ 27 | 28 | #ifndef UTERM_FBDEV_INTERNAL_H 29 | #define UTERM_FBDEV_INTERNAL_H 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "uterm_video.h" 37 | 38 | struct fbdev_mode { 39 | unsigned int width; 40 | unsigned int height; 41 | }; 42 | 43 | struct fbdev_display { 44 | int fd; 45 | struct fb_fix_screeninfo finfo; 46 | struct fb_var_screeninfo vinfo; 47 | unsigned int rate; 48 | const char *node; 49 | 50 | unsigned int bufid; 51 | size_t xres; 52 | size_t yres; 53 | size_t len; 54 | uint8_t *map; 55 | unsigned int stride; 56 | 57 | bool xrgb32; 58 | bool rgb24; 59 | bool rgb16; 60 | unsigned int Bpp; 61 | unsigned int off_r; 62 | unsigned int off_g; 63 | unsigned int off_b; 64 | unsigned int len_r; 65 | unsigned int len_g; 66 | unsigned int len_b; 67 | int_fast32_t dither_r; 68 | int_fast32_t dither_g; 69 | int_fast32_t dither_b; 70 | }; 71 | 72 | struct fbdev_video { 73 | char *node; 74 | bool pending_intro; 75 | }; 76 | 77 | int uterm_fbdev_display_blit(struct uterm_display *disp, 78 | const struct uterm_video_buffer *buf, 79 | unsigned int x, unsigned int y); 80 | int uterm_fbdev_display_fake_blendv(struct uterm_display *disp, 81 | const struct uterm_video_blend_req *req, 82 | size_t num); 83 | int uterm_fbdev_display_fill(struct uterm_display *disp, 84 | uint8_t r, uint8_t g, uint8_t b, 85 | unsigned int x, unsigned int y, 86 | unsigned int width, unsigned int height); 87 | 88 | #endif /* UTERM_FBDEV_INTERNAL_H */ 89 | -------------------------------------------------------------------------------- /src/uterm_input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal Input Handling 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Input Devices 28 | * This input object can combine multiple linux input devices into a single 29 | * device and notifies the application about events. It has several different 30 | * keyboard backends so the full XKB feature set is available. 31 | */ 32 | 33 | #ifndef UTERM_UTERM_INPUT_H 34 | #define UTERM_UTERM_INPUT_H 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | struct uterm_input; 42 | 43 | typedef void (*uterm_input_log_t) (void *data, 44 | const char *file, 45 | int line, 46 | const char *func, 47 | const char *subs, 48 | unsigned int sev, 49 | const char *format, 50 | va_list args); 51 | 52 | /* keep in sync with shl_xkb_mods */ 53 | enum uterm_input_modifier { 54 | UTERM_SHIFT_MASK = (1 << 0), 55 | UTERM_LOCK_MASK = (1 << 1), 56 | UTERM_CONTROL_MASK = (1 << 2), 57 | UTERM_ALT_MASK = (1 << 3), 58 | UTERM_LOGO_MASK = (1 << 4), 59 | }; 60 | 61 | /* keep in sync with TSM_VTE_INVALID */ 62 | #define UTERM_INPUT_INVALID 0xffffffff 63 | 64 | struct uterm_input_event { 65 | bool handled; /* user-controlled, default is false */ 66 | uint16_t keycode; /* linux keycode - KEY_* - linux/input.h */ 67 | uint32_t ascii; /* ascii keysym for @keycode */ 68 | unsigned int mods; /* active modifiers - uterm_modifier mask */ 69 | 70 | unsigned int num_syms; /* number of keysyms */ 71 | uint32_t *keysyms; /* XKB-common keysym-array - XKB_KEY_* */ 72 | uint32_t *codepoints; /* ucs4 unicode value or UTERM_INPUT_INVALID */ 73 | }; 74 | 75 | #define UTERM_INPUT_HAS_MODS(_ev, _mods) (((_ev)->mods & (_mods)) == (_mods)) 76 | 77 | typedef void (*uterm_input_cb) (struct uterm_input *input, 78 | struct uterm_input_event *ev, 79 | void *data); 80 | 81 | int uterm_input_new(struct uterm_input **out, struct ev_eloop *eloop, 82 | const char *model, const char *layout, const char *variant, 83 | const char *options, const char *locale, const char *keymap, 84 | const char *compose_file, size_t compose_file_len, 85 | unsigned int repeat_delay, unsigned int repeat_rate, 86 | uterm_input_log_t log, void *log_data); 87 | void uterm_input_ref(struct uterm_input *input); 88 | void uterm_input_unref(struct uterm_input *input); 89 | 90 | void uterm_input_add_dev(struct uterm_input *input, const char *node); 91 | void uterm_input_remove_dev(struct uterm_input *input, const char *node); 92 | 93 | int uterm_input_register_cb(struct uterm_input *input, uterm_input_cb cb, 94 | void *data); 95 | void uterm_input_unregister_cb(struct uterm_input *input, uterm_input_cb cb, 96 | void *data); 97 | 98 | void uterm_input_sleep(struct uterm_input *input); 99 | void uterm_input_wake_up(struct uterm_input *input); 100 | bool uterm_input_is_awake(struct uterm_input *input); 101 | 102 | #endif /* UTERM_UTERM_INPUT_H */ 103 | -------------------------------------------------------------------------------- /src/uterm_input_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Internal definitions */ 27 | 28 | #ifndef UTERM_INPUT_INTERNAL_H 29 | #define UTERM_INPUT_INTERNAL_H 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "eloop.h" 37 | #include "shl_dlist.h" 38 | #include "shl_llog.h" 39 | #include "shl_misc.h" 40 | #include "uterm_input.h" 41 | 42 | enum uterm_input_device_capability { 43 | UTERM_DEVICE_HAS_KEYS = (1 << 0), 44 | UTERM_DEVICE_HAS_LEDS = (1 << 1), 45 | }; 46 | 47 | struct uterm_input_dev { 48 | struct shl_dlist list; 49 | struct uterm_input *input; 50 | 51 | unsigned int capabilities; 52 | int rfd; 53 | char *node; 54 | struct ev_fd *fd; 55 | struct xkb_state *state; 56 | struct xkb_compose_state *compose_state; 57 | /* Used in sleep/wake up to store the key's pressed/released state. */ 58 | char key_state_bits[SHL_DIV_ROUND_UP(KEY_CNT, CHAR_BIT)]; 59 | 60 | unsigned int num_syms; 61 | struct uterm_input_event event; 62 | struct uterm_input_event repeat_event; 63 | 64 | bool repeating; 65 | struct ev_timer *repeat_timer; 66 | }; 67 | 68 | struct uterm_input { 69 | unsigned long ref; 70 | llog_submit_t llog; 71 | void *llog_data; 72 | struct ev_eloop *eloop; 73 | int awake; 74 | unsigned int repeat_rate; 75 | unsigned int repeat_delay; 76 | 77 | struct shl_hook *hook; 78 | struct xkb_context *ctx; 79 | struct xkb_keymap *keymap; 80 | struct xkb_compose_table *compose_table; 81 | 82 | struct shl_dlist devices; 83 | }; 84 | 85 | static inline bool input_bit_is_set(const unsigned long *array, int bit) 86 | { 87 | return !!(array[bit / LONG_BIT] & (1UL << (bit % LONG_BIT))); 88 | } 89 | 90 | int uxkb_desc_init(struct uterm_input *input, 91 | const char *model, 92 | const char *layout, 93 | const char *variant, 94 | const char *options, 95 | const char *locale, 96 | const char *keymap, 97 | const char *compose_file, 98 | size_t compose_file_len); 99 | void uxkb_desc_destroy(struct uterm_input *input); 100 | 101 | int uxkb_dev_init(struct uterm_input_dev *dev); 102 | void uxkb_dev_destroy(struct uterm_input_dev *dev); 103 | int uxkb_dev_process(struct uterm_input_dev *dev, 104 | uint16_t key_state, 105 | uint16_t code); 106 | void uxkb_dev_sleep(struct uterm_input_dev *dev); 107 | void uxkb_dev_wake_up(struct uterm_input_dev *dev); 108 | 109 | #endif /* UTERM_INPUT_INTERNAL_H */ 110 | -------------------------------------------------------------------------------- /src/uterm_monitor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal System Monitor 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * System Monitor 28 | * This watches the system for new seats, graphics devices or other devices that 29 | * are used by terminals. 30 | */ 31 | 32 | #ifndef UTERM_UTERM_MONITOR_H 33 | #define UTERM_UTERM_MONITOR_H 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | struct uterm_monitor; 41 | struct uterm_monitor_seat; 42 | struct uterm_monitor_dev; 43 | 44 | enum uterm_monitor_event_type { 45 | UTERM_MONITOR_NEW_SEAT, 46 | UTERM_MONITOR_FREE_SEAT, 47 | UTERM_MONITOR_NEW_DEV, 48 | UTERM_MONITOR_FREE_DEV, 49 | UTERM_MONITOR_HOTPLUG_DEV, 50 | }; 51 | 52 | enum uterm_monitor_dev_type { 53 | UTERM_MONITOR_DRM, 54 | UTERM_MONITOR_FBDEV, 55 | UTERM_MONITOR_INPUT, 56 | }; 57 | 58 | enum uterm_monitor_dev_flag { 59 | UTERM_MONITOR_DRM_BACKED = 0x01, 60 | UTERM_MONITOR_PRIMARY = 0x02, 61 | UTERM_MONITOR_AUX = 0x04, 62 | }; 63 | 64 | struct uterm_monitor_event { 65 | unsigned int type; 66 | 67 | struct uterm_monitor_seat *seat; 68 | const char *seat_name; 69 | void *seat_data; 70 | 71 | struct uterm_monitor_dev *dev; 72 | unsigned int dev_type; 73 | unsigned int dev_flags; 74 | const char *dev_node; 75 | void *dev_data; 76 | }; 77 | 78 | typedef void (*uterm_monitor_cb) (struct uterm_monitor *mon, 79 | struct uterm_monitor_event *event, 80 | void *data); 81 | 82 | int uterm_monitor_new(struct uterm_monitor **out, struct ev_eloop *eloop, 83 | uterm_monitor_cb cb, void *data); 84 | void uterm_monitor_ref(struct uterm_monitor *mon); 85 | void uterm_monitor_unref(struct uterm_monitor *mon); 86 | void uterm_monitor_scan(struct uterm_monitor *mon); 87 | 88 | void uterm_monitor_set_seat_data(struct uterm_monitor_seat *seat, void *data); 89 | void uterm_monitor_set_dev_data(struct uterm_monitor_dev *dev, void *data); 90 | 91 | #endif /* UTERM_UTERM_MONITOR_H */ 92 | -------------------------------------------------------------------------------- /src/uterm_systemd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Systemd integration 28 | * Systemd provides multi-seat support and other helpers that we can use in 29 | * uterm. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "shl_log.h" 40 | #include "uterm_monitor.h" 41 | #include "uterm_systemd_internal.h" 42 | 43 | #define LOG_SUBSYSTEM "systemd" 44 | 45 | struct uterm_sd { 46 | sd_login_monitor *mon; 47 | }; 48 | 49 | int uterm_sd_new(struct uterm_sd **out) 50 | { 51 | int ret; 52 | struct uterm_sd *sd; 53 | 54 | if (!out) 55 | return -EINVAL; 56 | 57 | ret = sd_booted(); 58 | if (ret < 0) { 59 | log_warning("cannot determine whether system booted with systemd (%d): %s", 60 | ret, strerror(-ret)); 61 | return -EOPNOTSUPP; 62 | } else if (!ret) { 63 | log_info("system not booted with systemd, disabling multi-seat support"); 64 | return -EOPNOTSUPP; 65 | } 66 | 67 | log_info("system booted with systemd, enabling multi-seat support"); 68 | 69 | sd = malloc(sizeof(*sd)); 70 | if (!sd) 71 | return -ENOMEM; 72 | memset(sd, 0, sizeof(*sd)); 73 | 74 | ret = sd_login_monitor_new("seat", &sd->mon); 75 | if (ret) { 76 | log_err("cannot create systemd login monitor (%d): %s", 77 | ret, strerror(-ret)); 78 | ret = -EFAULT; 79 | goto err_free; 80 | } 81 | 82 | *out = sd; 83 | return 0; 84 | 85 | err_free: 86 | free(sd); 87 | return ret; 88 | } 89 | 90 | void uterm_sd_free(struct uterm_sd *sd) 91 | { 92 | if (!sd) 93 | return; 94 | 95 | sd_login_monitor_unref(sd->mon); 96 | free(sd); 97 | } 98 | 99 | int uterm_sd_get_fd(struct uterm_sd *sd) 100 | { 101 | if (!sd) 102 | return -EINVAL; 103 | 104 | return sd_login_monitor_get_fd(sd->mon); 105 | } 106 | 107 | void uterm_sd_flush(struct uterm_sd *sd) 108 | { 109 | if (!sd) 110 | return; 111 | 112 | sd_login_monitor_flush(sd->mon); 113 | } 114 | 115 | int uterm_sd_get_seats(struct uterm_sd *sd, char ***seats) 116 | { 117 | int ret; 118 | char **s; 119 | 120 | if (!sd || !seats) 121 | return -EINVAL; 122 | 123 | ret = sd_get_seats(&s); 124 | if (ret < 0) { 125 | log_warning("cannot read seat information from systemd: %d", 126 | ret); 127 | return -EFAULT; 128 | } 129 | 130 | *seats = s; 131 | return ret; 132 | } 133 | -------------------------------------------------------------------------------- /src/uterm_systemd_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Systemd integration 28 | * Systemd provides multi-seat support and other helpers that we can use in 29 | * uterm. 30 | */ 31 | 32 | #ifndef UTERM_SYSTEMD_H 33 | #define UTERM_SYSTEMD_H 34 | 35 | #include 36 | #include "uterm_monitor.h" 37 | 38 | struct uterm_sd; 39 | 40 | #ifdef BUILD_ENABLE_MULTI_SEAT 41 | 42 | int uterm_sd_new(struct uterm_sd **out); 43 | void uterm_sd_free(struct uterm_sd *sd); 44 | int uterm_sd_get_fd(struct uterm_sd *sd); 45 | void uterm_sd_flush(struct uterm_sd *sd); 46 | int uterm_sd_get_seats(struct uterm_sd *sd, char ***seats); 47 | 48 | #else 49 | 50 | static inline int uterm_sd_new(struct uterm_sd **out) 51 | { 52 | return -EOPNOTSUPP; 53 | } 54 | 55 | static inline void uterm_sd_free(struct uterm_sd *sd) 56 | { 57 | } 58 | 59 | static inline int uterm_sd_get_fd(struct uterm_sd *sd) 60 | { 61 | return -1; 62 | } 63 | 64 | static inline void uterm_sd_flush(struct uterm_sd *sd) 65 | { 66 | } 67 | 68 | static inline int uterm_sd_get_seats(struct uterm_sd *sd, char ***seats) 69 | { 70 | return -EINVAL; 71 | } 72 | 73 | #endif 74 | 75 | #endif /* UTERM_SYSTEMD_H */ 76 | -------------------------------------------------------------------------------- /src/uterm_video_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Internal definitions */ 27 | 28 | #ifndef UTERM_VIDEO_INTERNAL_H 29 | #define UTERM_VIDEO_INTERNAL_H 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "eloop.h" 36 | #include "shl_dlist.h" 37 | #include "shl_hook.h" 38 | #include "uterm_video.h" 39 | 40 | /* backend-operations */ 41 | 42 | struct mode_ops { 43 | int (*init) (struct uterm_mode *mode); 44 | void (*destroy) (struct uterm_mode *mode); 45 | const char *(*get_name) (const struct uterm_mode *mode); 46 | unsigned int (*get_width) (const struct uterm_mode *mode); 47 | unsigned int (*get_height) (const struct uterm_mode *mode); 48 | }; 49 | 50 | struct display_ops { 51 | int (*init) (struct uterm_display *display); 52 | void (*destroy) (struct uterm_display *display); 53 | int (*activate) (struct uterm_display *disp, struct uterm_mode *mode); 54 | void (*deactivate) (struct uterm_display *disp); 55 | int (*set_dpms) (struct uterm_display *disp, int state); 56 | int (*use) (struct uterm_display *disp, bool *opengl); 57 | int (*get_buffers) (struct uterm_display *disp, 58 | struct uterm_video_buffer *buffer, 59 | unsigned int formats); 60 | int (*swap) (struct uterm_display *disp, bool immediate); 61 | int (*blit) (struct uterm_display *disp, 62 | const struct uterm_video_buffer *buf, 63 | unsigned int x, unsigned int y); 64 | int (*fake_blendv) (struct uterm_display *disp, 65 | const struct uterm_video_blend_req *req, 66 | size_t num); 67 | int (*fill) (struct uterm_display *disp, 68 | uint8_t r, uint8_t g, uint8_t b, unsigned int x, 69 | unsigned int y, unsigned int width, unsigned int height); 70 | }; 71 | 72 | struct video_ops { 73 | int (*init) (struct uterm_video *video, const char *node); 74 | void (*destroy) (struct uterm_video *video); 75 | void (*segfault) (struct uterm_video *video); 76 | int (*poll) (struct uterm_video *video); 77 | void (*sleep) (struct uterm_video *video); 78 | int (*wake_up) (struct uterm_video *video); 79 | }; 80 | 81 | struct uterm_video_module { 82 | const struct video_ops *ops; 83 | }; 84 | 85 | #define VIDEO_CALL(func, els, ...) (func ? func(__VA_ARGS__) : els) 86 | 87 | /* uterm_mode */ 88 | 89 | struct uterm_mode { 90 | struct shl_dlist list; 91 | unsigned long ref; 92 | struct uterm_display *disp; 93 | 94 | const struct mode_ops *ops; 95 | void *data; 96 | }; 97 | 98 | int mode_new(struct uterm_mode **out, const struct mode_ops *ops); 99 | int uterm_mode_bind(struct uterm_mode *mode, struct uterm_display *disp); 100 | void uterm_mode_unbind(struct uterm_mode *mode); 101 | 102 | /* uterm_display */ 103 | 104 | #define DISPLAY_ONLINE 0x01 105 | #define DISPLAY_VSYNC 0x02 106 | #define DISPLAY_AVAILABLE 0x04 107 | #define DISPLAY_OPEN 0x08 108 | #define DISPLAY_DBUF 0x10 109 | #define DISPLAY_DITHERING 0x20 110 | #define DISPLAY_PFLIP 0x40 111 | 112 | struct uterm_display { 113 | struct shl_dlist list; 114 | unsigned long ref; 115 | unsigned int flags; 116 | struct uterm_video *video; 117 | 118 | struct shl_hook *hook; 119 | struct shl_dlist modes; 120 | struct uterm_mode *default_mode; 121 | struct uterm_mode *current_mode; 122 | int dpms; 123 | 124 | bool vblank_scheduled; 125 | struct itimerspec vblank_spec; 126 | struct ev_timer *vblank_timer; 127 | 128 | const struct display_ops *ops; 129 | void *data; 130 | }; 131 | 132 | int display_new(struct uterm_display **out, const struct display_ops *ops); 133 | void display_set_vblank_timer(struct uterm_display *disp, 134 | unsigned int msecs); 135 | int display_schedule_vblank_timer(struct uterm_display *disp); 136 | int uterm_display_bind(struct uterm_display *disp, struct uterm_video *video); 137 | void uterm_display_unbind(struct uterm_display *disp); 138 | 139 | #define DISPLAY_CB(disp, act) shl_hook_call((disp)->hook, (disp), \ 140 | &(struct uterm_display_event){ \ 141 | .action = (act), \ 142 | }) 143 | 144 | static inline bool display_is_online(const struct uterm_display *disp) 145 | { 146 | return disp->video && (disp->flags & DISPLAY_ONLINE); 147 | } 148 | 149 | /* uterm_video */ 150 | 151 | #define VIDEO_AWAKE 0x01 152 | #define VIDEO_HOTPLUG 0x02 153 | 154 | struct uterm_video { 155 | unsigned long ref; 156 | unsigned int flags; 157 | struct ev_eloop *eloop; 158 | 159 | struct shl_dlist displays; 160 | struct shl_hook *hook; 161 | 162 | const struct uterm_video_module *mod; 163 | const struct video_ops *ops; 164 | void *data; 165 | }; 166 | 167 | static inline bool video_is_awake(const struct uterm_video *video) 168 | { 169 | return video->flags & VIDEO_AWAKE; 170 | } 171 | 172 | static inline bool video_need_hotplug(const struct uterm_video *video) 173 | { 174 | return video->flags & VIDEO_HOTPLUG; 175 | } 176 | 177 | #define VIDEO_CB(vid, disp, act) shl_hook_call((vid)->hook, (vid), \ 178 | &(struct uterm_video_hotplug){ \ 179 | .display = (disp), \ 180 | .action = (act), \ 181 | }) 182 | 183 | #if defined(BUILD_ENABLE_VIDEO_DRM3D) || defined(BUILD_ENABLE_VIDEO_DRM2D) 184 | 185 | #include 186 | 187 | static inline bool video_drm_available(void) 188 | { 189 | return drmAvailable(); 190 | } 191 | 192 | #else 193 | 194 | static inline bool video_drm_available(void) 195 | { 196 | return false; 197 | } 198 | 199 | #endif 200 | 201 | #endif /* UTERM_VIDEO_INTERNAL_H */ 202 | -------------------------------------------------------------------------------- /src/uterm_vt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * uterm - Linux User-Space Terminal VT API 3 | * 4 | * Copyright (c) 2011-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Virtual Terminals 28 | * Virtual terminals allow controlling multiple virtual terminals on one real 29 | * terminal. It is multi-seat capable and fully asynchronous. 30 | */ 31 | 32 | #ifndef UTERM_UTERM_VT_H 33 | #define UTERM_UTERM_VT_H 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | struct uterm_vt; 42 | struct uterm_vt_master; 43 | 44 | enum uterm_vt_action { 45 | UTERM_VT_ACTIVATE, 46 | UTERM_VT_DEACTIVATE, 47 | UTERM_VT_HUP, 48 | }; 49 | 50 | enum uterm_vt_flags { 51 | UTERM_VT_FORCE = 0x01, 52 | }; 53 | 54 | struct uterm_vt_event { 55 | unsigned int action; 56 | unsigned int flags; 57 | int target; 58 | }; 59 | 60 | enum uterm_vt_type { 61 | UTERM_VT_REAL = 0x01, 62 | UTERM_VT_FAKE = 0x02, 63 | }; 64 | 65 | typedef int (*uterm_vt_cb) (struct uterm_vt *vt, struct uterm_vt_event *ev, 66 | void *data); 67 | 68 | int uterm_vt_master_new(struct uterm_vt_master **out, 69 | struct ev_eloop *eloop); 70 | void uterm_vt_master_ref(struct uterm_vt_master *vtm); 71 | void uterm_vt_master_unref(struct uterm_vt_master *vtm); 72 | 73 | int uterm_vt_master_activate_all(struct uterm_vt_master *vtm); 74 | int uterm_vt_master_deactivate_all(struct uterm_vt_master *vtm); 75 | 76 | int uterm_vt_allocate(struct uterm_vt_master *vt, struct uterm_vt **out, 77 | unsigned int allowed_types, 78 | const char *seat, struct uterm_input *input, 79 | const char *vt_name, uterm_vt_cb cb, void *data); 80 | void uterm_vt_deallocate(struct uterm_vt *vt); 81 | void uterm_vt_ref(struct uterm_vt *vt); 82 | void uterm_vt_unref(struct uterm_vt *vt); 83 | 84 | int uterm_vt_activate(struct uterm_vt *vt); 85 | int uterm_vt_deactivate(struct uterm_vt *vt); 86 | void uterm_vt_retry(struct uterm_vt *vt); 87 | unsigned int uterm_vt_get_type(struct uterm_vt *vt); 88 | unsigned int uterm_vt_get_num(struct uterm_vt *vt); 89 | 90 | #endif /* UTERM_UTERM_VT_H */ 91 | -------------------------------------------------------------------------------- /tests/meson.build: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2022 Aetf 2 | # 3 | # SPDX-License-Identifier: MIT 4 | 5 | foreach name, deps : { 6 | 'output': [uterm_deps], 7 | 'vt': [uterm_deps], 8 | 'input': [uterm_deps], 9 | 'key': [], 10 | } 11 | deps += [ 12 | shl_deps, 13 | conf_deps, 14 | xkbcommon_deps, 15 | ] 16 | test_name = f'test_@name@' 17 | exe = executable(test_name, f'@test_name@.c', 18 | dependencies: deps, 19 | ) 20 | endforeach 21 | 22 | test_shl = executable('test_shl', 'test_shl.c', 23 | dependencies: [shl_deps, check_deps], 24 | ) 25 | test('test_shl', test_shl, 26 | protocol: 'tap', 27 | env: {'CK_TAP_LOG_FILE_NAME': '-', 'CK_VERBOSITY': 'silent'}, 28 | ) 29 | -------------------------------------------------------------------------------- /tests/test_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Kmscon - Test Helper 3 | * 4 | * Copyright (c) 2012-2013 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* 27 | * Test Helper 28 | * This header includes all kinds of helpers for testing. It tries to include 29 | * everything required and provides simple macros to avoid duplicating code in 30 | * each test. We try to keep tests as small as possible and move everything that 31 | * might be common here. 32 | * 33 | * We avoid sticking to our usual coding conventions (including headers in 34 | * source files, etc. ..) and instead make this the most convenient we can. 35 | */ 36 | 37 | #ifndef TEST_COMMON_H 38 | #define TEST_COMMON_H 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | /* lower address-space is protected from user-allocation, so this is invalid */ 48 | #define TEST_INVALID_PTR ((void*)0x10) 49 | 50 | #define UNUSED(x) (void)(x) 51 | 52 | #define TEST_DEFINE_CASE(_name) \ 53 | static TCase *test_create_case_##_name(void) \ 54 | { \ 55 | TCase *tc; \ 56 | \ 57 | tc = tcase_create(#_name); \ 58 | 59 | #define TEST(_name) tcase_add_test(tc, _name); 60 | 61 | #define TEST_END_CASE \ 62 | return tc; \ 63 | } \ 64 | 65 | #define TEST_END NULL 66 | 67 | #define TEST_CASE(_name) test_create_case_##_name 68 | 69 | static inline Suite *test_create_suite(const char *name, ...) 70 | { 71 | Suite *s; 72 | va_list list; 73 | TCase *(*fn)(void); 74 | 75 | s = suite_create(name); 76 | 77 | va_start(list, name); 78 | while ((fn = va_arg(list, TCase *(*)(void)))) 79 | suite_add_tcase(s, fn()); 80 | va_end(list); 81 | 82 | return s; 83 | } 84 | 85 | #define TEST_SUITE(_name, ...) test_create_suite((#_name), ##__VA_ARGS__) 86 | 87 | static inline int test_run_suite(Suite *s) 88 | { 89 | int ret; 90 | SRunner *sr; 91 | 92 | sr = srunner_create(s); 93 | srunner_run_all(sr, CK_ENV); 94 | ret = srunner_ntests_failed(sr); 95 | srunner_free(sr); 96 | 97 | return ret; 98 | } 99 | 100 | #define TEST_DEFINE(_suite) \ 101 | int main(int argc, char **argv) \ 102 | { \ 103 | return test_run_suite(_suite); \ 104 | } 105 | 106 | #ifndef ck_assert_mem_eq 107 | #include 108 | #define ck_assert_mem_eq(_x, _y, _len) \ 109 | ck_assert(memcmp((_x), (_y), (_len)) == 0) 110 | #define ck_assert_mem_ne(_x, _y, _len) \ 111 | ck_assert(memcmp((_x), (_y), (_len)) != 0) 112 | #define ck_assert_mem_lt(_x, _y, _len) \ 113 | ck_assert(memcmp((_x), (_y), (_len)) < 0) 114 | #define ck_assert_mem_le(_x, _y, _len) \ 115 | ck_assert(memcmp((_x), (_y), (_len)) <= 0) 116 | #define ck_assert_mem_gt(_x, _y, _len) \ 117 | ck_assert(memcmp((_x), (_y), (_len)) > 0) 118 | #define ck_assert_mem_ge(_x, _y, _len) \ 119 | ck_assert(memcmp((_x), (_y), (_len)) >= 0) 120 | #endif 121 | 122 | #endif /* TEST_COMMON_H */ 123 | -------------------------------------------------------------------------------- /tests/test_include.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kmscon - Common test functions 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "conf.h" 33 | #include "eloop.h" 34 | #include "shl_log.h" 35 | 36 | #define TEST_HELP \ 37 | "\t-h, --help [off] Print this help and exit\n" \ 38 | "\t-v, --verbose [off] Print verbose messages\n" \ 39 | "\t --debug [off] Enable debug mode\n" \ 40 | "\t --silent [off] Suppress notices and warnings\n" 41 | 42 | static struct { 43 | bool help; 44 | bool exit; 45 | bool verbose; 46 | bool debug; 47 | bool silent; 48 | } test_conf; 49 | 50 | static struct conf_ctx *test_ctx; 51 | 52 | static int aftercheck_debug(struct conf_option *opt, int argc, char **argv, 53 | int idx) 54 | { 55 | /* --debug implies --verbose */ 56 | if (test_conf.debug) 57 | test_conf.verbose = 1; 58 | 59 | return 0; 60 | } 61 | 62 | static int aftercheck_help(struct conf_option *opt, int argc, char **argv, 63 | int idx) 64 | { 65 | /* exit after printing --help information */ 66 | if (test_conf.help) { 67 | print_help(); 68 | test_conf.exit = true; 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | #define TEST_OPTIONS \ 75 | CONF_OPTION_BOOL_FULL('h', "help", aftercheck_help, NULL, NULL, &test_conf.help, false), \ 76 | CONF_OPTION_BOOL('v', "verbose", &test_conf.verbose, false), \ 77 | CONF_OPTION_BOOL_FULL(0, "debug", aftercheck_debug, NULL, NULL, &test_conf.debug, false), \ 78 | CONF_OPTION_BOOL(0, "silent", &test_conf.silent, false) 79 | 80 | static void sig_generic(struct ev_eloop *p, struct signalfd_siginfo *info, 81 | void *data) 82 | { 83 | struct ev_eloop *eloop = data; 84 | 85 | ev_eloop_exit(eloop); 86 | log_info("terminating due to caught signal %d", info->ssi_signo); 87 | } 88 | 89 | static int test_prepare(struct conf_option *opts, size_t len, 90 | int argc, char **argv, struct ev_eloop **out) 91 | { 92 | int ret; 93 | struct ev_eloop *eloop; 94 | 95 | ret = conf_ctx_new(&test_ctx, opts, len, &test_conf); 96 | if (ret) 97 | return ret; 98 | 99 | ret = conf_ctx_parse_argv(test_ctx, argc, argv); 100 | if (ret) 101 | goto err_out; 102 | 103 | if (test_conf.exit) { 104 | ret = -ECANCELED; 105 | goto err_out; 106 | } 107 | 108 | if (!test_conf.debug && !test_conf.verbose && test_conf.silent) 109 | log_set_config(&LOG_CONFIG_WARNING(0, 0, 0, 0)); 110 | else 111 | log_set_config(&LOG_CONFIG_INFO(test_conf.debug, 112 | test_conf.verbose)); 113 | 114 | log_print_init(argv[0]); 115 | 116 | ret = ev_eloop_new(&eloop, log_llog, NULL); 117 | if (ret) 118 | goto err_out; 119 | 120 | ret = ev_eloop_register_signal_cb(eloop, SIGTERM, sig_generic, eloop); 121 | if (ret) 122 | goto err_unref; 123 | 124 | ret = ev_eloop_register_signal_cb(eloop, SIGINT, sig_generic, eloop); 125 | if (ret) { 126 | ev_eloop_unregister_signal_cb(eloop, SIGTERM, 127 | sig_generic, eloop); 128 | goto err_unref; 129 | } 130 | 131 | *out = eloop; 132 | return 0; 133 | 134 | err_unref: 135 | ev_eloop_unref(eloop); 136 | err_out: 137 | conf_ctx_free(test_ctx); 138 | return ret; 139 | } 140 | 141 | static void test_fail(int ret) 142 | { 143 | if (ret) 144 | log_err("init failed, errno %d: %s", ret, strerror(-ret)); 145 | } 146 | 147 | static void test_exit(struct conf_option *opts, size_t len, 148 | struct ev_eloop *eloop) 149 | { 150 | ev_eloop_unregister_signal_cb(eloop, SIGINT, sig_generic, eloop); 151 | ev_eloop_unregister_signal_cb(eloop, SIGTERM, sig_generic, eloop); 152 | ev_eloop_unref(eloop); 153 | conf_ctx_free(test_ctx); 154 | } 155 | -------------------------------------------------------------------------------- /tests/test_key.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_key - Test client key-input 3 | * 4 | * Copyright (c) 2012 David Herrmann 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | int main() 33 | { 34 | int res; 35 | unsigned char buf; 36 | struct termios omode, nmode; 37 | bool reset = false; 38 | 39 | fprintf(stderr, "Quit with 'q' (maybe followed by 'enter'/'return')\r\n"); 40 | fprintf(stderr, "Maybe your terminal may be unusable after this, use 'reset' to fix it\r\n"); 41 | 42 | if (tcgetattr(0, &omode) < 0) { 43 | fprintf(stderr, "cannot retrieve terminal attributes (%d): %m\r\n", 44 | errno); 45 | } else { 46 | memcpy(&nmode, &omode, sizeof(nmode)); 47 | cfmakeraw(&nmode); 48 | if (tcsetattr(0, TCSANOW, &nmode) < 0) 49 | fprintf(stderr, "cannot set terminal attributes (%d): %m\r\n", 50 | errno); 51 | else 52 | reset = true; 53 | } 54 | 55 | while (1) { 56 | res = fread(&buf, 1, 1, stdin); 57 | if (res != 1) { 58 | fprintf(stderr, "error on stdin: %d %d: %m\r\n", 59 | res, errno); 60 | break; 61 | } 62 | 63 | if (buf == '\n') 64 | fprintf(stderr, "key: \r\n"); 65 | else 66 | fprintf(stderr, "key: %x %u %o '%c'\r\n", 67 | (int)buf, buf, buf, buf); 68 | 69 | if (buf == 'q') 70 | break; 71 | } 72 | 73 | if (reset && tcsetattr(0, TCSANOW, &omode) < 0) 74 | fprintf(stderr, "cannot reset terminal attributes (%d): %m\r\n", 75 | errno); 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /tests/test_shl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_shl - Test shl library 3 | * 4 | * Copyright (c) 2022 Victor Westerhuis 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files 8 | * (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include "test_common.h" 27 | #include "shl_misc.h" 28 | 29 | #define check_assert_string_list_eq(X, Y) \ 30 | do { \ 31 | unsigned int i; \ 32 | const char **x, **y; \ 33 | \ 34 | x = (X); \ 35 | y = (Y); \ 36 | \ 37 | for (i = 0; x[i] && y[i]; ++i) \ 38 | ck_assert_str_eq(x[i], y[i]); \ 39 | ck_assert_ptr_eq(x[i], NULL); \ 40 | ck_assert_ptr_eq(y[i], NULL); \ 41 | } while (0) 42 | 43 | START_TEST(test_split_command_string) 44 | { 45 | int ret; 46 | unsigned int i, n, n_list, n_expected; 47 | char **list; 48 | 49 | const char *invalid_command_strings[] = { 50 | "\"", "'", "\\", 51 | "\"/bin/true", "'/bin/true", "/bin/true\\", 52 | "ls -h \"*.c'", 53 | }; 54 | n = sizeof(invalid_command_strings) / sizeof(invalid_command_strings[0]); 55 | 56 | for (i = 0; i < n; ++i) { 57 | list = TEST_INVALID_PTR; 58 | n_list = -10; 59 | 60 | ret = shl_split_command_string(invalid_command_strings[i], 61 | &list, &n_list); 62 | ck_assert_int_eq(ret, -EINVAL); 63 | ck_assert_ptr_eq(list, TEST_INVALID_PTR); 64 | ck_assert_uint_eq(n_list, (unsigned int)-10); 65 | } 66 | 67 | const char *expected_command_list[] = { 68 | "'/bin/command with space", 69 | "\t\\argument=\"quoted\"", 70 | "plain\3argument", 71 | " an\tother='ere", 72 | "\"ends with \\", 73 | "\\\"more\\bquotes\\", 74 | NULL 75 | }; 76 | n_expected = sizeof(expected_command_list) / 77 | sizeof(expected_command_list[0]) - 1; 78 | const char *valid_command_strings[] = { 79 | "\\'/bin/command\\ with\\ space \\\t\\\\argument=\\\"quoted\\\" plain\3argument \\ an\\\tother=\\'ere \\\"ends\\ with\\ \\\\ \\\\\\\"more\\\\bquotes\\\\", 80 | "\"'/bin/command with space\" \"\t\\argument=\\\"quoted\\\"\" \"plain\3argument\" \" an\tother='ere\" \"\\\"ends with \\\\\" \"\\\\\\\"more\\bquotes\\\\\"", 81 | "\"'\"'/bin/command with space' '\t\\argument=\"quoted\"' 'plain\3argument' ' an\tother='\"'\"'ere' '\"ends with \\' '\\\"more\\bquotes\\'", 82 | " \\'/bin/command\\ with\\ space\t\t\\\t\\\\argument=\\\"quoted\\\"\t plain\3argument \t\\ an\\\tother=\\'ere \\\"ends\\ with\\ \\\\ \t \\\\\\\"more\\\\\\bquotes\\\\ \t \t", 83 | }; 84 | n = sizeof(valid_command_strings) / sizeof(valid_command_strings[0]); 85 | 86 | for (i = 0; i < n; ++i) { 87 | list = TEST_INVALID_PTR; 88 | n_list = -10; 89 | 90 | ret = shl_split_command_string(valid_command_strings[i], &list, 91 | &n_list); 92 | ck_assert_int_eq(ret, 0); 93 | ck_assert_ptr_ne(list, TEST_INVALID_PTR); 94 | check_assert_string_list_eq((const char**)list, expected_command_list); 95 | ck_assert_uint_eq(n_list, n_expected); 96 | } 97 | 98 | const char *empty_command_strings[] = { 99 | "", 100 | " ", 101 | "\t\t \t", 102 | }; 103 | n = sizeof(empty_command_strings) / sizeof(empty_command_strings[0]); 104 | 105 | for (i = 0; i < n; ++i) { 106 | list = TEST_INVALID_PTR; 107 | n_list = -10; 108 | 109 | ret = shl_split_command_string(empty_command_strings[i], &list, 110 | &n_list); 111 | ck_assert_int_eq(ret, 0); 112 | ck_assert_ptr_ne(list, TEST_INVALID_PTR); 113 | ck_assert_ptr_eq(list[0], NULL); 114 | ck_assert_uint_eq(n_list, 0); 115 | } 116 | 117 | { 118 | list = TEST_INVALID_PTR; 119 | n_list = -10; 120 | 121 | ret = shl_split_command_string(valid_command_strings[0], &list, 122 | &n_list); 123 | ck_assert_int_eq(ret, 0); 124 | ck_assert_ptr_ne(list, TEST_INVALID_PTR); 125 | check_assert_string_list_eq((const char**)list, expected_command_list); 126 | ck_assert_uint_eq(n_list, n_expected); 127 | } 128 | 129 | { 130 | list = TEST_INVALID_PTR; 131 | 132 | ret = shl_split_command_string(valid_command_strings[0], &list, 133 | NULL); 134 | ck_assert_int_eq(ret, 0); 135 | ck_assert_ptr_ne(list, TEST_INVALID_PTR); 136 | check_assert_string_list_eq((const char**)list, expected_command_list); 137 | } 138 | 139 | { 140 | n_list = -10; 141 | 142 | ret = shl_split_command_string(valid_command_strings[0], NULL, 143 | &n_list); 144 | ck_assert_int_eq(ret, -EINVAL); 145 | ck_assert_uint_eq(n_list, (unsigned int)-10); 146 | } 147 | 148 | { 149 | list = TEST_INVALID_PTR; 150 | n_list = -10; 151 | 152 | ret = shl_split_command_string(NULL, &list, &n_list); 153 | ck_assert_int_eq(ret, -EINVAL); 154 | ck_assert_ptr_eq(list, TEST_INVALID_PTR); 155 | ck_assert_uint_eq(n_list, (unsigned int)-10); 156 | } 157 | 158 | { 159 | n_list = -10; 160 | 161 | ret = shl_split_command_string(NULL, NULL, &n_list); 162 | ck_assert_int_eq(ret, -EINVAL); 163 | ck_assert_uint_eq(n_list, (unsigned int)-10); 164 | } 165 | } 166 | END_TEST 167 | 168 | TEST_DEFINE_CASE(misc) 169 | TEST(test_split_command_string) 170 | TEST_END_CASE 171 | 172 | TEST_DEFINE( 173 | TEST_SUITE(shl, 174 | TEST_CASE(misc), 175 | TEST_END 176 | ) 177 | ) 178 | -------------------------------------------------------------------------------- /tests/test_vt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_console - Test VT Layer 3 | * 4 | * Copyright (c) 2011-2012 David Herrmann 5 | * Copyright (c) 2011 University of Tuebingen 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining 8 | * a copy of this software and associated documentation files 9 | * (the "Software"), to deal in the Software without restriction, including 10 | * without limitation the rights to use, copy, modify, merge, publish, 11 | * distribute, sublicense, and/or sell copies of the Software, and to 12 | * permit persons to whom the Software is furnished to do so, subject to 13 | * the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included 16 | * in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | 27 | /* 28 | * Test VT Layer 29 | * This opens a new VT and prints some text on it. You can then change the VT 30 | * and change back. This is only to test the VT subsystem and event engine. 31 | * This automatically switches to the new VT. Currently, the display gets 32 | * frozen because we aren't painting to the framebuffer yet. Use 33 | * ctrl+alt+FX (or some equivalent) to switch back to X/VT. 34 | */ 35 | 36 | static void print_help(); 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include "eloop.h" 46 | #include "shl_log.h" 47 | #include "uterm_input.h" 48 | #include "uterm_vt.h" 49 | #include "test_include.h" 50 | 51 | static void print_help() 52 | { 53 | /* 54 | * Usage/Help information 55 | * This should be scaled to a maximum of 80 characters per line: 56 | * 57 | * 80 char line: 58 | * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 59 | * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" 60 | * 80 char line starting with tab: 61 | * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | 62 | * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" 63 | */ 64 | fprintf(stderr, 65 | "Usage:\n" 66 | "\t%1$s [options]\n" 67 | "\t%1$s -h [options]\n" 68 | "\n" 69 | "You can prefix boolean options with \"no-\" to negate it. If an argument is\n" 70 | "given multiple times, only the last argument matters if not otherwise stated.\n" 71 | "\n" 72 | "General Options:\n" 73 | TEST_HELP 74 | "\n" 75 | "VT Options:\n" 76 | "\t --vt [-] Path to VT to use\n" 77 | "\t-s, --switchvt [off] Switch automatically to the new VT\n", 78 | "test_vt"); 79 | /* 80 | * 80 char line: 81 | * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 82 | * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" 83 | * 80 char line starting with tab: 84 | * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | 85 | * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" 86 | */ 87 | } 88 | 89 | static const char *vtpath = NULL; 90 | static bool switchvt = false; 91 | 92 | struct conf_option options[] = { 93 | TEST_OPTIONS, 94 | CONF_OPTION_STRING(0, "vt", &vtpath, NULL), 95 | CONF_OPTION_BOOL('s', "switchvt", &switchvt, false), 96 | }; 97 | 98 | int main(int argc, char **argv) 99 | { 100 | int ret; 101 | struct ev_eloop *eloop; 102 | struct uterm_vt_master *vtm; 103 | struct uterm_input *input; 104 | struct uterm_vt *vt; 105 | size_t onum; 106 | 107 | onum = sizeof(options) / sizeof(*options); 108 | ret = test_prepare(options, onum, argc, argv, &eloop); 109 | if (ret) 110 | goto err_fail; 111 | 112 | ret = uterm_vt_master_new(&vtm, eloop); 113 | if (ret) 114 | goto err_exit; 115 | 116 | ret = uterm_input_new(&input, eloop, "", "", "", "", "C", "", "", 0, 0, 117 | 0, log_llog, NULL); 118 | if (ret) 119 | goto err_vtm; 120 | 121 | ret = uterm_vt_allocate(vtm, &vt, UTERM_VT_FAKE | UTERM_VT_REAL, 122 | "seat0", input, vtpath, NULL, NULL); 123 | if (ret) 124 | goto err_input; 125 | 126 | if (switchvt) { 127 | ret = uterm_vt_activate(vt); 128 | if (ret == -EINPROGRESS) 129 | log_debug("VT switch in progress"); 130 | else if (ret) 131 | log_warn("cannot switch to VT: %d", ret); 132 | } 133 | 134 | ev_eloop_run(eloop, -1); 135 | 136 | log_debug("Terminating"); 137 | 138 | /* switch back to previous VT but wait for eloop to process SIGUSR0 */ 139 | if (switchvt) { 140 | ret = uterm_vt_deactivate(vt); 141 | if (ret == -EINPROGRESS) 142 | ev_eloop_run(eloop, 50); 143 | } 144 | 145 | uterm_vt_unref(vt); 146 | err_input: 147 | uterm_input_unref(input); 148 | err_vtm: 149 | uterm_vt_master_unref(vtm); 150 | err_exit: 151 | test_exit(options, onum, eloop); 152 | err_fail: 153 | if (ret != -ECANCELED) 154 | test_fail(ret); 155 | return abs(ret); 156 | } 157 | -------------------------------------------------------------------------------- /tools/embedded_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # SPDX-FileCopyrightText: 2022 Aetf 3 | # 4 | # SPDX-License-Identifier: MIT 5 | import inspect 6 | import re 7 | from pathlib import Path 8 | from typing import List, Tuple 9 | from itertools import islice 10 | 11 | 12 | def chunk(it, size): 13 | it = iter(it) 14 | return iter(lambda: tuple(islice(it, size)), ()) 15 | 16 | 17 | def make_c_identifier(s): 18 | for ptn, repl in [ 19 | (re.compile(r'[^a-zA-Z0-9_]'), '_'), 20 | (re.compile(r'^(\d)'), r'_\1'), 21 | ]: 22 | s = re.sub(ptn, repl, s) 23 | return s 24 | 25 | 26 | def generate( 27 | src: Path, 28 | dest_dir: Path, 29 | regex: List[Tuple[re.Pattern, str]], 30 | zero_term: bool, 31 | ): 32 | # prepare 33 | name = src.name 34 | c_name = make_c_identifier(name) 35 | 36 | # read content 37 | if regex: 38 | with src.open() as f: 39 | lines = [] 40 | for line in f: 41 | for ptn, sub in regex: 42 | line = ptn.sub(sub, line) 43 | lines.append(line) 44 | content = '\n'.join(lines).encode('utf-8') 45 | else: 46 | with src.open('rb') as f: 47 | content = f.read() 48 | 49 | if zero_term: 50 | content = content + b'\x00' 51 | 52 | # format content to c array and 16 bytes per row 53 | content_output = ',\n '.join( 54 | ', '.join(f'{b:#04x}' for b in row) 55 | for row in chunk(content, 16) 56 | ) 57 | 58 | content_c = inspect.cleandoc(f''' 59 | #include 60 | static const unsigned char data[] = {{ 61 | {content_output} 62 | }}; 63 | const char *const _binary_{c_name}_start = (const char*)data; 64 | const char *const _binary_{c_name}_end = (const char*)data + sizeof(data); 65 | const size_t _binary_{c_name}_size = sizeof(data); 66 | ''') 67 | content_h = inspect.cleandoc(f''' 68 | #ifndef {c_name}_H 69 | #define {c_name}_H 70 | #include 71 | extern const char *const _binary_{c_name}_start; 72 | extern const char *const _binary_{c_name}_end; 73 | extern size_t _binary_{c_name}_size; 74 | #endif // {c_name}_H 75 | ''') 76 | 77 | # generate the file 78 | with (dest_dir / f'{name}.bin.c').open('w') as f: 79 | f.write(content_c) 80 | with (dest_dir / f'{name}.bin.h').open('w') as f: 81 | f.write(content_h) 82 | dest_dir.mkdir(exist_ok=True, parents=True) 83 | 84 | 85 | def main(): 86 | import argparse 87 | parser = argparse.ArgumentParser() 88 | parser.add_argument( 89 | '--zero_term', 90 | action='store_true', 91 | help='Add an additional 0 byte at the end of data' 92 | ) 93 | parser.add_argument( 94 | '--regex', metavar=('pattern', 'replace'), 95 | type=str, nargs = 2, action='append', default=[], 96 | help='Treat the binary as text, and for each line replace all occurance matching the regex' 97 | ) 98 | parser.add_argument( 99 | 'src', 100 | type=Path, 101 | help='The source binary file' 102 | ) 103 | parser.add_argument( 104 | 'dest_dir', 105 | type=Path, 106 | help='The destination directory to put output files' 107 | ) 108 | args = parser.parse_args() 109 | 110 | args.regex = [ 111 | (re.compile(ptn), sub) 112 | for ptn, sub in args.regex 113 | ] 114 | generate(args.src, args.dest_dir, args.regex, args.zero_term) 115 | 116 | 117 | if __name__ == '__main__': 118 | main() 119 | -------------------------------------------------------------------------------- /tools/extract_release_note.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # SPDX-FileCopyrightText: 2022 Aetf 3 | # 4 | # SPDX-License-Identifier: MIT 5 | import re 6 | import inspect 7 | 8 | PTN_RELEASE_NOTE = re.compile(r'^CHANGES WITH.+$([\s\S]+?)^CHANGES WITH.+$', re.MULTILINE) 9 | 10 | 11 | def extract(src: str) -> str: 12 | """Find section between the first and the next 'CHANGES WITH xx:' lines, 13 | and strip common prefix whitespace 14 | """ 15 | m = PTN_RELEASE_NOTE.search(src) 16 | if m is not None: 17 | return inspect.cleandoc(m.group(1)) + '\n' 18 | else: 19 | return '' 20 | 21 | 22 | def main(): 23 | import argparse 24 | import sys 25 | 26 | parser = argparse.ArgumentParser() 27 | parser.add_argument( 28 | 'src', 29 | type=argparse.FileType('r'), 30 | nargs='?', 31 | help='input NEWS', 32 | default=sys.stdin, 33 | ) 34 | parser.add_argument( 35 | 'dest', 36 | type=argparse.FileType('w'), 37 | nargs='?', 38 | help='output', 39 | default=sys.stdout, 40 | ) 41 | args = parser.parse_args() 42 | 43 | args.dest.write(extract(args.src.read())) 44 | 45 | 46 | if __name__ == '__main__': 47 | main() 48 | --------------------------------------------------------------------------------